我需要在具有以下要求的画布上绘制 PNG(在 TPicture 中):
- 它需要非常快(由于目标 PC 运行缓慢的 CPU)。
- 它不需要任何会增加 exe 大小的额外库(由于目标 PC 通过 2G 移动连接自动更新)。
下面的代码完成了这项工作,但使用了GDI+并且:
- 比使用
BitBlt
. 在快速处理器上,绘制时间从 1 毫秒增加到 16 毫秒。在慢速 CPU 上,它从 100 毫秒增加到 900 毫秒。 - 将 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+ 方法完全相同。有什么办法可以优化吗?