2014-10-01 60 views
2

我目前正在開發基於png文件格式的專有文件格式。我到目前爲止已完成,除非它不起作用:-p我實現的deflate解壓縮器就像一個魅力一樣工作,但png解碼器不想很好地執行,所以我查看了原始png文件。IDAT大塊的PNG文件格式

該標準說明,在IDAT頭後,壓縮數據緊隨其後。因此,由於數據是放氣流,IDAT之後的第一個字符是0x78 == 01111000,這意味着,模式一塊(未壓縮),而不是最後一個。

奇怪 - 雖然我很難想象PNG編碼器不使用動態霍夫曼編碼來壓縮濾波後的原始圖像數據。放氣標準表示當前字節的其餘部分在模式1中被跳過。

所以接下來的四個字節表示未壓縮塊的大小及其一個補碼。 但0x59FD不是0xECDA的補碼。即使我搞砸了字節順序:0xFD59也不是0xDAEC的補碼。

那麼,淘汰賽字節緊隨其後。 0x97被認爲是未壓縮但仍然過濾的原始png圖像數據的第一個字節,因此必須是filtertype。但0x97 == 10010111不是有效的過濾器類型。事件,如果我擰了位打包訂單11101001 == 0xe9仍然沒有有效的過濾器類型。

因爲我能夠使用我的deflate解壓縮器實現來擴充所有類型的文件,所以我懷疑我的一些誤解是認識到PNG標準。

我一遍又一遍地讀了RFC 2083,但我在這裏看到的數據與RFC不匹配,它對我沒有意義,必須有一個缺失的部分!

當我看下面的字節時,實際上我看不到有效的過濾器類型字節,這使我認爲過濾後的png數據流畢竟是壓縮的。

如果0x78(IDAT之後的第一個字節)從MSB讀到LSB,但RFC 1951另有說明,這將是有意義的。另一個想法(更可能是我)是在IDAT字符串和壓縮deflate流的開始之間存在一些數據,但RFC 2083另有說明。佈局是清楚

4字節大小 4字節ChunkName(IDAT) [大小]字節(壓縮的放氣流) 4字節CRC校驗

所以IDAT後的第一個字節必須是壓縮的放氣流的第一個字節 - 表示模式1未壓縮的數據塊。這意味着,0x97必須是未壓縮但過濾的PNG圖像數據的第一個字節 - 這意味着0x97是第一行的filtertype - 這是無效的...

我只是不明白,我是愚蠢的還是什麼??

總結: 可能性1: 有IDAT和,如果使是真實的,沒有在RFC2083也不在任何書meantioned壓縮放氣流的有效開始之間的某個其它數據I閱讀有關圖像壓縮。

可能性2: 數0x78被解釋MSB - > LSB其將指示一個模式3塊(動態霍夫曼編碼),但是這與RF1951大約是位打包非常明確矛盾:(LSB - > MSB)

我已經知道了,缺少的部分必須有一些非常愚蠢的,我會覺得urgend需要賣掉我的靈魂,如果有隻在堆棧溢出:-P

enter image description here

回答

3

兩個修正刪除按鈕這可能會幫助你找到自己的方向:

  1. 標誌中zlib字節的數量爲2,而不是1 - 請參閱RFC 1950。第一個是CMF,下一個FLG

在您的數據:

78 DA 

---CMF--- ---FLG--- 
0111.1000 1101.0101 
CINF -CM- +-|| 
      | |+- FCHECK 
      | +-- FDICT 
      +---- FLEVEL 

CINF是7,表示標準32Kb的壓縮窗口。
CM是8,表明壓縮算法的確是DEFLATE。
FCHECK只是一個校驗和;我沒有檢查它是否正確(但我敢打賭是這樣)。
FDICT很清楚,這意味着沒有預設的字典存儲。
FLEVEL是3,表示最大壓縮。

另請參閱Trying to understand zlib/deflate in PNG files,特別是。博士。阿德勒的回答。

  1. LEN and NLEN只設置爲未壓縮的塊;這就是爲什麼你沒有找到它們。 (另外,局部的,因爲你正在尋找在錯誤的字節。)

流中的下一個字節EC;按位,這是1110 1100,但記得讀取從低到高位。因此讀取的下一位是0,意思是而不是 FINAL,並且接下來的2位讀取是10(以該順序!),表示常規的動態霍夫曼編碼數據塊。

+0

我沒有意識到deflate流被包裝在一個zlib容器中。我認爲它是一個純粹的縮小流。所以我現在簡單地跳過了兩個字節,並且瞧 - png進口商的工作! :-) 非常感謝! – Silverdust 2014-10-01 23:50:55