上面我們已經對PNG的存儲格式有了了解,因此,生成PNG圖片只需要按照以上的數據塊寫入文件即可。
(由于IHDR、PLTE的結構都非常簡單,因此,這里我們只是重點講一講IDAT的生成方法,IHDR和PLTE的數據內容都沿用以上的數據內容)
問題確實是這樣的,我們知道,對于大多數的圖形文件來說,我們都可以將實際的圖像內容映射為一個二維的顏色數組,對于上面的PNG文件,由于它用的是16色的調色板(實際是13色),因此,對于圖片的映射可以如下:

(調色板對照圖)
PNG Spec中指出,假如PNG文件不是采用隔行掃描方法存儲的話,那么,數據是按照行(ScanLine)來存儲的,為了區分第一行,PNG規定在每一行的前面加上0以示區分,因此,上面的圖像映射應該如下:
0 12 11 10 9 8 7 6 5 0 11 10 9 8 7 6 5 4 0 10 9 8 7 6 5 4 3 0 9 8 7 6 5 4 3 2 0 8 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0 6 5 4 3 2 1 0 0 0 5 4 3 2 1 0 0 0另外,需要注重的是,由于PNG在存儲圖像時為了節省空間,因此每一行是按照位(Bit)來存儲的,而并不是我們想象的字節(Byte),假如你沒有忘記的話,我們的IHDR數據塊中的色深就指明了這一點,所以,為了湊成PNG所需要的IDAT,我們的數據得改成如下:
0 203 169 135 101 0 186 152 118 84 0 169 135 101 67 0 152 118 84 50 0 135 101 67 33 0 118 84 50 16 0 101 67 33 0 0 84 50 16 0最后,我們對這些數據進行LZ77壓縮就可以得到IDAT的正確內容了。
然而,事情并不是這么簡單,因為我們研究的是手機上的PNG,假如需要在手機上完成LZ77壓縮工作,消耗的時間是可想而知的,因此,我們得再想辦法加減少壓縮時消耗的時間。
好在LZ77也提供了無壓縮的壓縮方法(希奇吧?),因此,我們只需要簡單的使用無壓縮的方式寫入數據就可以了,這樣雖然浪費了空間,卻換回了時間!
好了,讓我們看一看怎么樣湊成無壓縮的LZ77壓縮塊:
其中的LEN是指數據的長度,占用兩個字節,對于我們的圖像來說,第一個Scan Line包含了5個字節(如第一行的0, 203, 169, 135, 101),所以LEN的值為5(字節/行) * 8(行) = 40(字節),生成字節為28 00(低字節在前),NLEN是LEN的補碼,即NLEN = LEN ^ 0xFFFF,所以NLEN的為 D7 FF,Adler32信息為24 A7 0B A4(具體算法見源程序),因此,按照這樣的順序,我們生成IDAT數據塊,最后,我們將IHDR、PLTE、IDAT和IEND數據塊寫入文件中,就可以得到PNG文件了,如圖:
至此,我們已經能夠采用最快的時間將數組轉換為PNG圖片了。
生成的PNG文件:![]()
范例(附源程序)
新聞熱點
疑難解答