На главную Пишем плагинСоздаем библиотеку Flip.dpr. Напишем сначала основную процедуру плагина: procedure ENTRYPOINT(selector : smallint; var param : FilterRecord; var data : integer; var result: smallint); cdecl; begin resultCode := noErr; case selector of filterSelectorAbout: DoAbout; filterSelectorParameters: DoParameters(param); filterSelectorPrepare: DoPrepare(param); filterSelectorStart: DoStart(param); filterSelectorContinue: DoContinue(param); filterSelectorFinish: DoFinish(param); else resultCode := filterBadParameters; end; { Нужно не забывать инициализировать переменную result при каждом вызове плагина } result := resultCode; end; В переменной selector нам передается код запрашиваемого действия. Каждое действие будет обрабатывать отдельная процедура. В записи param передаются параметры изображения и всякая другая информация. Переменную data мы никак не будем использовать. Для хранения значения параметра result будем использовать глобальную переменную resultCode. Это удобней и быстрей, чем все время передавать ссылку в параметрах процедур. Только нужно не забывать всегда инициализировать переменную (первая строчка процедуры) и возвращать значение редактору (последняя строчка). Теперь реализуем процедуры, обрабатывающие разные действия (по значению selector). DoAbout. Действие на запрос вывода диалога About плагина. Забудем пока про рекомендации по оформлению этого диалога и обойдемся просто процедурой MessageBox. procedure DoAbout; begin MessageBox(0, 'Мой первый фильтр.', 'Flip', MB_OK); end; DoParameters. Выводим пользователю диалог задания параметров. Обойдемся простым MessageBox с двумя кнопками: YES и NO. Если пользователь отменит обработку изображения, то вернем редактору код userCanceledErr. procedure DoParameters(var param : FilterRecord); var ans : integer; begin ans := MessageBox(0, 'Развернуть картинку?', 'Flip', MB_YESNO); case ans of 0: begin MessageBox(0, 'Невозможно загрузить диалог.', 'Ошибка', MB_OK); resultCode := userCanceledErr; end; IDYES: resultCode := noErr; else resultCode := userCanceledErr; end; end; При вызове плагина на этом этапе пользователь увидит такое окно: DoPrepare. Здесь нужно вычислить необходимый плагину размер памяти, но мы ничего делать не будем. procedure DoPrepare(var param : FilterRecord); begin end; DoStart. Вообще, в целях экономии ресурсов нужно обрабатывать изображение кусками, но для простоты запросим сразу все изображение. Запишем в поля param.inRect (исходное изображение) и param.outRect (результат) размеры всего изображения. Обратите внимание, что у каждого угла сначала указывается координата Y, а потом X. Если выделить прямоугольную часть изображения, то правый край выделения будет проходить по правым границам выделенных пикселей и правая координата выделения будет на 1 больше, чем максимальная координата выделенных пикселей. Аналогично с нижним краем. Т.е. горизонтальные координаты пикселей изменяются в диапазоне от 0 до param.imageSize.h - 1, но координаты соответствующего выделения будут 0 и param.imageSize.h. procedure DoStart(var param : FilterRecord); begin SetRect(param.inRect, 0, 0, param.imageSize.v, param.imageSize.h); param.outRect := param.inRect; param.inLoPlane := 0; param.inHiPlane := param.planes - 1; param.outLoPlane := 0; param.outHiPlane := param.planes - 1; end; Мы использовали процедуру SetRect. Напишем ее. Еще раз обращаю внимание на порядок задания параметров (сначала Y, а потом X - именно в таком порядке задаются поля записи Rect, будем следовать принятым в Photoshop соглашениям). procedure SetRect(var r : Rect; top, left, bottom, right : smallint); begin r.top := top; r.left := left; r.bottom := bottom; r.right := right; end; DoContinue. Редактор может несколько раз вызывать эту операцию, пока хотя бы одно из полей inRect, outRect или maskRect указывает на непустую часть изображения. Мы обрабатываем изображение сразу целиком и процедура вызовется всего один раз. procedure DoContinue(var param : FilterRecord); type DataBuffer = array [0..1000000000] of byte; var x, y, p : integer; inData : ^DataBuffer; outData : ^DataBuffer; begin inData := param.inData; outData := param.outData; { Переворачиваем изображение } for y := 0 to param.imageSize.v - 1 do for x := 0 to param.imageSize.h - 1 do for p := 0 to param.planes - 1 do outData[param.outRowBytes*y + param.planes*x + p] := inData[param.inRowBytes*y + param.planes*(param.imageSize.h - x - 1) + p]; SetRect(param.inRect, 0, 0, 0, 0); param.outRect := param.inRect; param.maskRect := param.inRect; end; DoFinish. Здесь можно произвести какие-нибудь завершающие действия для своих нужд. procedure DoFinish(var param : FilterRecord); begin end; Теперь укажем компилятору расширение библиотеки 8bf, присоединим ресурсы, подключим модули, объявим переменную resultCode и экспортируем процедуру ENTRYPOINT: library Flip; {$E 8bf} {$R Flip_prop.res} uses Windows, PITypes, PIFilter; var resultCode : smallint; { ... здесь должны быть описанные выше процедуры } exports ENTRYPOINT; end. Для компиляции плагина понадобятся модули PITypes.pas, PIGeneral.pas и PIFilter.pas. Эти модули я написал на основе аналогичных заголовочных файлов PITypes.h, PIGeneral.h и PIFilter.h из Adobe Photoshop 6.0 SDK. Назад | Содержание | Вперед
© Ярослав Музыкантов muzykantov@mail.ru |