題 鑑於PNG具有壓縮參數,PNG如何無損?


據說PNG文件使用無損壓縮。但是,每當我在圖像編輯器中時,例如 GIMP 並嘗試將圖像保存為PNG文件,它要求壓縮參數,範圍在0到9之間。如果它有一個壓縮參數影響壓縮圖像的視覺精度,它如何使PNG無損?

僅當我將壓縮參數設置為9時才能獲得無損行為嗎?


150
2017-11-26 18:11


起源


大多數無損壓縮算法都具有可調參數(如字典大小),這些可調參數在“應盡量減少輸出大小”滑塊中進行推廣。這適用於ZIP,GZip,BZip2,LZMA,...... - Daniel B
問題可以用不同的方式說明。如果壓縮沒有損失質量,那麼為什麼不總是使用產生最小尺寸的壓縮?答案就是,因為它需要更多的RAM和更多的CPU時間來壓縮和解壓縮。有時您需要更快的壓縮並且不關心壓縮率。 - kasperd
PNG壓縮幾乎與ZIPping文件相同。您可以或多或少地壓縮它們,但是在解壓縮時會得到準確的文件 - 這就是它無損的原因。 - mikebabcock
大多數壓縮軟件(如Zip和Rar)允許您輸入“壓縮級別”,這允許您在較短的文件< - >更短的時間內進行選擇。這並不意味著這些軟件在壓縮期間丟棄數據。此設置(在GIMP,pngcrush等中)類似。 - Salman A
@naxa:png實際上是無損的,沒有任何警告。它總是100%無損。本文僅警告您一些舊瀏覽器在其PNG實現中用於處理伽馬校正的錯誤。只有當您需要將顏色與CSS顏色(未經過伽馬校正)匹配時,這才有意義。 - Pauli L


答案:


PNG無損。在這種情況下,GIMP很可能只是沒有使用最好的詞。可以將其視為“壓縮質量”,換句話說,“壓縮程度”。壓縮率越低,您獲得的文件越大,但生成時間越短,而壓縮率越高,生成的文件越小,生成時間越長。通常,當達到最高壓縮級別時,您獲得的收益遞減(即,與所需時間的增加相比沒有那麼大的減少),但這取決於您。


182
2017-11-26 18:31



此外,PNG壓縮實際上有許多可調參數,其中任一方向的調整都可以根據源的內容縮小輸出大小 - 它比簡單的“更好”和“更差”滑塊複雜得多。出於一般目的,它不是太重要,但如果你想要絕對最小,那麼使用像這樣的工具 pngcrush 可以比較盡可能小的變化。 - Bob
較高的壓縮級別會增加壓縮時間,但也會影響壓縮時間 減壓 還有? - Nolonar
@Nolonar一般沒有;如果有任何更高的壓縮級別通常會減少解壓縮時間,因為它需要讀取和處理的數據較少。更長的壓縮時間是由於更徹底地找到要壓縮的模式(過度簡化)。 - fluffy
@fluffy LordNeckbeard的答案壓縮率最高,解碼時間比最低時間長5倍。 - André Chalella
對於PNG,它 是 對於更好壓縮的文件,有更長的解壓縮時間是很常見的。問題是,對於PNG,一個可能的技巧是只要文件變小就反复應用壓縮算法。一旦尺寸增加,您就會停止應用它。因此,很有可能將壓縮算法應用5或6次,這意味著您必須將文件解壓縮5到6次才能顯示圖像。 - yo'


PNG是壓縮的,但無損

壓縮級別是文件大小和編碼/解碼速度之間的折衷。過於概括,甚至非圖像格式(例如FLAC)也具有類似的概念。

不同的壓縮級別,相同的解碼輸出

雖然文件大小不同,但由於壓縮級別不同,實際解碼輸出也是相同的。

你可以比較一下 MD5 已解碼輸出的哈希值 ffmpeg 使用 MD5復用器

最好通過一些示例顯示:

