【问题标题】:What quality level does Image.Save() use for jpeg files?Image.Save() 对 jpeg 文件使用什么质量级别?
【发布时间】:2011-04-26 19:52:21
【问题描述】:

当我加载一个 jpg 文件并转身以 100 的质量保存它并且大小几乎是原始文件的 4 倍时,我感到非常惊讶。为了进一步调查,我在没有明确设置质量的情况下打开并保存,文件大小完全相同。我认为这是因为没有任何改变,所以它只是将完全相同的位写回文件。为了测试这个假设,我在图像上对角画了一条粗线,并在没有设置质量的情况下再次保存(这次我希望文件会跳起来,因为它会“脏”)但它减少了 ~10Kb!

此时我真的不明白当我简单地调用 Image.Save() 而不指定压缩质量时发生了什么。当我将质量设置为100(基本上没有压缩)时,文件大小如何(在修改图像后)与原始大小如此接近,当我将质量设置为100(基本上没有压缩)时,文件大小是原始大小的几倍?

我已阅读有关 Image.Save() 的文档,但其中没有关于幕后发生的事情的任何细节。我已经用谷歌搜索了我能想到的所有方式,但我找不到任何可以解释我所看到的其他信息。我已经连续工作了 31 个小时,所以也许我遗漏了一些明显的东西;0)

所有这些都是在我实现一些库方法以将图像保存到数据库时发生的。我已经重载了我们的“SaveImage”方法以允许明确设置质量,并且在我的测试过程中,我遇到了上面解释的奇怪(对我来说)结果。您能提供的任何启发都将不胜感激。

这里有一些代码可以说明我正在经历的事情:

string filename = @"C:\temp\image testing\hh.jpg";
string destPath = @"C:\temp\image testing\";

using(Image image = Image.FromFile(filename))
{
    ImageCodecInfo codecInfo = ImageUtils.GetEncoderInfo(ImageFormat.Jpeg);

    //  Set the quality
    EncoderParameters parameters = new EncoderParameters(1);

    // Quality: 10
    parameters.Param[0] = new EncoderParameter(
        System.Drawing.Imaging.Encoder.Quality, 10L);
    image.Save(destPath + "10.jpg", codecInfo, parameters);

    // Quality: 75
    parameters.Param[0] = new EncoderParameter(
        System.Drawing.Imaging.Encoder.Quality, 75L);
    image.Save(destPath + "75.jpg", codecInfo, parameters);

    // Quality: 100
    parameters.Param[0] = new EncoderParameter(
        System.Drawing.Imaging.Encoder.Quality, 100L);
    image.Save(destPath + "100.jpg", codecInfo, parameters);

    //  default
    image.Save(destPath + "default.jpg", ImageFormat.Jpeg);

    //  Big line across image
    using (Graphics g = Graphics.FromImage(image))
    {
        using(Pen pen = new Pen(Color.Red, 50F))
        {
            g.DrawLine(pen, 0, 0, image.Width, image.Height);
        }
    }

    image.Save(destPath + "big red line.jpg", ImageFormat.Jpeg);
}

public static ImageCodecInfo GetEncoderInfo(ImageFormat format)
{
    return ImageCodecInfo.GetImageEncoders().ToList().Find(delegate(ImageCodecInfo codec)
    {
        return codec.FormatID == format.Guid;
    });
}

【问题讨论】:

  • 我对 .NET 中 JPG 的压缩以及相应的错误做了一些实验,请参阅c4real.biz/jpgCompression.aspx
  • 基于一些快速测试,您最初的直觉似乎是正确的:如果您有一个最初是 jpg 的图像并在没有指定质量的情况下调用 Save,它只会将原始位转储到文件。如果您修改了内存中的图像,或者如果您请求特定的压缩级别,它将重新编码图像。如果您为来自低质量来源的图像请求高质量级别,那么您将浪费大量空间来非常准确地描述原始压缩引入的所有伪影。

