Собственный 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, что немного странно.
27.10.2010 в 12:14
28.10.2010 в 22:44
если соберусь, то статью напишу (:
19.05.2017 в 23:20
I'd be very thankful if you could elaborate a little bit
further. Bless you!
27.06.2017 в 00:32
read this paragraph i thought i could also create comment due
to this good post.
27.06.2017 в 02:45
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.
. . . . .
27.06.2017 в 03:30
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?
27.06.2017 в 07:48
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!
27.06.2017 в 08:44
be famous, due to its feature contents.
02.07.2017 в 12:20
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!
03.07.2017 в 01:34
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
03.07.2017 в 20:10
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!
04.07.2017 в 01:22
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!