posts - 495,comments - 227,trackbacks - 0

          Visual C++中DDB與DIB位圖編程全攻略
          來源: 天極網

          1. 基本概念

          先來用通俗的語句講解位圖和調色板的概念。
          我們知道,自然界中的所有顏色都可以由紅、綠、藍(R,G,B)三基色組合而成。針對含有紅、綠、藍色成分的多少,可以對其分別分成0~255個等級,而紅、綠、藍的不同組合共有256×256×256種,因此約能表示1600萬種顏色。對于人眼而言,這已經是"真彩色"了。

          對每個像素進行了(R,G,B)量化的圖像就是位圖,其在計算機中對應文件的擴展名一般為.bmp。既然用R,G,B的量化值就可以直接記錄一張位圖的所有像素,那我們需要調色板干什么呢?

          首先,我們可以計算完全利用(R,G,B)組合來存儲一個800×600的位圖所需要的空間為:

          800×600×3 = 1440000(字節)= 1.37M(字節)

          驚人的大!因此,調色板橫空出世了,它的功能在于緩解位圖文件存儲空間過大的問題。

          假設一個位圖為16色,其像素總數為800×600。我們只需要用4個bit就可以存儲這個位圖的每個像素在16種顏色中所處的等級,然后調色板提供了這16種等級對應的(R,G,B)值,這樣,存儲這個16色位圖只需要:

          800×600×4/8 = 240000(字節)= 0.22 M(字節)

          額外的存儲R,G,B表的開銷(即調色板Palette,也稱為顏色查找表LUT)僅僅為16×3=48字節。

          存儲空間被大為減少!

          常見的位圖有單色、16色、256色、16位及24位真彩色5種,對于前三者(即不大于256色)都可以調色板方式進行存儲,而對16位及24位真彩色以調色板進行存儲是不劃算的,它們直接按照R,G,B分量進行存儲。

          在此基礎上我們來分析DDB位圖(Device-dependent bitmap,與設備相關的位圖)與DIB位圖(Device-independent bitmap,與設備無關的位圖)的概念以及二者的區別。

          DDB依賴于具體設備,它只能存在于內存中(視頻內存或系統內存),其顏色模式必須與特定的輸出設備相一致,使用系統調色板。一般只能載入色彩較簡單的DDB位圖,對于顏色較豐富的位圖,需使用DIB才能長期保存。

          DIB不依賴于具體設備,可以用來永久性地保存圖象。DIB一般是以*.BMP文件的形式保存在磁盤中的,有時也會保存在*.DIB文件中。 DIB位圖的特點是將顏色信息儲存在位圖文件自身的顏色表中,應用程序要根據此顏色表為DIB創建邏輯調色板。因此,在輸出一幅DIB位圖之前,程序應該將其邏輯調色板選入到相關的設備上下文并實現到系統調色板中。

          2. 例程簡述

          本文后續的講解都基于這樣的一個例子工程,它是一個基于對話框的MFC應用程序,包括2個父菜單:

          (1) DDB位圖

          DDB位圖父菜單又包括兩個子菜單:

          a. ID:IDM_LOADDDBPIC caption:加載

          單擊事件:加載資源中的DDB位圖并顯示之

          b. ID:IDM_MARK_DDBPIC caption:標記

          單擊事件:在DIB位圖中透明地添加天極網logo

          (2) DIB位圖

          DIB位圖父菜單又包括兩個子菜單:

          a. ID:IDM_OPENDIBPIC caption:打開

          單擊事件:彈出文件對話框,打開.bmp位圖文件,并顯示

          b. ID:IDM_MARK_DIBPIC caption:標記

          單擊事件:在DIB位圖中透明地添加天極網logo

          工程中還包含下列位圖資源:

          (1)IDB_LOADED_BITMAP:要加載的位圖資源

          (2)IDB_YESKY_BITMAP:天極網logo

          后續篇章將集中在對4個子菜單單擊事件消息處理函數的講解,下面的代碼是整個對話框類CBitMapExampleDlg的消息映射:

          BEGIN_MESSAGE_MAP(CBitMapExampleDlg, CDialog)
          //{{AFX_MSG_MAP(CBitMapExampleDlg)
          ON_WM_SYSCOMMAND()
          ON_WM_PAINT()
          ON_WM_QUERYDRAGICON()
          ON_COMMAND(IDM_LOADDDBPIC, OnLoadddbpic)
          ON_COMMAND(IDM_MARK_DDBPIC, OnMarkDdbpic)
          ON_COMMAND(IDM_OPENDIBPIC, OnOpendibpic)
          ON_COMMAND(IDM_MARK_DIBPIC,OnMarkDibpic) //}}AFX_MSG_MAP
          END_MESSAGE_MAP()

          ?

          3. DDB位圖編程

          先看DDB加載按鈕的單擊事件代碼:

          void CBitMapExampleDlg::OnLoadddbpic()
          {
          1: CBitmap bmpDraw;
          2: bmpDraw.LoadBitmap( IDB_LOADED_BITMAP );//裝入要加載的DDB位圖
          3: BITMAP bmpInfo;
          4: bmpDraw.GetBitmap( &bmpInfo ); //獲取要加載DDB位圖的尺寸
          5: CDC memDC;//定義一個兼容DC
          6: CClientDC dc( this );
          7: memDC.CreateCompatibleDC( &dc );//創建兼容DC
          8: CBitmap* pbmpOld = memDC.SelectObject( &bmpDraw );//保存原有DDB,并選入新DDB入DC

          9: dc.BitBlt( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY );

          10: memDC.SelectObject( pbmpOld );//選入原DDB
          }

          上述代碼將產生如圖1所示的效果,位圖被安置在對話框(0,0)坐標開始的位置上。

          圖1 加載DDB位圖資源

          ?


          我們來逐行解析上述代碼是怎樣產生圖1的效果的。

          第1、2行定義了一個CBitmap對象,并調用其成員函數LoadBitmap加載工程中的位圖資源IDB_LOADED_BITMAP。第3、4行定義了BITMAP結構體的實例并調用CBitmap的成員函數GetBitmap獲得位圖信息,BITMAP結構體定義在頭文件中,其形式為:

          /* Bitmap Header Definition */
          typedef struct tagBITMAP
          {
          LONG bmType; //必需為0
          LONG bmWidth; //位圖的寬度(以像素為單位)
          LONG bmHeight; //位圖的高度(以像素為單位)
          LONG bmWidthBytes; //每一掃描行所需的字節數,應是偶數
          WORD bmPlanes; //色平面數
          WORD bmBitsPixel; //色平面的顏色位數
          LPVOID bmBits; //指向存儲像素陣列的數組
          } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;

          第5~8行的作用是:構建一個CDC對象,調用CDC::CreateCompatibleDC創建一個兼容的內存設備上下文,接著調用CDC::SelectObject將DDB選入內存設備上下文中。

          第9行調用函數CDC::BitBlt繪制位圖,CDC::BitBlt的原型為:

          CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int xSrc, int ySrc, DWORD dwRop)
          CDC::BitBlt執行的操作為將源DC中位圖復制到目的DC中。其中前四個參數為目的區域的坐標(x,y)及長度和寬度(Width, nHeight),第五個參數是源DC指針,接下來的參數是源DC中的起始坐標,最后一個參數為光柵操作的類型。

          第10行調用CDC::SelectObject把原來的DDB選入到內存設備上下文中并使新DDB脫離出來。

          與CDC::BitBlt對應的還有另一個函數CDC::StretchBlt,它具有縮放功能,其原型為:

          BOOL CDC::StretchBlt(int x, int y, int nWidth, int nHeight, CDC *pSrcDC, int
          xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop);

          該函數把位圖從源矩形拷貝到目的矩形中,如果源和目的矩形尺寸不同,那么將縮放位圖的功能以適應目的矩形的大小。函數的大部分參數與BitBlt的相同,但多了兩個參數nSrcWidth和nSrcHeight用來指定源矩形的寬和高。

          如果我們將函數CBitMapExampleDlg::OnLoadddbpic() 中的第9行改為:

          CRect clientRect;
          GetClientRect(&clientRect); //獲得對話框窗口的大小
          dc.StretchBlt(0, 0, clientRect.right, clientRect.bottom, &memDC, 0, 0,
          bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY);

          則單擊加載按鈕后的對話框如圖2所示,位圖被拉伸至整個對話框的范圍。



          圖2 拉伸位圖

          CDC::BitBlt和dc.StretchBlt函數中的dwRop參數較為有用,它定義光柵操作的類型。請看"DDB位圖"父菜單下"標記"子菜單單擊事件的消息處理函數代碼:

          void CBitMapExampleDlg::OnMarkDdbpic()
          {
          CBitmap bmpDraw;
          bmpDraw.LoadBitmap(IDB_YESKY_BITMAP); //裝入天極網logo DDB位圖資源
          BITMAP bmpInfo;
          bmpDraw.GetBitmap(&bmpInfo); //獲取天極網logo位圖的尺寸

          CDC memDC; //定義一個兼容DC
          CClientDC dc(this);
          memDC.CreateCompatibleDC(&dc); //創建DC

          CBitmap *pbmpOld = memDC.SelectObject(&bmpDraw);
          //保存原有DDB,并選入天極網logo位圖入DC
          dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND);
          memDC.SelectObject(pbmpOld); //選入原DDB
          }

          單擊該按鈕后,將產生如圖3的效果,天極網的logo被透明地添加到了位圖中!



          圖3 在DDB位圖中加入天極網logo

          能產生這個效果的原因在于我們在代碼行:

          dc.BitBlt ( 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCAND );

          中使用了參數SRCAND(不同于先前代碼中SRCCOPY,它僅僅意味著復制源位圖到目的位圖),它的含義為源和目的間進行AND操作。我們不知道天極網的編輯同志是怎么為文章中的圖片加logo的,有可能他們就使用了具有自動AND功能的圖像加logo批處理軟件。的確,我們可以利用例程中的原理寫一個批處理軟件,一次對一堆圖片自動添加logo。

          參數dwRop除了可以為SRCAND和SRCCOPY外,還可以有如下取值:

          BLACKNESS:輸出區域為黑色

          DSTINVERT:反轉目的位圖

          MERGECOPY:用與操作把圖案(Pattern)與源位圖融合起來

          MERGEPAINT:用或操作把反轉的源位圖與目的位圖融合起來

          NOTSRCCOPY:把源位圖反轉然后拷貝到目的地

          NOTSRCERASE:用或操作融合源和目的位圖,然后再反轉

          PATCOPY:把圖案拷貝到目的位圖中

          PATINVERT:用異或操作把圖案與目的位圖相融合

          PATPAINT:用或操作融合圖案和反轉的源位圖,然后用或操作把結果與目的位圖融合

          SRCERASE:先反轉目的位圖,再用與操作將其與源位圖融合

          SRCINVERT:用異或操作融合源位圖和目的位圖

          SRCPAINT:用或操作融合源位圖和目的位圖

          WHITENESS:輸出區域為白色

          合理利用這些取值將幫助我們制作出特定要求的圖像處理軟件。

          從上述實例我們可以看出,在VC中使用CBitmap類,必須將位圖放入工程的資源中,并使用類 CBitmap的成員函數LoadBitmap加載之,再通過CDC類的成員函數BitBlt進行DC拷貝等操作達到顯示的目的。CBitmap有顯示的不足:

          (1) 位圖需要放入工程資源中,這將導致工程的可執行文件變大;

          (2) 因為位圖需放入工程資源中,而資源中不能無窮無盡地包含位圖,應用程序無法自適應地選取其它位圖,能使用的位圖十分有限的;

          (3) 類CBitmap只是DDB位圖操作API的封裝,不能獨立于平臺。

          DIB位圖則可以解決上述問題,其特點是以.BMP位圖文件格式存儲獨立于平臺的圖像數據,下面我們來詳細分析。
          4. DIB位圖編程

          4.1位圖文件格式

          先來分析DIB位圖文件的格式。位圖文件分為四部分:

          (1)位圖文件頭BITMAPFILEHEADER

          位圖文件頭BITMAPFILEHEADER是一個結構體,長度為14字節,定義為:

          typedef struct tagBITMAPFILEHEADER
          {
          WORD bfType; //文件類型,必須是0x424D,即字符串"BM"
          DWORD bfSize; //文件大小,包括BITMAPFILEHEADER的14個字節
          WORD bfReserved1; //保留字
          WORD bfReserved2; //保留字
          DWORD bfOffBits; //從文件頭到實際的位圖數據的偏移字節數
          } BITMAPFILEHEADER;

          (2)位圖信息頭BITMAPINFOHEADER

          位圖信息頭BITMAPINFOHEADER也是一個結構體,長度為40字節,定義為:

          typedef struct tagBITMAPINFOHEADER
          {
          DWORD biSize; //本結構的長度,為40
          LONG biWidth; //圖象的寬度,單位是象素
          LONG biHeight; //圖象的高度,單位是象素
          WORD biPlanes; //必須是1
          WORD biBitCount;
          //表示顏色時要用到的位數,1(單色), 4(16色), 8(256色), 24(真彩色)
          DWORD biCompression;
          //指定位圖是否壓縮,有效的值為BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS等,BI_RGB表示不壓縮
          DWORD biSizeImage;
          //實際的位圖數據占用的字節數,即 biSizeImage=biWidth’ × biHeight,biWidth’是biWidth 按照4的整倍數調整后的結果
          LONG biXPelsPerMeter; //目標設備的水平分辨率,單位是每米的象素個數
          LONG biYPelsPerMeter; //目標設備的垂直分辨率,單位是每米的象素個數
          DWORD biClrUsed; //位圖實際用到的顏色數,0表示顏色數為2biBitCount
          DWORD biClrImportant; //位圖中重要的顏色數,0表示所有顏色都重要
          } BITMAPINFOHEADER;

          (3)調色板Palette

          調色板Palette針對的是需要調色板的位圖,即單色、16色和256色位圖。對于不以調色板方式存儲的位圖,則無此項信息。調色板是一個數組,共有biClrUsed個元素(如果該值為0,則有2biBitCount個元素)。數組中每個元素是一個RGBQUAD結構體,長度為4個字節,定義為:

          typedef struct tagRGBQUAD
          {
          BYTE rgbBlue; //藍色分量
          BYTE rgbGreen; //綠色分量
          BYTE rgbRed; //紅色分量
          BYTE rgbReserved; //保留值
          } RGBQUAD;

          (4)實際的位圖數據ImageDate

          對于用到調色板的位圖,實際的圖象數據ImageDate為該象素的顏色在調色板中的索引值;對于真彩色圖,圖象數據則為實際的R、G、B值:

          a.單色位圖:用1bit就可以表示象素的顏色索引值;

          b.16色位圖:用4bit可以表示象素的顏色索引值;

          c. 256色位圖:1個字節表示1個象素的顏色索引值;

          d.真彩色:3個字節表示1個象素的顏色R,G,B值。

          此外,位圖數據每一行的字節數必須為4的整倍數,如果不是,則需要補齊。奇怪的是,位圖文件中的數據是從下到上(而不是從上到下)、從左到右方式存儲的。
          4.2位圖的顯示

          Visual C++ MFC中沒有提供一個專門的類來處理DIB位圖,因此,為了方便地使用位圖文件,我們有必要派生一個CDib類。類的源代碼如下:

          (1) CDib類的聲明

          // DIB.h:類CDib聲明頭文件
          #ifndef __DIB_H__
          #define __DIB_H__
          #include
          class CDib
          {
          public:
          CDib();
          ~CDib();

          BOOL Load( const char * );
          BOOL Save( const char * );
          BOOL Draw( CDC *, int nX = 0, int nY = 0, int nWidth = -1, int nHeight = -1, int mode = SRCCOPY);
          BOOL SetPalette( CDC * );

          private:
          CPalette m_Palette;
          unsigned char *m_pDib, *m_pDibBits;
          DWORD m_dwDibSize;
          BITMAPINFOHEADER *m_pBIH;
          RGBQUAD *m_pPalette;
          int m_nPaletteEntries;
          };
          #endif

          (2) CDib類的實現

          // DIB.cpp:類CDib實現文件
          #include "stdafx.h"
          #include "DIB.h"

          CDib::CDib()
          {
          m_pDib = NULL;
          }

          CDib::~CDib()
          {
          // 如果位圖已經被加載,釋放內存
          if (m_pDib != NULL)
          delete []m_pDib;
          }

          下面這個函數非常重要,其功能為加載位圖,類似于CBitmap類的LoadBitmap函數:

          BOOL CDib::Load(const char *pszFilename)
          {
          CFile cf;

          // 打開位圖文件
          if (!cf.Open(pszFilename, CFile::modeRead))
          return (FALSE);

          // 獲得位圖文件大小,并減去BITMAPFILEHEADER的長度
          DWORD dwDibSize;
          dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER);

          // 為DIB位圖分配內存
          unsigned char *pDib;
          pDib = new unsigned char[dwDibSize];
          if (pDib == NULL)
          return (FALSE);

          BITMAPFILEHEADER BFH;

          // 讀取位圖文件數據
          try
          {
          // 文件格式是否正確有效
          if ( cf.Read(&BFH, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER) ||
          BFH.bfType != ’MB’ || cf.Read(pDib, dwDibSize) != dwDibSize)
          {
          delete []pDib;
          return (FALSE);
          }
          }
          catch (CFileException *e)
          {
          e->Delete();
          delete []pDib;
          return (FALSE);
          }

          // delete先前加載的位圖
          if (m_pDib != NULL)
          delete m_pDib;

          // 將臨時Dib數據指針和Dib大小變量賦給類成員變量
          m_pDib = pDib;
          m_dwDibSize = dwDibSize;

          // 為相應類成員變量賦BITMAPINFOHEADER和調色板指針
          m_pBIH = (BITMAPINFOHEADER*)m_pDib;
          m_pPalette = (RGBQUAD*) &m_pDib[sizeof(BITMAPINFOHEADER)];

          // 計算調色板中實際顏色數量
          m_nPaletteEntries = 1 << m_pBIH->biBitCount;
          if (m_pBIH->biBitCount >8)
          m_nPaletteEntries = 0;
          else if (m_pBIH->biClrUsed != 0)
          m_nPaletteEntries = m_pBIH->biClrUsed;

          // 為相應類成員變量賦image data指針
          m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof (RGBQUAD)];

          // delete先前的調色板
          if (m_Palette.GetSafeHandle() != NULL)
          m_Palette.DeleteObject();

          // 如果位圖中存在調色板,創建LOGPALETTE 及CPalette
          if (m_nPaletteEntries != 0)
          {
          LOGPALETTE *pLogPal = (LOGPALETTE*)new char[sizeof(LOGPALETTE) + m_nPaletteEntries *sizeof(PALETTEENTRY)];

          if (pLogPal != NULL)
          {
          pLogPal->palVersion = 0x300;
          pLogPal->palNumEntries = m_nPaletteEntries;

          for (int i = 0; i < m_nPaletteEntries; i++)
          {
          pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed;
          pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen;
          pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgbBlue;
          }

          //創建CPalette并釋放LOGPALETTE的內存
          m_Palette.CreatePalette(pLogPal);
          delete []pLogPal;
          }
          }

          return (TRUE);
          }

          //函數功能:保存位圖入BMP文件
          BOOL CDib::Save(const char *pszFilename)
          {
          if (m_pDib == NULL)
          return (FALSE);

          CFile cf;
          if (!cf.Open(pszFilename, CFile::modeCreate | CFile::modeWrite))
          return (FALSE);

          try
          {
          BITMAPFILEHEADER BFH;
          memset(&BFH, 0, sizeof(BITMAPFILEHEADER));
          BFH.bfType = ’MB’;
          BFH.bfSize = sizeof(BITMAPFILEHEADER) + m_dwDibSize;
          BFH.bfOffBits = sizeof(BITMAPFILEHEADER) +
          sizeof(BITMAPINFOHEADER) + m_nPaletteEntries *sizeof(RGBQUAD);

          cf.Write(&BFH, sizeof(BITMAPFILEHEADER));
          cf.Write(m_pDib, m_dwDibSize);
          }
          catch (CFileException *e)
          {
          e->Delete();
          return (FALSE);
          }
          return (TRUE);
          }

          下面這個函數也非常重要,其功能為在pDC指向的CDC中繪制位圖,起點坐標為(nX,nY),繪制寬度和高度為nWidth、nHeight,最后一個參數是光柵模式:

          BOOL CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)
          {
          if (m_pDib == NULL)
          return (FALSE);

          // 獲取位圖寬度和高度賦值
          if (nWidth == - 1)
          nWidth = m_pBIH->biWidth;
          if (nHeight == - 1)
          nHeight = m_pBIH->biHeight;

          // 繪制位圖
          StretchDIBits(pDC->m_hDC, nX, nY, nWidth, nHeight, 0, 0, m_pBIH->biWidth, m_pBIH->biHeight, m_pDibBits, (BITMAPINFO*)m_pBIH, BI_RGB, mode);

          return (TRUE);
          }

          //函數功能:設置調色板
          BOOL CDib::SetPalette(CDC *pDC)
          {
          if (m_pDib == NULL)
          return (FALSE);

          // 檢查當前是否有一個調色板句柄,對于大于256色的位圖,為NULL
          if (m_Palette.GetSafeHandle() == NULL)
          return (TRUE);

          // 選擇調色板,接著實施之,最后恢復老的調色板
          CPalette *pOldPalette;
          pOldPalette = pDC->SelectPalette(&m_Palette, FALSE);
          pDC->RealizePalette();
          pDC->SelectPalette(pOldPalette, FALSE);

          return (TRUE);
          }

          從整個CDib類的代碼中我們可以看出,DIB位圖的顯示需遵循如下步驟:

          (1)讀取位圖,本類中使用pDib = new unsigned char[dwDibSize]為位圖中的信息分配內存,另一種方法是調用API函數CreateDIBSection,譬如:

          m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),
          (LPBITMAPINFO) m_lpBMPHdr, DIB_RGB_COLORS,
          (LPVOID*) &m_lpDIBits, NULL, 0);

          m_hBitmap定義為:

          HBITMAP m_hBitmap;
          (2)根據讀取的位圖信息,計算出調色板大小,然后創建調色板;

          (3)調用CDib::SetPalette( CDC *pDC )設置調色板,需要用到CDC::SelectPalette及CDC::RealizePalette兩個函數;

          (4)調用CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)函數繪制位圖。在此函數中,真正發揮顯示位圖作用的是對StretchDIBits API函數的調用。StretchDIBits函數具有縮放功能,其最后一個參數也是光柵操作的模式。

          下面給出DIB位圖的打開及顯示并在其中加入天極網logo的函數源代碼。"DIB位圖"父菜單下"打開"子菜單的單擊事件消息處理函數為(其功能為打開位圖并顯示之):

          void CBitMapExampleDlg::OnOpendibpic()
          {
          // 彈出文件對話框,讓用戶選擇位圖文件
          CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL,"位圖文件(*.BMP)|*.bmp;*.BMP|");
          if (IDOK == fileDialog.DoModal())
          {
          // 加載位圖并顯示之
          CDib dib;
          if (dib.Load(fileDialog.GetPathName()))
          {
          CClientDC dc(this);
          dib.SetPalette(&dc);
          dib.Draw(&dc);
          }
          }
          }

          "DIB位圖"父菜單下"標記"子菜單的單擊事件消息處理函數為(其功能為給位圖加上天極網logo):

          void CBitMapExampleDlg::OnMarkDibpic()
          {
          // 彈出文件對話框,讓用戶選擇標記logo
          CFileDialog fileDialog(TRUE, "*.BMP", NULL, NULL, "標記位圖文件(*.BMP)|*.bmp;*.BMP|");
          if (IDOK == fileDialog.DoModal())
          {
          // 加載標記logo位圖并與目標位圖相與
          CDib dib;
          if (dib.Load(fileDialog.GetPathName()))
          {
          CClientDC dc(this);
          dib.SetPalette(&dc);
          dib.Draw(&dc, 0, 0, - 1, - 1, SRCAND);
          }
          }
          }

          圖4顯示了DIB位圖加載天極網logo后的效果,要好于圖3中加天極網logo后的DDB位圖。圖4顯示的是真彩色位圖相互與的結果,而圖3中的圖像顏色被減少了。


          圖4 在DIB位圖中加入天極網logo

          5. 結束語

          本文介紹了位圖及調色板的概念,并講解了DDB位圖與DIB位圖的區別。在此基礎上,本文以實例講解了DDB位圖和DIB位圖的操作方式。DDB位圖的處理相對比較簡單,對于DIB位圖,我們需要定義一個MFC所沒有的新類CDib,它屏蔽位圖信息的讀取及調色板創建的技術細節,應用程序可以方便地使用之。

          本文中的所有程序在Visual C++6.0及Windows XP平臺上調試通過。?



          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1518334


          posted on 2007-03-09 15:58 SIMONE 閱讀(777) 評論(0)  編輯  收藏 所屬分類: C++
          主站蜘蛛池模板: 囊谦县| 同江市| 澄迈县| 克山县| 泰宁县| 民县| 黄浦区| 克什克腾旗| 海林市| 石门县| 巴南区| 贺州市| 孟村| 宝山区| 哈尔滨市| 兰西县| 永定县| 枞阳县| 洮南市| 朝阳市| 兴化市| 崇信县| 冷水江市| 景德镇市| 襄城县| 靖远县| 德保县| 锡林浩特市| 孟津县| 察哈| 萍乡市| 南充市| 雷波县| 杭锦旗| 河池市| 巴南区| 府谷县| 板桥市| 安岳县| 拉萨市| 宣武区|