?? dib.cpp
字號(hào):
*
* \說明:
* 如果顏色表存在的話,該函數(shù)將讀取它,并創(chuàng)建一個(gè)Windows調(diào)色板。
* HPALETTE存儲(chǔ)在一個(gè)數(shù)據(jù)成員中。
*
************************************************************************
*/
BOOL CDib::MakePalette()
{
// 如果不存在調(diào)色板,則返回FALSE
if(m_nColorTableEntries == 0) return FALSE;
if(m_hPalette != NULL) ::DeleteObject(m_hPalette);
TRACE("CDib::MakePalette -- m_nColorTableEntries = %d\n", m_nColorTableEntries);
// 給邏輯調(diào)色板分配內(nèi)存
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +
m_nColorTableEntries * sizeof(PALETTEENTRY)];
// 設(shè)置邏輯調(diào)色板的信息
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nColorTableEntries;
// 拷貝DIB中的顏色表到邏輯調(diào)色板
LPRGBQUAD pDibQuad = (LPRGBQUAD) m_lpvColorTable;
for(int i = 0; i < m_nColorTableEntries; i++) {
pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
pDibQuad++;
}
// 創(chuàng)建邏輯調(diào)色板
m_hPalette = ::CreatePalette(pLogPal);
// 刪除臨時(shí)變量并返回TRUE
delete pLogPal;
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* SetSystemPalette()
*
* \輸入?yún)?shù):
* CDC* pDC - 設(shè)備上下文指針
*
* \返回值:
* BOOL - 如果成功,則為TRUE,
*
* \說明:
* 如果16bpp、24bpp或32bppDIB不具備調(diào)色板,則該函數(shù)可以為CDib對(duì)象創(chuàng)建一個(gè)邏輯調(diào)色板,
* 它與由CreatehalftonePalette函數(shù)返回的調(diào)色板相匹配。如果程序在256色調(diào)色板顯示器上
* 運(yùn)行,而你又沒有調(diào)用SetSystemPalette,那么,你將不具有任何調(diào)色板,只有20中標(biāo)準(zhǔn)的
* Windows顏色出現(xiàn)在DIB中
*
************************************************************************
*/
BOOL CDib::SetSystemPalette(CDC* pDC)
{
// 如果DIB不具備調(diào)色板,則需要利用系統(tǒng)的調(diào)色板
if(m_nColorTableEntries != 0) return FALSE;
// 為設(shè)備上下文創(chuàng)建中間調(diào)色板,并將其與CPalette對(duì)象連接
m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc());
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* CreateBitmap()
*
* \輸入?yún)?shù):
* CDC* pDC - 設(shè)備上下文指針
*
* \返回值:
* HBITMAP - 到GDI位圖的句柄;如果不成功,則為NULL
* - 該句柄不是作為公共數(shù)據(jù)成員存儲(chǔ)的
*
* \說明:
* 從已有的DIB中創(chuàng)建DDB位圖。不要將這個(gè)函數(shù)與CreateSection
* 弄混了,后者的作用是生成DIB并保存句柄
*
************************************************************************
*/
HBITMAP CDib::CreateBitmap(CDC* pDC)
{
// 如果不存在圖象數(shù)據(jù),則返回NULL
if (m_dwSizeImage == 0) return NULL;
// 用指定的DIB來創(chuàng)建DDB,并用DIB信息初始化位圖的圖象位
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH,
CBM_INIT, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS);
ASSERT(hBitmap != NULL);
// 返回DDB位圖句柄
return hBitmap;
}
/*************************************************************************
*
* \函數(shù)名稱:
* ConvertDDBToDIB()
*
* \輸入?yún)?shù):
* HBITMAP hBitmap - 指向源數(shù)據(jù)的BITMAP句柄
* CDib* pDibDst - 指向轉(zhuǎn)換目標(biāo)的CDib對(duì)象指針
*
* \返回值:
* BOOL - 如果操作成功,則返回TRUE
*
* \說明:
* 該函數(shù)將源BITMAP類pDibSrc中的數(shù)據(jù)拷貝到pDibDst中,并對(duì)相應(yīng)的數(shù)據(jù)成員賦值
*
*************************************************************************
*/
BOOL CDib::ConvertFromDDB(HBITMAP hBitmap, HPALETTE hPal)
{
// 聲明一個(gè)BITMAP結(jié)構(gòu)
BITMAP bm;
// 設(shè)備上下文
HDC hDC;
// 象素位數(shù)
WORD biBitCount;
// 調(diào)色板表項(xiàng)數(shù)
int nColorTableEntries;
// 如果hBitmap句柄無效,則返回
if(!hBitmap){
return FALSE;
}
// 釋放已分配的內(nèi)存
Empty();
// 填充圖象數(shù)據(jù)到bm中,其中最后一個(gè)參數(shù)表示接收這個(gè)指定的對(duì)象的指針
if(!GetObject(hBitmap,sizeof(BITMAP),(LPBYTE)&bm)){
return FALSE;
}
// 計(jì)算象素位數(shù)
biBitCount=bm.bmPlanes*bm.bmBitsPixel;
if(biBitCount<=1)
biBitCount=1;
else if(biBitCount<=4)
biBitCount=4;
else if(biBitCount<=8)
biBitCount=8;
else
biBitCount=24;
// 計(jì)算調(diào)色板的尺寸
// 如果biClrUsed為零,則用到的顏色數(shù)為2的biBitCount次方
switch(biBitCount) {
case 1:
nColorTableEntries = 2;
break;
case 4:
nColorTableEntries = 16;
break;
case 8:
nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256));
m_nColorTableEntries = nColorTableEntries;
// 分配DIB信息頭和調(diào)色板的內(nèi)存
m_lpBMIH = (LPBITMAPINFOHEADER) new char
[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries];
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = bm.bmWidth;
m_lpBMIH->biHeight = bm.bmHeight;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = biBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = nColorTableEntries;
m_lpBMIH->biClrImportant = nColorTableEntries;
// 獲得設(shè)備上下文句柄
hDC=GetDC(NULL);
// 如果沒有指定調(diào)色板,則從系統(tǒng)中獲得當(dāng)前的系統(tǒng)調(diào)色板
if(hPal==NULL){
hPal = GetSystemPalette();
}
hPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
// 調(diào)用GetDIBits填充信息頭,并獲得圖象數(shù)據(jù)的尺寸。注意這里圖象數(shù)據(jù)指針為NULL
GetDIBits( hDC, hBitmap, 0, (UINT)m_lpBMIH->biHeight, NULL, (LPBITMAPINFO)m_lpBMIH, DIB_RGB_COLORS);
// 如果沒有正確的獲得圖象數(shù)據(jù)尺寸,則重新計(jì)算
if( m_lpBMIH->biSizeImage == 0 ){
m_lpBMIH->biSizeImage=(((bm.bmWidth*biBitCount) + 31) / 32 * 4)*bm.bmHeight;
}
// 分配存放圖象數(shù)據(jù)的內(nèi)存
m_lpImage = (LPBYTE) new char[m_lpBMIH->biSizeImage];
// 調(diào)用GetDIBits加載圖象數(shù)據(jù),注意這里給出了圖象數(shù)據(jù)指針
// 如果加載圖象數(shù)據(jù)不成功,則釋放已經(jīng)分配的內(nèi)存,并返回FALSE
if( GetDIBits( hDC, hBitmap, 0, (UINT)m_lpBMIH->biHeight, (LPBYTE)m_lpImage,
(LPBITMAPINFO)m_lpBMIH, DIB_RGB_COLORS) == 0 ){
//clean up and return NULL
Empty();
SelectPalette( hDC, hPal, TRUE );
RealizePalette( hDC );
ReleaseDC( NULL, hDC );
return FALSE;
}
// 刪除臨時(shí)變量
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* Compress()
*
* \輸入?yún)?shù):
* CDC* pDC - 設(shè)備上下文指針
* BOOL bCompress - TRUE對(duì)應(yīng)于壓縮的DIB,F(xiàn)ALSE對(duì)應(yīng)于不壓縮的DIB
*
* \返回值:
* BOOL - 如果成功,則返回TRUE
*
* \說明:
* 該函數(shù)將DIB重新生成為壓縮或者不壓縮的DIB。在內(nèi)部,它轉(zhuǎn)換已有的DIB為DDB位圖
* 然后生成一個(gè)新的壓縮或者不壓縮的DIB。壓縮僅為4bpp和8bpp的DIB所支持。不能
* 壓縮DIB段
*
************************************************************************
*/
BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */)
{
// 判斷是否為4bpp或者8bpp位圖,否則,不進(jìn)行壓縮,返回FALSE
if((m_lpBMIH->biBitCount != 4) && (m_lpBMIH->biBitCount != 8)) return FALSE;
// 如果為DIB段,也不能支持壓縮,返回FALSE
if(m_hBitmap) return FALSE;
TRACE("Compress: original palette size = %d\n", m_nColorTableEntries);
// 獲得設(shè)備上下文句柄
HDC hdc = pDC->GetSafeHdc();
// 將此DIB的調(diào)色板選入設(shè)備上下文,并保存以前的調(diào)色板句柄
HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE);
HBITMAP hBitmap;
// 創(chuàng)建一個(gè)DDB位圖,如果不成功,則返回FALSE
if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE;
// 計(jì)算信息頭加上調(diào)色板的大小尺寸,并給它們分配內(nèi)存
int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
// 將信息頭和調(diào)色板拷貝到內(nèi)存中
memcpy(lpBMIH, m_lpBMIH, nSize); // new header
// 如果需要進(jìn)行壓縮,設(shè)置相應(yīng)的信息,并創(chuàng)建壓縮格式的DIB
if(bCompress) {
switch (lpBMIH->biBitCount) {
case 4:
lpBMIH->biCompression = BI_RLE4;
break;
case 8:
lpBMIH->biCompression = BI_RLE8;
break;
default:
ASSERT(FALSE);
}
// 設(shè)置位圖數(shù)據(jù)指針為NULL,調(diào)用GetDIBits來得到壓縮格式的DIB的尺寸
// 如果不能創(chuàng)建DIB,則進(jìn)行相應(yīng)的錯(cuò)誤處理。
if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) {
AfxMessageBox("Unable to compress this DIB");
// 刪除臨時(shí)變量,并釋放已分配內(nèi)存
::DeleteObject(hBitmap);
delete [] lpBMIH;
// 重新將以前的調(diào)色板選入,并返回FALSE
::SelectPalette(hdc, hOldPalette, FALSE);
return FALSE;
}
// 如果位圖數(shù)據(jù)為空,則進(jìn)行相應(yīng)的錯(cuò)誤處理
if (lpBMIH->biSizeImage == 0) {
AfxMessageBox("Driver can't do compression");
// 刪除臨時(shí)變量,并釋放已分配內(nèi)存
::DeleteObject(hBitmap);
delete [] lpBMIH;
// 重新將以前的調(diào)色板選入,并返回FALSE
return FALSE;
}
// 將位圖數(shù)據(jù)尺寸賦值給類的成員變量
else {
m_dwSizeImage = lpBMIH->biSizeImage;
}
}
// 如果是解壓縮,進(jìn)行相應(yīng)的處理
else {
// 設(shè)置壓縮格式為不壓縮
lpBMIH->biCompression = BI_RGB;
// 根據(jù)位圖的寬度和高度計(jì)算位圖數(shù)據(jù)內(nèi)存的大小
DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32;
if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
// 將得到位圖數(shù)據(jù)的大小尺寸保存在類的成員變量中
m_dwSizeImage = dwBytes * lpBMIH->biHeight;
// 將位圖數(shù)據(jù)內(nèi)存的大小賦值給臨時(shí)的信息頭中的相應(yīng)的變量
lpBMIH->biSizeImage = m_dwSizeImage;
}
// 再次調(diào)用GetDIBits來生成DIB數(shù)據(jù)
// 分配臨時(shí)存放位圖數(shù)據(jù)
LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage];
// 再次調(diào)用GetDIBits來生成DIB數(shù)據(jù),注意此時(shí)位圖數(shù)據(jù)指針不為空
VERIFY(::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,
lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS));
TRACE("dib successfully created - height = %d\n", lpBMIH->biHeight);
// 壓縮轉(zhuǎn)換完畢,進(jìn)行相應(yīng)的其他處理
// 刪除臨時(shí)的DDB位圖
::DeleteObject(hBitmap);
// 釋放原來的DIB分配的內(nèi)存
Empty();
// 重新設(shè)置圖象信息頭和圖象數(shù)據(jù)內(nèi)存分配狀態(tài)
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
// 重新定位信息頭和圖象數(shù)據(jù)指針
m_lpBMIH = lpBMIH;
m_lpImage = lpImage;
// 計(jì)算圖象數(shù)據(jù)尺寸,并設(shè)置DIB中調(diào)色板的指針
ComputeMetrics();
// 計(jì)算DIB中調(diào)色板的尺寸
ComputePaletteSize(m_lpBMIH->biBitCount);
// 如果DIB中調(diào)色板存在的話,讀取并創(chuàng)建一個(gè)Windows調(diào)色板
MakePalette();
// 恢復(fù)以前的調(diào)色板
::SelectPalette(hdc, hOldPalette, FALSE);
TRACE("Compress: new palette size = %d\n", m_nColorTableEntries);
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* Read()
*
* \輸入?yún)?shù):
* CFile* pFile - 指向CFile對(duì)象的指針
*
* \返回值:
* BOOL - 如果成功,則返回TRUE
*
* \說明:
* 該函數(shù)DIB從一個(gè)文件讀入CDib對(duì)象。該文件必須成功打開。如果該文件是BMP文件
* 讀取工作從文件頭開始。如果該文件是一個(gè)文檔,讀取工作則從當(dāng)前文件指針處開始
*
************************************************************************
*/
BOOL CDib::Read(CFile* pFile)
{
// 釋放已經(jīng)分配的內(nèi)存
Empty();
// 臨時(shí)存放信息的變量
int nCount, nSize;
BITMAPFILEHEADER bmfh;
// 進(jìn)行讀操作
try
{
// 讀取文件頭
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
// 如果文件類型部位"BM",則返回并進(jìn)行相應(yīng)錯(cuò)誤處理
if(bmfh.bfType != 0x4d42) {
throw new CException;
}
// 計(jì)算信息頭加上調(diào)色板的大小,并分配相應(yīng)的內(nèi)存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize];
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
// 讀取信息頭和調(diào)色板
nCount = pFile->Read(m_lpBMIH, nSize);
// 計(jì)算圖象數(shù)據(jù)大小并設(shè)置調(diào)色板指針
ComputeMetrics();
// 計(jì)算調(diào)色板的表項(xiàng)數(shù)
ComputePaletteSize(m_lpBMIH->biBitCount);
// 如果DIB中存在調(diào)色板,則創(chuàng)建一個(gè)Windows調(diào)色板
MakePalette();
// 分配圖象數(shù)據(jù)內(nèi)存,并從文件中讀取圖象數(shù)據(jù)
m_lpImage = (LPBYTE) new char[m_dwSizeImage];
nCount = pFile->Read(m_lpImage, m_dwSizeImage);
}
// 錯(cuò)誤處理
catch(CException* pe)
{
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
// 返回
return TRUE;
}
/*************************************************************************
*
* \函數(shù)名稱:
* ReadSection()
*
* \輸入?yún)?shù):
* CFile* pFile - 指向CFile對(duì)象的指針;對(duì)應(yīng)的磁盤
* - 文件中包含DIB
* CDC* pDC - 設(shè)備上下文指針
*
* \返回值:
* BOOL - 如果成功,則返回TRUE
*
* \說明:
* 該函數(shù)從BMP文件中讀取信息頭,調(diào)用CreateDIBSection來分配圖象內(nèi)存,然后將
* 圖象從該文件讀入剛才分配的內(nèi)存。如果你想從磁盤讀取一個(gè)DIB,然后通過調(diào)用
* GDI函數(shù)編輯它的話,可以使用該函數(shù)。你可以用Write或CopyToMapFile將DIB寫
* 回到磁盤
*
************************************************************************
*/
BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */)
{
// 釋放已經(jīng)分配的內(nèi)存
Empty();
// 臨時(shí)變量
int nCount, nSize;
BITMAPFILEHEADER bmfh;
// 從文件中讀取數(shù)據(jù)
try {
// 讀取文件頭
nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER));
if(nCount != sizeof(BITMAPFILEHEADER)) {
throw new CException;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -