创建位图

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;

 {Fill in the pixel buffer array with shades: black to white}
 {In a 256 color bitmap the color is an index into the color table}
  for i := 0 to 255 do
    for j := 0 to 255 do
     Byte(GetBigPointer(lpPixelBuffer, i + (j * 256))^) := j;

 {Fill in the palette structure}
  if IsPaletteDevice then begin
    lpPalBuffer^.palVersion := $300;
    lpPalBuffer^.palNumEntries := 256;
   {Fill in the palette structure color table}
    for i := 0 to 255 do begin
      lpPalBuffer^.PalPalEntry[i].peRed := i;
      lpPalBuffer^.PalPalEntry[i].peGreen := i;
      lpPalBuffer^.PalPalEntry[i].peBlue := i;
    end;

   {Create a palette}
    hPal := CreatePalette(lpPalBuffer^);
  end; 

 {Get the screen's dc to use for the conversion since}
 {memory dc's are not reliable to use for conversions}
  dc := GetDc(0);

  if IsPaletteDevice then begin
   {If we are using a palette, it must be}
   {selected into the dc during the conversion}
    OldPal := SelectPalette(dc, hPal, TRUE);
   {Realize the palette}
    RealizePalette(dc);
  end;

 {Do the conversion}
  hBm := CreateDiBitmap(dc,
                        lpBitmapInfo^.bmiHeader,
                        CBM_INIT,
                        pChar(lpPixelBuffer),
                        lpBitmapInfo^,
                        DIB_RGB_COLORS);


  if IsPaletteDevice then begin
   {Select the old palette back in}
    SelectPalette(dc, OldPal, TRUE);
   {Realize the old palette}
    RealizePalette(dc);
  end;

 {Give back the screen dc}
  dc := ReleaseDc(0, dc);

 {Create a temporory TBitmap}
  bm := TBitmap.Create;

 {Free up the memory we used}
  if IsPaletteDevice then
    FreeMem(lpPalBuffer, PaletteSize);
  GlobalUnlock(hPixelBuffer);
  GlobalFree(hPixelBuffer);
  FreeMem(lpBitmapInfo, BitmapInfoSize);

 {Assign the palette}
  if IsPaletteDevice then
    bm.Palette := hPal;

 {Assign the handle}
  bm.Handle := hBm;

 {Size Image1}
  Image1.Width := 256;
  Image1.Height := 256;

 {Assign the bitmap}
  Image1.Picture.Bitmap := bm;

  SelectPalette(Image1.Picture.Bitmap.Canvas.Handle,
                Image1.Picture.Bitmap.Palette,
                false);

{Turn range checking back on if it was on when we started}
{$IFDEF CKRANGE}
  {$UNDEF CKRANGE}
  {$R+}
{$ENDIF}
end;

 

转载于:https://www.cnblogs.com/yzryc/p/6373599.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值