我繼續並重複了實驗,以查看是否可以解決問題。
過程
我使用生成了一個256×256像素的隨機RGB圖像GIMP中的“固體噪聲”過濾器(“過濾器”>“渲染”>“雲”>“固體噪聲...”)使用默認設置(如下所示):
,結果如下:
然後我使用默認設置將圖像保存為JPEG:
然後我轉移了將該圖像導入Windows,然後通過在文件資源管理器中右鍵單擊該圖像並從菜單中選擇預覽,使用Windows Photo Viewer打開該圖像。然後,我使用底部的按鈕旋轉了圖像,並使用箭頭鍵導航到下一張圖像來保存圖像。
對於下面的每個測試,我都從原始圖像的副本開始,並在保存之前旋轉(單擊旋轉按鈕)相應的次數。以下是重新排序的大小( ls -l -r
):
大小(以字節為單位)最後修改日期VVVVV VVVVV-rwxrwx-- 1根vboxsf 6258 11月8日11:24 original.jpg-rwxrwx --- 1個根vboxsf 23645 Nov 8 11:30 cw.jpg-rwxrwx --- 1個根vboxsf 23636 Nov 8 11:30 cw-cw.jpg-rwxrwx --- 1個根vboxsf 23649 Nov 8 11:30 cw-cw-cw.jpg-rwxrwx --- 1個根vboxsf 6258 Nov 8 11:27 cw-cw-cw-cw.jpg-rwxrwx --- 1個根vboxsf 23649 Nov 8 11:31 cw-cw-cw-cw-cw.jpg-rwxrwx --- 1個根vboxsf 23649 11月8日11:29 ccw.jpg-rwxrwx --- 1個根vboxsf 23636 Nov 8 11:29 ccw-ccw.jpg-rwxrwx- -1個根vboxsf 23645 11月8日11:29 ccw-ccw-ccw.jpg-rwxrwx-1個根vboxsf 6258 11月8日11:27 ccw-ccw-ccw-ccw.jpg-rwxrwx-1個根vboxsf 23649 11月8日11:30 ccw-ccw-ccw-ccw-ccw.jpg
立即觀察
- Windows Photo Viewer(WPV)確實會大大增加尺寸;在此測試中,增加的數量大約是四倍!
- 所有新圖像都增加到大約相同的大小,但是它們並不相同。
當圖像旋轉360度的倍數時,- WPV不會重新編碼或什至重新保存圖像。 (時間戳為11:27,這是第一次復製文件的時間。)
在應該具有相同內容的文件上使用 cmp -l 可以使我們看到
robert @ unity ../jpeg-rotate-test%cmp -l cw.jpg ccw-ccw-ccw.jpg 2223 63 62 2224 60 71 2226 60 64 2227 60 66robert @ unity ../jpeg-rotate-test%cmp -l cw-cw.jpg ccw-ccw.jpg 2223 63 62 2224 60 71 2226 60 64 2227 62 64robert @ unity ..jpeg-rotate-test%cmp- l ccw.jpg cw-cw-cw.jpg 2223 62 63 2224 71 60 2226 64 60 2227 61 64robert @ unity ../jpeg-rotate-test%cmp -l cw.jpg cw-cw-cw-cw-cw。 jpg 2221 60 61 2223 63 61 2224 60 66 2226 60 61 2227 60 61robert @ unity ../jpeg-rotate-test%cmp -l ccw.jpg ccw-ccw-ccw-ccw-ccw.jpg 2223 62 63 2224 71 60 2226 64 65 2227 61 64
這些文件的區別僅在於四個字節(實際上是一個時間戳),這意味著WPV每次都在做相同的事情。現在我們只需要弄清楚是什麼。
詳細觀察
為此,我使用了 JPEGsnoop來查看圖像中的確切內容。
由於輸出的時間很長,因此我已要點鏈接到它們。以下是差異的摘要:
-
GIMP僅將 APP0
(JFIF)和 COM
(註釋)段用於元數據。 WPV使 APP0
段保持不變,但奇怪地在註釋中添加了一個空字節(以便它以空終止)。
-
WPV添加了兩個 APP1
段,它們是Exif和XMP元數據。這些段分別為4286和12726字節。它們在一起幾乎佔據了文件大小的全部增長。
-
GIMP生成漸進式JPEG,而WPV生成基線(非漸進式)JPEG。因此,GIMP的圖像有多個掃描段,而WPV圖像只有一個。以我的經驗,漸進圖像有時會稍小。
-
GIMP使用1×1色度二次採樣,而WPV使用2×2色度採樣。這使我相信WPV不會使用“真實的”無損旋轉,除非它能夠以某種方式檢測到這是黑白圖像。
這些問題,我進行了第二次測試。
過程
我遵循了與第一次測試類似的步驟。我使用RGB噪波濾鏡(濾鏡>鼻子> RGB鼻子...)創建了隨機256×256 RGB圖像,設置如下:
結果:
我使用以下設置將文件導出為JPEG:
漸進式已關閉,但是子採樣仍設置為4:4:4(這是1×1子採樣的另一個名稱)。質量提高到98。
我複制了圖像並順時針旋轉了複製件。然後復制旋轉的版本並逆時針旋轉該副本,以便我們可以直接比較原始和WPV處理的副本之間的質量。
結果
-rwxrwx-- -1個root vboxsf 159774 Nov 8 16:21 original-random.jpg-rwxrwx --- 1個root vboxsf 222404 Nov 8 16:24 cw-random.jpg-rwxrwx --- 1個root vboxsf 222467 Nov 8 16:24 cw- ccw-random.jpg
儘管這次的增加相對較小(大約40%),但絕對增加甚至更大-大約62kB。這表明WMV使用的編碼效率較低。
我將使用 ImageMagick比較兩個圖像:
robert @ unity。 ./jpeg-rotate-test%比較-verbose -metric AE original-random.jpg cw-ccw-random.jpg null:original-random.jpg JPEG 256x256 256x256 + 0 + 0 8位sRGB 160KB 0.000u 0:00.009
cw-ccw-random.jpg JPEG 256x256 256x256 + 0 + 0 8位sRGB 222KB 0.010u 0:00.010圖片:original-random.jpg通道失真:AE紅色:0綠色:0藍色:0全部:0原始隨機。 jpg = > JPEG 256x256 256x256 + 0 + 0 8位sRGB 0.050u 0:00.020
原始副本和旋轉副本之間存在零像素不同。因此,即使WPV沒有使用“真正的”無損旋轉,它也做得很好。我懷疑我知道發生了什麼,並且要解釋一下,我將稍微介紹一下JPEG壓縮背後的數學原理。
JPEG壓縮算法將圖像分解為8×8像素的塊。然後,對這些塊中的每個塊進行離散餘弦變換(DCT)。所得的DCT係數將該塊描述為不同頻率波的總和。然後,該算法“丟棄”高頻波中與噪聲和非常小的細節相對應的一些信息。解碼過程使DCT反轉,將存儲的波加在一起以返回塊。
可以旋轉DCT“波”,而無需實際撤消和重做變換(基本上,您可以旋轉所有水平波)成垂直波,反之亦然)。我認為在WPV中發生的事情是圖像實際上已解碼,旋轉然後重新編碼。在重新編碼過程中,由於我們的圖像尺寸在兩個維度上均為8的倍數,因此每個新塊都對應於一個原始塊。重要的是,由於每個塊都沒有高頻分量,因此該算法不會丟棄任何信息,並且可以找到“真正的”無損旋轉將具有的正確的DCT分量。
最後,我是再來看一下JPEG文件的組成部分。結果再次鏈接為要點。比較兩者:
-
WPV映像包含額外的4286 + 2字節的Exif元數據,註釋中的1個額外字節和12726 + 2字節的XMP元數據。這總共是17,017字節的其他元數據。這些數據全部用來做什麼?我用值得信賴的十六進制編輯器和相關標準的副本瀏覽了該文件:
-
Exif元數據的結構類似於TIFF圖像,其中包含許多標籤(其中有方式更加複雜,但我將跳過它)。 Exif段中的大多數字節都包含在兩個相同的標籤中,標籤號為 EA1C
(十進制59,932)。在我能找到的任何地方都沒有記錄該標籤號。這兩個標籤都包含2060個``未定義''類型的字節,除了前六個( 1C EA 00 00 00 08
)之外,它們都是空字節。我不知道這些標籤是什麼,為什麼有兩個,為什麼每個標籤都需要2 kB。
-
XMP元數據實際上是一個完整的嵌入式XML文檔。具有名稱間隔和長UUID,僅包含WPV版本字符串(該字符串已在Exif元數據中)。但是,這僅佔大約400個字節。該段的其餘部分是 122個重複的100個空格,後跟一個換行符。總共浪費了超過12,000個字節的空間。
-
像以前的測試一樣,GIMP和WPV都使用相同的DCT量化表。這意味著他們應該計算出完全相同的DCT係數,這就是為什麼圖像完全相同的原因。我不確定WPV是否恰好使用了相同的量化表,還是從輸入中復制了這些表。
-
與以前的測試不同,這次WPV使用1 ×1二次採樣,因此實際上可能是在檢測這是彩色圖像(或者至少需要更高的採樣才能無損地重新編碼圖像)。
-
GIMP和WPV使用不同的霍夫曼表(熵編碼步驟的一部分)。 WPV的表大了總共279個字節,並且在一種情況下,包含7倍的代碼。
從JPEGsnoop的統計數據來看,我們發現其中一些代碼很少使用。例如,在 ID:1,Class:AC
表中,在定義的119個16位代碼中,實際上僅使用了23個。總體而言,在WPV版本中,實際掃描段要大28.5%。
摘要
版本信息:
-
OS(Linux)( uname -a
):
Linux統一3.16.0-4-amd64#1 SMP Debian 3.16.36-1 + deb8u1(2016-09-03)x86_64 GNU / Linux
-
OS(Windows):
-
GIMP(Linux):2.8.14(來自軟件包 gimp
,版本 2.8.14-1 + deb8u1
)
-
Window Photo Viewer (根據圖像元數據):
Microsoft Windows Photo Viewer 10.0.10586.0