Image 减少PNG存储大小
为了减少Web服务的文件上载大小,我们将图像文件的高度/宽度限制为最大值。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
对于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