創建PNG文件:

$ ffmpeg -i input -vframes 1 -compression_level 0 0.png
$ ffmpeg -i input -vframes 1 -compression_level 100 100.png
  • 默認情況下 ffmpeg 將使用 -compression_level 100 用於PNG輸出。

比較文件大小:

$ du -h *.png
  228K    0.png
  4.0K    100.png

解碼PNG文件並顯示MD5哈希:

$ ffmpeg -loglevel error -i 0.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

$ ffmpeg -loglevel error -i 100.png -f md5 -
3d3fbccf770a51f9d81725d4e0539f83

由於兩個哈希值相同,因此可以確保解碼後的輸出(未壓縮的原始視頻)完全相同。


210
2017-11-27 08:27



+1不知道ffmpeg可以處理png。 - Lekensteyn
@Lekensteyn這很棒 製作截圖。示例跳過30秒並截取屏幕截圖: ffmpeg -ss 30 -i input -vframes 1 output.png 也適合 用圖像製作視頻 反之亦然。 - LordNeckbeard
這是否意味著每次必須渲染PNG時都需要解壓縮?因為如果這是真的,我們一定是 - akshay2000
如果您從磁盤或緩存重新讀取文件,是的,它必須解壓縮。在同一頁面內,緩存可能會重用解壓縮版本。 - David Mårtensson
@ akshay2000取決於程序如何工作以呈現PNG。通常,文件從磁盤讀取,解壓縮並緩沖在RAM中。因此,只要它在RAM中緩衝,就不需要再次解壓縮圖像。 - xZise


PNG壓縮分兩個階段進行。

  1. 預壓縮重新排列圖像數據,以便通過通用壓縮算法更加可壓縮。
  2. 實際壓縮由DEFLATE完成,DEFLATE通過用短令牌替換它們來搜索並消除重複的字節序列。

由於步驟2是非常耗費時間/資源的任務,因此底層zlib庫(原始DEFLATE的封裝)採用的壓縮參數範圍為1 =最快壓縮,9 =最佳壓縮,0 =無壓縮。這就是0-9範圍的來源,而GIMP只是將該參數傳遞給zlib。觀察到在0級,你的png實際上會比同等的位圖略大。

但是,9級只是zlib嘗試的“最佳”,並且仍然非常多 折衷方案
要真正感受到這一點,如果您願意在詳盡的搜索上花費1000倍以上的處理能力,那麼您可以使用高出3-8%的數據密度 zopfli 而不是zlib。
壓縮仍然是無損的,它只是數據的更優化DEFLATE表示。這接近zlib兼容庫的限制,因此是使用PNG可以實現的真正“最佳”壓縮。


24
2017-11-28 09:55



注意:無論壓縮級別如何,或者使用zopflipng時的迭代次數,解壓縮時間都是相同的。 - Adria


PNG格式的主要動機是為GIF創建一個替代品,它不僅是免費的,而且在幾乎所有方面都是對它的改進。因此,PNG壓縮是完全無損的 - 也就是說,原始圖像數據可以精確地重建,一點一滴地進行 - 就像在GIF和大多數形式的TIFF中一樣。

