创建位图的函数,没有成功,请高手帮忙看看,分析哪里错了。非常感谢!
其中cx,cy为位图高度,ibitcount为位深度,lpData为图像数据,bSave为是否保存标志。HBITMAP CreatBMP(long cx, long cy, UINT ibitcount, LPBYTE lpData, bool bSave)
{
// 宽度为 4 的整数倍
cx = ((cx+3)/4 * 4); ASSERT((ibitcount == 1) || (ibitcount == 4) ||
(ibitcount == 8) || (ibitcount == 16)
|| (ibitcount == 24) ||(ibitcount == 32));
int iSize = sizeof(BITMAPINFOHEADER);
switch(ibitcount){
case 8:
iSize += 4*4;
break;
case 1:
case 4:
case 16:
case 24:
case 32:
break;
default:
break;
} // 创建信息头
BITMAPINFO* pBmpInfo;
BYTE *pByte;
pByte = new BYTE[iSize];
pBmpInfo = (BITMAPINFO*) pByte;
memset(pBmpInfo, 0, iSize); pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = cx;
pBmpInfo->bmiHeader.biHeight = cy;
pBmpInfo->bmiHeader.biPlanes = 1;
pBmpInfo->bmiHeader.biBitCount = ibitcount;
pBmpInfo->bmiHeader.biCompression = BI_RGB;
pBmpInfo->bmiHeader.biSizeImage = 0;
pBmpInfo->bmiHeader.biClrUsed = 0; // 创建DIB
CDC *pDC = new CDC;
pDC->CreateCompatibleDC(NULL);
LPVOID lpBits;
HBITMAP hDIB = ::CreateDIBSection(pDC->GetSafeHdc(),
pBmpInfo,
DIB_RGB_COLORS,
&lpBits,
NULL,
0);
// 填充图像数据
LONG lineBytes = cx * ibitcount*8;
memcpy(lpBits, (void* )lpData, lineBytes*cy);
// 是否保存
if( bSave )
{
int iBmpBytes = cx * cy * ibitcount/8;
BITMAPFILEHEADER fileHeader;
ZeroMemory(&fileHeader, sizeof(BITMAPFILEHEADER));
*((char* )&fileHeader.bfType) = 'B';
*(((char*)&fileHeader.bfType) + 1) = 'M';
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) + ibitcount*sizeof(RGBTRIPLE);
fileHeader.bfSize = fileHeader.bfOffBits + iBmpBytes; CFile file;
if(file.Open("temp.bmp", CFile::modeWrite | CFile::modeCreate))
{
file.Write(&fileHeader, sizeof(BITMAPFILEHEADER));
file.Write(&(pBmpInfo->bmiHeader), sizeof(BITMAPINFOHEADER));
file.WriteHuge(lpBits, iBmpBytes);
file.Close();
}
} delete pDC;
delete pBmpInfo;
delete pByte; return hDIB;
}一执行就s了啊。
其中cx,cy为位图高度,ibitcount为位深度,lpData为图像数据,bSave为是否保存标志。HBITMAP CreatBMP(long cx, long cy, UINT ibitcount, LPBYTE lpData, bool bSave)
{
// 宽度为 4 的整数倍
cx = ((cx+3)/4 * 4); ASSERT((ibitcount == 1) || (ibitcount == 4) ||
(ibitcount == 8) || (ibitcount == 16)
|| (ibitcount == 24) ||(ibitcount == 32));
int iSize = sizeof(BITMAPINFOHEADER);
switch(ibitcount){
case 8:
iSize += 4*4;
break;
case 1:
case 4:
case 16:
case 24:
case 32:
break;
default:
break;
} // 创建信息头
BITMAPINFO* pBmpInfo;
BYTE *pByte;
pByte = new BYTE[iSize];
pBmpInfo = (BITMAPINFO*) pByte;
memset(pBmpInfo, 0, iSize); pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = cx;
pBmpInfo->bmiHeader.biHeight = cy;
pBmpInfo->bmiHeader.biPlanes = 1;
pBmpInfo->bmiHeader.biBitCount = ibitcount;
pBmpInfo->bmiHeader.biCompression = BI_RGB;
pBmpInfo->bmiHeader.biSizeImage = 0;
pBmpInfo->bmiHeader.biClrUsed = 0; // 创建DIB
CDC *pDC = new CDC;
pDC->CreateCompatibleDC(NULL);
LPVOID lpBits;
HBITMAP hDIB = ::CreateDIBSection(pDC->GetSafeHdc(),
pBmpInfo,
DIB_RGB_COLORS,
&lpBits,
NULL,
0);
// 填充图像数据
LONG lineBytes = cx * ibitcount*8;
memcpy(lpBits, (void* )lpData, lineBytes*cy);
// 是否保存
if( bSave )
{
int iBmpBytes = cx * cy * ibitcount/8;
BITMAPFILEHEADER fileHeader;
ZeroMemory(&fileHeader, sizeof(BITMAPFILEHEADER));
*((char* )&fileHeader.bfType) = 'B';
*(((char*)&fileHeader.bfType) + 1) = 'M';
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) + ibitcount*sizeof(RGBTRIPLE);
fileHeader.bfSize = fileHeader.bfOffBits + iBmpBytes; CFile file;
if(file.Open("temp.bmp", CFile::modeWrite | CFile::modeCreate))
{
file.Write(&fileHeader, sizeof(BITMAPFILEHEADER));
file.Write(&(pBmpInfo->bmiHeader), sizeof(BITMAPINFOHEADER));
file.WriteHuge(lpBits, iBmpBytes);
file.Close();
}
} delete pDC;
delete pBmpInfo;
delete pByte; return hDIB;
}一执行就s了啊。
http://community.csdn.net/Expert/topic/3567/3567472.xml?temp=.551449
bitcount = 8时isize = 256*4 = 1024
计算行像数个数,4字节对齐
这两句都有问题
LONG lineBytes = cx * ibitcount*8; 这里应该是(cx*ibitcount/8 +3)/4*4
memcpy(lpBits, (void* )lpData, lineBytes*cy);另的地方不看了
)。To MZP(mzp): 首先谢了。还有,bitcount=4 时iSize += 16*4 吧?这一句
memcpy(lpBits, (void* )lpData, lineBytes*cy);哪里错了?麻烦大家帮帮忙,主要是创建部分。
bitcount=4 时iSize += 16*4 是对的。
biSizeImage = 0 没错的,当不使用压缩时置0。
调色板可能要考虑。但是我创建24位色位图时程序也不行。不知道是不是创建过程逻辑有问题。热切期望各位再帮忙!多谢。
{
CDC dc;
dc.CreateDC("DISPLAY", NULL, NULL, NULL);
CBitmap bm;
int Width = 800;//GetSystemMetrics(SM_CXSCREEN);
int Height = 600;//GetSystemMetrics(SM_CYSCREEN);
bm.CreateCompatibleBitmap(&dc, Width, Height);
CDC tdc;
tdc.CreateCompatibleDC(&dc);
CBitmap* pOld = tdc.SelectObject(&bm);
tdc.BitBlt(0, 0, Width, Height, &dc, 0, 0, SRCCOPY);
tdc.SelectObject(pOld); BITMAP btm;
bm.GetBitmap(&btm);
DWORD size = btm.bmWidthBytes* btm.bmHeight;
LPSTR lpData = (LPSTR) GlobalAllocPtr(GPTR, size);
/////////////////////////////////////////////
/////////////////////////////////////////////
BITMAPINFOHEADER bih;
bih.biBitCount = btm.bmBitsPixel;
bih.biClrImportant = 0;
bih.biClrUsed = 0;
bih.biCompression = 0;
bih.biHeight = btm.bmHeight;
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = size;
bih.biWidth = btm.bmWidth;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
///////////////////////////////////
GetDIBits(dc, bm, 0, bih.biHeight, lpData, (BITMAPINFO *) &bih,
DIB_RGB_COLORS);
// bm.GetBitmapBits(size,lpData); //此函数在处理5-5-5模式的16位色下会出现颜色混乱
//////////////////////////////
//修改RGB值
int nWidth = btm.bmWidth * 4;
for (int i = 0; i < btm.bmHeight; i++)
{
for (int j = 0; j < btm.bmWidth; j++)
{
lpData[i * nWidth + j * 4 + 2] = GetRandomRGBValue(); //R
lpData[i * nWidth + j * 4 + 1] = GetRandomRGBValue(); //G
lpData[i * nWidth + j * 4] = GetRandomRGBValue(); //B
TRACE("\nR = %d; G = %d; B = %d\n",
lpData[i * nWidth + j * 4 + 2],
lpData[i * nWidth + j * 4 + 1], lpData[i * nWidth + j * 4]);
}
} static int filecount = 0;
CString name;
name = "D:\\Test.bmp";//m_Path+name;
BITMAPFILEHEADER bfh;
bfh.bfReserved1 = bfh.bfReserved2 = 0;
bfh.bfType = ((WORD) ('M' << 8) | 'B');
bfh.bfSize = 54 + size;
bfh.bfOffBits = 54; CFile bf;
if (bf.Open(name, CFile::modeCreate | CFile::modeWrite))
{
bf.WriteHuge(&bfh, sizeof(BITMAPFILEHEADER));
bf.WriteHuge(&bih, sizeof(BITMAPINFOHEADER));
bf.WriteHuge(lpData, size);
bf.Close();
}
GlobalFreePtr(lpData);
AfxMessageBox("Create BMP File Over!");
}