Implementing a custom process

The process XML

A process in ArcGIS Image Server is defined by a set of parameters. These parameters can be defined by the user and are read by ArcGIS Image Server in the form of an Extensible Markup Language (XML) string. This XML string is known as the process XML. It consists of standard nodes that must be present for the process to be recognized. An example of a process XML is

<Process>

  <Description>Sultans Process</Description>

  <Name>SultansProcess</Name>

  <ProcessId>CustomProcess</ProcessId>

  <Version>1.0.0.0</Version>

  <Alias>Sultans Process [0]</Alias>

  <Enabled>True</Enabled>

</Process>

The standard nodes in every process XML are as follows:

DescriptionName of the process that will appear in the Processes Available list on the Image Service Properties dialog box.
NameName of the process. The value within this node must be the same name given to the custom process dynamic-link library (DLL).
ProcessIdA standard node defining the process being used. For a custom process this node must have the value "CustomProcess". This node tells ArcGIS Image Server that a custom process is being used and to use the Name node to load the custom process DLL.
Version—Version of the custom process DLL.
AliasThis node can be changed by the process chain manager to distinguish more than one instance of the same process in a process chain. This value must be unique for each process within the process chain.
EnabledSpecifies whether the process is to be used for processing. This node enables the user to quickly turn off a process without removing it from the chain.

Other nodes required as parameters for a process are added to this XML structure as child nodes to the Process node. The standard nodes help identify the process and control how it is displayed in the user interface. The additional nodes provide user-definable parameters that control how the process works. This is the same for custom and software-provided processes.

There are two parts to implementing a custom process. The first part is the implementation of the process itself by making the custom process DLL. This DLL is responsible for the main processing work. The second part lets you see the new process in ArcGIS Image Server and edit its parameters.

The custom process DLL

The first part in making a custom process is implementing the custom process DLL. This is a simple C++ DLL that implements the functions declared in the custom process user interface (CustomProcess.h). It uses the structures defined in the interface to communicate with ArcGIS Image Server, gets the parameters you enter that control the processing, and performs the processing. The functions defined in the interface file are briefly described below:

CustomProcess_Create—The CustomProcess_Create function is mainly responsible for creating the Client Handle object. The client handle is a unique id generated by the process for each client. It is used to ensure the dll can handle simultaneous calls by multiple clients. All subsequent calls to the process will use the client handle generated by the create function. The method to generate a client handle is left up to the user. The CustomProcess_Create function also takes in the Process XML as an array of node-value pairs.
CustomProcess_Initialize—The CustomProcess_Initialize function is used to parse the process parameters obtained in the CustomProcess_Create function. It also gets as input, the properties of the input raster that it is going to process in the form of a CustomRasterInfo object. This information is useful for validation e.g. if the process works only on a 3 band 8bit input, the rasterInfo object can be checked to see if the input raster matches those requirements.
CustomProcess_SetWindow—The CustomProcess_SetWindow function is used to define the area of the input raster that will be processed in rows and columns. It defines indexes for the start and stop rows and columns. The information provided in the CustomProcess_Initialize function coupled with the window extents enables the process to calculate the exact size of one row of the processed output. This information is used to allocate an output buffer used to store a processed row. The CustomProcess_SetWindow function is also used to define the window set on the input raster. This information is used to calculate the size of one row of the input raster. If the parameters that define the start and end row and columns are not changed, then the same parameters are used to set the window on the input raster. However, if the process requires more pixels, the start and end row and column values can be changed and a value of 1 returned to tell Image Server to use the changed window. If the process requires an auxiliary image, the createAuxRasterfn is used. This function uses the ID provided in the Process XML of the raster to request image server to load an auxiliary raster. It returns the properties for the auxiliary raster in the form of a CustomRasterInfo object.

Note: It is important to note that the window that is originally specified in the function defines the extents of the output of the process. The original window should be used to calculate the size of the output buffer and it can be used to determine the size of the input buffer as well, if the window is not changed. Any change to the start stop rows and columns specified in the parameters reflects a change in the size of the input buffer.

