共有三个函数与之相关:
CMyDoc::CMyDoc()
{
// 在doc的构造函数里初始化了一个BITMAPINFO
m_pBitmapInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFO)];
m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_pBitmapInfo->bmiHeader.biPlanes = 1;
m_pBitmapInfo->bmiHeader.biBitCount = 8;//8位格式
m_pBitmapInfo->bmiHeader.biCompression = 0;
m_pBitmapInfo->bmiHeader.biSizeImage = 0;
m_pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biClrUsed = 0;
m_pBitmapInfo->bmiHeader.biClrImportant = 0;
m_pBitmapInfo->bmiHeader.biWidth = 0;
m_pBitmapInfo->bmiHeader.biHeight = 0;
}
///从一个采集卡里获得宽度,高度和每行字节数信息,应该没有错,因为图像能够显示。
void CMyDoc::GetBitmapInfo()
{
int SizeX=GetCurrentCamera()->GetImageWidth();//宽度
int SizeY=GetCurrentCamera()->GetImageHeight();//高度
int Bitys=GetCurrentCamera()->GetImageBytes();//每行字节数
m_pBitmapInfo->bmiHeader.biWidth = Bitys / ( m_pBitmapInfo->bmiHeader.biBitCount / 8); // Width = Pitch(bytes) divided by the number of bytes per pixel
m_pBitmapInfo->bmiHeader.biHeight = -SizeY ;
}
//这是一个按钮的相应函数,希望点击后存下图像,图像是存了,可以打开时警告: 图像必须大于一个像素,打开后,里面什么也没有,就是说一个像素都没有存上,为什么呢。
void CMyDoc::OnGrab()
{
int size=0-m_pBitmapInfo->bmiHeader.biWidth*m_pBitmapInfo->bmiHeader.biHeight;//因为是8位,就直接相乘了
m_pBitmapInfo->bmiHeader.biSizeImage = size; BITMAPFILEHEADER bfh; //这是文件头
bfh.bfReserved1=bfh.bfReserved2=0;
bfh.bfType=((WORD)('M'<< 8)|'B');
bfh.bfSize=54+256*sizeof(RGBQUAD)+m_pBitmapInfo->bmiHeader.biSizeImage;
bfh.bfOffBits=54+256*sizeof(RGBQUAD);
RGBQUAD rgbq[256];
for(int i=0;i<256;i++)
{
rgbq[i].rgbBlue=i;
rgbq[i].rgbGreen=i;
rgbq[i].rgbRed=i;
rgbq[i].rgbReserved=0;
}//从图像采集卡的得到的是裸的8位图像的数据地址,我想以灰度图显示,就自己写了一个颜色板。
CString name = "C:\\picttest.bmp";
CFile bf;
if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)){
bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
bf.WriteHuge(&m_pBitmapInfo->bmiHeader,sizeof(BITMAPINFOHEADER));
bf.WriteHuge(rgbq,256*sizeof(RGBQUAD));
bf.WriteHuge(GetCurrentCamera()->GetImagePlace(),size); //这个写入的是像素的地址,应该也没有错,因为显示的时候,放入SetDibToDevice的就是GetCurrentCamera()->GetImagePlace()
bf.Close();
}
}
CMyDoc::CMyDoc()
{
// 在doc的构造函数里初始化了一个BITMAPINFO
m_pBitmapInfo = (BITMAPINFO *) new BYTE[sizeof(BITMAPINFO)];
m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_pBitmapInfo->bmiHeader.biPlanes = 1;
m_pBitmapInfo->bmiHeader.biBitCount = 8;//8位格式
m_pBitmapInfo->bmiHeader.biCompression = 0;
m_pBitmapInfo->bmiHeader.biSizeImage = 0;
m_pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
m_pBitmapInfo->bmiHeader.biClrUsed = 0;
m_pBitmapInfo->bmiHeader.biClrImportant = 0;
m_pBitmapInfo->bmiHeader.biWidth = 0;
m_pBitmapInfo->bmiHeader.biHeight = 0;
}
///从一个采集卡里获得宽度,高度和每行字节数信息,应该没有错,因为图像能够显示。
void CMyDoc::GetBitmapInfo()
{
int SizeX=GetCurrentCamera()->GetImageWidth();//宽度
int SizeY=GetCurrentCamera()->GetImageHeight();//高度
int Bitys=GetCurrentCamera()->GetImageBytes();//每行字节数
m_pBitmapInfo->bmiHeader.biWidth = Bitys / ( m_pBitmapInfo->bmiHeader.biBitCount / 8); // Width = Pitch(bytes) divided by the number of bytes per pixel
m_pBitmapInfo->bmiHeader.biHeight = -SizeY ;
}
//这是一个按钮的相应函数,希望点击后存下图像,图像是存了,可以打开时警告: 图像必须大于一个像素,打开后,里面什么也没有,就是说一个像素都没有存上,为什么呢。
void CMyDoc::OnGrab()
{
int size=0-m_pBitmapInfo->bmiHeader.biWidth*m_pBitmapInfo->bmiHeader.biHeight;//因为是8位,就直接相乘了
m_pBitmapInfo->bmiHeader.biSizeImage = size; BITMAPFILEHEADER bfh; //这是文件头
bfh.bfReserved1=bfh.bfReserved2=0;
bfh.bfType=((WORD)('M'<< 8)|'B');
bfh.bfSize=54+256*sizeof(RGBQUAD)+m_pBitmapInfo->bmiHeader.biSizeImage;
bfh.bfOffBits=54+256*sizeof(RGBQUAD);
RGBQUAD rgbq[256];
for(int i=0;i<256;i++)
{
rgbq[i].rgbBlue=i;
rgbq[i].rgbGreen=i;
rgbq[i].rgbRed=i;
rgbq[i].rgbReserved=0;
}//从图像采集卡的得到的是裸的8位图像的数据地址,我想以灰度图显示,就自己写了一个颜色板。
CString name = "C:\\picttest.bmp";
CFile bf;
if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)){
bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
bf.WriteHuge(&m_pBitmapInfo->bmiHeader,sizeof(BITMAPINFOHEADER));
bf.WriteHuge(rgbq,256*sizeof(RGBQUAD));
bf.WriteHuge(GetCurrentCamera()->GetImagePlace(),size); //这个写入的是像素的地址,应该也没有错,因为显示的时候,放入SetDibToDevice的就是GetCurrentCamera()->GetImagePlace()
bf.Close();
}
}
--------
零减?这个size是负数吗?信息头的填充没有在这个函数中,所以不知道有没有问题,别的我觉得没太大的出入。你可以调试一下,看看
bf.WriteHuge(GetCurrentCamera()->GetImagePlace(),size);
这个函数的返回值是多少,是不是图像像素总字节数的大小。我这里有一个以前写的测试函数,它是自定义一个数组,并以数组的内的值为像素值存成一个灰度位图。可以加在任意一个按钮响应函数中。你可以参考一下。void CXXXDlg::OnButton2()
{
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
// TODO: Add your control notification handler code here
int i,j; BYTE* m_bitData=new BYTE[800*600];
ZeroMemory((void*)m_bitData, 800*600); for (i=0; i<600; i++)
{
for(j=0; j<800; j++)
{
m_bitData[i*800+j]=255*i/600;
}
}
LONG lWidth=800;
LONG lHeight=600;
LPBITMAPINFO lpbmi;
// BMP文件头的句柄
HANDLE hBmpFileHead;
//计算信息头和调色板的大小
hBmpFileHead=::GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)
+ sizeof(RGBQUAD)
* 256);
if(hBmpFileHead==0)
{
AfxMessageBox("分配内存失败");
return;
}
//填充信息头
lpbmi=(LPBITMAPINFO)::GlobalLock((HGLOBAL)hBmpFileHead); lpbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpbmi->bmiHeader.biWidth=lWidth;
lpbmi->bmiHeader.biHeight=lHeight;
lpbmi->bmiHeader.biPlanes=1;
lpbmi->bmiHeader.biBitCount=8;
lpbmi->bmiHeader.biCompression=BI_RGB;
lpbmi->bmiHeader.biSizeImage=WIDTHBYTES(lWidth*8)*lHeight;
lpbmi->bmiHeader.biXPelsPerMeter=0;
lpbmi->bmiHeader.biYPelsPerMeter=0;
lpbmi->bmiHeader.biClrUsed=256;
lpbmi->bmiHeader.biClrImportant=256; //填充256级灰度调色板
//int i,j;
for( i=0;i<256;i++)
{
lpbmi->bmiColors[i].rgbBlue=i;
lpbmi->bmiColors[i].rgbGreen=i;
lpbmi->bmiColors[i].rgbRed=i;
lpbmi->bmiColors[i].rgbReserved=0;
} //填充文件头
BITMAPFILEHEADER bmfHeader;
ZeroMemory(&bmfHeader,sizeof(bmfHeader));
bmfHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+ sizeof(RGBQUAD) * 256;
bmfHeader.bfSize=lpbmi->bmiHeader.biSizeImage+bmfHeader.bfOffBits;
bmfHeader.bfType='MB'; BYTE* pBits=new BYTE[lpbmi->bmiHeader.biSizeImage];
ZeroMemory((void*)pBits, lpbmi->bmiHeader.biSizeImage);
for (i=0; i<lHeight; i++)
{
for (j=0; j<lWidth;j++)
{
pBits[WIDTHBYTES(lWidth*8)*(lHeight-1-i)+j]=m_bitData[i*lWidth+j];
}
}
CString str="c:\\test1.bmp";
HANDLE hFile=CreateFile(str,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dwRet=0;
WriteFile(hFile,&bmfHeader,sizeof(bmfHeader),&dwRet,NULL);
WriteFile(hFile,&lpbmi->bmiHeader,sizeof(lpbmi->bmiHeader),&dwRet,NULL);
WriteFile(hFile,&lpbmi->bmiColors[0],sizeof(RGBQUAD) * 256,&dwRet,NULL);
WriteFile(hFile,pBits,lpbmi->bmiHeader.biSizeImage,&dwRet,NULL);
CloseHandle(hFile);
}
delete[] pBits;
delete[] m_bitData;
::GlobalUnlock((HGLOBAL)hBmpFileHead);
::GlobalFree((HGLOBAL) hBmpFileHead);
}