Ofline
На старте программы создаим экземляр канвы TDirect2DCanvas, а также загрузим изображенеи из файла в поток данных:
Как видно из кода, в блоке try-finally происходит вызов метода LoadD2DBitmap(), который создает нужный d2d-растр. Создание изображение здесь происходит с помощью WIC. Первым делом мы создаем экзземпляр TWicImage и загружем данные из потока. Затем нам необходимо преобразовать формат изображения для его использования в d2d. Для этих целей, используя WIC-фабрику получаем экземляр IWicFormatConverter, после чего производим конвертацию. Теперь, используя полученное изображение и RenderTarget создаем D2D-растр:
Из подводных камней следует отметить, что здесь специально используется промежуточная переменная wicFactory, хотя, казалось бы, можно просто сделать вызов wi.ImageFactory.CreateFormatConverter(). Но в таком случае к моменту разрушения экземляра wi, остается одна дополнительная неявная ссылка на фабрику, что ведет к тому, что фабрика остается жить и после завершения метода, в результате чего будет получена ошибка при закрытии программы.
Имея готовое изображение, отрисовать его на форме труда не составит. Добавим пару строк для центрирования изображения на форме. Используя идеология матриц преобразований, нам потребуется две матрицы переноса: первая - в центр формы, а вторая - сдвиг изображения относительно центра:
Искомая позиция - произведение данных матриц
Код:
procedure TMainForm.FormCreate(Sender: TObject);
var fs : TFileStream;
begin
FCanvas := TDirect2DCanvas.Create(handle);
FRt := FCanvas.RenderTarget as ID2D1HwndRenderTarget;
FRt.SetDpi(96,96);
fs := TFileStream.Create('D:\folder-open.png', fmOpenRead);
try
FBitmap := LoadD2DBitmap(fs);
finally
fs.Free();
end;
end;
Код:
function TMainForm.LoadD2DBitmap(data : TStream):ID2D1Bitmap;
var wi : TWicImage;
wicFactory : IWICImagingFactory;
fc : IWICFormatConverter;
begin
result := nil;
wi := TWicImage.Create();
try
wi.LoadFromStream(data);
wicfactory := wi.ImagingFactory;
wicFactory.CreateFormatConverter(fc);
fc.Initialize(wi.Handle, GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nil,
0,
WICBitmapPaletteTypeCustom);
FRt.CreateBitmapFromWicBitmap(fc, nil, result);
fc := nil;
wicFactory := nil;
finally
wi.Free();
end;
end;
Имея готовое изображение, отрисовать его на форме труда не составит. Добавим пару строк для центрирования изображения на форме. Используя идеология матриц преобразований, нам потребуется две матрицы переноса: первая - в центр формы, а вторая - сдвиг изображения относительно центра:
Код:
procedure TMainForm.FormPaint(Sender: TObject);
var size : TD2DSizeF;
formCenter, imageCenter : TD2D1Matrix3x2F;
begin
FRt.BeginDraw();
try
FRt.Clear(D2D1ColorF(clRed));
FBitmap.GetSize(size);
formCenter := TD2DMatrix3x2F.Translation(clientWidth div 2, ClientHeight div 2);
imageCenter := TD2DMatrix3x2F.Translation( -size.width / 2, -size.height / 2);
FRt.SetTransform(formCenter * imageCenter);
if assigned(FBitmap) then
FRt.DrawBitmap(FBitmap);
finally
FRt.EndDraw();
end;
end;