[英]Reduce PNG storage size
为了减少文件上传到Web服务的大小,我们将图像文件的高度/宽度限制为最大值。
对于JPG文件,这可以很好地工作:(向下)调整图像大小会减小文件的大小。
不过,对于PNG文件却不是这样:在大多数情况下,我们的代码会导致文件较大 :
procedure TFrmImageCheckAndResize.ResizePNGImage;
var
lSrcPNGImage, lTrgPNGImage: TdxPNGImage;
lSrcBitmap,lDestBitMap: TcxAlphaBitmap;
lNewWidth,lNewHeight: Integer;
lFactor: Real;
begin
lSrcPNGImage := TdxPNGImage.Create;
lSrcPNGImage.LoadFromFile(FFileName);
lSrcBitmap := TcxAlphaBitmap.CreateSize(lSrcPNGImage.Width, lSrcPNGImage.Height, True);
lSrcBitmap.Canvas.Draw(0, 0, lSrcPNGImage);
if lSrcPNGImage.Width > lSrcPNGImage.Height then
if lSrcPNGImage.Width > FEditImageRes.Value then
lFactor := lSrcPNGImage.Width
else
lFactor := 0
else
if lSrcPNGImage.Height > FEditImageRes.Value then
lFactor := lSrcPNGImage.Height
else
lFactor := 0;
if lFactor <> 0 then
begin
lFactor := lFactor / FEditImageRes.Value;
lNewWidth := Trunc(lSrcPNGImage.Width / lFactor);
lNewHeight := Trunc(lSrcPNGImage.Height / lFactor);
lDestBitMap := TcxAlphaBitmap.CreateSize(lNewWidth,lNewHeight, True);
cxSmoothResizeBitmap(lSrcBitMap, lDestBitMap, true);
lTrgPNGImage := TdxPNGImage.CreateFromBitmap(lDestBitmap);
end
else
begin
lDestBitmap := nil; // Silence the compiler
lTrgPNGImage := TdxPNGImage.CreateFromBitmap(lSrcBitmap);
end;
lTrgPNGImage.SaveToFile(StringReplace(FFileName,'.','_' + IntToStr(FEditImageRes.Value) + '.',[]));
lSrcBitmap.Free;
lDestBitmap.Free;
lTrgPNGImage.Free;
lSrcPNGImage.Free;
end;
FFileName
是从磁盘加载的映像, FEditImageRes.Value
包含我们减小到的最大尺寸。
请注意,我们使用Developer Express组件,并且此代码维护alpha通道(透明度)。
我也没有依恋。
我已经用DevExpress发布了票证 ,但这不是他们代码中的问题。
我查看了其他软件的功能:
在Paint.Net中,如果将上述890 * 161屏幕截图缩小为512 * 93,则根据调整大小所使用的算法,我会看到混合的结果:
15.697 Original.png
21.904 Resized_BiCubic.png
19.995 Resized_Bilineair.png
22.905 Resized_Fant.png
6.729 Resized_NearestNeigbour.png
对于将此550x386照片缩小为512 * 353,Paint.Net结果为:
375.229 Photo.png
419.122 Photo_Bicubic.png
402.277 Photo_Bilineair.png
407.959 Photo_Fant.png
416.619 Photo_NearestNeighbor.png
因此,结果将是很难预测的。
题:
有什么我可以做的(更改我的代码),以确保(大多数)调整大小的PNG文件实际上将具有减小的文件大小?
一些规则如何从vcl.imaging.PngImage
使用TPngImage
获得最小的图像大小
首先,它具有CompressionLevel
属性,您可以设置整数值0..9,0表示完全不压缩,9表示最佳压缩(但最慢)。 默认情况下,设置为7。 注意:PNG始终是无损的,此设置仅影响保存图像所需的时间。
其次,有Filters
属性,默认情况下,其值为[pfSub]
,但是要实现最佳压缩效果,应将其设置为[pfNone, pfSub, pfUp, pfAverage, pfPaeth]
。 这些是应用于每个图像行的预测过滤器,以便使用相邻像素之间的相关性以获得更好的压缩效果。 设置所有过滤器后,将尝试每种过滤器,并使用最佳过滤器。
确保InterlaceMethod
属性设置为imNone。 也许原始图像是隔行扫描的,在这种情况下,与非隔行扫描相比,文件大小增加了5..20%。
还有一种方法可以减小图像尺寸,即增加MaxIDATSize
属性使其值比图像尺寸大。 重点是,PNG像素数据存储在一个或多个IDAT块中,每个块的大小为4个字节,然后是其名称的4个字节(“ IDAT”),然后是数据,然后是4个字节的CRC。 默认情况下,每个块的大小为65535字节,因此在大图中,您将拥有很多块,每个块浪费12个字节。 但是这里的增加很小,为0.2%,不是很大。
实际上,通过这样的设置,PNGImage可以生成很小的文件,通常比Paint.NET小10..20%,但是专用程序可以更好地压缩PNG。
关于调整大小。 尝试调整屏幕截图大小时,通常会出现较大的文件大小。 原始屏幕截图的颜色很少,在您的情况下为431,主要是因为渐变。 有很多相同颜色的区域保存得很好。 调整大小后,从一种颜色到另一种颜色的每个尖锐过渡都变得模糊了,因此创建了更多的“混合”颜色,实际上很难压缩。 如您所见,最接近的邻居恰好导致文件大小最小,因为它不会创建原始图像中还没有的新颜色。
您的第二个示例550x386照片在调整大小后必须具有较小的文件大小,实际上,我已经设法将大小调整为512x353的照片压缩为303 kB。 Paint.net根本不使用预测过滤器,这就是为什么它对照片和其他真彩色图像进行了可怕的压缩的原因。
最好的方法是使用专用工具来减小png大小。
查看此页面 ,了解有关如何优化png大小的一些技术细节
有一些工具效果很好,我使用了http://optipng.sourceforge.net
另请参见png优化工具的此比较 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.