скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Как создать Bitmap из массива пикселей



Cегодня вот... оживленно треплюсь с парнем, сидящим за соседним компом... и от возбуждения разговором слегка теряю равновесие и почти падаю на него :))... Он мне говорит: "отойди от меня...", - "отойти на 20 пунктов?" - несмело интересуюсь я... "Нет", - задумчиво продолжает он... - "отойди на 30 пикселей"...

Один из способов создания битмапа из массива пикселей заключается в использовании 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;
end;






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook