DIB,全稱Device Independent Bitmap,,設(shè)備無(wú)關(guān)位圖文件,,這是一種文件格式,其目的是為了保證用某個(gè)應(yīng)用程序創(chuàng)建的位圖圖形可以被其它應(yīng)用程序裝載或顯示一樣,。
DIB(Device-indepentent bitmap)的與設(shè)備無(wú)關(guān)性主要體現(xiàn)在以下兩個(gè)方面: DIB的顏色模式與設(shè)備無(wú)關(guān),。例如,一個(gè)256色的DIB即可以在真彩色顯示模式下使用,,也可以在16色模式下使用,。 256色以下(包括256色)的DIB擁有自己的顏色表,像素的顏色獨(dú)立于系統(tǒng)調(diào)色板,。 由于DIB不依賴于具體設(shè)備,因此可以用來(lái)永久性地保存圖象,。DIB一般是以*.BMP文件的形式保存在磁盤(pán)中的,,有時(shí)也會(huì)保存在*.DIB文件中。運(yùn)行在不同輸出設(shè)備下的應(yīng)用程序可以通過(guò)DIB來(lái)交換圖象,。 DIB還可以用一種RLE算法來(lái)壓縮圖像數(shù)據(jù),,但一般來(lái)說(shuō)DIB是不壓縮的。 DIB的結(jié)構(gòu) 與Borland C++下的框架類庫(kù)OWL不同,MFC未提供現(xiàn)成的類來(lái)封裝DIB,。盡管Microsoft列出了一些理由,,但沒(méi)有DIB類確實(shí)給MFC用戶帶來(lái)很多不便。用戶要想使用DIB,,首先應(yīng)該了解DIB的結(jié)構(gòu),。 在內(nèi)存中,一個(gè)完整的DIB由兩部分組成:一個(gè)BITMAPINFO結(jié)構(gòu)和一個(gè)存儲(chǔ)像素陣列的數(shù)組,。BITMAPINFO描述了位圖的大小,,顏色模式和調(diào)色板等各種屬性,其定義為 typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors[1]; //顏色表 } BITMAPINFO; RGBQUAD結(jié)構(gòu)用來(lái)描述顏色,,其定義為 typedef struct tagRGBQUAD { BYTE rgbBlue; //藍(lán)色的強(qiáng)度 BYTE rgbGreen; //綠色的強(qiáng)度 BYTE rgbRed; //紅色的強(qiáng)度 BYTE rgbReserved; //保留字節(jié),,為0 } RGBQUAD; 注意,RGBQUAD結(jié)構(gòu)中的顏色順序是BGR,,而不是平常的RGB,。 BITMAPINFOHEADER結(jié)構(gòu)包含了DIB的各種信息,其定義為 typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //該結(jié)構(gòu)的大小 LONG biWidth; //位圖的寬度(以像素為單位) LONG biHeight; //位圖的高度(以像素為單位) WORD biPlanes; //必須為1 WORD biBitCount //每個(gè)像素的位數(shù)(1,、4,、8、16,、24或32) DWORD biCompression; //壓縮方式,,一般為0或BI_RGB (未壓縮) DWORD biSizeImage; //以字節(jié)為單位的圖象大小(僅用于壓縮位圖) LONG biXPelsPerMeter; //以目標(biāo)設(shè)備每米的像素?cái)?shù)來(lái)說(shuō)明位圖的水平分辨率 LONG biYPelsPerMeter; //以目標(biāo)設(shè)備每米的像素?cái)?shù)來(lái)說(shuō)明位圖的垂直分辨率 DWORD biClrUsed; /*顏色表的顏色數(shù),若為0則位圖使用由biBitCount指定的最大顏色數(shù)*/ DWORD biClrImportant; //重要顏色的數(shù)目,,若該值為0則所有顏色都重要 } BITMAPINFOHEADER; 與DDB不同,,DIB的字節(jié)數(shù)組是從圖象的最下面一行開(kāi)始的逐行向上存儲(chǔ)的,也即等于把圖象倒過(guò)來(lái)然后在逐行掃描,。另外,,字節(jié)數(shù)組中每個(gè)掃描行的字節(jié)數(shù)必需是4的倍數(shù),如果不足要用0補(bǔ)齊 DIB可以存儲(chǔ)在*.BMP或*.DIB文件中,。DIB文件是以BITMAPFILEHEADER結(jié)構(gòu)開(kāi)頭的,,該結(jié)構(gòu)的定義為 typedef struct tagBITMAPFILEHEADER { WORD bfType; //文件類型,必須為"BM" DWORD bfSize; //文件的大小 WORD bfReserved1; //為0 WORD bfReserved2; //為0 DWORD bfOffBits; //存儲(chǔ)的像素陣列相對(duì)于文件頭的偏移量 } BITMAPFILEHEADER; 緊隨該結(jié)構(gòu)的是一個(gè)BITMAPINFOHEADER結(jié)構(gòu),,然后是RGBQUAD結(jié)構(gòu)組成的顏色表(如果有的話),,文件最后存儲(chǔ)的是DIB的像素陣列。 DIB的顏色信息儲(chǔ)存在自己的顏色表中,,程序一般要根據(jù)顏色表為DIB創(chuàng)建邏輯調(diào)色板,。在輸出一幅DIB之前,程序應(yīng)該將其邏輯調(diào)色板選入到相關(guān)的設(shè)備上下文中并實(shí)現(xiàn)到系統(tǒng)調(diào)色板中,,然后再調(diào)用相關(guān)的GDI函數(shù)(如::SetDIBitsToDevice或::StretchDIBits)輸出DIB,。在輸出過(guò)程中,,GDI函數(shù)會(huì)把DIB轉(zhuǎn)換成DDB,這項(xiàng)工作主要包括以下兩步: 將DIB的顏色格式轉(zhuǎn)換成與輸出設(shè)備相同的顏色格式,。例如,,在真彩色的顯示模式下要顯示一個(gè)256色的DIB,則應(yīng)該將其轉(zhuǎn)換成24位的顏色格式,。 將DIB像素的邏輯顏色索引轉(zhuǎn)換成系統(tǒng)調(diào)色板索引,。 編寫(xiě)DIB類 由于MFC未提供DIB類,,用戶在使用DIB時(shí)將面臨繁重的Windows API編程任務(wù),。幸運(yùn)的是,Visual C++提供了一個(gè)較高層次的API,,簡(jiǎn)化了DIB的使用,。這些API函數(shù)實(shí)際上是由MFC的DibLook例程提供的,它們位于DibLook目錄下的dibapi.cpp,、myfile.cpp和dibapi.h文件中,,主要包括: ReadDIBFile //把DIB文件讀入內(nèi)存 SaveDIB //把DIB保存到文件中 CreateDIBPalette //從DIB中創(chuàng)建一個(gè)邏輯調(diào)色板 PaintDIB //顯示DIB DIBWidth //返回DIB的寬度 DIBHeight //返回DIB的高度 DIB區(qū)塊 DIB區(qū)塊 DIB能擁有幾種色彩組織中的一種,DDB必須是單色的或是與真實(shí)輸出設(shè)備相同的格式,。DIB是一個(gè)檔案或記憶體塊,;DDB是GDI點(diǎn)陣圖物件并由點(diǎn)陣圖代號(hào)表示。DIB能被顯示或轉(zhuǎn)換為DDB并轉(zhuǎn)換回DIB,,但是這里包含了裝置無(wú)關(guān)位元和設(shè)備相關(guān)位元之間的轉(zhuǎn)換程序,。 現(xiàn)在您將遇到一個(gè)函式,它打破了這些規(guī)則,。該函式在32位元Windows版本中發(fā)表,,稱為CreateDIBSection,語(yǔ)法為: hBitmap = CreateDIBSection ( hdc, // device context handle pInfo, // pointer to DIB information fClrUse, // color use flag ppBits, // pointer to pointer variable hSection, // file-mapping object handle dwOffset) ; // offset to bits in file-mapping object CreateDIBSection是Windows API中最重要的函式之一(至少在使用點(diǎn)陣圖時(shí)),,然而您會(huì)發(fā)現(xiàn)它很深?yuàn)W并難以理解,。 讓我們從它的名稱開(kāi)始,我們知道DIB是什么,,但「DIB section」到底是什么呢,?當(dāng)您第一次檢查CreateDIBSection時(shí),可能會(huì)尋找該函式與DIB區(qū)塊工作的方式,。這是正確的,,CreateDIBSection所做的就是建立了DIB的一部分(點(diǎn)陣圖圖素位元的記憶體塊)。 現(xiàn)在我們看一下傳回值,,它是GDI點(diǎn)陣圖物件的代號(hào),,這個(gè)傳回值可能是該函式呼叫最會(huì)拐人的部分。傳回值似乎暗示著CreateDIBSection在功能上與CreateDIBitmap相同,。事實(shí)上,它只是相似但完全不同。實(shí)際上,,從CreateDIBSection傳回的點(diǎn)陣圖代號(hào)與我們?cè)诒菊潞蜕弦徽掠龅降乃悬c(diǎn)陣圖建立函式傳回的點(diǎn)陣圖代號(hào)在本質(zhì)上不同,。 一旦理解了CreateDIBSection的真實(shí)特性,您可能覺(jué)得奇怪為什么不把傳回值定義得有所區(qū)別,。您也可能得出結(jié)論:CreateDIBSection應(yīng)該稱之為CreateDIBitmap,,并且如同我前面所指出的CreateDIBitmap應(yīng)該稱之為CreateDDBitmap。 首先讓我們檢查一下如何簡(jiǎn)化CreateDIBSection,,并正確地使用它,。首先,把最後兩個(gè)參數(shù)hSection和dwOffset,,分別設(shè)定為NULL和0,,我將在本章最後討論這些參數(shù)的用法。第二,,僅在fColorUse參數(shù)設(shè)定為DIB_ PAL_COLORS時(shí),,才使用hdc參數(shù),如果fColorUse為DIB_RGB_COLORS(或0),,hdc將被忽略(這與CreateDIBitmap不同,,hdc參數(shù)用於取得與DDB相容的設(shè)備的色彩格式)。 因此,,CreateDIBSection最簡(jiǎn)單的形式僅需要第二和第四個(gè)參數(shù),。第二個(gè)參數(shù)是指向BITMAPINFO結(jié)構(gòu)的指標(biāo),我們以前曾使用過(guò),。我希望指向第四個(gè)參數(shù)的指標(biāo)定義的指標(biāo)不會(huì)使您困惑,,它實(shí)際上很簡(jiǎn)單。 假設(shè)要建立每圖素24位元的384×256位元DIB,,24位元格式不需要色彩對(duì)照表,,因此它是最簡(jiǎn)單的,所以我們可以為BITMAPINFO參數(shù)使用BITMAPINFOHEADER結(jié)構(gòu),。 您需要定義三個(gè)變數(shù):BITMAPINFOHEADER結(jié)構(gòu),、BYTE指標(biāo)和點(diǎn)陣圖代號(hào): BITMAPINFOHEADER bmih ; BYTE * pBits ; HBITMAP hBitmap ; 現(xiàn)在初始化BITMAPINFOHEADER結(jié)構(gòu)的欄位 bmih->biSize = sizeof (BITMAPINFOHEADER) ; bmih->biWidth = 384 ; bmih->biHeight = 256 ; bmih->biPlanes = 1 ; bmih->biBitCount = 24 ; bmih->biCompression = BI_RGB ; bmih->biSizeImage = 0 ; bmih->biXPelsPerMeter = 0 ; bmih->biYPelsPerMeter = 0 ; bmih->biClrUsed = 0 ; bmih->biClrImportant = 0 ; 在基本準(zhǔn)備後,我們呼叫該函式: hBitmap = CreateDIBSection (NULL, (BITMAPINFO *) &bmih, 0, &pBits, NULL, 0) ; 注意,,我們?yōu)榈诙€(gè)參數(shù)賦予BITMAPINFOHEADER結(jié)構(gòu)的位址,。這是常見(jiàn)的,但一個(gè)BYIE指標(biāo)pBits的位址,,就不常見(jiàn)了,。這樣,第四個(gè)參數(shù)是函式需要的指向指標(biāo)的指標(biāo),。 這是函式呼叫所做的:CreateDIBSection檢查BITMAPINFOHEADER結(jié)構(gòu)并配置足夠的記憶體塊來(lái)載入DIB圖素位元,。(在這個(gè)例子里,,記憶體塊的大小為384×256×3位元組。)它在您提供的pBits參數(shù)中儲(chǔ)存了指向此記憶體塊的指標(biāo),。函式傳回點(diǎn)陣圖代號(hào),,正如我說(shuō)的,它與CreateDIBitmap和其他點(diǎn)陣圖建立函式傳回的代號(hào)不一樣,。 然而,,我們還沒(méi)有做完,點(diǎn)陣圖圖素是未初始化的,。如果正在讀取DIB檔案,,可以簡(jiǎn)單地把pBits參數(shù)傳遞給ReadFile函式并讀取它們?;蛘呖梢允褂靡恍┏淌酱a「人工」設(shè)定 |
|
來(lái)自: JohnnyChan > 《C 基礎(chǔ)》