【发布时间】: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