在第一篇文章中我們建立了一個沒有UI的基本濾鏡框架,並且引入PIPL資源使之能被PS加載到選單。在第二篇文章中我們又引入了濾鏡參數和對應的對話框資源,並且講解了對話框在濾鏡呼叫流程中的顯示時機。這篇文章我們將使濾鏡支援動作記錄和回放,也就是透過添加“術語資源”,使我們的濾鏡參數被PS的腳本系統所獲知(scripting-aware),並能夠記錄和回放。
從Photoshop 4.0開始引入了一個新的面板以及對應的指令和回呼函數:動作面板(浮動視窗),以及Descriptor 回呼函數集。動作面板是Photoshop腳本系統用於和使用者互動的接口,也是其核心所在。 Photoshop 5.0擴展了動作結構,使自動化插件能夠支援可描述的Photoshop指令。 (《Photoshop API Guide》第11章)
關於PS的 Scripting System,其來源是 PS 對蘋果系統的事件與腳本機制的繼承與支援,PS 的發展同時針對兩種作業系統平台。這裡我們介紹如何讓我們的濾鏡被PS腳本系統接納。
則以我們為方式增加術語資源(terminology resource)。因此首先在 pipl 資源中增加一個 HasTerminology 結構,其定義如下:
//这个属性指明滤镜是否提供了 'aete'资源。 typedef struct HasTerminology { int32 classID; // classID from 'aete' int32 eventID; // eventID from 'aete' or NULL if none int16 aeteResNum; // number of 'aete' resource CString uniqueID; // unique ID string (UUID or your own ™/©). If present, ignores AppleScript and keeps local to Photoshop. } HasTerminology;
這個結構將被增加到 r檔案的 pipl資源內。下面我們在pipl資源後面新增了 aete 資源。
在先前我們在一個通用的頭檔中新增一些aete資源所需要的定義:
//定义 Scripting Keys #define KEY_FILLCOLOR 'fiCo' #define KEY_OPACITY 'opcA' #define plugInSuiteID 'filR' #define plugInClassID 'filR' #define plugInEventID 'filR' #define plugInUniqueID "18EC4E8F-DB34-4aff-AF99-77C8013BD74F" #define plugInAETEComment "FillRed example filter By hoodlum1980" #define vendorName "hoodlum1980"
定義 Scripting Keys##define
KEY_FILLCOLOR 'fiCo'#define##
##define plugInSuiteID 'filR'
##define
然后我们对r文件增加aete 资源,aete 资源模板如下:
resource 'aete' (0) { // aete version and language specifiers { /* suite descriptor */ { /* filter/selection/color picker descriptor */ { /* any parameters */ / * additional parameters */ } }, { /* import/export/format descriptors */ { /* properties. First property defines inheritance. */ /* any properties */ }, { /* elements. Not supported for plug-ins. */ }, /* class descriptions for other classes used as parameters or properties */ }, { /* comparison ops. Not currently supported. */ }, { /* any enumerations */ { /* additional values for enumeration */ }, /* any additional enumerations */ /* variant types are a special enumeration: */ { /* additional types for variant */ }, /* any additional variants */ /* class and reference types are a special enumeration: */ { }, /* any additional class or reference types */ } } }
请注意的是这是一个针对PS插件的aete资源模板,也就是说它不仅仅针对滤镜,也包括其他种类的PS插件。关于其具体含义这里我们不做详细讨论,可以参考相关PS SDK文档。
【注意】即使有的节不需要,也必须提供一个空的花括号占位,而不能有缺失。
下面我们给出添加了aete资源后的 FillRed.r 文件,内容如下:
// ADOBE SYSTEMS INCORPORATED // Copyright 1993 - 2002 Adobe Systems Incorporated // All Rights Reserved // // NOTICE: Adobe permits you to use, modify, and distribute this // file in accordance with the terms of the Adobe license agreement // accompanying it. If you have received this file from a source // other than Adobe, then your use, modification, or distribution // of it requires the prior written permission of Adobe. //------------------------------------------------------------------------------- #define plugInName "FillRed Filter" #define plugInCopyrightYear "2009" #define plugInDescription \ "FillRed Filter.\n\t - http:\\www.cnblogs.com\hoodlum1980" #include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\includes\PIDefines.h" #ifdef __PIMac__ #include "Types.r" #include "SysTypes.r" #include "PIGeneral.r" #include "PIUtilities.r" #include "DialogUtilities.r" #include "CommonDefine.h" /* 包含了术语定义 */ #elif defined(__PIWin__) #define Rez #include "PIGeneral.h" #include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\PIUtilities.r" #include "E:\Codes\Adobe Photoshop CS2 SDK\samplecode\common\resources\WinDialogUtils.r" #include "CommonDefine.h" /* 包含了术语定义 */ #endif #include "PITerminology.h" #include "PIActions.h" /* 包含对 NO_REPLY 的定义 */ resource 'PiPL' ( 16000, "FillRed", purgeable ) { { Kind { Filter }, Name { plugInName }, Category { "Demo By hoodlum1980" }, Version { (latestFilterVersion << 16) | latestFilterSubVersion }, #ifdef __PIWin__ CodeWin32X86 { "PluginMain" }, #else CodeMachOPowerPC { 0, 0, "PluginMain" }, #endif SupportedModes { noBitmap, doesSupportGrayScale, noIndexedColor, doesSupportRGBColor, doesSupportCMYKColor, doesSupportHSLColor, doesSupportHSBColor, doesSupportMultichannel, doesSupportDuotone, doesSupportLABColor }, HasTerminology { plugInClassID, plugInEventID, 16000, /* int16 aeteResNum; number of 'aete' resource */ plugInUniqueID }, EnableInfo { "in (PSHOP_ImageMode, RGBMode," "CMYKMode, HSLMode, HSBMode, " "DuotoneMode, LabMode)" }, PlugInMaxSize { 2000000, 2000000 }, FilterCaseInfo { { /* array: 7 elements */ /* Flat data, no selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Flat data with selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Floating selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Editable transparency, no selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Editable transparency, with selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Preserved transparency, no selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination, /* Preserved transparency, with selection */ inStraightData, outStraightData, doNotWriteOutsideSelection, doesNotFilterLayerMasks, doesNotWorkWithBlankData, copySourceToDestination } } } }; resource 'aete' (16000, "FillRed dictionary", purgeable) { 1, 0, english, roman, /* aete version and language specifiers */ { vendorName, /* vendor suite name */ "FillRed Demo By hoodlum1980", /* optional description */ plugInSuiteID, /* suite ID */ 1, /* suite code, must be 1 */ 1, /* suite level, must be 1 */ { /* structure for filters */ plugInName, /* unique filter name */ plugInAETEComment, /* optional description */ plugInClassID, /* class ID, must be unique or Suite ID */ plugInEventID, /* event ID, must be unique to class ID */ NO_REPLY, /* never a reply */ IMAGE_DIRECT_PARAMETER, /* direct parameter, used by Photoshop */ { /* parameters here, if any */ "FillColor", /* parameter name */ KEY_FILLCOLOR, /* parameter key ID */ typeInteger, /* parameter type ID */ "Fill color in RGB", /* optional description */ flagsSingleParameter, /* parameter flags */ "Opacity", /* optional parameter */ KEY_OPACITY, /* key ID */ typeInteger, /* type */ "opacity in RGB", /* optional desc */ flagsSingleParameter /* parameter flags */ } }, { /* non-filter plug-in class here */ }, { /* comparison ops (not supported) */ }, { /* any enumerations */ } } };
在上面的文件中,我们可以看到我们的滤镜含有的两个主要参数:填充颜色 和 不透明度。位于 IMAGE_DIRECT_PARAMETER 结构中,typeInteger 指明它们是整数类型。flagsSingleParameter指明它们是基本类型(具有单一值)。此外,还可以把参数定义为枚举类型,同时把枚举的值域定义放在最后一节中,这里我们对此不做介绍了。
滤镜被重新编译后,我们在PS中对它录制一个动作,命名为“测试 FillRed”,录制完成后,可以看到在动作面板上的左侧,出现了对话框选项的CheckBox,我们可以设置播放时是否弹出对话框。我们把FillRed滤镜命令的下拉列表展开可以看到滤镜参数:
FillColor: 10
Opacity:90
请注意参数的名字就是来自于上面的aete资源中的定义的滤镜参数名字属性,这就是我们需要给它定义一个可读的参数名的原因。需要注意的是,由于我们把对话框上三个参数合成为了一个参数,这就使得上面的参数显示是三个参数的合成值(10进制)。因此这里为了看清楚,我就只设置了 R 和 O1,其他参数都为0,这样我们在动作面板看到的参数值就和滤镜的对话框上的参数值是一致的。否则我们看到的将是三个参数合成后的值。
更多怎样编写一个Photoshop滤镜-- Scripting Plug-ins相关文章请关注PHP中文网!