【问题标题】:ImageResizer/System.Drawing and CMYK JPEGsImageResizer/System.Drawing 和 CMYK JPEG
【发布时间】:2012-11-22 19:54:32
【问题描述】:

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

有问题的 JPEG 文件不是太大 (700x500) 或其他非标准文件 - 所有网络浏览器和 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

有什么想法吗?

【问题讨论】:

  • 您使用的是“旋转”还是“旋转”? GDI 在 WS2008 R2 内部使用 WIC,并且似乎正在加载 CMYK 数据,但似乎实际上不能支持对其进行旋转操作。 rotate 应该可以工作,即使 srotate(源旋转)不工作。
  • @ComputerLinguist 我使用的是 srotate——我的应用需要先旋转图像,然后再裁剪。
  • @ComputerLinguist 我想这正是 ImageResizer 之类的库存在的原因——抽象出这些奇怪的错误和怪癖。也许你可以考虑更新它来处理这种情况。
  • 绝对在TODO清单上;事实上,我已经对其进行了测试,但忘记测试“旋转”和“旋转”。如果你在 GitHub 上,你甚至可以提交一个补丁来加快速度。
  • 此错误已在 3.3.1 版本中修复。

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


【解决方案1】:

经过更多的研究和测试,我发现只有在源位图上调用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;
    }

我本来想将新BitmapPixelFormat 设置为源代码中的那个-但是这样做会在遇到有问题的CMYK JPEG 文件时引发奇怪的GDI+“内存不足”错误。这让我想知道这种奇怪的行为是否与this GDI+ 错误/怪癖有关,它在 Windows 7/Server 2008 R2 和 Windows Vista/Server 2008 上返回不同的 ImageFlagsPixelFormat 值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 2011-11-28
    相关资源
    最近更新 更多