我目前正在编写一个小程序,从磁盘读取png文件,做一些修改并保存回来。一切都很顺利,除了一个小问题,我把文件保存回磁盘后,它的大小总是变大,例如,一个27.1MB的文件变成了33.3MB。
经过一些调试后,我最终将其缩小到我的阅读和保存代码。这是我目前使用的代码:
Bitmap img = new Bitmap(<path to file>);
//omitted
img.Save(<path to new file>, ImageFormat.Png);
我已经验证过,无论我做或不做任何修改,简单地读取和保存图像将导致它的大小改变。此外,如果我用Paint打开保存的文件并从那里保存,文件会缩小到原来的大小。
如何读取和保存图像而不改变其大小?
除了颜色深度和使用多少通道(w/o alpha)外,保存的PNG文件大小主要取决于两个因素:
- 如何对图像线条进行预处理(称为滤波)。
- deflate算法的压缩级别(0-9)。
这两个因素将极大地影响输出图像文件的大小。滤波是经验性的,你可以对所有图像线使用四种滤波算法中的一种,或者对不同的线使用不同的算法,甚至在单个线上自适应地尝试不同的算法,并选择最大的压缩率。自适应的方式是最耗时和不切实际的大多数图像作家。
过滤后的图像数据被放气压缩。deflate算法的压缩级别通常为0-9,从最低压缩率到最高压缩率。压缩率越高,压缩过程越慢。通常对于大多数图像来说,4是最好的。
过滤过程在PNG压缩过程中起着非常重要的作用,有时是至关重要的。不同的滤波算法可能导致保存的图像大小差异较大。另一方面,图像大小对压缩级别不太敏感。
你可以使用像TweakPNG这样的工具来检查图像包含的颜色深度和通道数量。如果原始图像和重新保存的图像具有相同的颜色深度和通道,那么很可能过滤和压缩级别是增加文件大小的罪魁祸首。
事实是,如果编码器没有优化,通常情况下,文件大小会增加。然而,如果你不介意对生成的图像进行后期处理,有很多PNG优化软件。
你试过玩Endoder吗?ColorDepth字段?PNG也支持透明度,可能会保存一些图像不需要的信息。
ImageCodecInfo pngCodec = ImageCodecInfo.GetImageEncoders().Where(codec => codec.FormatID.Equals(ImageFormat.Png.Guid)).FirstOrDefault();
if (pngCodec != null)
{
EncoderParameters parameters = new EncoderParameters();
parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 24); //8, 16, 24, 32 (base on your format)
image.Save(stream, pngCodec, parameters);
}
附加信息:https://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoder.colordepth(v=vs.110).aspx
我想你错过了压缩部分。
像这样添加到代码中-
Bitmap img = new Bitmap(<path to file>);
这是你错过的-
ImageCodecInfo myImageCodecInfo = GetEncoderInfo("image/jpeg");
EncoderParameter myEncoderParameter = new EncoderParameter(Encoder.Quality, 25L);
EncoderParameters myEncoderParameters.Param[0] = myEncoderParameter;
然后保存-
img.Save(<path to file>, myImageCodecInfo, myEncoderParameters);
这是MSDN链接。