共有三个函数与之相关:
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();   
          }   
}

解决方案 »

  1.   

    int size=0-m_pBitmapInfo->bmiHeader.biWidth*m_pBitmapInfo->bmiHeader.biHeight;
    --------
    零减?这个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);
    }
      

  2.   

    m_pBitmapInfo->bmiHeader.biHeight是由采集卡的库函数得出的,得出的是负值,对照你的程序,我的颜色板好像没有传到结构里面去,另外清零可能也是个问题,明天到机子上修改一下,多谢  草莓猪