如何将TCanvas包装在现有的像素数据周围?

3

问题

我有一个32位像素数据的数组,它保存了一个位图图像。

TPixel = packed record
  B: Byte;
  G: Byte;
  R: Byte;
  A: Byte;
end;

Size = MyBitmapWidth * MyBitmapHeight;

MyBitmapData : array[0..Size-1] of TPixel;

能否创建一个新的TCanvas对象并将其附加到现有的像素数据上?该画布对象还需要分配一个句柄。

背景

我正在使用一个第三方库来创建位图数据(作为32位像素数组)。我想在另一个函数中使用相同的像素数据,该函数需要TCanvas.Handle作为参数。


如果函数以 TCanvas.Handle 作为其参数,则您实际上并不需要一个 TCanvas。您需要的是一个 HDC - Windows 设备上下文的句柄。 - Rob Kennedy
1
我一开始写了一个回答解释为什么不可能,但现在我认为可能是可以的。这将需要能够创建一个HBitmap来持有对像素缓冲区的引用,然后创建一个DC(使用CreateCompatibleDC),最后将位图选择到DC中(使用SelectObject)。我不确定的唯一部分是第一个;我无法从文档中确定CreateDIBitmapCreateDIBSection是否保留对原始数据的引用。(TCanvas与此过程无关,但如果您真的需要它,只需在准备就绪时分配Handle := hDC即可。) - Rob Kennedy
1个回答

1

根据您的数组中数据的方向,您可能需要进行类似以下的方向更改: pscanLine32[j].rgbReserved := Arr[i * Width + Height - j].A;

type
  TPixel = packed record
    B: Byte;
    G: Byte;
    R: Byte;
    A: Byte;
  end;

  TMyBitmapData = array of TPixel;

type
  pRGBQuadArray = ^TRGBQuadArray;
  TRGBQuadArray = ARRAY [0 .. $EFFFFFF] OF TRGBQuad;

Procedure FillBitMap(var bmp: TBitMap; Arr: TMyBitmapData; Width, Height: Integer);
var
  pscanLine32: pRGBQuadArray;
  i, j: Integer;
begin
  if not Assigned(bmp) then
    bmp := TBitMap.Create;
  bmp.PixelFormat := pf32Bit;
  bmp.ignorepalette := true;
  bmp.Width := Width;
  bmp.Height := Height;
  for i := 0 to bmp.Height - 1 do
  begin
    pscanLine32 := bmp.Scanline[i];
    for j := 0 to bmp.Width - 1 do
    begin
      pscanLine32[j].rgbReserved := Arr[i * Width + j].A;
      pscanLine32[j].rgbBlue := Arr[i * Width + j].B;
      pscanLine32[j].rgbRed := Arr[i * Width + j].R;
      pscanLine32[j].rgbGreen := Arr[i * Width + j].G;
    end;
  end;
end;

procedure TForm4.Button1Click(Sender: TObject);
var
  MyBitmapWidth: Integer;
  MyBitmapHeight: Integer;
  Size: Cardinal;
  MyBitmapData: TMyBitmapData;
  bmp: TBitMap;
  x: Integer;
begin
  MyBitmapWidth := 100;
  MyBitmapHeight := 100;
  Size := MyBitmapWidth * MyBitmapHeight;
  SetLength(MyBitmapData, Size );

  for x := 0 to MyBitmapWidth - 1 do
  begin
    MyBitmapData[x * MyBitmapWidth + x].A := 255;
    MyBitmapData[x * MyBitmapWidth + x].R := 255;
  end;


  bmp := TBitMap.Create;
  try
    FillBitMap(bmp, MyBitmapData, MyBitmapWidth,MyBitmapHeight );
    Image1.picture.Assign(bmp);
  finally
    bmp.Free;
  end;

end;

2
你的回答似乎是在创建一个全新的像素数据副本。我认为这不是问题所要求的。相反,问题是如何将TCanvas对象包装在现有的像素缓冲区周围;效果将是调用该TCanvas对象上的方法将直接修改原始缓冲区的内容。 - Rob Kennedy
@RobKennedy 我不确定,但我认为不可能使用外部的DBI结构来处理位图和它的HDC。我应该删除我的帖子吗?因为这是离题的内容。 - bummi
谢谢你的回答,Bummi,但Rob是正确的。我想创建一个TCanvas对象并在现有像素数据上绘制。 - Shannon Matthews

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接