肖峰
(安徽大學(xué); 安徽職業(yè)技術(shù)學(xué)院 學(xué)生處,安徽 合肥 230001)
VC++ 下的 BMP 格式圖像和 PNG 格式圖像的轉(zhuǎn)換
肖峰
(安徽大學(xué); 安徽職業(yè)技術(shù)學(xué)院 學(xué)生處,安徽 合肥 230001)
初步探討了在 VC++的 BMP 格式圖像和 PNG 格式圖像的轉(zhuǎn)換.首先分析了 BMP 和 PNG 兩種圖像文件的詳細(xì)格式,然后在 VC++環(huán)境下建立了這兩種圖像格式文件的處理類 CBmp 和 CPng,在這兩個(gè)類中實(shí)現(xiàn)了 BMP 文件的讀取、顯示和 PNG 文件的保存等操作.在理解 LZ77 壓縮算法和霍夫曼編碼算法的基礎(chǔ)上,在 VC++的環(huán)境下實(shí)現(xiàn)這兩種算法.這樣,我們就可以讀取 BMP 圖像文件,然后將圖像顯示在程序界面上,通過壓縮和編碼,從而將對(duì)應(yīng)的 BMP 圖像數(shù)據(jù)轉(zhuǎn)換為PNG 圖像數(shù)據(jù),實(shí)現(xiàn)了圖像格式的轉(zhuǎn)換.
VC++;BMP;PNG;LZ77 算法;霍夫曼編碼
隨著網(wǎng)絡(luò)的發(fā)展,圖像越來越成為人們之間重要的信息傳輸和共享方式.在生活和工作中經(jīng)常用到的圖像格式有BMP、PNG、jpe、gif和 tiff等等.其中 BMP 和 PNG 格式是采用的無損壓縮圖像格式,它們之間格式的互相轉(zhuǎn)換就成了數(shù)字圖像處理中經(jīng)常遇到的問題.
BMP是最常用最基本的圖像文件格式,圖像軟件基本上都能讀取和顯示BMP圖像格式.和其他圖像格式相比,BMP格式是一種非常簡(jiǎn)單的格式,設(shè)計(jì)目的是為了能在程序設(shè)計(jì)中輕松的進(jìn)行圖形編程.它具有比較足夠的顏色深度支持,可以支持 1 位、2 位、4 位和 8 位的彩色索引圖像以及16 位、24 位和 32 位的真彩 RGB 圖像.BMP 格式的圖像通常都很大,因?yàn)樗辉?位和8位彩色索引圖像中支持最簡(jiǎn)單的行程編碼格式.
一般來說BMP圖像文件由四部分組成:
1.1 位圖文件頭
BMP文件的位圖文件頭是一種簡(jiǎn)單的供應(yīng)用程序識(shí)別BMP 文件的文件頭.它保存了 BMP 文件簽名、文件長(zhǎng)度字段和數(shù)據(jù)等相關(guān)信息.
1.2 位圖信息頭
位圖信息頭保存了真正的圖像信息,它存儲(chǔ)了相關(guān)的圖像格式、圖像大小、壓縮方式和顏色說明信息等等.
1.3 顏色表
這部分在圖像文件中不是必須的,有些高彩或者真彩圖像是不需要顏色表的.對(duì)于少于 256 色的圖像,位圖數(shù)據(jù)中的像素就是顏色表的索引,用于將索引值轉(zhuǎn)換成 RGB 值.
很多時(shí)候會(huì)把位圖信息頭和顏色表組合在一起組成位圖信息結(jié)構(gòu).這里需要指出的是由于位圖信息的位圖信息頭字段的定義在不同的系統(tǒng)或者平臺(tái)上可能存在定義版本不一致的情況,應(yīng)用程序不應(yīng)該依靠位圖信息去定位位圖顏色表,而是應(yīng)該在運(yùn)行時(shí)根據(jù)圖像信息頭計(jì)算出顏色表的偏移量.
1.4 位圖數(shù)據(jù)
位圖數(shù)據(jù)是圖像實(shí)際像素保存的地方.通常情況下,圖像是對(duì)齊到32位邊界的掃描線的序列.掃描線的默認(rèn)次序是由下向上.由下向上表示位圖數(shù)據(jù)中的第一個(gè)像素實(shí)際上是在屏幕上顯示時(shí)最后一行掃描線的第一個(gè)像素.在每行掃描線內(nèi)部,像素被壓縮在一起以節(jié)省空間.由于掃描線是雙字節(jié)對(duì)齊的,在掃描線的結(jié)尾可能會(huì)加上更多的位將其湊成雙字的整數(shù)倍.對(duì)于使用顏色表的位圖,像素?cái)?shù)據(jù)就是顏色表中的顏色索引值,其他的真彩位圖中直接使用 RGB 值.
利用 VC++ 實(shí)現(xiàn) BMP 文件的讀取、顯示和保存,先用VC++ 創(chuàng)建一個(gè)文檔視圖應(yīng)用程序,所有的功能都會(huì)在這個(gè)程序中實(shí)現(xiàn).
首先我們實(shí)現(xiàn)一個(gè) BMP 文件操作的類 CBmp,包括Bmp.h 和 Bmp.Cpp 文件.
其次通過 File 菜單下的打開子菜單來打開 BMP 文件,通過類函數(shù) Read()來判斷文件是否打開成功.如果返回值為負(fù),則是讀取打開文件失敗,則提示打開 BMP 文件失敗.如果返回值為正,則是正確打開 BMP 文件,程序繼續(xù)向下執(zhí)行.
最后通過消息函數(shù)來調(diào)用類 CBmp 的 Draw()函數(shù)來把BMP文件的內(nèi)容顯示到界面上.
這樣,一個(gè) BMP圖像文件就被讀取顯示在程序中了.
PNG 是一種無損壓縮的、易傳輸?shù)墓鈻艌D像文件格式,設(shè)計(jì)目的是用來替代 GIF 和 TIFF 文件格式,并增加一些這兩種所不具有的文件特性.PNG 圖像文件是現(xiàn)在網(wǎng)絡(luò)、媒體、游戲中最常用的文件格式之一.
相比 BMP 格式文件,PNG 格式文件顯得更復(fù)雜些.它支持灰度圖像、索引彩色圖像和真彩圖像,并且支持額外的 α通道.采樣的深度范圍是從 1 位到 16 位.采用的壓縮算法是LZ77 派生的無損數(shù)據(jù)壓縮算法.
3.1 文件結(jié)構(gòu)
PNG 數(shù)據(jù)流包含 PNG 文件簽名和數(shù)據(jù)塊序列,每個(gè)數(shù)據(jù)塊都有自己的類型和功能.
3.1.1 PNG 文件簽名
PNG 文件簽名包含一個(gè) 8字節(jié)的數(shù)據(jù),用來識(shí)別該文件是不是 PNG 文件.
3.1.2 數(shù)據(jù)塊
PNG 包含兩種類型的數(shù)據(jù)塊,一種叫關(guān)鍵數(shù)據(jù)塊,有 4種.在每個(gè) PNG 文件中都必須必須包含這四種數(shù)據(jù)塊,另一種叫做輔助數(shù)據(jù)塊,有 14 種,PNG 文件中可以包含也可以不包含,可以包含一種也可以同時(shí)包含多種.
關(guān)鍵數(shù)據(jù)塊有以下類型:文件頭 (IHDR)、調(diào)色板(PLTE)、圖像數(shù)據(jù)(IDAT)和圖像結(jié)束數(shù)據(jù)(IEND).
輔助數(shù)據(jù)塊包含了很多信息,這些輔助數(shù)據(jù)塊在 PNG文件中根據(jù)需要被包含一部分或者全部包含.
數(shù)據(jù)塊結(jié)構(gòu)
每個(gè)數(shù)據(jù)塊由3個(gè)或者4個(gè)部分組成:
Length:4 字節(jié),塊中數(shù)據(jù)的長(zhǎng)度,可以為 0
Chunk Type Code(類型碼):4 字節(jié),取值范圍 65~90 和97~122
Chunk Data(數(shù)據(jù)塊數(shù)據(jù)):可變,數(shù)據(jù)段
CRC:4 字節(jié),循環(huán)冗余校驗(yàn)碼
數(shù)據(jù)塊解析
下面我們對(duì)四種類型的關(guān)鍵數(shù)據(jù)塊進(jìn)行解析.
(1)IHDR:文件頭數(shù)據(jù)塊,按照 PNG 文件規(guī)范,整個(gè)數(shù)據(jù)流或者文件中只能有一個(gè)文件頭數(shù)據(jù)塊.而且它是首個(gè)出現(xiàn)在數(shù)據(jù)流中數(shù)據(jù)塊,數(shù)據(jù)塊的構(gòu)成格式如下:
Width、Height:寬和高,都是 4 字節(jié)
Bit depth:1 字節(jié),圖像采樣或調(diào)色板索引的位數(shù)
ColorType:1 字節(jié),圖像類型
Compression method:1 字節(jié),壓縮方法,目前定義了一種壓縮方法
Filter method:1 字節(jié),目前只定義了一種濾波器方法,0
Interlace method:1 字 節(jié) 0 是 沒 有 Interlace,1 是 采 用Adam7 方法
(2)PLTE:調(diào)色板數(shù)據(jù)塊,如果文件是真彩圖像或者包含α數(shù)據(jù)通道的真彩圖像,調(diào)色板數(shù)據(jù)塊不是必須存在的,如果文件是索引彩色圖像,調(diào)色板數(shù)據(jù)塊是存在的.調(diào)色板數(shù)據(jù)塊包含從 1 到 256 個(gè)調(diào)色板信息,每一個(gè)調(diào)色板信息由3個(gè)字節(jié)組成.
(3)IDAT:圖像數(shù)據(jù)塊,它存儲(chǔ)著壓縮后真正的圖像數(shù)據(jù),可以有多個(gè)圖像數(shù)據(jù)塊,但是在 PNG 數(shù)據(jù)流中必須以連續(xù)順序的方式存放.
(4)IEND:圖像結(jié)束數(shù)據(jù):放在文件的尾部,是文件結(jié)束的標(biāo)志.它的數(shù)據(jù)域部分必為空.
關(guān)于輔助數(shù)據(jù)塊的詳細(xì)解析這里不再一一列舉.
3.1 基本原理
PNG 使用的是 LZ77 算法派生的一個(gè)叫 DEFLATE 的無損壓縮算法.DEFLATE 實(shí)際上是兩種算法的組合實(shí)現(xiàn),它先用 LZ77 算法進(jìn)行預(yù)處理,然后用霍夫曼編碼,快速的得到非常不錯(cuò)的壓縮效果.
LZ77 的基本原理如下:它引入滑動(dòng)窗口的概念,把這個(gè)滑動(dòng)窗口作為一個(gè)動(dòng)態(tài)的字典來維護(hù),用一個(gè)三元符號(hào)組來表示 offset,len 和分割符.offset表示從文件起始位置到當(dāng)前 Phase 的起始位置的距離,len 記錄當(dāng)前 Phase 有多少個(gè)字符,分割符僅用于分割不同的 Phase.Phase 就是 offset到offset+len 之間的子串減掉分隔符.
霍夫曼編碼的基本原理:首先要把整個(gè)文件中每個(gè)符合出現(xiàn)的次數(shù)統(tǒng)計(jì)下來.然后根據(jù)這些符號(hào)的次數(shù)和出現(xiàn)頻率,建立霍夫曼樹,通過霍夫曼樹生成每個(gè)符號(hào)的編碼.在文件中出現(xiàn)頻率高的符號(hào),它對(duì)應(yīng)的霍夫曼編碼的長(zhǎng)度比較短.對(duì)于文件中出現(xiàn)頻率低的符號(hào),它的霍夫曼編碼的長(zhǎng)度比較長(zhǎng).此時(shí)再讀入一遍文件,逐個(gè)編碼,得到的碼流就是壓縮后的數(shù)據(jù).
3.2 實(shí)現(xiàn)過程
下面用偽代碼來示意 LZ77 的算法過程:
假設(shè)我們用一個(gè)三元組 (i,j,X) 來表示上面提到的三元組.
關(guān)于霍夫曼編碼這里不再贅述.
在 VC++ 中實(shí)現(xiàn)從 BMP 格式到 PNG 格式的轉(zhuǎn)換,是基于前面的 BMP 文件讀取顯示保存操作和 LZ77 算法與霍夫曼編碼實(shí)現(xiàn)的基礎(chǔ)之上的,并且同時(shí)要求分析 PNG 文件的詳細(xì)格式和讀寫方法,利用前面建立的 VC++ 下的文檔視圖程序具體實(shí)現(xiàn)這個(gè)過程.
首先建立基本的應(yīng)用程序和 CBmp、CPng 類,把類CBmp 和 CPng的成員變量和成員函數(shù)初始化.
其次把 LZ77 壓縮算法和霍夫曼編碼算法用 VC++ 代碼實(shí)現(xiàn),確保下面的數(shù)據(jù)處理能正確進(jìn)行.
最后,當(dāng)前面的這些準(zhǔn)備工作完成以后,將 BMP 圖像文件中的圖像數(shù)據(jù)通過 CBmp類讀出來,通過編碼程序轉(zhuǎn)換為 PNG 圖像數(shù)據(jù),并將 BMP 的圖像信息寫入 PNG 文件的對(duì)應(yīng)域的值,通過 CPng 類的方法將之保存為 PNG 格式文件.
首先進(jìn)行的是讀取 BMP文件的操作.在分析和理解BMP 文件的格式以后,我們創(chuàng)建了一個(gè) VC++ 的應(yīng)用程序,并且實(shí)現(xiàn)了詳細(xì)的類 CBmp用于 BMP 的操作.接下來我們解析了 PNG 文件的格式和其相關(guān)的壓縮算法,創(chuàng)建和實(shí)現(xiàn)了類 CPng 和 LZ77 派生算法的處理函數(shù).最后在 VC++ 實(shí)現(xiàn)BMP 圖像格式文件向 PNG 圖像格式文件的轉(zhuǎn)換.
〔1〕韓姣.基 于 VC++的 BMP 格 式圖像與 GIF 格 式圖 像 轉(zhuǎn)換[J].武漢理工大學(xué)學(xué)報(bào),2007,29(12):23-25.
〔2〕(美)Feng Yuan.Windows 圖 形 編 程 [M].北 京 :機(jī) 械 工 業(yè)出版社,2002.
〔3〕(美)懷特著,楊浩等.GDI+程序設(shè)計(jì)[M].北京:清華 大學(xué)出版社,2002.
TP317.4
:A
:1673-260X(2016)02-0017-02
2015 年 10 月 9 日
赤峰學(xué)院學(xué)報(bào)·自然科學(xué)版2016年3期