Mega Code Archive

 
Categories / Delphi / Graphic
 

Creating a bitmap form a pixel array

Title: Creating a bitmap form a pixel array Question: How can I quickly create a bitmap form a pixel array? Answer: One way to create a bitmap from a pixel array is to use the Windows API function CreateDiBitmap(). This will allow you to use one of many device independent bitmap formats that Windows uses to store your pixel data. This has the advantage that it will work on any Windows system, without knowing the pixel format that the device uses ahead of time. Properly executed by optimizing your code, theCreateDiBitmap function can be quite fast as well. The following example creates a 256 color bitmap from a pixel array. The bitmap fades from white to black using 256 gray shades. Note that normally, Windows reserves the first and last ten colors for use as system colors, so you may only get a maximum of 236 gray shades. {$IFNDEF WIN32} type {Used for pointer math under Win16} PPtrRec = ^TPtrRec; TPtrRec = record Lo : Word; Hi : Word; end; {$ENDIF} {Used for huge pointer math} function GetBigPointer(lp : pointer; Offset : Longint) : Pointer; begin {$IFDEF WIN32} GetBigPointer := @PByteArray(lp)^[Offset]; {$ELSE} Offset := Offset + TPtrRec(lp).Lo; GetBigPointer := Ptr(TPtrRec(lp).Hi + TPtrRec(Offset).Hi * SelectorInc, TPtrRec(Offset).Lo); {$ENDIF} end; procedure TForm1.Button1Click(Sender: TObject); var hPixelBuffer : THandle; {Handle to the pixel buffer} lpPixelBuffer : pointer; {pointer to the pixel buffer} lpPalBuffer : PLogPalette; {The palette buffer} lpBitmapInfo : PBitmapInfo; {The bitmap info header} BitmapInfoSize : longint; {Size of the bitmap info header} BitmapSize : longint; {Size of the pixel array} PaletteSize : integer; {Size of the palette buffer} i : longint; {loop variable} j : longint; {loop variable} OldPal : hPalette; {temp palette} hPal : hPalette; {handle to our palette} hBm : hBitmap; {handle to our bitmap} Bm : TBitmap; {temporary TBitmap} Dc : hdc; {used to convert the DOB to a DDB} IsPaletteDevice : bool; begin Application.ProcessMessages; {If range checking is on - turn it off for now} {we will remember if range checking was on by defining} {a define called CKRANGE if range checking is on.} {We do this to access array members past the arrays} {defined index range without causing a range check} {error at runtime. To satisfy the compiler, we must} {also access the indexes with a variable. ie: if we} {have an array defined as a: array[0..0] of byte,} {and an integer i, we can now access a[3] by setting} {i := 3; and then accessing a[i] without error} {$IFOPT R+} {$DEFINE CKRANGE} {$R-} {$ENDIF} {Lets check to see if this is a palette device - if so, then} {we must do palette handling for a successful operation.} {Get the screen's dc to use since memory dc's are not reliable} dc := GetDc(0); IsPaletteDevice := GetDeviceCaps(dc, RASTERCAPS) and RC_PALETTE = RC_PALETTE; {Give back the screen dc} dc := ReleaseDc(0, dc); {The bitmap info size must be the size of the BitmapInfo} {plus the size of the color table - one color table entry} {is already defined in TBitmapInfo} BitmapInfoSize := sizeof(TBitmapInfo) + (sizeof(TRGBQUAD) * 255); {The bitmap size must be the width of the bitmap rounded} {up to the nearest 32 bit boundary} BitmapSize := (sizeof(byte) * 256) * 256; {The size of the palette must be the size of a TLogPalette} {plus the number of color palette entries - 1, since there} {is already one palette entry defined in TLogPalette} if IsPaletteDevice then PaletteSize := sizeof(TLogPalette) + (sizeof(TPaletteEntry) * 255); {Get the memory for the BitmapInfo, the PixelBuffer, and the Palette} GetMem(lpBitmapInfo, BitmapInfoSize); hPixelBuffer := GlobalAlloc(GHND, BitmapSize); lpPixelBuffer := GlobalLock(hPixelBuffer); if IsPaletteDevice then GetMem(lpPalBuffer, PaletteSize); {Zero out the BitmapInfo, the PixelBuffer, and the Palette} FillChar(lpBitmapInfo^, BitmapInfoSize, #0); FillChar(lpPixelBuffer^, BitmapSize, #0); if IsPaletteDevice then FillChar(lpPalBuffer^,PaletteSize, #0); {Fill in the BitmapInfo structure} lpBitmapInfo^.bmiHeader.biSize := sizeof(TBitmapInfoHeader); lpBitmapInfo^.bmiHeader.biWidth := 256; lpBitmapInfo^.bmiHeader.biHeight := 256; lpBitmapInfo^.bmiHeader.biPlanes := 1; lpBitmapInfo^.bmiHeader.biBitCount := 8; lpBitmapInfo^.bmiHeader.biCompression := BI_RGB; lpBitmapInfo^.bmiHeader.biSizeImage := BitmapSize; lpBitmapInfo^.bmiHeader.biXPelsPerMeter := 0; lpBitmapInfo^.bmiHeader.biYPelsPerMeter := 0; lpBitmapInfo^.bmiHeader.biClrUsed := 256; lpBitmapInfo^.bmiHeader.biClrImportant := 256; {Fill in the BitmapInfo color table with gray shades: black to white} for i := 0 to 255 do begin lpBitmapInfo^.bmiColors[i].rgbRed := i; lpBitmapInfo^.bmiColors[i].rgbGreen := i; lpBitmapInfo^.bmiColors[i].rgbBlue := i; end;