繁体   English   中英

减少PNG存储空间

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM