您好,欢迎访问一九零五行业门户网

Photoshop滤镜开发简介--Photoshop回调函数

在上一篇文章中,我们介绍了开发photoshop滤镜插件最基本的一些概念和基础。ps为了满足插件的应用需求,同时也给插件提供了大量的回调函数(或服务)。例如,滤镜可以在一次调用后,保存最近一次用户设置的参数,并应用到下次调用或显示ui。这就是通过ps的回调函数完成的。这一篇文章我们将讲解最重要的一些ps回调函数。了解本文之后,我们将能够使用回调函数,完成例如存储我们的滤镜参数等必要的工作。本篇文章将比第一篇复杂和深入的多,但同时从这篇文章我们也可以一窥ps内部的秘密:缜密的系统设计,完善的接口以及复杂的工作机制。
(一)回调函数的分类:
         ps的回调函数按照获取他们的位置可以被分为两种:
        (1)direct callback:(可以直接调用的回调函数)
         这些回调函数是filterrecord的直接成员,可以从filterrecord参数中直接获取。例如advancestateproc(更新数据),testabortproc(测试用户取消)等,属于此类。
        (2)callback suite:(回调函数集)
         把函调函数按功能分类而提供的回调函数集,是一组回调函数组成的集合,它是一个指针,指向包含了一组回调函数的结构体(struct),我们可以从filterrecord获取某个回调函数集,然后调用其中的函数。
当前提供的主要回调函数集有:
         buffer suite:缓存内存管理(申请和释放缓存空间)。
         ui hook suite:一组和ui操作有关的函数。
         channel ports suite:通道端口读写,用于读写ps内部的真正选区数据!而不是副本拷贝。
         descriptor suite:描述符操作集,用于脚本记录系统,它本身又包含“读”“写”两个sub-suite(子函数集)。
         color space suite:颜色空间服务(颜色转换等)。
         handle suite:句柄管理(ps封装的句柄和内存管理,和buffer suite类似)。
         error suite:接收和向用户显示错误信息(接收不同类型的错误信息字符串)。
         getfilelist suite:获取文件列表(获取文件,调用浏览器浏览网页等)。
         getpath suite:   获取路径。
         zstring suite:封装字符串处理。
例如ui hook suite,提供了一组和ui有关的回调函数。它的第一版本被定义为:
ui hooks suite version1
#define kpsuihookssuiteversion1  1       // suite版本 
typedef struct 
 {
      processeventproc     processevent;
      displaypixelsproc    displaypixels;
      progressproc     progressbar;
      testabortproc     testabort;
      mainappwindowproc    mainappwindow;
      hostsetcursorproc    setcursor;
      hosttickcountproc    tickcount;
      pluginnameproc     getpluginname;
 } psuihookssuite1;
请注意,有些回调函数即属于直接回调,又被存储到某个suite中,例如testabout和displaypixels。我推测,在早期这些函数指针都被添加到filterrecord中,但随着升级,添加的回调函数越来越多,这样就会使filterrecord不断升级和增加成员,使维护困难,所以adobe开始把回调函数归类,分为几种suite,而只把suite放到filterrecord中,这样添加函数时只要添加到相应的suite,并升级该suite即可,而不影响filterrecord。这样早期的一些回调函数,就同时位于两个位置,filterrecord和其所属的suite中,导致他们即可以直接调用,也可以通过相应的suite来调用。
(二)suite pea (插件函数集管理模块(层),我翻译的名字,有待商讨)
        suite pea是一些adobe系列软件使用的插件体系,它为宿主程序提供了通用的插件管理核心层,并为插件提供了一个标准接口。
        和直接调用略有区别的是,函数集应该在使用前,先进行获取请求(acquired),在使用后释放(release)suite。
        一个获取的函数集本质上是一个结构体指针,指向一个包含了一组函数指针的结构,因此我们调用某个函数时候的形式如下:
        ssuite->function();
