2011-12-19 17 views
7

Estoy buscando la solución simple de cómo convertir el mapa de bits de 32 bits a escala de grises usando GDI (no GDI +). ¿Hay alguna posibilidad, p. cambiando la paleta del mapa de bits o algo así?¿Cómo convertir el mapa de bits a escala de grises por intensidad de píxel usando GDI?

Por supuesto, hay muchos ejemplos en Delphi como this one, pero estoy buscando una función WinAPI que lo haga sin iteración a través de las líneas.

+2

No sé acerca de la función GDI única que haría eso ni sobre la conversión de paleta, pero la tercera función del enlace que ha mencionado lo hace. Supongo que temes al rendimiento, ¿verdad? – TLama

+0

No se trata solo de rendimiento, estoy buscando una solución más fácil (tal vez mediante la conversión de paleta o algo así). –

+0

El mapa de bits de 32 bits no contiene paleta. – MBo

Respuesta

8

No he encontrado ninguna función GDI haciendo esto. La manera más fácil, como David mencionó en su comentario, es escanear cada línea y calcular los colores de los píxeles. Lo que está buscando es probablemente la fórmula luminance.

Existen algunas variaciones de esta fórmula y en el siguiente ejemplo he utilizado la recomendada por ITU, ver this document sección 2.5.1. Como encontré en alguna parte, esta fórmula se usa, por ejemplo. incluso por conocidos Adobe Photoshop. El ejemplo de código apoya y espera solamente mapas de bits formato de píxel de 24 bits como una entrada:

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; 
+3

Gracias TLama, parece que no hay realmente una función WinAPI para esto. –

5

Usted puede crear una sección DIB con paleta, 8 bits por píxel y 256 colores, e inicializar la paleta a tonos de gris {0 , 0, 0}, {1, 1, 1}, ... {255, 255, 255}.

Un único GDI BitBlt en este mapa de bits grisá su imagen original. Aquí está el fragmento de código (en C++, ATL y WTL, pero debería hacerse una 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)); 
+0

¿Permitirá GDI abandonar los colores de sistema reservados de la paleta de medios tonos? – OnTheFly

+3

Esto hace que una paleta completamente en escala de grises con 256 tonos de gris, sin colores del sistema. –

+0

@RomanR .: No entiendo dónde entra en juego aquí el mapa de bits inicial (el que se va a convertir). ¿Podría aclarar por favor? –

Cuestiones relacionadas