您的位置:首页 > 其它

WINCE下由HBITMAP获取位图RGB颜色数据

2015-08-18 16:31 351 查看
以下代码未经过测试,只是编译没有问题,以前同事问到这个,所以才有下面代码:
class CBitmapBits
{
public:
    CBitmapBits()
        : m_pBitsBuf(NULL)
        , m_dwWidth(0)
        , m_dwHeight(0)
    { 

    }

    ~CBitmapBits()
    {
       Destroy();
    }

    // 释放位图数据
    void Destroy()
    {
        if (m_pBitsBuf != NULL)
        {
            delete[] m_pBitsBuf;
            m_pBitsBuf = NULL;
        }
        m_dwWidth = 0;
        m_dwHeight = 0;
    }

public:
    BYTE *m_pBitsBuf;    // 据按RGB排列,按行优先排列,无4字节对齐,大小等于:宽度*高度*3
    DWORD m_dwWidth;     // 位图宽度
    DWORD m_dwHeight;    // 位图高度
};

// 把HBITMAP绘制到DC左上角
BOOL
DrawHBitmapToDC(
    IN  HBITMAP hBitmap,               // 位图句柄
    IN  HDC hDC                        // 待绘制DC
    )
{
    // 参数有效性
    if (hBitmap==NULL || hDC==NULL)
    {
        return FALSE;
    }

    // 取得位图数据信息,宽度高度等
    BITMAP bmpObj = {0};
    if (   ::GetObject(hBitmap, sizeof(bmpObj), &bmpObj) == 0
        || bmpObj.bmWidth <= 0
        || bmpObj.bmHeight <= 0
        )
    {
        return FALSE;
    }

    // 创建内存DC
    HDC hMemDC = ::CreateCompatibleDC(hDC);			
    if (hMemDC == NULL)
    {
        return FALSE;
    }

    // 把HBITMAP选入内存DC
    HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap);

    // 把内存DC拷贝绘制到目标DC上
    ::BitBlt(hDC, 0, 0, bmpObj.bmWidth, bmpObj.bmHeight, hMemDC, 0, 0, SRCCOPY);

    // 释放内存DC
    ::SelectObject(hMemDC, hOldBitmap);
    ::DeleteDC(hMemDC);           

    // 绘制成功
    return TRUE;
}

// 由HBITMAP获取位图数据
BOOL 
GetHBitmapBits(
    IN  HBITMAP hBitmap,               // 位图句柄
    OUT CBitmapBits &bitmapBits        // 输出颜色数
    )
{
    // 初始化输出参数
    bitmapBits.Destroy();

    // 参数有效性
    if (hBitmap == NULL)
    {
        return FALSE;
    }

    // 取得位图数据信息,宽度高度等
    BITMAP bmpObj = {0};
    if (   ::GetObject(hBitmap, sizeof(bmpObj), &bmpObj) == 0
        || bmpObj.bmWidth <= 0
        || bmpObj.bmHeight <= 0
        )
    {
        return FALSE;
    }

    // 创建DIB内存DC
    HDC hDIBDC = ::CreateCompatibleDC(NULL);  
    if (hDIBDC == NULL)
    {
        return FALSE;
    }

    // 创建DIB兼容位图
    BITMAPINFO hdr;   
    ZeroMemory(&hdr , sizeof(BITMAPINFO));  
    hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  
    hdr.bmiHeader.biWidth = bmpObj.bmWidth;  
    hdr.bmiHeader.biHeight = -bmpObj.bmHeight;  // 这里的目的是直接按正常行顺序使用数据
    hdr.bmiHeader.biPlanes = 1;  
    hdr.bmiHeader.biBitCount = 32;  
    BYTE * pbtPixels = NULL;   
    HBITMAP hDIBitmap = ::CreateDIBSection(hDIBDC, (BITMAPINFO *)&hdr, DIB_RGB_COLORS, (void **)&pbtPixels, NULL, 0);  
    if (hDIBitmap == NULL)
    {
        ::DeleteDC(hDIBDC);
        return FALSE;
    }

    // 把DIB位图选入DIB内存DC
    HBITMAP hOldDIBBmp = (HBITMAP)::SelectObject(hDIBDC, hDIBitmap);  

    // 把HBITMAP绘制到DIB内存DC上
    if (DrawHBitmapToDC(hBitmap, hDIBDC) == FALSE)
    {
        ::SelectObject(hDIBDC, hOldDIBBmp);
        ::DeleteDC(hDIBDC);
        ::DeleteObject(hDIBitmap);
        return FALSE;
    }

    // 从pbtPixels中取得位图数据存放到bitmapBits中
    // 申请存放数据内存
    bitmapBits.m_pBitsBuf = new BYTE[bmpObj.bmWidth*bmpObj.bmHeight*3];
    if (bitmapBits.m_pBitsBuf == NULL)
    {
        ::SelectObject(hDIBDC, hOldDIBBmp);
        ::DeleteDC(hDIBDC);
        ::DeleteObject(hDIBitmap);
        return FALSE;
    }

    // 记录图片宽度高度
    bitmapBits.m_dwWidth = bmpObj.bmWidth;
    bitmapBits.m_dwHeight = bmpObj.bmHeight;

    // 行优先遍历取得每点RGB数据
    long lSrcRowStartPos = 0;
    long lSrcPos = 0;
    long lDstRowStartPos = 0;
    long lDstPos = 0;
    for (long lRowIndex=0; lRowIndex<bmpObj.bmHeight; lRowIndex++)
    {
        // 计算行首位置
        lSrcRowStartPos = lRowIndex * bmpObj.bmWidth * 4;
        lDstRowStartPos = lRowIndex * bmpObj.bmWidth * 3;

        // 遍历每一列
        for (long lColumnIndex=0; lColumnIndex<bmpObj.bmWidth; lColumnIndex++)
        {
            // 计算当前像素点的起始位置,以及目标存放位置
            lSrcPos = lSrcRowStartPos + lColumnIndex*4;
            lDstPos = lDstRowStartPos + lColumnIndex*3;
            
            // 源中应该是BGRA的4字节顺序,这里转存为RGB数据
            bitmapBits.m_pBitsBuf[lDstPos] = pbtPixels[lSrcPos+2];
            bitmapBits.m_pBitsBuf[lDstPos+1] = pbtPixels[lSrcPos+1];
            bitmapBits.m_pBitsBuf[lDstPos+2] = pbtPixels[lSrcPos];
        }
    }

    // 释放DIB内存DC及位图
    ::SelectObject(hDIBDC, hOldDIBBmp);
    ::DeleteDC(hDIBDC);
    ::DeleteObject(hDIBitmap);

    // 取得数据成功
    return TRUE;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: