以下代码未经过测试,只是编译没有问题,以前同事问到这个,所以才有下面代码:
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;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/werocpp/article/details/47753931