Click here to Skip to main content
15,867,771 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
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;
Posted
Updated 20-Apr-11 6:27am
v2
Comments
CPallini 20-Apr-11 5:31am    
What are the 'compiler errors'?
Mr. Tomay 20-Apr-11 12:35pm    
I have corrected the compiler error issue which was that it can not cast from void * to unsigned char *
I am facing other problems now (the output gray bitmap is not showing)
mbue 20-Apr-11 12:52pm    
What a cryptic calculation for the grey value. Why you dont calc it by: (r+g+b)/3 (or predefined table - faster)?
You should not cast the rgb-values in the plane itselves to a COLORREF value. Every byte in the plane represents r,g, and b. shure only in 8-bit deepth color bitmaps (but its true windows doesnt support 16-bit color deepth).
Regards.
mbue 22-Apr-11 6:32am    
lol ;-) calculations for NeverTheSameColor (ntsc format).

This article contains a few useful things about bitmaps in MFC. Have a look to the GrayImage method.
Add fast user-extensible image processing support to CBitmap[^]
 
Share this answer
 
To create and save a Grayscale image, you can do something like that:

C++
// 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;
...
 
Share this answer
 
v2
Comments
Mr. Tomay 21-Apr-11 17:25pm    
I'll test it
Its a long way:
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.
 
Share this answer
 
v2
Comments
Mr. Tomay 22-Apr-11 13:37pm    
I'll test it (its missing comments to understand)
mbue 22-Apr-11 14:47pm    
Well ive updated the code with comments. ive spent more time for the comments than for the code.
btw: i dont understand why the comments arent green.
Regards.
Mr. Tomay 23-Apr-11 12:22pm    
Well done mbue, it's working great except one thing: the bitmap is drawn flipped vertically. I've fixed this issue:
bmig->bmiHeader.biHeight = bmpg.bmHeight;
should be:
bmig->bmiHeader.biHeight = -bmpg.bmHeight;

without you I am lost ;)
You need to make sure all scan lines are WORD aligned. Which means you might have to do some padding depending on your bm.bmWidth. (It has to be an even number.)
C++
// Round up if needed
int width = (bm.bmWidth % 2 == 0 ? bm.bmWidth : bm.bmWidth + 1);

// Create buffer
LPBYTE lpBits = new BYTE[bm.bmHeight * width];

// Init scan lines here with added logic for the padding byte if applicable


Edit: Another issue might be with how you get values from the color bitmap. Your code, in the for loop, assumes 8-bit values since you're indexing on byte level.
 
Share this answer
 
v2
Comments
mbue 20-Apr-11 12:46pm    
No! All scan lines are DWORD (4-bytes) aligned.
You cannot use a modified width - you you have to use bytes-per-line with 4-bytes boundary to get the next line.
Regards.
Niklas L 20-Apr-11 13:44pm    
From MSDN on CreateBitmap():
"lpvBits [in]

A pointer to an array of color data used to set the colors in a rectangle of pixels. Each scan line in the rectangle must be word aligned (scan lines that are not word aligned must be padded with zeros). If this parameter is NULL, the contents of the new bitmap is undefined.
"
mbue 20-Apr-11 13:54pm    
Congratulations, but this isnt true. Every bitmap beginnig from 1-bit color deepth is DWORD aligned.
Regards.
Niklas L 20-Apr-11 14:45pm    
So what do you use to back that up? There are plenty more statements on MSDN claiming 16 bit alignment for up to 16 bits per pixel. Hera are a few: http://msdn.microsoft.com/en-us/library/k1sf4cx2.aspx

Also, you state that he cannot use a modified width. In fact he has to, and since you claim DWORD alignment, even more so. What if his original bitmap is 3 pixels wide? He can't use 3 bytes per scan line, as will be the case if he doesn't modify the width. Have a look at how he allocates the pixel buffer.

Notice that he uses two separate bitmaps.
mbue 20-Apr-11 15:03pm    
You wont understand!? Since windows 3.0 EVERY line of bitmap bits (palette or rgb) MUST be padded do DWORD length in bytes. i.e. try to load 299 pixel width (24-bit rgb) bitmap (that remains 1 byte) with "your" word padding or with dword (4-byte) padding. What will you see?
btw: i must not read any m$ statements its my experience!
There is no difference between the bitmaps cause the grey bitmap is created by the values of the original bitmap. take a look at the op's posted code.
Regards.
I have created 3 Gray test images using GIMP, & I found that it is possible to create Gray scale images using 3 different modes "RGB mode & Grayscale mode & Indexed mode" take a look at this screenshot:

& the result looks the same, but actually they have different file sizes, here are the 3 images:
RGB mode

Grayscale mode

Indexed mode


& I found that the Grayscale mode is the most fit because is uses only 8 bits (BYTE) to define a pixel
all I want is how to make such a kind of images (Grayscale mode) from an existing Bitmap !?
 
Share this answer
 
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
}
}
 
Share this answer
 
v2
Comments
mbue 23-Apr-11 7:16am    
??? Why did you post my code again? Is there something wrong?
C++
...
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*sizeof(DWORD)];
 

 
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]);

   R*=0.2989 ;
   G*=0.5870 ;
   B*=0.1140;
 
   lpBits[i] = RGB(R,G,B);
}

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


The code comes next is completely wrong, because you have to add color values to each other after you shift green and blue (<<8), (<<16), respectivelly

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


to solve it just use the MACRO RGB();
the bitmap here is 32 bpp, to avoid dealing with palette;
 
Share this answer
 
Comments
Richard MacCutchan 24-Feb-15 12:05pm    
This question is nearly four years old!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900