Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4447.html
 

Поворот PNG и WIC

Опубликовано 03.12.2010 г. 22:14

Понадобилось в коде переворачивать прозрачную png картинку, залитую изначально в TImage. По скольку с графикой сталкиваюсь редко, то это вызвало некоторые затруднения.

Во поддержание идеи Влада о разработке новогодней утилиты потребовалось зеркально отразить картинку по горизонтали. Сам TImage никаких средств для поворота не имеет. Попиксельно копировать не интересно. Функция StretchBlt требует bitmap, т.е. тут надо сделать, что то с исходным PNG. Опять же не знаток работы с графическими файлами. Вспомнилось про Windows Imaging Component (WIC). Исходная PNG картинка была загружена в ресурсы. Далее требовалось ее загрузить, и реализовать функцию зеркального поворота при необходимости. Загрузка из ресурсов, с которыми я опять же редко работаю сначала выглядела следующим образом (сам TWICImage грузиться из ресурсов не умеет, только с файла/потока):
var rHandle, dataHandle : THandle;
    size : integer;
    resPtr : pointer;
    ms : TMemoryStream;
    i : integer;
    wic : TWICImage;
begin
    try
        wic := TWICImage.Create();
        ms := TMemoryStream.Create();

        rHandle := FindResource(0, 'Santa', RT_RCDATA);
        size := SizeofResource(0, rHandle);
        dataHandle := LoadResource(0, rHandle);
        resPtr := LockResource(dataHandle);

        ms.Write(resPtr^,size);
        ms.Position := 0;

        wic.LoadFromStream(ms);
        img.Picture.Assign(wic);

        ms.free();
    except
        MessageDlg('Cant initialize WIC.', mtError, [mbOk], 0);
    end;
end;
Но затем оказалось, что RTL предоставляет нам класс TResourceStream и функция загрузки стала весьма проще:
        wic := TWICImage.Create();
        rs := TResourceStream.Create(0,'Santa',RT_RCDATA);

        wic.LoadFromStream(rs);
        img.Picture.Assign(wic);

        rs.free();
Теперь компонент img: TImage содержит в своем поле picture.graphic png-изображение в представлении TWICImage. Далее нам требуется устроить поворот изображения, для чего потребуется использовать несколько интерфейсов: IWICBitmapSource, IWICBitmap и IWICBitmapFlipRotator. Последний наверное самый интересный, поскольку указывает действие которое надо провести. Инициализируется константой WICBitmapTransformFlipHorizontal для определения метода поворота.
    procedure FlipSanta();
    var bmpSource : IWICBitmapSource;
        wic : TWICImage;
        flipRotator : IWICBitmapFlipRotator;
        newBmp : IWICBitmap;
        w,h : cardinal;
    begin
          wic := TWICImage(img.Picture.Graphic);
          bmpSource := wic.Handle as IWICBitmapSource;
          w := wic.Width;
          h := wic.height;

          wic.ImagingFactory.CreateBitmapFlipRotator(flipRotator);
          flipRotator.Initialize(bmpSource, WICBitmapTransformFlipHorizontal);
          flipRotator.GetSize(w, h);

          wic.ImagingFactory.CreateBitmapFromSourceRect(flipRotator, 0,0, w, h, newBmp);
          wic.Handle := newBmp;
          img.Repaint();
    end;
Вместо гугла использовал книжку Marco Cantu "Delphi 2010 Handbook", в которой был приведен пример поворота изображения на 90 градусов.
Метки:  WIC 

Комментарии

Нет комментариев
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно