?
Solved

HBITMAP Color->GrayScale

Posted on 2001-07-30
8
Medium Priority
?
1,308 Views
Last Modified: 2013-12-03
Hi, How do I convert a HBITMAP in Colors to GrayScale, or black & white bitmap ?

CB.
0
Comment
Question by:win32
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
8 Comments
 

Author Comment

by:win32
ID: 6333741
Please people, I am waiting for your answer!
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 6333886
Hi win32,

to simply convert it you can create a DDB as shown at http://www.codeguru.com/bitmap/dib_to_ddb.shtml ... this code uses MFC but it shouldn't be too hard to do the same in pure Win32 API.

Other helpful link maybe this: http://www.codeguru.com/bitmap/ChangingColorDepth.html

hope that helps,

ZOPPO
0
 

Author Comment

by:win32
ID: 6333976
What I realy need is somthing like a LoadDIImage() function, how is that made ?
0
NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

 

Author Comment

by:win32
ID: 6334004
Can't you mail me the code at codeguro man, my internet Cant connect to the site at the moment...

cb_priv@hotmail.com
0
 
LVL 31

Accepted Solution

by:
Zoppo earned 800 total points
ID: 6334048
This is from http://www.codeguru.com/bitmap/dib_to_ddb.shtml :
-----------------------------------------------------------------------------------------------------------------
You can render a device-independent bitmap (DIB) onto a device without having to convert it into a device-dependent bitmap (DDB). However, the
                      process is slower when using a DIB and you also don't have access to few very versatile functions such as BitBlt() which handle only DDBs.

                      The basic steps involved in creating a device-dependent bitmap from a device-independent bitmap are:

                        1.Create a logical palette from the information in the DIB color table. You need to do this only if the device supports palettes. To create the palette,
                           allocate enough memory for a LOGPALETTE structure with memory for the color table as well. Initialize the palVersion and palNumEntries fields
                           and copy the color values from the color table in the DIB. Then call CreatePalette() using the LOGPALETTE structure we initialized.
                        2.Select the logical palette into the device for which we are creating the DDB, then realize the palette.
                        3.Create the DDB using the CreateDIBitmap() function.
                        4.Don't forget to release any memory allocated for the LOGPALETTE structure.

                      Although this function creates a logical palette, it doesn't return this information to the calling code. If the DIB represents a 256 color bitmap and the device
                      supports only 256 colors, then rendering the DDB onto the device will probably not result in the proper image. That's because the system palette colors may
                      not match the colors that are being used by the bitmap. You may, therefore, want to modify the function so that it returns the logical palette as well. You
                      would have to select and realize this palette onto the device context before drawing the bitmap image.


                      HBITMAP DIBToDDB( HANDLE hDIB )
                      {
                              LPBITMAPINFOHEADER      lpbi;
                              HBITMAP                 hbm;
                              CPalette                pal;
                              CPalette*               pOldPal;
                              CClientDC               dc(NULL);

                              if (hDIB == NULL)
                                      return NULL;

                              lpbi = (LPBITMAPINFOHEADER)hDIB;

                              int nColors = lpbi->biClrUsed ? lpbi->biClrUsed :
                                                                      1 << lpbi->biBitCount;

                              BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
                              LPVOID lpDIBBits;
                              if( bmInfo.bmiHeader.biBitCount > 8 )
                                      lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
                                              bmInfo.bmiHeader.biClrUsed) +
                                              ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
                              else
                                      lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);

                              // Create and select a logical palette if needed
                              if( nColors <= 256 && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
                              {
                                      UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
                                      LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

                                      pLP->palVersion = 0x300;
                                      pLP->palNumEntries = nColors;

                                      for( int i=0; i < nColors; i++)
                                      {
                                              pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
                                              pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
                                              pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
                                              pLP->palPalEntry[i].peFlags = 0;
                                      }

                                      pal.CreatePalette( pLP );

                                      delete[] pLP;

                                      // Select and realize the palette
                                      pOldPal = dc.SelectPalette( &pal, FALSE );
                                      dc.RealizePalette();
                              }

                             
                              hbm = CreateDIBitmap(dc.GetSafeHdc(),           // handle to device context
                                              (LPBITMAPINFOHEADER)lpbi,       // pointer to bitmap info header
                                              (LONG)CBM_INIT,                 // initialization flag
                                              lpDIBBits,                      // pointer to initialization data
                                              (LPBITMAPINFO)lpbi,             // pointer to bitmap info
                                              DIB_RGB_COLORS );               // color-data usage

                              if (pal.GetSafeHandle())
                                      dc.SelectPalette(pOldPal,FALSE);

                              return hbm;
                      }
-----------------------------------------------------------------------------------------------------------------

The other one can be downloaded from http://www.codeguru.com/bitmap/ChangingColorDepth_src.zip ... if you can't donwload it either you can post me your email and I send you the zip-file as attachement.

ZOPPO
0
 

Author Comment

by:win32
ID: 6337254
That might work fine. I wanna explain my problem more carefully!
My problem is that I want to print a color bitmap. Naturaly my SelectObject function failes if I try to print the color bitmap to a printer that don't have color support. That is a problem, I am not realy sure of the best way to solve the problem so I'll give you my code, then hopfully you can tell me:

I get a DC from the printer when i init the PrintDialog

CODE LOKKS LIKE THIS:
...

BOOL PrintBitMap(HDC hdcPrinter)
HBITMAP hbmp, holdbmp;
BITMAP bm;
HDC hMemDC;

if (hdcPrinter)// hdc from the printer
 hMemDC = CreateCompatibleDC(hdcPrinter);
hbmp = (HBITMAP) LoadImage(hInstPrint,
              MAKEINTRESOURCE(iResID),
           IMAGE_BITMAP,                                 iResW,
           (iResH == -1 ? iH : iResH),
            LR_CREATEDIBSECTION);

// The LoadBmp has always success
if (hbmp != NULL)
  {
    GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bm);
    holdbmp = (HBITMAP)SelectObject(hMemDC, hbmp);
/* SelectObject failes if the DC for the printer and the Bitmap does not fit. That is the problem, printer HDC can't alwayes take my bitmap!! */

    StretchBlt(hdcContext, X, Y, iW*iS*iFontScale,
                                 iH*iS*iFontScale,
                                 hMemDC,
                     iW*iI,                                0,
                     iW,                                     iH,                                     SRCCOPY);  
         
    DeleteDC(hMemDC);
    DeleteObject(hbmp);

    return true;
  }
  DeleteDC(hMemDC);

  return false;
}
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 6339946
Well, you can try to create the memDC as not compatible to the printerDC but i.e. to a temporary created, none-monochrome ScreenDC or a TrueColorDC, since StretchBlt will convert the colors/bitsPerPixel as needed.
0
 

Author Comment

by:win32
ID: 6407208
Ok, you are telling me that HDC's can't alwayes take BMP's How do I know that, Can you tell me how I can see if a HDC can take a bitmap ?
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question