本文介绍了CBitmap :: CreateBitmap:如何!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法使用 CBitmap :: CreateBitmap(int nWidth,int nHeight,UINT nPlanes,UINT nBitcount,const void * lpBits)创建CBitmap对象;



如何从 RGB 中的现有指针初始化并填充 lpBits 指针BITMAP



这样做的目的是从RGB构建灰度位图



我这样做会导致错误编译

I am unable to create a CBitmap object using CBitmap::CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits);

How to initialize and fill up the lpBits pointer from an existing one in an RGB BITMAP

The purpose of this is to build a Grayscale Bitmap from an RGB one

I did this which compiles with errors

...
CBitmap bmpRGB; // this is the input RGB bitmap
CBitmap bmpGray; // this will be the output one

BITMAP bm;
bmpRGB.GetBitmap(&bm);

LPBYTE lpBits = new BYTE[bm.bmHeight * bm.bmWidth];

bmpGray.CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 8, lpBits);

BYTE R, G, B;

for (long i = 0; i < bm.bmHeight * bm.bmWidth; i ++)
{
   R = GetRValue((DWORD)bm.bmBits[i]);
   G = GetGValue((DWORD)bm.bmBits[i]);
   B = GetBValue((DWORD)bm.bmBits[i]);

   lpBits[i] = (BYTE)(0.2989 * R + 0.5870 * G + 0.1140 * B);
}
...





我做错了代码!?



请帮助我这样做;



Im I doing the wrong code !?

Help me please to do that;

推荐答案


// Bitmap information + palette information
struct CUSTOM_BITMAPINFO
{
   // bitmap information
   BITMAPINFOHEADER bmiHeader;
   /// A 256 colors palette
   RGBQUAD bmiColors[256];
};
//saves an 8 bits-per-pixel image with a gray-scaled palette
BOOL SaveGrayScale(const BYTE* image, int width, int height, LPCTSTR fileName)
{
   //fullwidth must be multiple of 4
   int fullWidth = (width + 3) & 0xfffffffc;
   //copy each scan line in a temporary buffer
   BYTE* bytes = new BYTE[fullWidth * height];
   for (int i = 0; i < height; i++)
      CopyMemory(bytes + i * fullWidth, image + i * width, width);
   //BMP header
   BITMAPFILEHEADER header;
   ZeroMemory(&header, sizeof(BITMAPFILEHEADER));
   header.bfType = ((WORD) ('M' << 8) | 'B');
   header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(CUSTOM_BITMAPINFO) + fullWidth * height;
   header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(CUSTOM_BITMAPINFO); 
   //Bitmap information
   CUSTOM_BITMAPINFO bitmapInfo;
   ZeroMemory(&bitmapInfo, sizeof(CUSTOM_BITMAPINFO));
   bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   bitmapInfo.bmiHeader.biPlanes = 1;	
   bitmapInfo.bmiHeader.biBitCount = 8;
   bitmapInfo.bmiHeader.biCompression = BI_RGB;
   bitmapInfo.bmiHeader.biSizeImage = 0;
   bitmapInfo.bmiHeader.biWidth = width;
   //negative height for a top-down bitmap
   bitmapInfo.bmiHeader.biHeight = -height;
   //create the gray scale palette
   for (int i = 0; i < 256; i++)
   {
      bitmapInfo.bmiColors[i].rgbRed = 0;
      bitmapInfo.bmiColors[i].rgbGreen = 0;
      bitmapInfo.bmiColors[i].rgbBlue = i;
      bitmapInfo.bmiColors[i].rgbReserved = 0;
   }
   //save the image
   HANDLE hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
   if (hFile == INVALID_HANDLE_VALUE)
   {
      delete [] bytes;
      return FALSE;
   }
   DWORD writtenBytes = 0;
   if ( !WriteFile(hFile, &header, sizeof(BITMAPFILEHEADER), &writtenBytes, NULL) || writtenBytes != sizeof(BITMAPFILEHEADER)
     || !WriteFile(hFile, &bitmapInfo, sizeof(CUSTOM_BITMAPINFO), &writtenBytes, NULL) || writtenBytes != sizeof(CUSTOM_BITMAPINFO)
     || !WriteFile(hFile, bytes, fullWidth * height, &writtenBytes, NULL) || writtenBytes != fullWidth * height)
   {
      delete [] bytes;
      CloseHandle(hFile);
      return FALSE;
   }
   CloseHandle(hFile);
   return TRUE;
}
//simple test function
void Test()
{
   int width = 199;
   int height = 200;
   BYTE* image = new BYTE[width * height];
   for (int y = 0; y < height; y++)
      for (int x = 0; x < width; x++)
	   image[y * width + x] = x;
   SaveGrayScale(image, width, height, "c:\\test.bmp");
   delete [] image;
}





