Загрузка Изображений В Direct2d

  • Автор темы Автор темы Lomanu4
  • Дата начала Дата начала

Lomanu4

Команда форума
Администратор
Ofline
На старте программы создаим экземляр канвы TDirect2DCanvas, а также загрузим изображенеи из файла в поток данных:
Код:
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;
Как видно из кода, в блоке try-finally происходит вызов метода LoadD2DBitmap(), который создает нужный d2d-растр. Создание изображение здесь происходит с помощью WIC. Первым делом мы создаем экзземпляр TWicImage и загружем данные из потока. Затем нам необходимо преобразовать формат изображения для его использования в d2d. Для этих целей, используя WIC-фабрику получаем экземляр IWicFormatConverter, после чего производим конвертацию. Теперь, используя полученное изображение и RenderTarget создаем D2D-растр:
Код:
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;
Из подводных камней следует отметить, что здесь специально используется промежуточная переменная wicFactory, хотя, казалось бы, можно просто сделать вызов wi.ImageFactory.CreateFormatConverter(). Но в таком случае к моменту разрушения экземляра wi, остается одна дополнительная неявная ссылка на фабрику, что ведет к тому, что фабрика остается жить и после завершения метода, в результате чего будет получена ошибка при закрытии программы.

Имея готовое изображение, отрисовать его на форме труда не составит. Добавим пару строк для центрирования изображения на форме. Используя идеология матриц преобразований, нам потребуется две матрицы переноса: первая - в центр формы, а вторая - сдвиг изображения относительно центра:
Код:
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;
Искомая позиция - произведение данных матриц

5783-original.png
 
Назад
Сверху Снизу