ImageResizer / System.Drawing和CMYK JPEG

时间:2012-11-22 19:54:33

标签: c# asp.net system.drawing imageresizer

我正在使用ImageResizer库在ASP.NET MVC 4项目中进行一些简单的图像大小调整和旋转。问题是,当我用它来处理32-bpp的CMYK JPEG文件时,它会因ArgumentException而失败,但只能在我的(Windows Server 2008 R2)服务器上运行 - 它在我的(Windows Vista)笔记本电脑上运行正常。

有问题的JPEG文件不是太大(700x500)或非标准 - 所有Web浏览器和Paint都可以打开它们,即使在有问题的服务器上也是如此。 JPEG已经使用ImageMagick生成,如果我要求ImageMagick使用RGB颜色空间(-colorspace sRGB),一切正常。)

奇怪的是,只是调整图像大小在所有情况下都能正常工作,但如果我尝试调整服务器上的图像大小并旋转它,它就会失败。

看起来一些较低级别的Win32或GDI +函​​数调用是失败的 - 这里是堆栈跟踪的相关部分:

[ArgumentException: Parameter is not valid.]
   System.Drawing.Graphics.CheckErrorStatus(Int32 status) +1621285
   System.Drawing.Graphics.DrawImage(Image image, PointF[] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr, DrawImageAbort callback, Int32 callbackData) +727
   System.Drawing.Graphics.DrawImage(Image image, PointF[] destPoints, RectangleF srcRect, GraphicsUnit srcUnit, ImageAttributes imageAttr) +73
   ImageResizer.ImageBuilder.RenderImage(ImageState s) +763
   ImageResizer.ImageBuilder.Render(ImageState s) +174
   ImageResizer.ImageBuilder.Process(ImageState s) +105
   ImageResizer.ImageBuilder.buildToBitmap(Bitmap source, ResizeSettings settings, Boolean transparencySupported) +276
   ImageResizer.ImageBuilder.buildToStream(Bitmap source, Stream dest, ResizeSettings settings) +149
   ImageResizer.ImageBuilder.BuildJob(ImageJob job) +940
   ImageResizer.ImageBuilder.Build(ImageJob job) +223

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

经过一些更多的研究和测试后,我发现只有在源位图上调用Bitmap.RotateFlip方法之后才会出现问题,然后将其绘制到目标位图上进行裁剪和调整大小。

我最终不得不自己使用普通的System.Drawing重新编写代码,因为无法改变ImageResizer库的行为。具体来说,我编写了自己的旋转函数,它使用变换矩阵来做同样的事情。

    private Bitmap RotateImage(Bitmap source, float angle)
    {
        if (angle == 0) return (Bitmap)source.Clone();

        Bitmap target;
        using (GraphicsPath path = new GraphicsPath())
        using (Matrix matrix = new Matrix())
        {
            path.AddRectangle(new RectangleF(0.0f, 0.0f, source.Width, source.Height));
            matrix.Rotate(angle);
            RectangleF rect = path.GetBounds(matrix);

            target = new Bitmap((int)Math.Round(rect.Width), (int)Math.Round(rect.Height));
            target.SetResolution(source.HorizontalResolution, source.VerticalResolution);

            using (Graphics g = Graphics.FromImage(target))
            {
                g.TranslateTransform(-rect.X, -rect.Y);
                g.RotateTransform(angle);
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImageUnscaled(source, 0, 0);
            }
        }
        return target;
    }

我本来希望将新PixelFormat的{​​{1}}设置为来自源{1}},但这样做会在遇到有问题的CMYK JPEG文件时引发奇怪的GDI +“Out of memory”错误。这让我想知道这种奇怪的行为是否与this GDI + bug / quirk相关联,它会在Windows 7 / Server 2008 R2和Windows Vista / Server 2008上返回不同的BitmapImageFlags值。< / p>