【问题标题】:ImageProcessor.ImageFactory compression not reducing image file sizeImageProcessor.ImageFactory 压缩不减小图像文件大小
【发布时间】:2017-04-24 21:15:31
【问题描述】:

我正在尝试实现用于上传到我网站的图像的图像压缩功能。我想拍摄原始图像并保存 3 个不同的尺寸/质量级别。为此,我使用ImageProcessor.ImageFactory。三个层次:

ISupportedImageFormat sm_format = new JpegFormat { Quality = 40 };
Size sm_size = new Size(150, 0);

ISupportedImageFormat md_format = new JpegFormat { Quality = 60 };
Size md_size = new Size(280, 0);

ISupportedImageFormat lg_format = new JpegFormat { Quality = 100 };
Size lg_size = new Size(1000, 0);

imageFactory.Load(or_directoryPath + "/" + fileName)
            .Resize(sm_size)
            .Format(sm_format)
            .BackgroundColor(Color.Transparent)
            .Save(Path.Combine(sm_directory, fileName));
// same for md and lg images

发生的情况是中小图像没有预期的较小文件大小。

一个例子: 原始图片为 .jpg 3000x3000,大小为 3.7MB。

大图大小为 2.96MB 中等图像大小为 2.63MB 小图大小为2.62MB

我在小图像上尝试了以下操作,以进一步将其压缩到 10% 的质量:

// Encoder parameter for image quality 
EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, 10);
// JPEG image codec 
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
img.Save(path, jpegCodec, encoderParams);

最终的结果是质量明显下降,但图像文件大小仍为 2.62MB

编辑:上传的原始图片在 postimg 上共享

中图:

小图:

压缩后的小图:

原图:

【问题讨论】:

  • 确定输出格式是jpeg.BackgroundColor(Color.Transparent) 暗示支持透明度的格式,jpeg 不是。当我将“中等”文件 (77.8 kB) 放入 Paint.NET 并将其重新保存为 10% 编码器质量的 jpeg 时,我得到了 3.58 kB 的图片,因此可以按预期工作。可以上传原始的 3000x3000px 文件吗?
  • 但是大的附件图片文件大小是78KB,最小的是21KB
  • @MaximilianGerhardt - 所以不允许我上传原始图像(或 md 或 sm 图像),因为它们超过 2mb。我会尝试托管图像并分享它们。
  • @MaximilianGerhardt - 我能够在不同的网站上托管原始图像并将它们链接到我的帖子中。
  • @esiprogrammer - 我已经上传了托管在 postimg.org 上的原始图像

标签: c# image jpeg image-compression


【解决方案1】:

进一步检查图像后,EXIF 数据确实该文件的问题。它包含一个带有自定义颜色配置文件的部分,其中存储的数据大小约为 2.64 兆字节。这可以通过将图像上传到http://regex.info/exif.cgi 并单击“显示 ICC 配置文件数据”来检查。

剥离奇怪的配置文件数据可以消除极端开销,并将文件大小降低到 1000x1000 像素时的 348 KB。

正如您已经发现的那样,您必须将ImageFactory 对象的构造函数中的preserveExifData 参数设置为false 以使其剥离数据。或者调用默认构造函数为

ImageFactory imageFactory = new ImageFactory();

【讨论】:

    【解决方案2】:

    当使用ImageProcessor 时,可以在 processing.config 中设置一个选项

    <processing preserveExifMetaData="true" fixGamma="false" interceptAllRequests="false" allowCacheBuster="true">
    

    设置preserveExifMetaData="false" 也会删除 EXIF 数据。

    也可以在 ImageFactory 构造函数中设置选项:

    var imageFactory = new ImageFactory(preserveExifData:true);
    

    【讨论】: