您的位置:首页 > 其它

GetBitmapBits和GetDIBits的区别(Windows GDI)

2012-10-16 12:15 267 查看
Windows GDI中有两个用来得到位图图像数据的API,分别是GetBitmapBits和GetDIBits;

按照MSDN的解释,前者是用来得到设备独立位图的BITS,

后者是得到兼容位图的BITS,

所以在调用该函数的时候,

第一个主要的区别是:GetDIBits需要提供一个设备内容,同时需要将位图的HANDLE选进这个设备内容(DC)才能能够得到位图的信息。

我想上面的区别大家可能都知道,

其实它还隐藏着另一个区别:就是对于同一个位图,得到的BITS内容的BUFFER不一样!

大家都知道BMP文件存储数据是倒叙的,也就是从图像的右下角开始存储,文件的最后是图像的左上角(这个来历可以看:WINDOWS编程中介绍);

使用GetBitmapBits取得的BUFFER,位图的右下角的内容为第一个字节,实际上和真正的图像字节应该是一样的,

而GetDIBits刚好相反,其BUFFER的顺序符合BMP文件中的顺序,如果按照正常的坐标,其存储顺序应该是倒叙。

所以在程序中要合理的使用这两个API来得到你想要的位图数据。

以上是摘自网上的,下面是具体例子展示说明:

---------------------------------------------------------------------------------------------------

一,如果我们的CBitmap是得到设备兼容的位图:即:CreateCompatibleBitmap来创建的位图,则最好使用

GetDIBits得到位图数据; ::GetDIBits(memdc.m_hDC, btp, 0, bp.bmHeight, pData, pBpInfo, DIB_RGB_COLORS);

之后就可以根据位图数据显示该位图了

// 在客户区显示位图

CClientDC dc(this);

StretchDIBits(dc.m_hDC, 0, 0, bp.bmWidth, bp.bmHeight, 0, 0, bp.bmWidth, bp.bmHeight, pData, pBpInfo, DIB_RGB_COLORS, SRCCOPY);

也可以利用GetBitmapBits得到位图信息,但是得到的位图数据需要转化才与本来位图实际数据对应。

// 对于与设备兼容的位图,用GetBitmapBits得到的位图数据需要转换才可以正确显示位图

// 用GetBitmapBits,然后交换每行数据,最后再交行整个缓冲数据

// 位图本来存储格式如下:

// [g....k]

// [j....t]

// [......]

// [y....b]

// [x....a]

// 但是利用GetBitmapBits得到位图数据格式为 [x...a][y...b][....][j...t][g...k]

// 我们需要将其转化为[g...k][j...t][...][y...b][x...a]

// 步骤为:第一步将每行数据逆置,得到[a...x][b...y][...][t...j][k...g]

// 第二步:将第一步得到的格式,当做一个整体,进行逆置则得到[g...k][j...t][...][y...b][x...a]

dwRet = btp.GetBitmapBits(bp.bmWidthBytes * bp.bmHeight, pData); // 该方式获取位图信息,位图对象应该是LoadBitmap形式获取的

int nRow = bp.bmHeight; // 行数

// 先交换每行的位图数据

char *pS = NULL, *pE= NULL;

for (int j = 1; j <= nRow; j++)

{

pS = pData+(j-1)*bp.bmWidthBytes;

pE = pData+j*bp.bmWidthBytes -1 ;

SwapArray(pS, pE, bp.bmWidthBytes);

}

// 再交换整个数组数据

SwapArray(pData, pData+dwRet-1, dwRet);



// 在客户区显示位图

CClientDC dc(this);

StretchDIBits(dc.m_hDC, 0, 0, bp.bmWidth, bp.bmHeight, 0, 0, bp.bmWidth, bp.bmHeight, pData, pBpInfo, DIB_RGB_COLORS, SRCCOPY);

LocalFree(pData);

void SwapArray(char *pS, char *pE, int nCount)

{

int nMidIndex = nCount / 2;

char tmp;

for (int i = 0; i < nMidIndex; i ++)

{

tmp = *pS;

*pS = *pE;

*pE = tmp;

pS++;

pE--;

}



}



二,如果位图是与设备无关,例如:利用LoadBitmap加载了位图资源,则利用GetBitmapBits得到问题数据,也需要转化的,才可以显示位图了,例如:



// 创建独立于设备的位图

CClientDC dc1(this);

CBitmap btp1;

btp1.LoadBitmap(IDB_BITMAP1);

btp1.GetBitmap(&bp);

pData = (char*)LocalAlloc(LPTR, bp.bmWidthBytes * bp.bmHeight);

btp1.GetBitmapBits(bp.bmWidthBytes * bp.bmHeight, pData);

pBtInfo->bmiHeader.biBitCount = bp.bmBitsPixel;

pBtInfo->bmiHeader.biClrImportant = 0;

pBtInfo->bmiHeader.biCompression = 0;

pBtInfo->bmiHeader.biHeight = bp.bmHeight;

pBtInfo->bmiHeader.biWidth = bp.bmWidth;

pBtInfo->bmiHeader.biPlanes = bp.bmPlanes;

pBtInfo->bmiHeader.biSizeImage = bp.bmWidthBytes * bp.bmHeight;

pBtInfo->bmiHeader.biSize = sizeof(BITMAPINFO);

pBtInfo->bmiHeader.biXPelsPerMeter = 0;

pBtInfo->bmiHeader.biYPelsPerMeter = 0;

int nRows = bp.bmHeight; // 位图行数

char *pS = NULL, *pE = NULL;

for (int i = 0; i < nRows; i++)

{

pS = pData + i * bp.bmWidthBytes;

SwapArray(pS, bp.bmWidthBytes);

}



SwapArray(pData, bp.bmWidthBytes * bp.bmHeight);

StretchDIBits(dc1.m_hDC, 0, 0, bp.bmWidth, bp.bmHeight, 0, 0, bp.bmWidth, bp.bmHeight, pData, pBtInfo, DIB_RGB_COLORS, SRCCOPY);
// 参数pS:要交换的数组的起始地址

// 参数dwCount:要交换的数据的总长度

void CTddDlg::SwapArray(char *pS, UINT dwCount)

{

char temp;

for (UINT i = 0; i < dwCount / 2; i++)

{

temp = pS[i];

pS[i] = pS[dwCount - i -1];

pS[dwCount - i - 1] = temp;

}

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