2011-12-19 12 views
7

Sto cercando la soluzione semplice di come convertire la bitmap a 32 bit in scala di grigi utilizzando GDI (non GDI +). C'è una possibilità, ad es. cambiando il pallete della bitmap o qualcosa del genere?Come convertire la bitmap in scala di grigi in base all'intensità dei pixel mediante GDI?

Ovviamente ci sono molti esempi in Delphi come this one, ma sto cercando una funzione WinAPI che faccia questo senza iterazione attraverso le linee.

+2

Non conosco la funzione GDI singola che lo farebbe né la conversione della tavolozza, ma la terza funzione del collegamento che hai citato lo fa. Immagino che tu abbia paura delle prestazioni, vero? – TLama

+0

Non si tratta solo di prestazioni, sto cercando una soluzione più semplice (magari convertendo la tavolozza o qualcosa del genere). –

+0

La bitmap a 32 bit non contiene palette. – MBo

risposta

8

Non ho trovato alcuna funzione GDI singola che esegue questa operazione. Il modo più semplice, come David ha menzionato nel suo commento, è di scansionare ogni riga e calcolare i colori dei pixel. Quello che stai cercando è probabilmente la formula luminance.

Esistono poche varianti di questa formula e nell'esempio seguente ho utilizzato quello consigliato da ITU, vedere la sezione 2.5.1 this document. Come ho trovato da qualche parte, questa formula è usata per es. anche da ben noto Adobe Photoshop. Il seguente esempio di codice supporta e si aspetta solo bitmap formato pixel a 24 bit come 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; 
+3

Grazie TLama, sembra che non ci sia davvero alcuna funzione WinAPI per questo. –

5

è possibile creare una tavolozza Sezione DIB, 8 bit per pixel e 256 colori, e inizializzare tavolozza per tonalità di grigio {0 , 0, 0}, {1, 1, 1}, ... {255, 255, 255}.

Un singolo GDI BitBlt in questa bitmap renderà grigia l'immagine originale. Ecco lo snippet di codice (in C++, ATL e WTL - ma dovresti avere l'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

GDI consente di abbandonare i colori di sistema riservati dalla palette di mezzitoni? – OnTheFly

+3

Questo rende una tavolozza completamente in scala di grigi con 256 sfumature di grigio, senza colori di sistema. –

+0

@RomanR .: Non capisco dove entra in gioco la bitmap iniziale (quella da convertire). Potresti chiarire per favore? –

Problemi correlati