Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image 减少PNG存储大小_Image_Delphi_Png_Filesize_Delphi 10 Seattle - Fatal编程技术网

Image 减少PNG存储大小

Image 减少PNG存储大小,image,delphi,png,filesize,delphi-10-seattle,Image,Delphi,Png,Filesize,Delphi 10 Seattle,为了减少Web服务的文件上载大小,我们将图像文件的高度/宽度限制为最大值。 对于JPG文件,这很好:图像(向下)调整大小会减少文件大小 但对于PNG文件则不是这样:在大多数情况下,我们的代码会导致更大的文件大小: procedure TFrmImageCheckAndResize.ResizePNGImage; var lSrcPNGImage, lTrgPNGImage: TdxPNGImage; lSrcBitmap,lDestBitMap: TcxAlphaBitmap; lN

为了减少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;  

对于这张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文件实际上会减小文件大小吗?

最好的方法是使用专用工具来减小PNG大小

请看一些关于如何优化png大小的技术细节

我使用了一些非常有效的工具


另请参见。

最佳方法是使用专用工具减小png大小

请看一些关于如何优化png大小的技术细节

我使用了一些非常有效的工具


另请参见。

如何从
vcl.imaging.PngImage

首先,它具有
CompressionLevel
属性,您可以设置整数值0..9,0表示无压缩,9表示最佳压缩(但速度最慢)。默认设置为7。注意:PNG始终是无损的,此设置仅影响保存图像所需的时间

第二,有
过滤器
属性,默认情况下,其值为
[pfSub]
,但要实现最佳压缩,应将其设置为
[pfNone,pfSub,pfUp,pfAverage,pfPaeth]
。这些是应用于每一行图像的预测滤波器,以便利用相邻图像之间的相关性来获得更好的压缩。当所有过滤器都设置好后,每个过滤器都将被尝试,并使用最好的过滤器

确保
interracemethod
属性设置为imNone。可能您的原始图像是隔行扫描的,在这种情况下,与非隔行扫描相比,文件大小增加了5..20%

还有一种方法可以降低图像的大小,那就是将
MaxIDATSize
属性的值增加到比图像大小稍大的值。关键是,PNG像素数据存储在一个或多个IDAT块中,每个块有其大小的4个字节,然后是其名称的4个字节(“IDAT”),然后是数据,然后是CRC的4个字节。默认情况下,每个区块的大小是65535字节,所以在大图像中,您将拥有大量的区块,每个区块有12个字节的浪费。但是这里的增长很小,0.2%,不是很多

事实上,有了这些设置,PNGImage可以生成非常小的文件,通常比Paint.NET小10..20%,但是专门的程序可以更好地压缩PNG

关于调整大小。当试图调整屏幕截图的大小时,通常会出现较大的文件大小。原始屏幕截图很少有颜色,在你的例子中是431,很大程度上是因为渐变。相同颜色的大面积区域保存得非常好。调整大小后,从一种颜色到另一种颜色的每个急剧过渡都会模糊,因此创建的“混合”颜色越多,压缩就越困难。正如您所看到的,最近邻产生最小的文件大小,正是因为它不会创建原始图像中没有的新颜色


您的第二个示例550x386照片在调整大小后必须具有较低的文件大小,事实上,我已经设法将大小调整为512x353的照片压缩到303KB。Paint.net根本不使用预测过滤器,这就是为什么它对照片和其他真彩色图像进行了糟糕的压缩。

一些规则如何使用
vcl.imaging.PngImage中的
TPngImage
获得尽可能小的图像大小

首先,它具有
CompressionLevel
属性,您可以设置整数值0..9,0表示无压缩,9表示最佳压缩(但速度最慢)。默认设置为7。注意:PNG始终是无损的,此设置仅影响保存图像所需的时间

第二,有
过滤器
属性,默认情况下,其值为
[pfSub]
,但要实现最佳压缩,应将其设置为
[pfNone,pfSub,pfUp,pfAverage,pfPaeth]
。这些是应用于每一行图像的预测滤波器,以便利用相邻图像之间的相关性来获得更好的压缩。当所有过滤器都设置好后,每个过滤器都将被尝试,并使用最好的过滤器

确保
interracemethod
属性设置为imNone。可能您的原始图像是隔行扫描的,在这种情况下,与非隔行扫描相比,文件大小增加了5..20%

还有一种方法可以降低图像的大小,那就是将
MaxIDATSize
属性的值增加到比图像大小稍大的值。关键是,PNG像素数据存储在一个或多个IDAT块中,每个块有其大小的4个字节,然后是其名称的4个字节(“IDAT”),然后是数据,然后是CRC的4个字节。默认情况下,每个区块的大小是65535字节,所以在大图像中,您将拥有大量的区块,每个区块有12个字节的浪费。但是这里的增长很小,0.2%,不是很多

事实上,有了这些设置,PNGImage可以生成非常小的文件,通常比Paint.NET小10..20%,但是专门的程序可以更好地压缩PNG

关于调整大小。当试图调整屏幕截图的大小时,通常会出现较大的文件大小。原始屏幕截图很少有颜色,在你的例子中是431,很大程度上是因为渐变。相同颜色的大面积区域保存得非常好。调整大小后,从一种颜色到另一种颜色的每个急剧过渡都会模糊,因此创建的“混合”颜色越多,压缩就越困难。正如您所看到的,最近邻产生最小的文件大小,正是因为它不会创建原始图像中没有的新颜色

您的第二个示例,550x386照片在调整大小后必须具有较小的文件大小,事实上,我已经设法将调整大小后的照片压缩到512x353,以
375.229 Photo.png
419.122 Photo_Bicubic.png
402.277 Photo_Bilineair.png
407.959 Photo_Fant.png
416.619 Photo_NearestNeighbor.png