In the previous article, we introduced some of the most basic concepts and foundations for developing Photoshop filter plug-ins. Ps In order to meet the application needs of the plug-in, it also provides a large number of callback functions (or services) for the plug-in. For example, a filter can save the parameters set by the latest user after a call and apply them to the next call or display of the UI. This is done through the callback function of Ps. In this article we will explain some of the most important PS callback functions. After understanding this article, we will be able to use callback functions to complete the necessary work such as storing our filter parameters. This article will be much more complex and in-depth than the first one, but at the same time, from this article we can also get a glimpse of the internal secrets of PS: careful system design, perfect interface and complex working mechanism.
(1) Classification of callback functions:
The callback functions of PS can be divided into two types according to the location of obtaining them:
(1) Direct Callback: (can Directly called callback functions)
These callback functions are direct members of FilterRecord and can be obtained directly from the FilterRecord parameters. For example, AdvanceStateProc (update data), TestAbortProc (test user cancels), etc., fall into this category.
(2) CallBack Suite: (Receiving function set)
The recovery function set provided by the transfer function according to the function classification is a set of a set of callback functions. It is a pointer, which contains a set of sets The structure (struct) of the callback function, we can get a certain callback function set from FilterRecord, and then call the function in it.
The main callback function sets currently provided are:
Buffer Suite: Cache memory management (application and release of cache space).
UI Hook Suite: A set of functions related to UI operations.
Channel Ports Suite: Channel port reading and writing, used to read and write the real selection data inside PS! Rather than a copy copy.
Descriptor Suite: Descriptor operation set, used for script recording systems, which itself contains two sub-suites (sub-function sets): "read" and "write".
Color Space Suite: Color space services (color conversion, etc.).
Handle Suite: Handle management (PS encapsulated handle and memory management, similar to Buffer suite).
Error Suite: Receive and display error messages to users (receives different types of error message strings).
GetFileList Suite: Get the file list (get files, call the browser to browse the web, etc.).
GetPath Suite: Get the path.
ZString Suite: Encapsulates string processing.
For example, UI Hook Suite provides a set of callback functions related to UI. Its first version was defined as:
UI Hooks Suite Version1
#define kPSUIHooksSuiteVersion1 1 // suite version
typedef struct
{
ProcessEventProc processEvent;
DisplayPixelsProc displayPixels;
ProgressProc progressBar;
TestAbortProc testAbort;
MainAppWindowProc MainAppWindow;
HostSetCursorProc SetCursor;
HostTickCountProc TickCount;
PluginNameProc GetPluginName;
} PSUIHooksSuite1;
# Please note that some callback functions are direct callbacks and are stored in a suite , such as testAbout and displayPixels. I speculate that in the early days, these function pointers were added to FilterRecord, but with the upgrade, more and more callback functions were added, which would cause FilterRecord to continuously upgrade and add members, making maintenance difficult, so Adobe began to add callback functions Classification is divided into several suites, and only the suite is placed in FilterRecord. In this way, when adding a function, you only need to add it to the corresponding suite and upgrade the suite without affecting the FilterRecord. In this way, some early callback functions are located in two places at the same time, FilterRecord and the suite to which they belong, so that they can be called directly or through the corresponding suite.
(2) Suite PEA (Plug-in function set management module (layer), my translated name, to be discussed) Suite PEA is a plug-in system used by some Adobe series software. It provides a common plug-in management core layer for the host program and a standard interface for plug-ins.
It is slightly different from the direct call in that the function set should be acquired (Acquired) before use, and the suite should be released (release) after use.
# );
Therefore, a function in the callback function set is called, in the following form:
Suite的获取和释放
ADMBasicSuite *sADMBasic;
//获取ADMBasic Suite:
filterParamBlock->sSPBasic->AcquireSuite(
kADMBasicSuite,
kADMBasicSuiteVersion,
&sADMBasic );
//调用
sADMBasic->Beep( );
//释放
filterParamBlock->sSPBasic->ReleaseSuite(
kADMBasicSuite,
kADMBasicSuiteVersion );
# (3) Part of the more important callback function profile
This Here we will introduce some recovery functions that I think are more important for the filter plug -in . Briefly introduce the location and use of these callback functions.
3.1 DisplayPixelsProc( )
Function: Output pixel data (draw a picture) at the specified position on the specified DC. (Of course, we can actually complete this function ourselves.)
Location: Direct Callback, UI Hook Suite;
Definition:
OSErr (*DisplayPixelsProc) (const PSPixelMap *source ,
CONST VRECT *SRCRECT, Int32 DStrow, Int32 DStcol,
UNSIGNED32 PlatformContext);
## Source Instructions: Source: The first parameter is a structure that describes pixel information (PSPIXELMAP). pointer, which is defined as follows:
PSPixelMap Struct Define
typedef struct PSPixelMap{
int32 version; /
Version number # int32 imageMode; //
Mode## int32 rowBytes; / /Scan line width
# int32 colBytes; //Number of column bytes
int32 planeBytes; //Number of bytes per channel
void
*baseAddr; //Pixel data starting address
//--------------------// Omitted .. } PSPixelMap;
srcRect: Source rectangle (copy range of the source image)
dstRow, dstCol: Target starting point coordinates (upper left corner), because it is not stretched and drawn, so only the coordinates of the upper left corner are enough.
platformContext: Under Windows system, that is, device context (DC);
3.2 Descriptor suite (descriptor function set)
The descriptor set is mainly used for the script system of PS. It is used to record (record) the information and parameters required during a series of actions in PS, and can be played back. It is divided into two sub-function sets: "read" and "write". We can use this function set to make PS's scripting system "know" our filters and record them into an action sequence.
The way to obtain it is to first get PIDescriptorParameters through FilterRecord:
PIDescriptorParameters Struct Define
typedef struct PIDescriptorParameters
{
int16 descriptorParametersVersion; //Version number
## int16 playInfo; // Action playback identification: 0-dialog box optional; 1-dialog box required; 2-no dialog box;
## int16 recordInfo; //Action recording identification: 0-The dialog box is not displayed; 1-The dialog box is displayed; 2-The dialog box is silent; ## PIDescriptorHandle descriptor;
//The handle of the descriptor is very important, we will use it to read and write data! ## WriteDescriptorProcs
* writeDescriptorProcs; //"Write" sub-function Set## ReadDescriptorProcs*
readDescriptorProcs; //"read" sub Function set} PIDescriptorParameters;
Then we can get the "read" or "write" sub-function set:
Get the "read" and "write" sub-suite
//Get the descriptor parameter structure:
PIDescriptorParameters*## descParams = gFilterRecord- >descriptorParameters;
if (descParams == NULL) return err;
##//Get the "read" sub-function set:
ReadDescriptorProcs*## readProcs = gFilterRecord->descriptorParameters ->readDescriptorProcs; if
(readProcs == NULL) return err;
//
Get the "write" sub-function set: WriteDescriptorProcs
* writeProcs = gFilterRecord-> descriptorParameters->writeDescriptorProcs; if
(writeProcs == NULL) return err;
Having obtained two sub-function sets, we can call the functions under the corresponding sub-function sets to "read" and "write" our parameters. The use of the two sub-function sets is similar to the registry operation. Before reading and writing, we first need to open the corresponding descriptor. Therefore we first introduce the opening and closing descriptor operations.
OpenReadDescriptorProc( ): Open a "read" descriptor
Definition:
PIReadDescriptor (*OpenReadDescriptorProc) (PIDescriptorHandle, DescriptorKeyIDArray);
Parameter description:
PIDescriptorHandle:
Descriptor handle, we will use it to read and write data in subsequent operations, similar to the Key of the registry.
DescriptorKeyIDArray:
uint32 array, stores the key set that needs to be queried.其相关定义为:
typedef unsigned long DescriptorKeyID;
typedef DescriptorKeyID DescriptorKeyIDArray[];
The elements in the array are the key names you need, that is, the parameter names you want to query, that is, which keys you want to query. Note that because it is an int32 type, each key can hold an ASCII code represented by 4 characters. If it is less than 4 bytes, it can be filled with spaces. For example, setting this parameter assignment can set {'Pam1','Pam2',NULL}, which means you need to query two parameters, 'Pam1' and 'Pam2'. For example, in the script system, the key of the Gaussian Blur (GaussianBlur) filter is 'GsnB'.
Each key value is obtained by calling GetKeyProc(). Each time a value is returned, the corresponding key in this string array will be set to empty ('\0'). Under normal circumstances, when you call CloseReadDescriptorProc(), this array will become all empty. Otherwise, it means that some keys have not been queried. At this time, you will lose your data or display the dialog box. Ask users to provide data.
## CloseReadDescriptorProc(): Close a "read" descriptor Definition:
OSErr (*CloseReadDescriptorProc) (PIReadDescriptor);
Description; Close a descriptor. If an error occurs during reading, it will return the main error.
GetKeyProc( ): Get a Key
Definition:
(*GetKeyProc) (PIReadDescriptor descriptor, DescriptorKeyID *key, DescType *type, int16 *flags); Description: This function returns a KeyID (parameter name), descriptor type, and identification. According to the key returned by the function, it indicates which key is currently queried. We can then use the corresponding query function mentioned below to obtain the value of this key. Related type definitions:
typedef unsigned long DescriptorKeyID; typedef unsigned long DescriptorTypeID;
Definition: PIWriteDescriptor (*OpenWriteDescriptorProc) (void);
Description: Open a write descriptor, if failed, return NULL;CloseWriteDescriptorProc()
Definition: OSErr ( *CloseWriteDescriptorProc) (PIWriteDescriptor descriptor, PIDescriptorHandle *newDescriptor);
Description:
This function closes a write descriptor and creates a new descriptor handle. You need to set the new descriptor to PIDescriptorParameteres to return it to the host program. The behavior of the function here is somewhat similar to SelectObject in GDI operations. In a GDI operation, when you set new properties on the device context, it returns the existing properties to you, expecting you to make a backup.
‐ ’ ’ s ’ s ’ s ’ s to ’ s ’ s ‐ ‐ ‐ ‐ ‐ ‐ ‐ ‐ I will explain them one by one. Here I only introduce the general form and explain them separately when necessary. Most have relatively standardized characteristics (there are a few functions with exception forms, which we will introduce separately later), that is, reading starts with Get, writing starts with Put, the first parameter is the corresponding descriptor, and the second parameter is The corresponding type of data pointer used to receive query results (or to store written data). Assuming that the data type we need to query is TypeName, it is as follows:
OSErr (*Get
TypeName
Proc) (PIReadDescriptor descriptor, TypeName *dest); //Read OSErr (*PutTypeName
Proc) (PIWriteDescriptor descriptor, DescriptorKeiD, Typename * Dest); // Write: Below we list the functions of all readable functions and write sub -function sets (at pilation. h): Read Descriptor sub-suite
##Code highlighting produced by Actipro CodeHighlighter (freeware)http:// m.sbmmt.com/-->
////写子函数集成员,形式类似前面的函数,但都额外需要提供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;
Reading and writing parameter examples:
Reading parameters from the script system: Suppose the key of our parameter is 'Pam1', we use a temporary variable param1 to receive it:
Read A Parameter Demo Code
PIReadDescriptor token = NULL; //Read operator
DescriptorKeyID key = NULL; //uint32, that is, char*, Key name
DescriptorTypeID type = NULL; //Descriptor Type
int32 flags = 0; #//Identification# DescriptorKeyIDArray array
= { 'Pam1', NULL }; //The key set to be queried
double param1; //The parameters we want to read //
Get the descriptor parameter structure## PIDescriptorParameters
* descParams = gFilterRecord->descriptorParameters; if
(descParams == NULL) return err; //
Get the "read" sub-function in Descriptor Suite Set## ReadDescriptorProcs*
readProcs = gFilterRecord->descriptorParameters->readDescriptorProcs; if (readProcs
== NULL) return err; if (descParams->descriptor != NULL)
{
//Open the "read" descriptor
## 1 readProcs->openReadDescriptorProc(descParams->descriptor, array); if
(token != NULL)
##
while(readProcs->
getKeyProc(token, &key, &type, &#flags) && !err) ## case 'Pam1
'
:/ /
Read our parameters
## >getFloatProc(token, ¶m1); #default: Since #
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: (Descriptor registration function set)
The descriptor registration function set is mainly used for the registration and acquisition of descriptors. This allows ps to be entrusted to save our parameters while the filter is called multiple times. It contains several key functions for registration, removal, and key acquisition.
Register()
.
# or descriptor, //Descriptor handle
Remove a Key Definition:
OSErr (*Erase)
(
) /* IN */ const char* key // Unique string or ID
);
##Get()
Description: Returns a Key. The returned descriptor is a copy, so you must actively release it after use.
/* OUT */ PIActionDescriptor* descriptor / / Release him after use );
3.4 ActionDescriptor suite: (Action descriptor function set)
## Action Descriptor function set, is used to store keys (or objects) into descriptors, read them from descriptors, and other descriptor management. This function set contains both read and write functions, and the usage method is similar to the descriptor in the previous section. It is defined as follows:
PSActionDescriptorProcs Struct
Code highlighting produced by Actipro CodeHighlighter (freeware)http:// m.sbmmt.com/-->typedef
struct
PSActionDescriptorProcs { //
ALLOCATES: descriptor//Write parameters and register
SPErr WriteRegistryParameters(void)
{
SPErr err = noErr;
#// Obtain SPBasicSuite, which is the basis for obtaining other Suites
## SPBasicSuite* basicSuite = gFilterRecord->sSPBasic;
// Descriptor registration function set pointer
## PSDescriptorRegistryProcs*## registryProcs = NULL; //
Descriptor function set pointer PSActionDescriptorProcs
* descriptorProcs = NULL; //
Descriptor handle PIActionDescriptor descriptor
= NULL; //
Our parameters
double param1=0.1;
//
Get the descriptor registration function set err
= basicSuite->AcquireSuite(kPSDescriptorRegistrySuite, (const
void **)®istryProcs);//Get the action descriptor function set
## err = basicSuite ->AcquireSuite(kPSActionDescriptorSuite, (
const void **)&descriptorProcs); ## descriptorProcs
->Make(&descriptor); //Write us Parameters err =
descriptorProcs
->PutFloat(descriptor, 'Pam1',param1); //Register the descriptor of the specified ID err = registryProcs- >Register(plugInUniqueID, descriptor, true);
//
Release descriptor
if
(descriptor != NULL) descriptorProcs->Free (descriptor);
//Release function set
if
(registryProcs != NULL) basicSuite->ReleaseSuite(kPSDescriptorRegistrySuite, kPSDescriptorRegi strySuiteVersion);
if (descriptorProcs
!= NULL) basicSuite->ReleaseSuite(kPSActionDescriptorSuite, Example of reading our parameters:
Reading registered parameters
//Read registered parameters
SPErr ReadRegistryParameters(void)
{
SPErr err = noErr;
/ /Get the basic function set, SPBasicSuite, and get other function sets through it
SPBasicSuite* basicSuite = gFilterRecord->sSPBasic;
PSDescriptorRegistryProcs* registryProcs = NULL;
PSActionDescriptorProcs* descriptorProcs = NULL;
PIActionDescriptor descriptor = NULL;
double param1;
//Get the descriptor registration function set
## err = basicSuite-> AcquireSuite(kPSDescriptorRegistrySuite, #const
void **)®istryProcs); //
Get the action descriptor Function set err
= basicSuite->AcquireSuite(kPSActionDescriptorSuite ) ** )
&descriptorProcs);
//Get the descriptor of the specified ID
## err = registryProcs->Get(plugInUniqueID, &descriptor);
//Read registered Parameter err
= descriptorProcs->GetFloat(descriptor, 'Pam1',¶m1);
//Release descriptor
if (descriptor != NULL ) descriptorProcs
->Free(descriptor);
//Release descriptor registration function set
## if (registryProcs != NULL) #->
ReleaseSuite(kPSDescriptorRegistrySuite,
## ##->
ReleaseSuite(kPSActionDescriptorSuite, ## (4) Summary
This article, we introduced some photoshop to the plug -in (not just to the filter plug -in) recovery function. It is divided into two major categories, one is directly included in the plug-in parameter structure, called a direct callback function; the other is a callback function included in the callback function set. For the direct callback function, the text only explains that DisplayPixelsProc can be used to map on the device DC. Including AdvanceStateProc, TestAbortProc, and UpdateProgressProc mentioned in the first article, they are all direct callbacks, and some direct callback functions belong to a certain Suite. but also for the callback function set (Callback Suite), we focused on the reading, writing, registration and other operations in the Descriptor Suite in the callback function set. This function set can enable PS to record our filter parameters into the action sequence, or it can Register our filter parameters to save and read them across multiple calls. Other callback function sets such as memory management, color space services and other function sets have not been covered yet due to space limitations. (--By hoodlum1980)For more introduction to Photoshop filter development--Photoshop callback function related articles, please pay attention to the PHP Chinese website!