CustomProcess_GetRow—The CustomProces_GetRow function is responsible for returning one row of pixels of the processed raster corresponding to the rowIndex given. The rowIndex parameter corresponds to a row of pixels of the processed raster. The size of the row is can be determined by the information provided in the previous two functions. The startRow and endRow indexes provided by the CustomProcess_SetWindow function are used as the bounds for valid CustomProcess_GetRow calls, i.e. the rowIndex parameter ranges from startRow to (endRow 1). Processing the row can be done in a myriad of ways. The simplest way is to request one row of pixels from the input raster. This is done using the getRowfn callback function (see CustomProcess.h) to request one row of pixels from the input raster. The rowIndex supplied to the getRowfn is usually the same as the one given to CustomProcess_GetRow, unless the input window has been modified. The row is returned as an array of unsigned char values. The size of the row is calculated in the CustomProces_SetWindow function. This row is then processed and copied to the output buffer, which is then returned.

If an auxiliary image is required to generate the processed output, then the getAuxRowfn callback function is used to get a row from the auxiliary image.

If the size of the Input raster is different from the output (i.e. if the start/stop rows/columns were changed in the CustomProcess_SetWindow function) then the difference in sizes will have to be taken into account.

If the process requires more than one row of the input raster, then a buffer can be allocated and more than one call to the getRowfn can be made.

There is a lot of control offered by the interface if required.

CustomProcess_GetLastError—If any of the above functions fails for some reason, be it a validation check, or a failure from the callback functions, they have an easy way to communicate this to Image Server. The reason for the failure however is an essential tool to debug the error. This can be easily communicated to Image Server through the CustomProcess_GetLastError function. The function that failed writes out an error message into a string. This string is then copied into the string that is passed as a parameter to the CustomProcess_GetLastError function. In this way, users who use the Custom Process can easily see the reason for failures.
CustomProcess_Cleanup—The CustomProcess_Cleanup function is called after the processing is done. It is usually the last function to be called, signifying that the object will not be reused. Its main purpose is the cleanup of variables, allocated memory and destruction of the client handle.
CustomProcess_GetMetadata—Image Server provides the user with the option to view metadata from processes. The same functionality can be added to the Custom Process. If left blank, the metadata just shows that name of the Custom Process. If needed, the process can store information about its parameters and any other information it wishes in an array of NVMs (just like the process properties) and return it through the CustomProcess_GetMetadata function.
CustomProcess_SetAreaOfInterestSets the ground coordinates of the area of interestSometimes a process requires the ground coordinates of the input raster to perform its processing. This information is provided in the form of a AreaOfInterest object, the pointer to which is passed as a parameter in the CustomProcess_SetAreaOfInterest function.
CustomProcess_SetCallbackFunctions—Image Server provides a few callback functions to enable the Custom Process to have more control over its tasks. These are passed as pointers in the CustomProcess_SetCallbackFunctions function. These pointers must be stored uniquely for every client to the dll, so it is a good idea to link them to the client handle (see Samples).

The interface also defines structures that are used for transferring information between the image server and custom process.

Enumerators used for more readable code:

CustomProcess_PixelDataValue—This is an enumerator that defines values corresponding to different pixel data types. It is one parameter of the CustomRasterInfo object.
CustomProcess_ColorSpaceValue—This an enumerator that defines values corresponding to different color spaces. It is one parameter of the CustomRasterInfo object.

Structures used for communication of information:

CustomRasterInfo—The CustomRasterInfo object is used to communicate information about a raster. For the Custom Process it is used to communicate information pertaining to the input raster and the auxiliary raster if needed. The Custom Process also gives out the properties of the processed raster if needed.
NVMUsed to communicate properties required for the process and process metadata
AOIArea of interest (AOI) in ground coordinates

Once the DLL is implemented, put it in the same directory as the rest of the ArcGIS Image Server processes (The default location is <ArcGIS Image Server Installation Drive>\Program Files\ArcGIS\ImageServer10.0\Raster Processes\). The extension for the DLL should be “.dll” itself. It should not be “.process” like the rest of the ArcGIS Image Server processes.

This completes the first part of implementing a custom process. Even though the process is there, you will still not be able to see it in ArcGIS Imager Server until you complete the second part.

Learn more about implementing a custom process DLL

The custom process UI

