HDC hDC = ::GetDC(NULL);
HDC hMemDC = CreateCompatibleDC(hDC);HBITMAP hBitmap = CreateCompatibleBitmap(hDC,200,200);
SelectObject(hMemDC,hBitmap);
BitBlt(hMemDC,0,0,
200,200,
hDC,
100,100,
SRCCOPY);
BITMAP bmp;
GetObject(hBitmap,sizeof(BITMAP),&(bmp));bmp.bmBitsPixel =8;BITMAPINFOHEADER bmpH;
bmpH.biSize = sizeof(BITMAPINFOHEADER);
bmpH.biWidth = bmp.bmWidth;
bmpH.biHeight = bmp.bmHeight;
bmpH.biPlanes = 1;
bmpH.biBitCount = (WORD)bmp.bmPlanes * (WORD)bmp.bmBitsPixel;
bmpH.biCompression = BI_RGB;
bmpH.biSizeImage = 0;
bmpH.biXPelsPerMeter = 0;
bmpH.biYPelsPerMeter = 0;
bmpH.biClrUsed = 0;
bmpH.biClrImportant = 0;DWORD dwSize = bmp.bmWidth * bmp.bmHeight * bmpH.biBitCount / 8;buff = new BYTE[dwSize];
GetDIBits(hDC,hBitmap,0,bmp.bmHeight,buff,(BITMAPINFO *)&bmpH,DIB_RGB_COLORS);
运行到红色代码的时候,bmp.bmBitsPixel 的值是24,也就是每个像素点占24位,3个字节,想改变bmp.bmBitsPixel 的值,使获取的图像信息的灰度或者叫分辨率小一点,但这样不行。
求哪位高手帮忙怎么改,或者给个实现方案也行。。

解决方案 »

  1.   

    24位RGB转化为8位灰度的公式为 gray = (R*30+G*59+B*11)/100
    /********************************************************************
    //函数名称:void COpenBmpView::OnBitmapGray()
    //功能: 24位真彩色位图灰度化处理
    *********************************************************************/
    void COpenBmpView::OnBitmapGray()  
    {
    // TODO: Add your command handler code here  UpdateData();
      if(m_sourcefile==""||m_target_Grayfile=="")
      return;  
      FILE *sourcefile,*targetfile;
    //位图文件头和信息头
      BITMAPFILEHEADER sourcefileheader,targetfileheader;
      BITMAPINFOHEADER sourceinfoheader,targetinfoheader;
      memset(&targetfileheader,0,sizeof(BITMAPFILEHEADER));
      memset(&targetinfoheader,0,sizeof(BITMAPINFOHEADER));  sourcefile=fopen(m_sourcefile,"rb"); //以二进制形式读文件
      fread((void*)&sourcefileheader,1,sizeof(BITMAPFILEHEADER),sourcefile);//提取原图文件头
      if(sourcefileheader.bfType!=0x4d42)

      fclose(sourcefile);
      MessageBox("原图象不为BMP图象!");
      return;
    }
      fread((void*)&sourceinfoheader,1,sizeof(BITMAPINFOHEADER),sourcefile);//提取文件信息头
      if(sourceinfoheader.biBitCount!=24)
    {
      fclose(sourcefile);
      MessageBox("原图象不为24位真彩色!");
      return;
    }
      if(sourceinfoheader.biCompression!=BI_RGB)
    {
      fclose(sourcefile);
      MessageBox("原图象为压缩后的图象,本程序不处理压缩过的图象!");
      return;
    }//构造灰度图的文件头
      targetfileheader.bfOffBits=54+sizeof(RGBQUAD)*256;
      targetfileheader.bfSize=targetfileheader.bfOffBits+sourceinfoheader.biSizeImage/3;
      targetfileheader.bfReserved1=0;
      targetfileheader.bfReserved2=0;
      targetfileheader.bfType=0x4d42;//构造灰度图的信息头
      targetinfoheader.biBitCount=8;
      targetinfoheader.biSize=40;
      targetinfoheader.biHeight=sourceinfoheader.biHeight;
      targetinfoheader.biWidth=sourceinfoheader.biWidth;
      targetinfoheader.biPlanes=1;
      targetinfoheader.biCompression=BI_RGB;
      targetinfoheader.biSizeImage=sourceinfoheader.biSizeImage/3;
      targetinfoheader.biXPelsPerMeter=sourceinfoheader.biXPelsPerMeter;
      targetinfoheader.biYPelsPerMeter=sourceinfoheader.biYPelsPerMeter;
      targetinfoheader.biClrImportant=0;
      targetinfoheader.biClrUsed=256;//构造灰度图的调色板  RGBQUAD rgbquad[256];
      int i,j,m,n,k;
      for(i=0;i<256;i++)
    {
      rgbquad[i].rgbBlue=i;
      rgbquad[i].rgbGreen=i;
      rgbquad[i].rgbRed=i;
      rgbquad[i].rgbReserved=0;
    }
      targetfile=fopen(m_target_Grayfile,"wb");//写入灰度图的文件头,信息头和调色板信息
      fwrite((void*)&targetfileheader,1,sizeof(BITMAPFILEHEADER),targetfile);
      fwrite((void*)&targetinfoheader,1,sizeof(BITMAPINFOHEADER),targetfile);
      fwrite((void*)&rgbquad,1,sizeof(RGBQUAD)*256,targetfile);
      BYTE* sourcebuf;
      BYTE* targetbuf;//这里是因为BMP规定保存时长度和宽度必须是4的整数倍,如果不是则要补足
      m=(targetinfoheader.biWidth/4)*4;
      if(m<targetinfoheader.biWidth)
      m=m+4;  n=(targetinfoheader.biHeight/4)*4;
      if(n<targetinfoheader.biHeight)
      n=n+4;  sourcebuf=(BYTE*)malloc(m*n*3);//读取原图的颜色矩阵信息
      fread(sourcebuf,1,m*n*3,sourcefile);
      fclose(sourcefile);
      targetbuf=(BYTE*)malloc(m*n);
      BYTE color[3];   //通过原图颜色矩阵信息得到灰度图的矩阵信息
      for(i=0;i<n;i++)
    {
    for(j=0;j<m;j++)
    {  
    for(k=0; k<3; k++)   
    color[k]=sourcebuf[(i*m+j)*3+k];targetbuf[(i*m)+j]=color[0]*0.114+color[1]*0.587+color[2]*0.299;   
    if(targetbuf[(i*m)+j]>255)
    targetbuf[(i*m)+j]=255;
    }
    }  
      fwrite((void*)targetbuf,1,m*n+1,targetfile);
    fclose(targetfile);
      MessageBox("位图文件转换成功!");
      
      Invalidate(TRUE); //重绘
    }
      

  2.   

    你也就是想把24位真彩图像转换为 8位的灰度图像吧,这样转换后确实文件会小,因为RGB 都存储在颜色索引表了,像素数据段只是存储了在这个颜色索引表里的索引号而已,只要8位也就是一个字节就可以存储了。至于转换方法,楼上的可以。
      

  3.   

    要想改变每一个象素占用的位数不能仅仅改变bmBitsPixel 值,象素信息也得改变,有时候(就像你这个要将24位位图转换为8位位图)还要修改调色板
      

  4.   

    彩色转灰度,opencv的cvCvtcolor函数即可实现
      

  5.   

    你把不同类型的位图格式弄清楚了就不存在这个问题了。好像没有现成的API函数提供,都是别人写的。