标签: c# gdi+ system.drawing.imaging


【解决方案1】:

使用反射器,Image.Save() 归结为 GDI+ 函数GdipSaveImageToFileencoderParams 为 NULL。所以我认为问题是 JPEG 编码器在得到空 encoderParams 时会做什么。这里建议了 75%,但我找不到任何可靠的参考。

编辑您可能会自己发现,通过运行上面的程序以获得 1..100 的质量值并将它们与以默认质量保存的 jpg 进行比较(例如,使用 fc.exe /B)

【讨论】:

  • 啊,我忘了反射器! ;0) 很高兴知道这种方法不会发生神秘的魔法。我想我会按照你的建议做一个测试,让我放心。我将在此线程上报告结果。
  • 我做了一个快速测试并打开了一个 *.bmp 文件,然后使用默认设置保存为 jpg,并将质量明确设置为 75。文件大小完全相同。所以肯定是编码器在内部默认为 75。我认为这应该在文档中的某个地方,不是吗?
  • 当然,但我不确定哪个文档。据我了解,这是默认 windows JPEG 编码器的一项功能,其文档位于我不知道的地方...
  • 在找到这个问题之前,我在这里查看了msdn.microsoft.com/en-us/library/…。所以我本来希望得到答案或指向其他文档的链接。
  • @ComputerLinguist:您的评论没有任何意义。质量 100 优于质量 90。
【解决方案2】:

IIRC,它是 75%,但我不记得我在哪里看到的。

【讨论】:

  • 我用他的方法保存为75L,我用默认保存了另一个。结果:75L = 36.7 KBdefault = 36.8 KB。如果不是 75%,那就是 75.1%...
【解决方案3】:

我对 Image.Save 方法了解不多,但我可以告诉你,添加这条粗线会在逻辑上减小 jpg 图像的大小。这是由于 jpg 的保存(和编码)方式。

粗黑线使得编码非常简单且更小(如果我没记错的话,这主要是在离散余弦变换之后),因此可以使用更少的数据(字节)存储修改后的图像。

jpg encoding steps

关于大小的变化(没有添加的行),我不确定您重新打开并重新保存了哪个图像

为了进一步调查,我在没有明确设置质量的情况下打开并保存,文件大小完全相同

如果您打开旧(原始正常大小)图像并重新保存它,那么默认压缩和原始图像压缩可能相同。 如果您打开新的(4 倍大)图像并重新保存它,那么保存方法的默认压缩可能源自图像(就像加载时一样)。

再说一次,我不知道保存方法,所以我只是抛出一些想法(也许他们会给你一个线索)。

【讨论】:

  • 你是对的,一个大的、实心的区域可以有效地压缩是完全合理的。我试图完成并且应该更好地解释的是强制重新编码数据。我试图确定我是否看到相同的文件大小,因为 Save() 正在将位直接转储到磁盘。我想如果我踩过图像然后保存它会触发文件重新编码。感谢您提供链接和其他信息。
【解决方案4】:

当您将图像保存为质量级别为

这也是为什么如果您打算之后对文件进行任何编辑,您应该始终尝试以无损格式(例如 PNG)保存,否则您将通过多次有损影响输出质量转换。

【讨论】:

  • 作为切线,以高色深保存也很重要。在对图像进行某些操作时,尤其是具有梯度的图像,可能会导致后处理。使用高颜色深度源图像有助于平滑颜色渐变以保持平滑。
  • 感谢您的信息。我在 Photoshop 中做了一个快速测试,看看以 100 质量保存时它会如何处理此图像,实际上它的大小与我在 100 时所做的测试大致相同。
猜你喜欢
  • 2011-01-02
  • 2019-10-11
  • 2013-10-18
  • 2020-06-10
  • 1970-01-01
  • 2011-06-02
  • 2021-07-03
  • 2013-11-21
  • 2018-12-04
相关资源
最近更新 更多