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