因此调用一个回调函数集中的函数,形式如下:
suite的获取和释放
admbasicsuite *sadmbasic;
//获取admbasic suite:
filterparamblock->sspbasic->acquiresuite(
              kadmbasicsuite,
              kadmbasicsuiteversion,
              &sadmbasic );
//调用
sadmbasic->beep( );
//释放
filterparamblock->sspbasic->releasesuite(
               kadmbasicsuite,
               kadmbasicsuiteversion );
(三)一部分比较重要的回调函数简介
下面我们将介绍一些我认为对于滤镜插件比较重要的回调函数。简单介绍这些回调函数的位置和使用方法。
3.1   displaypixelsproc( )
        功能:在指定的dc上在指定位置输出像素数据(绘制图片)。(当然这个功能实际上我们也可以自己来完成。)
        位置:direct callback,  ui hook suite;
        定义:
        oserr (*displaypixelsproc) (const pspixelmap *source,
                                                 const vrect *srcrect, int32 dstrow, int32 dstcol,
                                                 unsigned32 platformcontext);
        参数说明:
         source:第一个参数是一个描述像素信息的结构(pspixelmap)的指针,它定义如下:
pspixelmap struct define
typedef struct pspixelmap
{
 int32 version;        //版本号     
 vrect bounds;      //边界
 int32 imagemode;  //模式
 int32 rowbytes;    //扫描行宽度
 int32 colbytes;      //列字节数
 int32 planebytes;  //每通道字节数
 void *baseaddr;    //像素数据起始地址
//--------------------
//  省略.. 
} pspixelmap;
         srcrect:源矩形(源图的复制范围)
         dstrow,  dstcol:目标起始点坐标(左上角),因为不拉伸绘制,所以只要左上角坐标就够了。
         platformcontext:在windows系统下,即device context(dc);
3.2 descriptor suite(描述符函数集)
        描述符集主要是用于ps的脚本系统的,它用于记录(录制)一系列ps中的动作过程中需要的信息和参数,并能够回放。它有分为“读”和“写”两个子函数集。我们可以使用这个函数集,使ps的脚本系统“获知”我们的滤镜并能够记录到某个动作序列中。
        获取方式是先通过filterrecord得到pidescriptorparameters:
pidescriptorparameters struct define
typedef struct pidescriptorparameters
{
       int16 descriptorparametersversion;  //版本号
       int16 playinfo; //动作播放标识:0-对话框可选;1-需要对话框;2-无对话框;
       int16 recordinfo; //动作录制标识:0-对话框不显示;1-对话框显示;2-对话框静寂;
       pidescriptorhandle descriptor; //描述符的句柄,非常重要,我们将用它读写数据!
       writedescriptorprocs* writedescriptorprocs; //“写”子函数集
        readdescriptorprocs* readdescriptorprocs; //“读”子函数集
} pidescriptorparameters;
        然后我们就可以获得“读”或者“写”子函数集:
获取“读”和“写” sub-suite
//获得描述符参数结构:
pidescriptorparameters* descparams = gfilterrecord->descriptorparameters;
 if (descparams == null) return err;
//获得“读”子函数集:
 readdescriptorprocs* readprocs = gfilterrecord->descriptorparameters->readdescriptorprocs;
 if (readprocs == null) return err;
//获得“写”子函数集:
 writedescriptorprocs* writeprocs = gfilterrecord->descriptorparameters->writedescriptorprocs;
 if (writeprocs == null) return err;
获取了两个子函数集,我们就可以调用相应子函数集下面的函数进行“读”“写”我们的参数了。两个子函数集的使用和注册表操作类似,我们在进行读写前,首先需要打开相应描述符。因此我们先介绍打开和关闭描述符操作。
        openreaddescriptorproc( ):打开一个“读”描述符
        定义:
        pireaddescriptor (*openreaddescriptorproc) (pidescriptorhandle,  descriptorkeyidarray);
        参数说明:
        pidescriptorhandle:
        描述符句柄,我们将用它在后面的操作中读写数据,类似注册表的key。
        descriptorkeyidarray:
        uint32数组,存储需要查询的key集合。其相关定义为:
                  typedef unsigned long descriptorkeyid;
                  typedef descriptorkeyid descriptorkeyidarray[];
        数组里面的元素是你需要的key名,即你要查询的参数名称,即你要求查询哪些key。注意因为是int32类型,所以每个key可以容纳4个字符表示的ascii码,如果不足4个字节,可以用空格补足。例如,设置这个参数赋为可以设置{'pam1','pam2',null},这表示你需要查询两个参数,'pam1'和'pam2'。 例如脚本系统中,高斯模糊(gaussianblur)滤镜的key是'gsnb'。
       每个键值通过调用getkeyproc()来得到的,每返回一个值,这个字符串数组中的相应key将被设置为空('\0')。正常情况下,当你在调用closereaddescriptorproc()时,这个数组将变成全部是空,否则说明有的key并没有被查询到,这时你将丢失你的数据,或者通过显示对话框要求用户来提供数据。
closereaddescriptorproc( ):关闭一个“读”描述符
      定义:
      oserr (*closereaddescriptorproc) (pireaddescriptor);
      描述;关闭一个描述符,如果读过程中产生错误,它将返回最主要的错误。
getkeyproc( ):获取一个key
       定义:
        (*getkeyproc) (pireaddescriptor descriptor, descriptorkeyid *key, desctype *type, int16 *flags);
        描述:这个函数返回一个keyid(参数名),描述符类型,和标识。根据函数返回时的key,表示当前查询到的是哪个key。然后我们可以使用下面将要提到的相应的查询函数获得这个key的value。相关类型定义:
        typedef unsigned long descriptorkeyid;
        typedef unsigned long descriptortypeid;
openwritedescriptorproc( )
         定义: piwritedescriptor (*openwritedescriptorproc) (void);
         描述:打开一个写描述符,失败时,返回null;
         closewritedescriptorproc( )
         定义:
         oserr (*closewritedescriptorproc) (piwritedescriptor descriptor, pidescriptorhandle *newdescriptor);
         描述:
         这个函数关闭一个写描述符,并创建一个新的描述符句柄,你需要把新描述符通过设置到pidescriptorparameteres中,以返回给宿主程序。这里的函数的行为有些类似gdi操作中的selectobject。在gdi操作中,当你对设备上下文设置新的属性时,它会把现有属性返回给你,以期待你做个备份。
两个子函数集中读出和写入数据的函数:
         由于这里的函数较多,我们不一一逐个讲解,这里只是介绍大概形式,需要时单独讲解。
         大多数具有比较规范的特点(有少部分函数具有例外形式,我们后面单独介绍),即读用get开头,写用put开头,第一个参数是相应描述符,第二个参数是用于接收查询结果(或者用于存放写入数据)的相应类型数据指针。假设我们需要查询的数据类型是typename,则其如下:
oserr (*gettypenameproc) (pireaddescriptor descriptor,  typename *dest); //读
          oserr (*puttypenameproc) (piwritedescriptor descriptor,  descriptorkeyid, typename *dest);  //写:
          下面我们列出所有读子函数集和写子函数集的函数(在piaction.h中定义):
read descriptor sub-suite
//读子函数集成员
typedef struct readdescriptorprocs
 {
 int16 readdescriptorprocsversion; //版本号
 int16 numreaddescriptorprocs;     //函数数量
 openreaddescriptorproc  openreaddescriptorproc;  //打开一个读描述符
 closereaddescriptorproc  closereaddescriptorproc;  //关闭一个读描述符
 getkeyproc     getkeyproc;     //读取一个key
 getintegerproc    getintegerproc;  //获取一个整数
 getfloatproc    getfloatproc; //获取一个整数
 getunitfloatproc   getunitfloatproc; //获取一个double数
 getbooleanproc    getbooleanproc; //获取一个int32
 gettextproc     gettextproc; //获取一个text的handle
 getaliasproc    getaliasproc; //获取一个(别名?)的句柄
 getenumeratedproc   getenumeratedproc; //获取枚举类型
 getclassproc    getclassproc; //例外,提供一个类型,和一个接收对象句柄的指针
 getsimplereferenceproc  getsimplereferenceproc; //获取一个引用。
 getobjectproc    getobjectproc; //例外,额外提供对象类型
 getcountproc    getcountproc; //获取uint32数据
 getstringproc    getstringproc; //获取unsigned char[256](第一个字符是字符串长度,以\0结尾)
 getpinnedintegerproc  getpinnedintegerproc; //例外:获取指定范围内的整数,额外提供最小值和最大值。
 getpinnedfloatproc   getpinnedfloatproc;    //例外:获取指定范围内的double,额外提供最小值和最大值。
 getpinnedunitfloatproc  getpinnedunitfloatproc; //例外:获取指定范围内指定单位(距离,密度,角度,像素,百分比)的double,
                                                                       //额外提供最小值和最大值。
} readdescriptorprocs;
write descriptor sub-suite
//写子函数集成员,形式类似前面的函数,但都额外需要提供key
typedef struct writedescriptorprocs
 {
 int16 writedescriptorprocsversion;
 int16 numwritedescriptorprocs;
 openwritedescriptorproc  openwritedescriptorproc;
 closewritedescriptorproc closewritedescriptorproc;
 putintegerproc    putintegerproc;
 putfloatproc    putfloatproc;
 putunitfloatproc   putunitfloatproc;
 putbooleanproc    putbooleanproc;
 puttextproc     puttextproc;
 putaliasproc    putaliasproc;
 putenumeratedproc   putenumeratedproc;
 putclassproc    putclassproc;
 putsimplereferenceproc  putsimplereferenceproc;
 putobjectproc    putobjectproc;
 putcountproc    putcountproc; 
 putstringproc    putstringproc; 
 /* scoped classes are not for use by plug-ins in photoshop 4.0 */
  putscopedclassproc   putscopedclassproc;
 putscopedobjectproc   putscopedobjectproc; 
 } writedescriptorprocs;
读写参数实例:
         从脚本系统读出参数:假设我们的参数的key为'pam1',我们用一个临时变量param1来接收他:
read a parameter demo code
    pireaddescriptor token = null;  //读操作符
    descriptorkeyid key = null;  //uint32,即char*,键名
    descriptortypeid type = null; //描述符类型
    int32 flags = 0;     //标识
    descriptorkeyidarray array = { 'pam1', null }; //要查询的key集合
    double param1;    //我们要读取的参数
    //获取描述符参数结构
    pidescriptorparameters* descparams = gfilterrecord->descriptorparameters;
    if (descparams == null) return err;
    //获取descriptor suite中的“读”子函数集
    readdescriptorprocs* readprocs = gfilterrecord->descriptorparameters->readdescriptorprocs;
    if (readprocs == null) return err;
if (descparams->descriptor != null)
    {
        //打开“读”描述符
        token = readprocs->openreaddescriptorproc(descparams->descriptor, array);
        if (token != null)
        {
            //获取一个键
            while(readprocs->getkeyproc(token, &key, &type, &flags) && !err)
            {
                switch (key)
                {
                    case 'pam1'://读取到我们的参数
                        err = readprocs->getfloatproc(token, ¶m1);
                        break;
                    default:
                        err = readerr;
                        break;
                }
            }
            //关闭读描述符
            err = readprocs->closereaddescriptorproc(token);
            //释放描述符
            gfilterrecord->handleprocs->disposeproc(descparams->descriptor);
            descparams->descriptor = null;
        }
   }
        向脚本系统写入参数:同上面的例子:
write descriptor demo code
    oserr err = noerr;
    piwritedescriptor token = null;
    pidescriptorhandle h;
    const double param1 = 1.05;
pidescriptorparameters*    descparams = gfilterrecord->descriptorparameters;
    if (descparams == null) return err;
writedescriptorprocs* writeprocs = gfilterrecord->descriptorparameters->writedescriptorprocs;
    if (writeprocs == null) return err;
token = writeprocs->openwritedescriptorproc();
    if (token != null)
    {
        //写入参数~
        writeprocs->putfloatproc(token,'pam1',¶m1);
        //释放描述符
        gfilterrecord->handleprocs->disposeproc(descparams->descriptor);
        //关闭该“读”描述符
        writeprocs->closewritedescriptorproc(token, &h);
        //把新的描述符返还给photoshop
        descparams->descriptor = h;
    }
3.3  descriptorregistry suite:(描述符注册函数集)
        描述符注册函数集主要用于描述符的注册和获取。这样可以实现在滤镜多次被调用期间,委托ps保存我们的参数。它包含注册,移除,获取key的几个关键函数。
        register()
         描述:注册一个key。
         定义:
         oserr (*register)
         (
                /* in */ const char* key,     // 唯一的字符串或id
                /* in */ piactiondescriptor descriptor,  //描述符句柄
                /* in */ boolean ispersistent   // 是否委托ps维护以能够存储和恢复
         );
        erase()
        描述:移除一个key
        定义:
        oserr (*erase)
         (
                 /* in */ const char* key     // 唯一的字符串或id
         );
         get()
         描述:返回一个key。返回的描述符是一个拷贝,所以使用完后你必须主动释放它。
         定义:
         oserr (*get)
         (
                /* in */ const char* key,                        // 唯一的字符串或者id
                /* out */ piactiondescriptor* descriptor  // 使用完后释放他
          );
3.4 actiondescriptor suite: (动作描述符函数集)
         动作描述符函数集,用于存放keys(或对象)到描述符,以及从描述符读出他们,及其他描述符管理。这个函数集中同时包含了读写函数,使用方法和上一节中的描述符类似。它的定义如下:
psactiondescriptorprocs struct
typedef struct psactiondescriptorprocs
    {
    // allocates: descriptor
    spapi oserr (*make)(piactiondescriptor *descriptor);  
    spapi oserr (*free)(piactiondescriptor descriptor);
    spapi oserr (*gettype)(piactiondescriptor descriptor, descriptorkeyid key, descriptortypeid *type);
    // index is zero based
    spapi oserr (*getkey)(piactiondescriptor descriptor, uint32 index, descriptorkeyid *key);
    spapi oserr (*haskey)(piactiondescriptor descriptor, descriptorkeyid key, boolean *haskey);
    spapi oserr (*getcount)(piactiondescriptor descriptor, uint32 *count);
    spapi oserr (*isequal)(piactiondescriptor descriptor, piactiondescriptor other, boolean *isequal);
    spapi oserr (*erase)(piactiondescriptor descriptor, descriptorkeyid key);
    spapi oserr (*clear)(piactiondescriptor descriptor);
    /*存入数据*/    
    spapi oserr (*putinteger)(piactiondescriptor descriptor, descriptorkeyid key, int32 value);
    spapi oserr (*putfloat)(piactiondescriptor descriptor, descriptorkeyid key, double value);
    spapi oserr (*putunitfloat)(piactiondescriptor descriptor, descriptorkeyid key, descriptorunitid unit, double value);
    spapi oserr (*putstring)(piactiondescriptor descriptor, descriptorkeyid key,  char *cstrvalue);
    spapi oserr (*putboolean)(piactiondescriptor descriptor, descriptorkeyid key, boolean value);
    spapi oserr (*putlist)(piactiondescriptor descriptor, descriptorkeyid key,  piactionlist value);
    spapi oserr (*putobject)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid type,  piactiondescriptor value);
    spapi oserr (*putglobalobject)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid type,  piactiondescriptor value);
    spapi oserr (*putenumerated)(piactiondescriptor descriptor, descriptorkeyid key, descriptorenumtypeid type, descriptorenumid value);
    spapi oserr (*putreference)(piactiondescriptor descriptor, descriptorkeyid key,  piactionreference value);
    spapi oserr (*putclass)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid value);
    spapi oserr (*putglobalclass)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid value);
    spapi oserr (*putalias)(piactiondescriptor descriptor, descriptorkeyid key, handle value);
    /*获取数据*/
    spapi oserr (*getinteger)(piactiondescriptor descriptor, descriptorkeyid key, int32* value);
    spapi oserr (*getfloat)(piactiondescriptor descriptor, descriptorkeyid key, double* value);
    spapi oserr (*getunitfloat)(piactiondescriptor descriptor, descriptorkeyid key, descriptorunitid* unit, double* value);
    spapi oserr (*getstringlength)(piactiondescriptor descriptor, descriptorkeyid key, uint32 *stringlength);
    spapi oserr (*getstring)(piactiondescriptor descriptor, descriptorkeyid key, char *cstrvalue, uint32 maxlength);
    spapi oserr (*getboolean)(piactiondescriptor descriptor, descriptorkeyid key, boolean* value);
    spapi oserr (*getlist)(piactiondescriptor descriptor, descriptorkeyid key, piactionlist* value);
    spapi oserr (*getobject)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid* type, piactiondescriptor* value);
    spapi oserr (*getglobalobject)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid* type, piactiondescriptor* value);
    spapi oserr (*getenumerated)(piactiondescriptor descriptor, descriptorkeyid key, descriptorenumtypeid* type, descriptorenumid* value);
    spapi oserr (*getreference)(piactiondescriptor descriptor, descriptorkeyid key, piactionreference* value);
    spapi oserr (*getclass)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid* value);
    spapi oserr (*getglobalclass)(piactiondescriptor descriptor, descriptorkeyid key, descriptorclassid* value);
    spapi oserr (*getalias)(piactiondescriptor descriptor, descriptorkeyid key, handle* value);
    /*数组形式*/
    spapi oserr (*haskeys)(piactiondescriptor descriptor, descriptorkeyidarray requiredkeys, boolean *haskeys);
    spapi oserr (*putintegers)(piactiondescriptor descriptor, descriptorkeyid key, uint32 count,  int32* value);
    spapi oserr (*getintegers)(piactiondescriptor descriptor, descriptorkeyid key, uint32 count, int32* value);
    spapi oserr (*ashandle)(piactiondescriptor descriptor, pidescriptorhandle *value); /*转换为句柄*/
    spapi oserr (*handletodescriptor)(pidescriptorhandle value, piactiondescriptor *descriptor); /*句柄转换为描述符*/
    spapi oserr (*putzstring)(piactiondescriptor descriptor, descriptorkeyid key, aszstring zstring);
    spapi oserr (*getzstring)(piactiondescriptor descriptor, descriptorkeyid key, aszstring *zstring);
    spapi oserr (*putdata)(piactiondescriptor descriptor, descriptorkeyid key, int32 length, void *value);
    spapi oserr (*getdatalength)(piactiondescriptor descriptor, descriptorkeyid key, int32* value);
    spapi oserr (*getdata)(piactiondescriptor descriptor, descriptorkeyid key, void* value); 
    } psactiondescriptorprocs;
          把我们的参数写入描述符并注册的例子:在此之前,我们需要为我们的插件的参数指定一个唯一的id,以注册和提取属于我们的描述符,例如:
          #define pluginuniqueid  d9543b0c-3c91-11d4-97bc-00b0d0204936
写入我们的参数
//写入参数并注册
sperr writeregistryparameters(void)
{
    sperr err = noerr;
    //获得spbasicsuite,它是获取其他suite的基础
    spbasicsuite* basicsuite = gfilterrecord->sspbasic;
    //描述符注册函数集指针
    psdescriptorregistryprocs* registryprocs = null;
    //描述符函数集指针
    psactiondescriptorprocs* descriptorprocs = null;
    //描述符句柄
    piactiondescriptor descriptor = null;
    //我们的参数
    double param1=0.1;
//获取描述符注册函数集
    err = basicsuite->acquiresuite(kpsdescriptorregistrysuite, 
                                   kpsdescriptorregistrysuiteversion, 
                                   (const void **)®istryprocs);
//获取动作描述符函数集
    err = basicsuite->acquiresuite(kpsactiondescriptorsuite, 
                                   kpsactiondescriptorsuiteversion, 
                                   (const void **)&descriptorprocs);
err = descriptorprocs->make(&descriptor);
    //写入我们的参数
    err = descriptorprocs->putfloat(descriptor, 'pam1',param1);
    //注册指定id的描述符
    err = registryprocs->register(pluginuniqueid, descriptor, true);
    //释放描述符
    if (descriptor != null)
        descriptorprocs->free(descriptor);
    //释放函数集
    if (registryprocs != null)
        basicsuite->releasesuite(kpsdescriptorregistrysuite, 
                                 kpsdescriptorregistrysuiteversion);
    if (descriptorprocs != null)
        basicsuite->releasesuite(kpsactiondescriptorsuite, 
                                 kpsactiondescriptorsuiteversion);
    return err;
}
          读取我们的参数的例子:
读取注册的参数
//读取注册的参数
sperr readregistryparameters(void)
{
    sperr err = noerr;
    //获取基本函数集,spbasicsuite,通过它获取其他函数集
    spbasicsuite* basicsuite = gfilterrecord->sspbasic;
    psdescriptorregistryprocs* registryprocs = null;
    psactiondescriptorprocs* descriptorprocs = null;
    piactiondescriptor descriptor = null;
    double param1;
//获取描述符注册函数集
    err = basicsuite->acquiresuite(kpsdescriptorregistrysuite, 
                                   kpsdescriptorregistrysuiteversion, 
                                   (const void **)®istryprocs);
//获取动作描述符函数集
    err = basicsuite->acquiresuite(kpsactiondescriptorsuite, 
                                   kpsactiondescriptorsuiteversion, 
                                   (const void **)&descriptorprocs);
//获取指定id的描述符
    err = registryprocs->get(pluginuniqueid, &descriptor);
    //读取注册的参数
    err = descriptorprocs->getfloat(descriptor, 'pam1',¶m1);
    //释放描述符
    if (descriptor != null)
        descriptorprocs->free(descriptor);
    //释放描述符注册函数集
    if (registryprocs != null)
        basicsuite->releasesuite(kpsdescriptorregistrysuite, 
                                 kpsdescriptorregistrysuiteversion);
    //释放动作描述符函数集
    if (descriptorprocs != null)
        basicsuite->releasesuite(kpsactiondescriptorsuite, 
                                 kpsactiondescriptorsuiteversion);
    return err;
}
(四)小结
        这一篇文章中,我们介绍了一些photoshop提供给插件(不仅仅是给滤镜插件)的回调函数,他们主要分为两大类,一种是直接包含在插件参数结构中,称为直接回调函数;另一类是包含在回调函数集中的回调函数。
        对于直接回调函数,文本仅讲解了displaypixelsproc可以用于在设备dc上贴图。包括第一篇文中提到的advancestateproc,testabortproc,updateprogressproc都属于直接回调,同时有的直接回调函数又隶属于某个suite。
        对于回调函数集(callback suite),然后我们重点介绍了回调函数集中的descriptor suite中的读写,注册等操作,这个函数集可以使ps记录我们的滤镜参数到动作序列,也可以注册我们的滤镜参数以在多次调用期间保存和读取它们。其他回调函数集例如内存管理,颜色空间服务等函数集限于篇幅暂时还没有涉及。(--by hoodlum1980)
更多photoshop滤镜开发简介--photoshop回调函数。
其它类似信息

推荐信息