The second part of implementing a Custom Process is making it visible to the user. This is done in the form of a UI, which displays information about the process and parameters which the user can edit, if needed. The UI then adds these parameters to the process XML for the custom process as new nodes. Image Server then adds the process XML to the correct file depending on the level the process was applied at.

The second part can be accomplished in two ways:

1. If you are familiar with Image Server XML Attribute Definition (.XADef) and XML Form Definition (XFDef) files, you can create a .XADef and .XFDef file for the new process and add them to the <ArcGIS Image Server Installation Drive>\Program Files\ArcGIS\ImageServer10.0\XADefs\Raster Processes\ directory.
2. If you are not familiar with Image Server XADef and XFDef files, the procedure is slightly more complex. You will need to implement a custom process user interface DLL. This is a Windows .NET assembly that displays the user interface for the process, gets the user-defined parameters, and updates the process XML. This assembly is added to the Global Assembly Cache (GAC). You need to generate a .XADef file for the custom process, which has the default values for the standard nodes specific to the custom process and other information that ArcGIS Image Server uses. You can generate this file using the provided CustomProcessXADef generator. Add it to the <ArcGIS Image Server Installation Drive>\Program Files\ArcGIS\ImageServer10.0\XADefs\Raster Processes\ directory.

The custom process user interface DLL

Developers who are familiar with .NET and Windows forms can implement a simple .NET DLL. The custom process user interface DLL is a .NET assembly that displays a user interface containing the parameters used by the custom process, which you can modify. The user interface DLL is also responsible for updating the process XML supplied to it by ArcGIS Image Server with the parameters changed by you. This involves changing existing nodes in the XML or adding new ones if needed. The updated XML is then returned to ArcGIS Image Server.

The class for the form implements the IRasterProcessUI interface. This interface provides functions used by ArcGIS Image Server to display the user interface, send the process XML, and receive the updated XML. The functions of the interface are described briefly below:

InitInitializes the class
ShowModalDialogDisplays the user interface
GetUpdatedXMLReturns the updated process XML
GetStatusReturns the status describing the error, if any occurred
GetPropertyGets a property from the user interface class
SetPropertySets a property on the user interface class

The DLL has to be added to the GAC before it can be used. For more info on adding a DLL to the GAC, see http://msdn2.microsoft.com/en-us/library/ex0ss12c(vs.80).aspx.

Learn more about implementing a custom process user interface DLL

The custom process .XADef generator

The standard process XML specific to a custom process is generated by ArcGIS Image Server using a .XADef file that defines the default values for the standard nodes for a particular process. It also defines properties used by ArcGIS Image Server to determine what level the process can be applied at and details about which DLL to use for the user interface. The .XADef file is unique to each process and has to be generated for each process.

The custom .XADef generator is provided for exactly this purpose. It is a tool, used along with the custom process user interface DLL, to generate the custom .XADef file.

CustomProcessXADefGen_Process

Below is a short description of the process and properties parameters required by the Custom Process XADef Generator:

Process tab
-Process nameThe name of the custom process DLL. This node is important because ArcGIS Image Server uses this name to search for the process DLL.
-AliasA standard node in the process Xml. Its value can be changed by the user or the process manager to differentiate between multiple instances of the process in the chain.
-DescriptionA short outline of what the process does. This will be displayed in the small window at the bottom of the Process Manager dialog box.
-Output directorySpecifies where to write the Custom Process XADef file that is generate. If undefined, the file is generated in the same directory as the executable.
Properties tab
-Custom user interface DLL pathThe path to the custom user interface DLL.
-Class nameThe names of the class associated with the user interface form derived from the IRasterProcessUI.
-Service processSignifies whether the process can be added at the service level.
-Raster processSignifies whether the process can be added at the raster level.
-Raster dataset processSignifies whether the process can be added at the raster dataset level.

The Custom Process user interface DLL has to be implemented before running this program because it is required by the program.

The generator also comes with a template file. This file is important and should not be edited or moved.

Reusability

