繁体   English   中英

Delphi中,TBitmap.Monochrome和.PixelFormat对.ScanLine的格式有什么影响?

[英]In Delphi, how does TBitmap.Monochrome and .PixelFormat influcence the format of .ScanLine?

我想将具有 Mono8 格式(单色 8 位)位图的给定缓冲区分配给位图。 然后我将生成的位图分配给 TImage 组件以显示它。 图片是结果显示的屏幕截图。

以下代码有效,但似乎有点浪费:

procedure CopyToBitmapMono824(_Buffer: PByte; _Bmp: TBitmap);
var
  y: Integer;
  x: Integer;
  ScanLine: PdzRgbTripleArray;
begin
  for y := 0 to _Bmp.Height - 1 do begin
    ScanLine := _Bmp.ScanLine[y];
    for x := 0 to _Bmp.Width - 1 do begin
      // monochrome: all 3 colors set to the same value
      ScanLine[x].Red := _Buffer^;
      ScanLine[x].Green := _Buffer^;
      ScanLine[x].Blue := _Buffer^;
      Inc(_Buffer);
    end;
  end;
end;

// [...]
fBmp.PixelFormat := pf24Bit;
FBmp.Monochrome := False;
CopyToBitmap(Buffer, fBmp);

正确的灰度图像

我宁愿使用我尝试过的 pf8Bit 格式的位图:

procedure CopyToBitmapMono8(_Buffer: PByte; _Bmp: TBitmap);
var
  y: Integer;
  x: Integer;
  ScanLine: PByteArray;
begin
  for y := 0 to _Bmp.Height - 1 do begin
    ScanLine := _Bmp.ScanLine[y];
    for x := 0 to _Bmp.Width - 1 do begin
      ScanLine[x] := _Buffer^;
      Inc(_Buffer);
    end;
  end;
end;

// [...]
FBmp.PixelFormat := pf8bit;
FBmp.Monochrome := False; // I also tried Monochrome := true
CopyToBitmapMono8(Buffer, FBmp)

如果 MonoChrome 为 true,则图片只有预期宽度的 1/4 左右,其余部分为白色。

单色+白色

如果 MonoChrome 为 false,则图片具有预期的宽度,但其左侧 1/4 为单色,其余为假色。

单色+假色

我显然错过了一些东西,但是什么?

编辑:位图只有预期大小的 1/4 的效果显然是将其转换为 JPEG 以在显示之前保存的副作用(我上面没有显示的代码,我的过错)。 所以问题很简单,我没有为位图设置单色调色板。

Monochromepf1bit位图有意义。

否则Monochrome := True将位图格式更改为 DDB (pfDevice)。 您的屏幕是 32 位的,因此调用Scanline导致DibNeeded调用和转换为 32 位,并且使用函数CopyToBitmapMono8 (用于 8 位)仅占屏幕的 1/4。

为了正确使用 8 位位图,您必须将标准的奇怪调色板(用于最后一张图像的右侧部分)更改为灰色。

procedure CopyToBitmapMono8(_Buffer: PByte; _Bmp: TBitmap);
var
  y: Integer;
  x: Integer;
  ScanLine: PByteArray;
begin
  for y := 0 to _Bmp.Height - 1 do begin
    ScanLine := _Bmp.ScanLine[y];
    for x := 0 to _Bmp.Width - 1 do begin
      ScanLine[x] := _Buffer^;
      Inc(_Buffer);
    end;
  end;
end;

var
   FBmp: TBitmap;
   Buffer: PbyteArray;
   i: integer;
begin
  GetMem(Buffer, 512 * 100);
  for i := 0 to 512 * 100 - 1 do
     Buffer[i] := (i and 511) div 2; // gray gradient

  FBmp := Tbitmap.Create;
  FBmp.Width := 512;
  FBmp.Height := 100;
  FBmp.PixelFormat := pf8bit;
  CopyToBitmapMono8(PByte(Buffer), FBmp);
  Canvas.Draw(0, 0, FBmp);

  //now right approach
  FBmp.Palette := MakeGrayPalette; // try to comment
  CopyToBitmapMono8(PByte(Buffer), FBmp);
  Canvas.Draw(0, 110, FBmp);

end;

function TForm1.MakeGrayPalette: HPalette;
var
  i: integer;
  lp:  TMaxLogPalette;
begin
  lp.palVersion    := $300;
  lp.palNumEntries := 256;
  for i := 0 TO 255 do begin
     lp.palPalEntry[i].peRed   := i;
     lp.palPalEntry[i].peGreen := i;
     lp.palPalEntry[i].peBlue  := i;
     lp.palPalEntry[i].peFlags := PC_RESERVED;
   end;
   Result := CreatePalette(pLogPalette(@lp)^);
end;

在此处输入图片说明

和 efg2 页面上的示例

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM