If you look at how drawing graphic objects to TDirect2DCanvas
is implemented you will find that it routes through this routine.
procedure TDirect2DCanvas.StretchDraw(const Rect: TRect; Graphic: TGraphic;
Opacity: Byte);
var
D2DBitmap: ID2D1Bitmap;
D2DRect: TD2DRectF;
Bitmap: TBitmap;
begin
Bitmap := TBitmap.Create;
try
Bitmap.Assign(Graphic);
D2DBitmap := CreateBitmap(Bitmap);
D2DRect.Left := Rect.Left;
D2DRect.Right := Rect.Right;
D2DRect.Top := Rect.Top;
D2DRect.Bottom := Rect.Bottom;
RenderTarget.DrawBitmap(D2DBitmap, @D2DRect, Opacity/255);
finally
Bitmap.Free;
end;
end;
Let's unpick the steps involved:
- Create a temporary bitmap.
- Copy the graphic into that bitmap.
- Create a
ID2D1Bitmap
and copy the temporary bitmap into it.
- Draw that
ID2D1Bitmap
onto the render target.
This already looks pretty inefficient. Certainly it would be galling to call this function passing in a TBitmap
and have a copy made for no good reason.
This sort of thing is hard to avoid though when you try to blend two distinct graphics frameworks. Your image list is GDI based, and so bound to encounter friction when you try to send it to a Direct2D canvas. There simply is no way to pass GDI bitmaps directly to a Direct2D canvas, they have to be converted to Direct2D bitmaps first.
If performance is what matters to you then you should not be starting from an image list. That will inevitably incur costs as you extract the bitmap from the GDI image list, and then convert it into the equivalent Direct2D object, ID2D1Bitmap
.
In order to achieve optimal performance, don't work with image lists. Extract each image from the image list and use TDirect2DCanvas.CreateBitmap
to obtain a Direct2D bitmap, ID2D1Bitmap
. Store these rather than the image list. Then when you need to draw, call DrawBitmap
on RenderTarget
, passing a ID2D1Bitmap
.