Как создать Bitmap из массива пикселей
Один из способов создания битмапа из массива
пикселей заключается в использовании Windows API
функции CreateDiBitmap(). Это позволит использовать один
из многих форматов битмапа, которые Windows
использует для хранения пикселей. Следующий
пример создаёт 256-цветный битмап из массива
пикселей. Битмап состит из 256 оттенков серого
цвета плавно переходящих от белого к чёрному.
Обратите внимание, что Windows резервирует первые и
последние 10 цветов для системных нужд, поэтому Вы
можете получить максимум 236 оттенков серого.
{$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);
{Размер информации о рисунке должен равняться
размеру BitmapInfo}
{плюс размер таблицы цветов, минус одна таблица}
{так как она уже объявлена в 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;
{Размер палитры должен равняться размеру TLogPalette}
{плюс количество ячеек цветовой палитры - 1, так
как}
{одна палитра уже объявлена в TLogPalette}
if IsPaletteDevice then
PaletteSize := sizeof(TLogPalette) + (sizeof(TPaletteEntry) * 255);
{Выделяем память под BitmapInfo, PixelBuffer, и Palette}
GetMem(lpBitmapInfo, BitmapInfoSize);
hPixelBuffer := GlobalAlloc(GHND, BitmapSize);
lpPixelBuffer := GlobalLock(hPixelBuffer);
if IsPaletteDevice then
GetMem(lpPalBuffer, PaletteSize);
{Заполняем нулями BitmapInfo, PixelBuffer, и Palette}
FillChar(lpBitmapInfo^, BitmapInfoSize, #0);
FillChar(lpPixelBuffer^, BitmapSize, #0);
if IsPaletteDevice then
FillChar(lpPalBuffer^,PaletteSize, #0);
{Заполняем структуру BitmapInfo}
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;
{Заполняем таблицу цветов BitmapInfo оттенками серого:
от чёрного до белого}
for i := 0 to 255 do begin
lpBitmapInfo^.bmiColors[i].rgbRed := i;
lpBitmapInfo^.bmiColors[i].rgbGreen := i;
lpBitmapInfo^.bmiColors[i].rgbBlue := i;
end;
|