PNG使用兩階段壓縮過程:

  1. 預壓縮:過濾(預測)
  2. 壓縮:DEFLATE(見 維基百科

預壓縮步驟稱為過濾,其是可逆地變換圖像數據的方法,使得主壓縮引擎可以更有效地操作。

舉個簡單的例子,考慮一個從1到255均勻增加的字節序列:

1, 2, 3, 4, 5, .... 255

由於序列中沒有重複,因此它壓縮得非常差或根本不壓縮。但是對序列的一個微不足道的修改 - 即,僅保留第一個字節,但用它與它的前任之間的差別替換每個後續字節 - 將序列轉換為極其可壓縮的集合:

1, 1, 1, 1, 1, .... 1

上述轉換是無損的,因為沒有省略字節,並且完全可逆。 這個系列的壓縮尺寸將大大減少,但原始系列仍然可以 完美重組。

實際的圖像數據很少是完美的,但過濾確實可以改善灰度和真彩色圖像的壓縮,並且它也可以幫助一些調色板圖像。 PNG支持五種類型的濾鏡,編碼器可以選擇對圖像中的每行像素使用不同的濾鏡:

image

該算法適用於字節,但適用於大像素(例如,24位RGB或64位RGBA) 只比較相應的字節,意味著像素顏色的紅色成分 與綠色和藍色像素組件分開處理。

要為每行選擇最佳濾波器,編碼器需要測試所有可能的組合。 這顯然是不可能的,因為即使是20行圖像也需要測試超過95萬億個組合,其中“測試”將涉及過濾和壓縮整個圖像。

壓縮級別通常定義為0(無)和9(最佳)之間的數字。 這些是指速度和大小之間的權衡,並涉及多少組合 要嘗試行過濾器。這些壓縮級別沒有標準, 因此,每個圖像編輯器都可能有自己的算法,以確定何時嘗試過多少個過濾器 優化圖像大小。

壓縮級別0表示根本不使用過濾器,這很快但浪費。 更高的級別意味著在圖像行上嘗試越來越多的組合,只有最好的組合 保留。

我猜想最簡單的壓縮方法是用每個過濾器逐步測試壓縮每一行,保存最小的結果,然後重複下一行。這相當於對整個圖像進行五次濾波和壓縮,這對於將被多次發送和解碼的圖像來說可能是合理的折衷。較低的壓縮值將自行決定 該工具的開發人員。

除了過濾器之外,壓縮級別還可能影響zlib壓縮級別 這是一個介於0(無Deflate)和9(最大Deflate)之間的數字。如何指定0-9 級別會影響過濾器的使用,這是PNG的主要優化功能, 仍然依賴於該工具的開發人員。

結論是PNG具有壓縮參數,可以非常顯著地減小文件大小,所有這些都不會丟失甚至單個像素。

資料來源:

維基百科便攜式網絡圖形
libpng文檔第9章 - 壓縮和過濾


15
2017-11-29 15:12



我不認為壓縮級別設置會改變過濾器的使用。 1-9級設置可能只選擇zlib壓縮級別1-9,級別0意味著根本不使用deflate算法。大多數實現可能不會更改每行的過濾器,但只是一直使用Path過濾器。 - Pauli L
@PauliL:我不同意,因為在PNG壓縮軟件的所有比較中,生成的圖像的大小之間存在很大的差異。如果所有產品對同一個庫使用相同的參數,那麼所有大小應該是相同的,以及速度。 - harrymc
你有這種比較的鏈接嗎? - Pauli L
@PauliL:快速搜索了 這種比較。 - harrymc
@PauliL:zlib壓縮級別受PNG壓縮級別的影響可能是正確的。雖然沒有壓縮工具記錄他們的確切行為,但我已相應地修改了我的答案。也許對具有最差尺寸結果的工具的解釋是它們根本不使用濾波器,僅使用zlib壓縮。 - harrymc


好吧,我為賞金來得太晚了,但無論如何,這是我的答案。

PNG永遠是無損的。它使用Deflate / Inflate算法,類似於zip程序中使用的算法。

Deflate算法搜索重複的字節序列並用標籤替換它們。 壓縮級別設置指定程序使用多少努力來找到字節序列的最佳組合,以及為此保留多少內存。 它是時間和內存使用與壓縮文件大小之間的折衷。 但是,現代計算機速度非常快,並且具有足夠的內存,因此除了最高壓縮設置之外,很少需要使用。

許多PNG實現使用zlib庫進行壓縮。 Zlib有九個壓縮等級,1-9。 我不知道Gimp的內部,但由於它的壓縮級別設置為0-9(0 =無壓縮),我認為此設置只是選擇zlib的壓縮級別。

Deflate算法是一個 通用壓縮算法,它不是專為壓縮圖片而設計的。 與大多數其他無損圖像文件格式不同,PNG格式不限於此。 PNG壓縮利用了我們正在壓縮的知識 2D圖像。這是通過所謂的實現的 過濾器

(過濾器實際上是一個有點誤導性的術語。它實際上並沒有改變圖像內容,它只是以不同的方式編碼。 更準確的名稱將是delta編碼器。)

PNG規範指定了5個不同的過濾器(包括0 =無)。過濾器替換絕對像素值 與先前像素的差異 向左,向上,對角線或其組合。 這可以顯著提高壓縮比。 圖像上的每條掃描線都可以使用不同的濾鏡。編碼器可以通過為每條線選擇最佳濾波器來優化壓縮。

有關PNG文件格式的詳細信息,請參閱 PNG規範

由於幾乎有無數種組合,因此無法全部嘗試。因此,已經開發了不同類型的策略來尋找有效的組合。 大多數圖像編輯器甚至可能不會嘗試逐行優化濾鏡,而只是使用固定濾鏡(很可能是Paeth)。

命令行程序 pngcrush 嘗試幾種策略來找到最好的結果。它可以顯著減小其他程序創建的PNG文件的大小,但在較大的圖像上可能需要相當長的時間。 看到 來源鍛造 - pngcrush


5
2017-11-30 13:45





無損東西中的壓縮級別總是只交換編碼資源(通常是時間,有時也是RAM)與比特率。質量始終是100%。

當然,無損壓縮機可以 絕不保證 任何實際的壓縮。隨機數據是不可壓縮的,沒有找到的模式,也沒有相似性。香農信息論和所有這些。無損數據壓縮的全部意義在於人類通常使用高度非隨機數據,但對於傳輸和存儲,我們可以將其壓縮到盡可能少的位。希望盡可能接近 Kolmogorov複雜性 原來的。

無論是zip還是7z通用數據,png圖像,flac音頻或h.264(無損模式)視頻,都是一樣的。使用一些壓縮算法,如lzma(7zip)和bzip2,啟動壓縮設置將增加DECODER的CPU時間(bzip2),或者更多地增加所需的RAM量(lzma和bzip2,以及帶有更多參考幀的h.264) 。通常,解碼器必須在RAM中保存更多的解碼輸出,因為解碼下一個字節可以指代許多兆字節前解碼的字節(例如,與半秒之前最相似的視頻幀將被編碼為對12幀的引用)。與bzip2相同並選擇較大的塊大小,但也解壓縮較慢。 LZMA 有一個可變大小的字典,你可以製作需要1.5GB的RAM來解碼的文件。


3
2017-12-02 13:38



嗯,我看到了一種實施方法,可以直接控制驅動步進電機和頭部,以提供有保證的無損壓縮。如果您有高分辨率時鐘源,曼徹斯特編碼很容易被打敗。 - Joshua
@Joshua:使用更高密度的物理存儲格式與數據壓縮不同...... - SamB


首先,PNG始終是無損的。顯而易見的悖論是由於存在兩種不同類型的壓縮(對於任何類型的數據):有損和無損。

無損壓縮 使用各種技巧壓縮數據(即文件大小),保留所有內容並且不做任何近似。因此,無損壓縮實際上可能根本無法壓縮事物。 (從技術上講,具有高熵的數據可能非常難以甚至無法壓縮無損方法。)     有損壓縮 近似實際數據,但近似是不完美的,但這種“丟棄”的精度通常允許更好的壓縮。

以下是無損壓縮的一個簡單示例:如果您的圖像由1,000個黑色像素組成,而不是將該值存儲為黑色1,000次,則可以存儲計數(1000)和值(黑色),從而壓縮1000像素“將圖像“分成兩個數字。 (這是一種稱為遊程編碼的無損壓縮方法的粗略形式)。


0
2017-11-27 06:07