How to convert a bitmap to shades of gray by pixel intensity using GDI?

I'm looking for a simple solution to convert a 32-bit bitmap to grayscale using GDI (not GDI +). Is it possible, for example, by changing the raster palette or something else?

Of course, there are many examples in Delphi, like this one , but I'm looking for a WinAPI function that will do this without iterating through lines.

+7
source share
2 answers

I have not found any GDI function that does this. The easiest way, as David said in his comment, is to scan each line and calculate the colors of the pixels. You are probably looking for a luminance formula.

There are several variations of this formula, and in the following example I used the one recommended by ITU , see this document section 2.5.1. As I found somewhere, this formula is used, for example. even using the famous Adobe Photoshop. The following code example only supports and expects 24-bit bitmaps as input:

 procedure BitmapGrayscale(ABitmap: TBitmap); type PPixelRec = ^TPixelRec; TPixelRec = packed record B: Byte; G: Byte; R: Byte; end; var X: Integer; Y: Integer; Gray: Byte; Pixel: PPixelRec; begin for Y := 0 to ABitmap.Height - 1 do begin Pixel := ABitmap.ScanLine[Y]; for X := 0 to ABitmap.Width - 1 do begin Gray := Round((0.299 * Pixel.R) + (0.587 * Pixel.G) + (0.114 * Pixel.B)); Pixel.R := Gray; Pixel.G := Gray; Pixel.B := Gray; Inc(Pixel); end; end; end; 
+8
source

You can create a palette of the DIB section, 8 bits per pixel and 256 colors and initialize the palette to shades of gray {0, 0, 0}, {1, 1, 1}, ... {255, 255, 255}.

The single GDI BitBlt in this bitmap will be the gray source image. Here is a snippet of code (in C ++, ATL and WTL - but you should get an idea).

 CWindowDC DesktopDc(NULL); CDC BitmapDc; ATLVERIFY(BitmapDc.CreateCompatibleDC(DesktopDc)); CBitmap Bitmap; CTempBuffer<BITMAPINFO> pBitmapInfo; const SIZE_T nBitmapInfoSize = sizeof (BITMAPINFO) + 256 * sizeof (RGBQUAD); pBitmapInfo.AllocateBytes(nBitmapInfoSize); ZeroMemory(pBitmapInfo, nBitmapInfoSize); pBitmapInfo->bmiHeader.biSize = sizeof pBitmapInfo->bmiHeader; pBitmapInfo->bmiHeader.biWidth = 320; pBitmapInfo->bmiHeader.biHeight = 240; pBitmapInfo->bmiHeader.biPlanes = 1; pBitmapInfo->bmiHeader.biBitCount = 8; pBitmapInfo->bmiHeader.biCompression = BI_RGB; pBitmapInfo->bmiHeader.biSizeImage = 240 * 320; pBitmapInfo->bmiHeader.biClrUsed = 256; pBitmapInfo->bmiHeader.biClrImportant = 256; for(SIZE_T nIndex = 0; nIndex < 256; nIndex++) { pBitmapInfo->bmiColors[nIndex].rgbRed = (BYTE) nIndex; pBitmapInfo->bmiColors[nIndex].rgbGreen = (BYTE) nIndex; pBitmapInfo->bmiColors[nIndex].rgbBlue = (BYTE) nIndex; } Bitmap.Attach(CreateDIBSection(DesktopDc, pBitmapInfo, 0, DIB_RGB_COLORS, NULL, 0)); ATLVERIFY(Bitmap); BitmapDc.SelectBitmap(Bitmap); //////////////////////////////////////////////// // This is what greys it out: ATLVERIFY(BitBlt(BitmapDc, 0, 0, 320, 240, DesktopDc, 0, 0, SRCCOPY)); //////////////////////////////////////////////// ATLVERIFY(BitBlt(DesktopDc, 0, 240, 320, 240, BitmapDc, 0, 0, SRCCOPY)); 
+5
source

All Articles