从原始像素数据数组加载TPicture

时间:2019-08-30 12:11:16

标签: delphi

我对delphi完全陌生,我有一个项目需要从指针加载图片到包含原始像素数据的C数组。

我不能简单地使用TPicture.LoadFromFile,因为实际加载是在C ++ DLL中执行的。我从DLL中得到的只是指向图像宽度,高度,格式的指针,以及指向保存像素数据的数组的指针。

DLL_Image = packed record
        Width           : UInt32;        { Width of image. [px] }
        Height          : UInt32;    { Height of image. [px] }
        Format          : ImageFormat;   { (Color) Format of image. }
        Data            : ^UInt8;    { Points to image data. }
end;
DLL_PImage = ^DLL_Image;

我尝试的是将图像数据加载到TMemoryStream后跟TPicture.LoadFromStream()的情况,该方法不起作用。 IIRC,我必须向流中写入TPicture的适当实例,以使此工作生效。

有没有一种方法可以从数据数组中加载图像?

1 个答案:

答案 0 :(得分:5)

通过将像素数据复制到TBitmap的扫描线上,可以轻松地使用给定的像素数据创建VCL TBitmap对象。

这是一个简单的例子。

首先,我们创建一些样本原始像素数据:

function MakePixelData(const AWidth, AHeight: Integer): pointer;
var
  p: PRGBQuad;
  y, x: Integer;
begin
  GetMem(Result, AWidth * AHeight * sizeof(TRGBQuad));
  p := PRGBQuad(Result);
  y := 0;
  while y < AHeight do
  begin
    x := 0;
    while x < AWidth do
    begin
      p.rgbRed := 255 * x div AWidth;
      p.rgbGreen := 255 * y div AHeight;
      p.rgbBlue := 255;
      Inc(x);
      Inc(p);
    end;
    Inc(y);
  end;
end;

procedure FreePixelData(var AData: pointer);
begin
  FreeMem(AData);
end;

MakePixelData函数在堆上为给定大小的位图分配一些内存,并用简单的渐变填充它:

Sample bitmap with a simple gradient

然后使用FreePixelData过程释放此内存。

现在有趣的是,使用此原始像素数据获得VCL TBitmap对象:

procedure TForm1.FormCreate(Sender: TObject);
const
  W = 400;
  H = 200;
var
  RawPixelData: pointer;
  bm: TBitmap;
  y: Integer;

  function PixelData(ARowIndex: Integer): pointer;
  begin
    Result := PByte(RawPixelData) + ARowIndex * W * sizeof(TRGBQuad);
  end;

begin

  RawPixelData := MakePixelData(W, H);
  try

    bm := TBitmap.Create;
    try
      bm.SetSize(W, H);
      bm.PixelFormat := pf32bit;
      for y := 0 to bm.Height - 1 do
        CopyMemory(bm.ScanLine[y], PixelData(y), bm.Width * sizeof(TRGBQuad));
      bm.SaveToFile('D:\Desktop\Bitmap from raw pixel data.bmp');
    finally
      bm.Free;
    end;

  finally
    FreePixelData(RawPixelData);
  end;

end;

这将从原始像素数据创建VCL TBitmap。只是为了证明它有效,我将其另存为文件。但是您也可以将其显示在TImage控件中,也可以将其用于某些自定义VCL绘图。

请小心在所有地方使用相同的像素格式。在我的示例中,我使用32位RGBX数据。