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

Собственный Image Viewer

Опубликовано 14.06.2010 г. 20:49
После короткого знакомства с Direct2D & Windows Animation Manager посетила меня идея написать свою небольшую программку для просмотра изображений. В общем то почему бы и нет? Ну и что что их навалом вокруг, зато для закрепления навыков работы с упомянутыми технологиями.
Проект не обещает быть большим, скорее для собственного развития, почему то я сомневаюсь что кто либо захочет пользоваться этим (: ну и если я его не заброшу в добавок. Пока что вся структура достаточно проста. Имеется главная форма, на которой собственно и будет осуществляться просмотр картинок. И есть еще два вспомогательных модуля. О проблемах с реализацией которых и пойдет речь далее. Модуль первый - BrushManager. Суть модуля - аккумулирование информации о всех рабочих Direct2D кистях. С точки зрения удобства я решил что проще не иметь кучу переменных с кистями а иметь класс, который по имени (строке) будет возвращать требуемую кисть. Вроде бы ничего сложного. Вопрос был в том, с помощью чего организовать хранение самой коллекции. TStringList подумал я, умеет хранить и строки и связанные объекты. Однако если посмотреть например описание метода TStringList.Clear() то можно заметить, следующее:
      for I := 0 to FCount - 1 do
      begin
        Obj := GetObject(I);
        Obj.Free;
      end;
т.е при очистке список пытается освободить все объекты, что он хранит. В нашем случае, хранить мы собирались кисти - ID2D1Brush. Следовательно применение к такому объекту метода Free(), ничем хорошим не обернется. Так что, если написано что список хранит объекты TObject, то кроме TObject и его потомков ничего хранить там не следует. что в принципе логично. (: Поэтому хранение списка кистей было организовано с помощью словаря TDictionary Описание класса менеджера кистей весьма простое:
    TBrushManager = class( TObject)
      strict private
        FBrushList : TDictionary;

        function  getBrush(name:string):ID2D1Brush;
        procedure setBrush(name:string; brush : ID2D1Brush);

        function brushExists(name:string):boolean;
      public
        property Brushes[name:string] : ID2D1Brush  read getBrush write setBrush;
        property exists[name:string] : boolean read brushExists;

        constructor Create();
        destructor Destroy();

        procedure Initialize( rt : ID2D1HwndRenderTarget);
    end;
Реализованы свойства и функции/методы для получения/добавления кисти, а также для проверки наличия кисти по названию. В методы Initialize проводятся вся работа по созданию кистей. Модуль второй - менеджер изображений Данный модуль делает практически всю работу. Загрузка директории с изображениями, хранение списка миниатюр и их создание. Но загвоздка вышла в применении анимации. Представим что в нижней части формы представлен ряд миниатюр изображений. Нажимая кнопку лево/право, ряд сдвигается на одну миниатюру. По идее текущая картинка должна находится в центре ряда. Но если мы находимся в самом начале списка, то приходится не сдвигать картинки вперед/назад, а двигать рамку текущего изображение, пока оно не окажется в центре. Затем уже следует прокручивать сами изображения. Дак вот, при таком нажатии кнопки, вызывался метод настройки анимации, для как раз таки прокрутки списка картинок. Задавалась анимация координат вывода для каждой миниатюры. Таким образом находясь в самом начале списка, при движении вперед, позиции изображений оставались неизменными. в таком случае текущее и конечное значение переменной анимации совпадало. Как итог - invalid floating point operation при вызове IUIAnimationStoryBoard.Schedule(). На попытку осознать в чем причина возникновения данной ошибки я потратил 3 дня (: Что примечательного еще запомнилось мне при реализации модуля: как я писал в предыдущей статье создание миниатюры изображения с помощью фабрики IShellItemImageFactory.getImage может занимать достаточно большое время, поэтому создание миниатюр проводится по мере просмотра изображений, скажем так +20 штук вперед. Само создание миниатюры реализовано с помощью интерфейса IWICBitmap, код представлен ниже. Исходными данным для работы метода является имя файла - строка. Выходными - изображение ID2D1Bitmap.
procedure TImageItem.CreateThumbnail;
const THUMB_SIZE : TSize = (cx : 96; cy:96);
var imageFactory : IShellItemImageFactory;
    hBm : HBitmap;
    WICBitmap : IWICBitmap;
    bCtx : IBindCtx;
    WICImageFactory : IWICImagingFactory;
    converter : IWICFormatConverter;
begin
    SHCreateItemFromParsingName(pChar(filename), bCtx, IID_IShellItemImageFactory, imageFactory);
    imageFactory.GetImage(THUMB_SIZE,0,hBm);

    WICImageFactory := CreateComObject(CLSID_WICImagingFactory) as IWICImagingFactory;
    WICImageFactory.CreateBitmapFromHBITMAP(
                                    hBm, 0, WICBitmapUseAlpha, WICBitmap);

    imageManager.RenderTarget.CreateBitmapFromWicBitmap(WICBitmap, nil, thumbnail);
    if not assigned(thumbnail) then begin
        WICImageFactory.CreateFormatConverter(converter);
        converter.Initialize(WICBitmap,
                             GUID_WICPixelFormat32bppPBGRA,
                             WICBitmapDitherTypeNone, nil, 0,
                             WICBitmapPaletteTypeMedianCut);
        imageManager.RenderTarget.CreateBitmapFromWicBitmap(converter,0,thumbnail);
        converter := nil;
    end;

    WICBitmap := nil;
    imageFactory := nil;
end;
Кстати изначально при реализации столкнулся проблемой, при использовании TWICImage.ImagingFactory, которое объявлено как class property и соответственно вызывает class function. Следовательно пользоваться свойством я могу не создавая сам объект. Я, конечно, может чего то не понимаю, но в моем представлении вызов данной функции должен создаваться объект IWICImaginFactory, и возвращать его. Ну или если мы работаем с инициализированным объектом, и класс-фабрика является членом класса, тогда вернуть его. Описание метода следующее
class function TWICImage.GetImagingFactory: IWICImagingFactory;
begin
  Result := FImagingFactory;
end;
свойство FImagingFactory является также статическим и заполняется при создании экземпляра объекта. В конечном счете, по крайней мере в моем случае, попытка использовать свойство TWICImage.ImagingFactory приводила к возврату значения nil, что немного странно.
Метки:  Direct2D  |  animation  |  ImageViewer  |  WIC 

Комментарии

iFynk
27.10.2010 в 12:14
Спасибо большое за статьи по direct2d. Хотел бы вас попросить создать пример компонента, который основан на direct2d. Желательно с анимацией текста например. Буду очень благодарен. А то я начал делать компонент (очень простой, в нем я просто перемещаю кубик мышкой), но при анимации фон не перерисовывается и остается шлейф от предыдущих кадров. Если можете, то свяжитесь со мной по email. Спасибо.
ter
28.10.2010 в 22:44
есть мысль одна сделать графический компонент для отмечания рейтинга в клиенте для myshows.ru
если соберусь, то статью напишу (:
maurinekirscht.hatenablog.com
19.05.2017 в 23:20
Exceptional post but I was wondering if you could write a litte more on this topic?
I'd be very thankful if you could elaborate a little bit
further. Bless you!
foot pain gluten
27.06.2017 в 00:32
Hello i am kavin, its my first occasion to commenting anywhere, when i
read this paragraph i thought i could also create comment due
to this good post.
foot pain after sitting
27.06.2017 в 02:45
Howdy very nice site!! Man .. Beautiful .. Amazing ..

I'll bookmark your blog and take the feeds additionally?
I'm glad to find so many helpful information right here within the put up, we want work out extra strategies on this regard, thanks for sharing.
. . . . .
foot pain from walking
27.06.2017 в 03:30
I drop a comment when I like a post on a site or if I have
something to contribute to the conversation. Usually it's caused by the passion communicated
in the post I browsed. And after this article Delphi programming blog | 

 Image Viewer.
I was actually moved enough to drop a thought ;-) I actually do have 2 questions for you if you don't mind.
Is it simply me or does it look like like a few of the comments come across like coming from brain dead individuals?
:-P And, if you are posting on other online sites, I would like to follow you.
Would you make a list the complete urls of all your social pages like your Facebook page, twitter feed,
or linkedin profile?
foot pain big toe joint
27.06.2017 в 07:48
First of all I would like to say great blog! I had a quick question that I'd like to
ask if you do not mind. I was curious to know how you center yourself and clear your head
prior to writing. I've had a difficult time clearing my mind in getting my ideas out there.
I do take pleasure in writing but it just seems like the first
10 to 15 minutes are usually lost simply just trying to figure out how to
begin. Any ideas or tips? Cheers!
foot pain chart
27.06.2017 в 08:44
Since the admin of this site is working, no uncertainty very rapidly it will
be famous, due to its feature contents.
foot pain arch
02.07.2017 в 12:20
This is the perfect webpage for anybody who would like
to understand this topic. You understand so much its almost tough to argue with you (not that
I personally will need to?HaHa). You certainly put a new spin on a topic which has been discussed for a long time.
Wonderful stuff, just excellent!
vitamin c foot pain
03.07.2017 в 01:34
Sweet blog! I found it while browsing on Yahoo News.
Do you have any suggestions on how to get listed in Yahoo News?

I've been trying for a while but I never seem to get there!
Cheers
foot pain going up leg
03.07.2017 в 20:10
This is the perfect blog for anyone who wants to understand
this topic. You realize so much its almost tough to argue with you (not that I personally
will need to?HaHa). You definitely put a new spin on a subject that has been written about for many years.
Great stuff, just great!
foot pain getting worse
04.07.2017 в 01:22
First off I would like to say wonderful blog! I had a quick question in which
I'd like to ask if you do not mind. I was curious to find out how
you center yourself and clear your mind prior to writing.
I have had trouble clearing my mind in getting my
thoughts out. I do take pleasure in writing but it just seems like the first 10 to 15
minutes are generally wasted just trying to figure out how
to begin. Any suggestions or tips? Thanks!
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно