编程技巧15法之三

类别:VC语言 点击:0 评论:0 推荐:
 

1.         如何替换HBITMAP中的颜色值

#define COLORREF2RGB(Color) (Color & 0xff00) | ((Color >> 16) & 0xff) \

                                             | ((Color << 16) & 0xff0000)

 

HBITMAP ReplaceColor (HBITMAP hBmp,COLORREF cOldColor,COLORREF cNewColor)

{

    HBITMAP RetBmp=NULL;

    if (hBmp)

    {   

        HDC BufferDC=CreateCompatibleDC(NULL);       // 源位图DC

        if (BufferDC)

        {

            SelectObject(BufferDC,hBmp);         // 选入DC中

           

            HDC DirectDC=CreateCompatibleDC(NULL);      // 目标DC

            if (DirectDC)

            {

                // 获取源位图大小

                BITMAP bm;

                GetObject(hBmp, sizeof(bm), &bm);

               

                // 初始化BITMAPINFO信息,以便使用CreateDIBSection

                BITMAPINFO RGB32BitsBITMAPINFO;

                ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));

                RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);

                RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth;

                RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight;

                RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;

                RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;

                UINT * ptPixels;   

 

                HBITMAP DirectBitmap= CreateDIBSection(DirectDC,

                                              (BITMAPINFO *)&RGB32BitsBITMAPINFO,

                                              DIB_RGB_COLORS,(void **)&ptPixels, NULL, 0);

                if (DirectBitmap)

                {

                    HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap);

                    BitBlt(DirectDC,0,0,bm.bmWidth,bm.bmHeight,BufferDC,0,0,SRCCOPY);

 

                    // 转换 COLORREF 为 RGB

                    cOldColor=COLORREF2RGB(cOldColor);

                    cNewColor=COLORREF2RGB(cNewColor);

 

                    // 替换颜色

                    for (int i=((bm.bmWidth*bm.bmHeight)-1);i>=0;i--)

                    {

                        if (ptPixels[i]==cOldColor) ptPixels[i]=cNewColor;

                    }

                   

                    // 修改位图 DirectBitmap

                    SelectObject(DirectDC,PreviousObject);

                   

                    // 完成

                    RetBmp=DirectBitmap;

                }

                // 释放DC

                DeleteDC(DirectDC);

            }

            // 释放DC

            DeleteDC(BufferDC);

        }

    }

    return RetBmp;

}

 

用法:

HBITMAP hBmp2 = LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_SAMPLEBITMAP));

HBITMAP hBmp = ReplaceColor(hBmp2,0xff0000,0x00ff00); // 替换蓝色为绿色

 

......

 

DeleteObject(hBmp2);

DeleteObject(hBmp);

 

2.         如何转换并保存位图

//********************************************************************************

//* 名称:DDBToDIB

//* 作者:徐景周([email protected])

//* 功能:设备相关转换为设备无关位图

//********************************************************************************

HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_RGB */)

{

    BITMAP                      bm;

    BITMAPINFOHEADER    bi;

    LPBITMAPINFOHEADER  lpbi;

    DWORD                      dwLen;

    HANDLE                      hDIB;

    HANDLE                      handle;

    HDC                                   hDC;

    HPALETTE                     hPal;

 

    CWindowDC                dc( this );

    CPalette                 pal;

    //如果支持调色板的话,则建立它

    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE )

    {

        UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );

        LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];

        pLP->palVersion     = 0x300;

        pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255,

        pLP->palPalEntry );

 

        pal.CreatePalette( pLP );

 

        //释放

        delete[] pLP;

    }

 

    ASSERT( bitmap.GetSafeHandle() );

 

    //不支持BI_BITFIELDS类型

    if( dwCompression == BI_BITFIELDS )

        return NULL;

 

    //如果调色板为空,则用默认调色板

    hPal = (HPALETTE) pal.GetSafeHandle();

    if (hPal==NULL)

        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

 

    //获取位图信息

    bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

 

    //初始化位图信息头

    bi.biSize        = sizeof(BITMAPINFOHEADER);

    bi.biWidth        = bm.bmWidth;

    bi.biHeight         = bm.bmHeight;

    bi.biPlanes         = 1;

    bi.biBitCount        = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;

    bi.biCompression    = dwCompression;

    bi.biSizeImage        = 0;

    bi.biXPelsPerMeter    = 0;

    bi.biYPelsPerMeter    = 0;

    bi.biClrUsed        = 0;

    bi.biClrImportant    = 0;

 

    //计算信息头及颜色表大小

    int nColors = 0;

    if(bi.biBitCount <= 8)

        {

        nColors = (1 << bi.biBitCount);

        }

    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);

 

    hDC = ::GetDC(NULL);

    hPal = SelectPalette(hDC,hPal,FALSE);

    RealizePalette(hDC);

 

    //为信息头及颜色表分配内存

    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

 

    if (!hDIB){

        SelectPalette(hDC,hPal,FALSE);

        ::ReleaseDC(NULL,hDC);

        return NULL;

    }

 

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

 

    *lpbi = bi;

 

    //调用 GetDIBits 计算图像大小

    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,

            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

 

    bi = *lpbi;

 

    //图像的每一行都对齐(32bit)边界

    if (bi.biSizeImage == 0){

        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)

                        * bi.biHeight;

 

        if (dwCompression != BI_RGB)

            bi.biSizeImage = (bi.biSizeImage * 3) / 2;

    }

 

    //重新分配内存大小,以便放下所有数据

    dwLen += bi.biSizeImage;

    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;

    if (handle != NULL)

        hDIB = handle;

    else

        {

        GlobalFree(hDIB);

 

        //重选原始调色板

        SelectPalette(hDC,hPal,FALSE);

        ::ReleaseDC(NULL,hDC);

        return NULL;

        }

 

    //获取位图数据

    lpbi = (LPBITMAPINFOHEADER)hDIB;

 

    //最终获得的DIB

    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),

                0L,                      //扫描行起始处

                (DWORD)bi.biHeight,      //扫描行数

                (LPBYTE)lpbi             //位图数据地址

                + (bi.biSize + nColors * sizeof(RGBQUAD)),

                (LPBITMAPINFO)lpbi,      //位图信息地址

                (DWORD)DIB_RGB_COLORS);  //颜色板使用RGB

 

    if( !bGotBits )

    {

        GlobalFree(hDIB);

       

        SelectPalette(hDC,hPal,FALSE);

        ::ReleaseDC(NULL,hDC);

        return NULL;

    }

 

    SelectPalette(hDC,hPal,FALSE);

    ::ReleaseDC(NULL,hDC);

    return hDIB;

}

 

//********************************************************************************

//* 名称:SaveBitmapToFile

//* 修改:徐景周([email protected])

//* 功能:保存为位图文件

//********************************************************************************

BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName)

{          

       HDC                            hDC;                                                 //设备描述表 

    int                         iBits;                                                 //当前显示分辨率下每个像素所占字节数

       WORD            wBitCount;                                        //位图中每个像素所占字节数

       DWORD           dwPaletteSize=0,                            //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数

                                   dwBmBitsSize,

                                   dwDIBSize, dwWritten;

       BITMAP          Bitmap;        

       BITMAPFILEHEADER   bmfHdr;                                     //位图属性结构   

    BITMAPINFOHEADER   bi;                                           //位图文件头结构      

       LPBITMAPINFOHEADER lpbi;                                    //位图信息头结构    

    HANDLE          fh, hDib, hPal,hOldPal=NULL;       //指向位图信息头结构,定义文件,分配内存句柄,调色板句柄

 

   //计算位图文件每个像素所占字节数

   hDC = CreateDC("DISPLAY",NULL,NULL,NULL);

   iBits = GetDeviceCaps(hDC, BITSPIXEL) *

   GetDeviceCaps(hDC, PLANES);

   DeleteDC(hDC);

   if (iBits <= 1)

      wBitCount = 1;

   else if (iBits <= 4)

      wBitCount = 4;

   else if (iBits <= 8)

      wBitCount = 8;

   else if (iBits <= 24)

      wBitCount = 24;

   //计算调色板大小

   if (wBitCount <= 8)

      dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);

  

   //设置位图信息头结构

   GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);

   bi.biSize            = sizeof(BITMAPINFOHEADER);

   bi.biWidth           = Bitmap.bmWidth;

   bi.biHeight          = Bitmap.bmHeight;

   bi.biPlanes          = 1;

   bi.biBitCount         = wBitCount;

   bi.biCompression      = BI_RGB;

   bi.biSizeImage        = 0;

   bi.biXPelsPerMeter     = 0;

   bi.biYPelsPerMeter     = 0;

   bi.biClrUsed         = 0;

   bi.biClrImportant      = 0;

 

   dwBmBitsSize = ((Bitmap.bmWidth *

    wBitCount+31)/32)* 4

        *Bitmap.bmHeight ;

 

   //为位图内容分配内存

   hDib  = GlobalAlloc(GHND,dwBmBitsSize+

       dwPaletteSize+sizeof(BITMAPINFOHEADER));

   lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);

   *lpbi = bi;

 

   // 处理调色板  

   hPal = GetStockObject(DEFAULT_PALETTE);

   if (hPal)

   {

          hDC  = ::GetDC(NULL);

          hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);

       RealizePalette(hDC);

   }

 

   // 获取该调色板下新的像素值

   GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,

        (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,

        (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);

 

   //恢复调色板  

   if (hOldPal)

   {

      SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);

      RealizePalette(hDC);

      ::ReleaseDC(NULL, hDC);

   }

 

   //创建位图文件   

       fh = CreateFile(lpFileName, GENERIC_WRITE,

               0, NULL, CREATE_ALWAYS,

         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);

 

   if (fh == INVALID_HANDLE_VALUE)

      return FALSE;

 

   // 设置位图文件头

   bmfHdr.bfType = 0x4D42;  // "BM"

   dwDIBSize    = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 

   bmfHdr.bfSize = dwDIBSize;

   bmfHdr.bfReserved1 = 0;

   bmfHdr.bfReserved2 = 0;

   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER)

      + (DWORD)sizeof(BITMAPINFOHEADER)

     + dwPaletteSize;

 

   // 写入位图文件头

   WriteFile(fh, (LPSTR)&bmfHdr, sizeof

       (BITMAPFILEHEADER), &dwWritten, NULL);

   // 写入位图文件其余内容

   WriteFile(fh, (LPSTR)lpbi, dwDIBSize,

   &dwWritten, NULL);

 

   //消除内存分配 

   GlobalUnlock(hDib);

   GlobalFree(hDib);

   CloseHandle(fh);

 

   return TRUE;

}

 

 

 

联系方式:

地址:陕西省西安市劳动路2号院六单元

邮编:710082

作者EMAIL:[email protected]

未来工作室(Future Studio)

 

本文地址:http://com.8s8s.com/it/it2301.htm