<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    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(字節(jié))= 1.37M(字節(jié))

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

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

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

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

    存儲空間被大為減少!

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

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

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

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

    2. 例程簡述

    本文后續(xù)的講解都基于這樣的一個例子工程,它是一個基于對話框的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

    后續(xù)篇章將集中在對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 );//創(chuàng)建兼容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; //每一掃描行所需的字節(jié)數,應是偶數
    WORD bmPlanes; //色平面數
    WORD bmBitsPixel; //色平面的顏色位數
    LPVOID bmBits; //指向存儲像素陣列的數組
    } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;

    第5~8行的作用是:構建一個CDC對象,調用CDC::CreateCompatibleDC創(chuàng)建一個兼容的內存設備上下文,接著調用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執(zhí)行的操作為將源DC中位圖復制到目的DC中。其中前四個參數為目的區(qū)域的坐標(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); //創(chuàng)建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:輸出區(qū)域為黑色

    DSTINVERT:反轉目的位圖

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

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

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

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

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

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

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

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

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

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

    WHITENESS:輸出區(qū)域為白色

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

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

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

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

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

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

    4.1位圖文件格式

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

    (1)位圖文件頭BITMAPFILEHEADER

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

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

    (2)位圖信息頭BITMAPINFOHEADER

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

    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;
    //實際的位圖數據占用的字節(jié)數,即 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個字節(jié),定義為:

    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個字節(jié)表示1個象素的顏色索引值;

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

    此外,位圖數據每一行的字節(jié)數必須為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();

    // 如果位圖中存在調色板,創(chuàng)建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;
    }

    //創(chuàng)建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)根據讀取的位圖信息,計算出調色板大小,然后創(chuàng)建調色板;

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

    (4)調用CDib::Draw(CDC *pDC, int nX, int nY, int nWidth, int nHeight, int mode)函數繪制位圖。在此函數中,真正發(fā)揮顯示位圖作用的是對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位圖的區(qū)別。在此基礎上,本文以實例講解了DDB位圖和DIB位圖的操作方式。DDB位圖的處理相對比較簡單,對于DIB位圖,我們需要定義一個MFC所沒有的新類CDib,它屏蔽位圖信息的讀取及調色板創(chuàng)建的技術細節(jié),應用程序可以方便地使用之。

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



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


    posted on 2007-03-09 15:58 SIMONE 閱讀(774) 評論(0)  編輯  收藏 所屬分類: C++
    主站蜘蛛池模板: 亚洲美女在线观看播放| 尤物视频在线免费观看| 日本免费无遮挡吸乳视频电影| 免费国产成人18在线观看| 亚洲av无码av制服另类专区| 性短视频在线观看免费不卡流畅| 久久精品国产亚洲一区二区| 1000部拍拍拍18勿入免费凤凰福利| 亚洲午夜精品一级在线播放放| 国产亚洲欧美日韩亚洲中文色| 久久午夜免费视频| 国产成人精品亚洲一区| 久久精品国产亚洲夜色AV网站| 久久99精品免费一区二区| 337p日本欧洲亚洲大胆艺术| 国产精品无码一二区免费| 久9久9精品免费观看| 无码亚洲成a人在线观看| 久久亚洲AV成人无码| 亚洲人成电影网站国产精品 | 91嫩草私人成人亚洲影院| 日韩免费观看的一级毛片| 免费国产污网站在线观看| 亚洲欧美成人av在线观看| 亚洲国产成人一区二区精品区| a级成人毛片免费图片| 亚洲Av无码国产一区二区| 亚洲成人黄色网址| 亚洲精品无码久久久久| 最近中文字幕无吗免费高清 | 69视频在线观看高清免费| 免费手机在线看片| 亚洲国产精品综合久久网各| 亚洲夜夜欢A∨一区二区三区 | 亚洲熟妇无码另类久久久| 热99re久久精品精品免费| 成人免费福利视频| a级成人免费毛片完整版| 人人爽人人爽人人片av免费 | 精品国产亚洲AV麻豆| 亚洲三级在线免费观看|