A client to the custom process DLL might want to reuse rather than destroy the client handle object. This happens often in ArcGIS Image Server, especially during the optimization of a large service. Usually while previewing or consuming a published image service, the process object is created, initialized, used, and destroyed (cleaned up). However, when large requests are made, the objects can be reused without being destroyed. For example, after the last CustomProcess_GetRow has been called, a new area of interest is set and the object is initialized again without having been cleaned up. Take care while implementing the custom process DLL so that it supports such behavior.

Thread safety

The custom process DLL should be thread safe. ArcGIS Image Server is designed to take advantage of a multiprocessor environment. This makes it a very useful application, but it also introduces strict specifications for its components. One of them is the thread safety of all process DLLs. Make sure any custom process DLL can accept multiple simultaneous calls to its functions. This is one reason for the existence of the Client Handle Object, which you can see in the Sample custom process.

Callback functions

The callback function is used extensively throughout the developer documentation for processes. Callback functions are function pointers passed down as parameters to a functions which can be used to call a function in the calling object or anywhere else. In the process developer documentation, they are used to access functionality in ArcGIS Image Server in a simple, easy-to-use, and controlled manner. Below are the callback functions used in the custom process interface and brief descriptions for each.

CallbackObjectObject used as first argument to the callback functions
GetPropertyfnFunction used to request a special property from the ArcGIS Image Server
GetRowfnFunction used to request an input row
CreateAuxRasterfnFunction used to request ArcGIS Image Server to create an auxiliary raster
GetAuxRowfnFunction used to request a row of pixels from an auxiliary raster

Properties to be requested by a custom process

Listed below are the names of properties that a custom process can request using the 'GetPropertyfn' described above.

The properties below are described in the Changing image service properties in ArcGIS chapter in the ImageServer_Clients help file—

ClientProperties/Srs Spatial reference system based on which imagery should be displayed on the client application.
ClientProperties/SamplingMethod—Sampling method by which raster pixels are sampled by the server to match the resolution of the client request.
ClientProperties/MosaicMethodAn image returned to the client can be created from a number of input rasters. The mosaic method defines how the mosaic is created from different rasters.
ClientProperties/BackgroundColor—Background color of the image service. Where there is no imagery, the specified color is displayed.

The properties listed below are other properties specific to the client, which can be requested by the process.

ClientProperties/RequestId A unique GUID generated for each request.
ClientProperties/ScaleFactor A factor that is used to convert the pixel size of the area of interest from the units of the client spatial reference system to meters.
ClientProperties/SessionId A unique GUID generated per session.
ClientProperties/UserName The username of the client making the current request.
ClientProperties/IpAddress The IP address of the client making the current request.
ClientProperties/MachineName The name of the machine on which the client making the current request is running.

The properties listed below are specific to the raster on which the process is being applied.

RasterItemProperty/Id The Raster ID of the raster on which the process is being applied.
RasterItemProperty/PixelSize The Pixel Size in meters of the raster on which the process is being applied.
RasterItemProperty/Source The source image of the raster on which the process is being applied.

Note: Properties specific to the raster are only accessible when the process is applied at the Raster Dataset level or Raster level. This is because, the input image for a process applied at the service level is a combination of one or more rasters.

Ownership

Ownership refers to the objects that the custom process DLL cleans up. Usually this refers to objects created by the DLL, but sometimes ownership is transferred in ArcGIS Image Server and requires specific documentation. The custom process DLL is primarily responsible for the Client Handle object—its creation and destruction; all the members of the Client Handle structure, including the metadata array; and the safe deletion of any objects it creates for its internal purposes on cleanup.

It is not responsible for objects that are passed down to it, such as the processProps array that is a parameter in CustomProcess_Create, or the rasterInfo object passed as a parameter in the CustomProcess_Initialize function. As you can see in the sample custom process, the Client Handle structure maintains a pointer to the rasterInfo object and the processProps but does not delete it when cleanup is performed.

32-bit data

The GetRowfn callback function returns a pointer to an array of unsigned character values. Since these are integer values, floating point elevation data cannot be directly represented in them. Elevation data types are scaled so the precision is not lost when they are converted to unsigned character values. The scale value for 32-bit elevation data is 2^14 = 16384. To use elevation data, the values returned by GetRowfn should be divided by this value.

Example

For a detailed example on how to implement a custom process for ArcGIS Image Server, please see the Sample custom process.