簡體   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