繁体   English   中英

在不使用GDI +的情况下在画布上绘制PNG格式的TPicture

[英]Draw a PNG formated TPicture on a Canvas without using GDI+

我需要在画布上绘制一个PNG(在TPicture中),具有以下要求:

  1. 它需要非常快(由于目标PC运行缓慢的CPU)。
  2. 它不应该需要任何额外的库来增加exe的大小(由于目标PC通过2G移动连接自动更新)。

下面的代码完成了这项工作,但使用了GDI +和:

  1. 比使用BitBlt绘制简单的非透明位图要慢得多。 在快速处理器上,绘制时间从1ms增加到16ms。 在慢速CPU上,它从100ms增加到900ms。
  2. 将exe的大小增加大约0.5MB。

这是GDI +代码。 它旨在回归到标准BitBlt,如果:

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
  ComCtrls, ExtCtrls,

  GDIPObj, GDIPAPI;
...

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture);

  function PictureToGPBitmap(Picture: TPicture): TGPBitmap;
  var
    MemStream: TMemoryStream;
  begin
    MemStream := TMemoryStream.Create;
    try
      Picture.Graphic.SaveToStream(MemStream);

      MemStream.Position := 0;

      Result := TGPBitmap.Create(TStreamAdapter.Create(MemStream));
    finally
      FreeAndNil(MemStream);
    end;
  end;

var
  GDICanvas: TGPGraphics;
  GPImage: TGPImage;
begin
  GDICanvas := TGPGraphics.Create(Bitmap.Canvas.Handle);
  try
    GPImage := PictureToGPBitmap(Picture);
    try
      GDICanvas.DrawImage(GPImage, X, Y);

      // Did the draw succeed?
      if GDICanvas.GetLastStatus <> Ok then
      begin
        // No, try a BitBlt!
        BitBlt(Bitmap.Canvas.Handle, X, Y, Bitmap.Height, Bitmap.Width, Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
      end;
    finally
      FreeAndNil(GPImage);
    end;
  finally
    FreeAndNil(GDICanvas);
  end;
end;

更新1

使用David的建议我设法使用Delphi内置的PNG支持来摆脱GDI +。

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture);
var
  PNG: TPngImage;
  MemStream: TMemoryStream;
begin
  PNG := TPngImage.Create;
  try
    MemStream := TMemoryStream.Create;
    try
      Picture.Graphic.SaveToStream(MemStream);

      MemStream.Position := 0;

      PNG.LoadFromStream(MemStream);
    finally
      FreeAndNil(MemStream);
    end;

    PNG.Draw(Bitmap.Canvas, Rect(X, Y, X + Picture.Width, Y + Picture.Height));
  finally
    FreeAndNil(PNG);
  end;
end;

不幸的是,绘制时间与GDI +方法完全相同。 有没有什么方法可以优化它?

在我看来,你不必要地采用内存中的图形,压缩到PNG,然后解压缩。 您可以直接绘制图形。

只需在你的位Picture.Graphic布上调用Draw ,即可传递Picture.Graphic

procedure DrawPictureToBitmap(Bitmap: TBitmap; X, Y: Integer; Picture: TPicture);
begin
  Bitmap.Canvas.Draw(X, Y, Picture.Graphic);
end;

此时你可能会认为DrawPictureToBitmap没有意义,删除它,并直接调用Bitmap.Canvas.Draw()

根据问题中的代码,您的图片不仅限于包含PNG图像,这也将带来快乐的好处。

暂无
暂无

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

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