c# - Image.Save() 对 jpeg 文件使用什么质量级别?

标签 c# gdi+ system.drawing.imaging

当我加载一个 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;
    });
}

最佳答案

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

编辑 您可能会自己找到答案,方法是运行上述质量值为 1..100 的程序,并将它们与以默认质量保存的 jpg 进行比较(例如,使用 fc.exe/B)

关于c# - Image.Save() 对 jpeg 文件使用什么质量级别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3957477/

相关文章:

graphics - 如何在 .NET 3.5 中保存 EXIF 格式的图像文件

asp.net - .NET : How to Create thumbnail from flash

c# - 确定图像中是否使用了 Alpha channel

c# - ajax 不断发布过时的值

c# - 在 LINQ 中对 IEnumerable 进行排序

c# - ARKit 和 Vuforia - 标记识别

c# - 为什么 EnumerateMetafile 只能在启用 Aero 的情况下使用

c# - C# 可以让我的类看起来像另一个类吗?

c++ - GDIPlus::位图亮化图像 C++

c# - HTML 到图像使用 NReco.ImageGenerator : C#