从现有位图获取信息:



To get the information from an existing bitmap:

CBitmap bitmap;
...
BITMAP bmp;
bitmap.GetBitmap(&bmp);
int width = bmp.bmWidth;
int height = bmp.bmHeight;
int fullWidth = (width + 3) & 0xfffffffc;
BYTE* bytes = (BYTE*)bmp.bmBits;
...


void CChildView::OnPaint() 
{
  CPaintDC dc(this);
  
  BITMAP    bmp;
  // get the bitmap dimensions for bitblt
  if(_bmp_grey.m_hObject && _bmp_grey.GetObject(sizeof(bmp),&bmp))
  {
    CDC          mdc; mdc.CreateCompatibleDC(&dc);
    HGDIOBJ      obm = mdc.SelectObject(_bmp_grey);
    // draw the bitmap
    dc.BitBlt(0,0,bmp.bmWidth,bmp.bmHeight,&mdc,0,0,SRCCOPY);
    mdc.SelectObject(obm);
  }
}

CChildView::CChildView()
{
  _bmp.LoadBitmap(1); // load from resource
  ToGrey(_bmp,_bmp_grey,8); // convert to grey
}

void CChildView::ToGrey(CBitmap& color,CBitmap& grey,unsigned int bitspixel)
{
  BITMAP    bmp;
  // get the bitmap dimensions
  if(color.m_hObject && color.GetObject(sizeof(bmp),&bmp))
  {
    BITMAP          bmpg = bmp;
    unsigned int    bpls = bmp.bmWidthBytes; // bytes per line source
    unsigned int    bpld; // bytes per line dest
    unsigned int    bpps,bppd; // bytes per pixel source/dest
    unsigned char*  lps; // source bitmap buffer
    unsigned char*  lpd; // dest bitmap buffer
    unsigned char*  lines; // current line source
    unsigned char*  lined; // current line dest
    unsigned char*  linee; // line end pointer
    unsigned char*  lpps; // pixel pointer source
    unsigned char*  lppd; // pixel pointer dest
    unsigned char*  lppe; // end of line source
    
    double          ar[256]; // map table for grey values corresponding to the rgb (byte) value
    double          ag[256];
    double          ab[256];
    unsigned int    ix; // index

    // bitmap info structure to create dib bitmap
    // including palette
    BITMAPINFO*      bmig = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+(sizeof(RGBQUAD)*256)); if(!bmig) return;

    // fill 0
    memset(bmig->bmiColors,0,sizeof(RGBQUAD)*256);
    // create color mapping tables
    for(ix=0;ix<256;ix++) ar[ix] = 0.2989 * ix;
    for(ix=0;ix<256;ix++) ag[ix] = 0.5870 * ix;
    for(ix=0;ix<256;ix++) ab[ix] = 0.1140 * ix;
    // create grey scale palette
    for(ix=0;ix<256;ix++) bmig->bmiColors[ix].rgbBlue = bmig->bmiColors[ix].rgbGreen = bmig->bmiColors[ix].rgbRed = ix;

    // allocating buffer for the source bitmap bits
    lps = (unsigned char*)malloc(bpls * bmp.bmHeight);
    if(lps) // only go a head on existing buffer
    {
      bmpg.bmBitsPixel = bitspixel; // set the pixel width in bits (only 8,24,32 in this demo)
      // calculating the line width in bytes for the gray bitmap
      bmpg.bmWidthBytes = bpld = ((((bmpg.bmWidth*bmpg.bmBitsPixel)+7)>>3) + 3) & ~3;
   
      // inittializing the bitmap info header
      bmig->bmiHeader.biSize          = sizeof(BITMAPINFO);
      bmig->bmiHeader.biWidth         = bmpg.bmWidth;
      bmig->bmiHeader.biHeight        = bmpg.bmHeight;
      bmig->bmiHeader.biPlanes        = 1;
      bmig->bmiHeader.biBitCount      = bmpg.bmBitsPixel;
      bmig->bmiHeader.biCompression   = 0;
      bmig->bmiHeader.biSizeImage     = bmpg.bmWidthBytes * bmpg.bmHeight;
      bmig->bmiHeader.biXPelsPerMeter = 0;
      bmig->bmiHeader.biYPelsPerMeter = 0;
      bmig->bmiHeader.biClrUsed       = 256;
      bmig->bmiHeader.biClrImportant  = 0;

      // allocating the bitmap buffer for the grey bitmap
      lpd = (unsigned char*)malloc(bpld * bmpg.bmHeight);
      if(lpd) // continue only if you got the buffer
      {
        // get the bitmap bits from your original bitmap
        color.GetBitmapBits(bpls * bmp.bmHeight,lps);

        lines = lps; lined = lpd;
        // distinguish between the different bitmap resolutions
        // only valid for true color 24 or 32 bits per pixel
        switch(bmp.bmBitsPixel)
        {
          case 24:
          case 32:
            bpps = bmp.bmBitsPixel>>3;
            switch(bmpg.bmBitsPixel)
            {
              case  8:
                // this section makes a bitmap based on palette
                // loop through every line in source bitmap
                for(linee=lps+(bpls*bmp.bmHeight);lines<linee;lines+=bpls,lined+=bpld)
                {
                  // start of the line, set the pointers for source and dest
                  lpps = lines; lppd = lined;
                  // loop through the pixels in one line
                  for(lppe=lines+bpls;lpps<lppe;lpps+=bpps,lppd+=1)
                  {
                    // accumulete the pixel value by table and cast it to 8bit palette index
                    *lppd = (unsigned char)(ar[lpps[2]]+ag[lpps[1]]+ab[lpps[0]]);
                  }
                }
              break;
              case  24:
              case  32:
                // this section creates a bitmap with rgb values
                bppd = bmpg.bmBitsPixel>>3;
                // loop through every line in source bitmap
                for(linee=lps+(bpls*bmp.bmHeight);lines<linee;lines+=bpls,lined+=bpld)
                {
                  lpps = lines; lppd = lined;
                  // loop through the pixels in one line
                  for(lppe=lines+bpls;lpps<lppe;lpps+=bpps,lppd+=bppd)
                  {
                    // set rgb values to grey value
                    lppd[0] =
                    lppd[1] =
                    lppd[2] = (unsigned char)(ar[lpps[2]]+ag[lpps[1]]+ab[lpps[0]]);
                  }
                }
              break;
              default: ASSERT(0); /*not implemented*/ break;
          }
          break;
          default: ASSERT(0); /*not implemented*/ break;
        }

        // create the grey bitmap
        // usually the CreateBitmap functions are obsolet, thats why the bitmap is device dependant
        // that means if your screen resolution is 32-bit with this functions you can
        // only create 32-bit bitmaps
        // if you have 256 color resolution you only can create palette based bitmaps
        // oh yes i remember to the good old win 3.0 times
        switch(bmpg.bmBitsPixel)
        {
          case 8:
          {
            HDC    hdc = ::GetDC(0);
            bmig->bmiHeader.biClrImportant = 256;
            // you should use always this function
            // DIB stands for device independant bitmap
            grey.Attach(CreateDIBitmap(hdc,&bmig->bmiHeader,CBM_INIT,lpd,bmig,DIB_RGB_COLORS));
            ::ReleaseDC(0,hdc);
          }
          break;
          default:
            // this function creates a device dependant bitmap
            // you should never use that!
            // this function will fail if your screen resolution is 256 or hicolor (16-bit)
            grey.CreateBitmapIndirect(&bmpg); // create the bitmap
            grey.SetBitmapBits(bpld * bmpg.bmHeight,lpd); // apply the bitmap bits
          break;
        }
        free(lpd); // free the buffer
      }
      free(lps); // free the buffer
    }
    free(bmig); // free the buffer
  }
}



祝你好运。


Good luck.


这篇关于CBitmap :: CreateBitmap:如何!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 00:58