HDRShop supports a flexible plug-in architecture that lets a user write a new image editing operation and integrate it with the HDRshop interface. Plug-ins are special stand-alone command-line programs that receive parameters via the command-line arguments. Because the interface with HDRShop uses command-line arguments and the standard pipes, a plug-in can be written in any language and perform arbitrary processing on an image. For this tutorial, we will assume the language of choice is C++.
We will illustrate how to write a plug-in with a simple example plug-in that blurs an image and optionally halfsizes the image as well.
The plug-in communicates with HDRshop via the stdin stream. When the plugin is invoked with a single command-line argument "--help" or "/?" it must output its list of parameters in a specific format and then exit. Our plug-in will output the following message to stderr:
This is a simple test plugin to blur an image.
HDRSHOPFLAGS:
HDRSHOPVERSION: 1.0.1
USAGE: sample_plugin [input.pfm] [output.pfm] [options]
OPTIONS:
/V:[int=10] Blur Variance
/D Downsample 50%
The plugin must list information about itself in the following blocks:
Parameter descriptors are enclosed in square brackets: [], except for
a multiple-selection, which is surrounded by curly braces: {}. Inside the
square brackets is the descriptor type, followed by an optional default value.
If a default value is specified, then HDR Shop will initialize the option's
generated user interface to that value. The available parameter descriptor
types are:
Type | Descriptor | Default | Example (identifier + descriptor) | Notes |
boolean | false | /downsample | If this option is present on the command line, the value is true, otherwise false | |
integer | [integer=X],[int=X] | X | --iterations=[int=6] | |
string | [string=X],[str=X] | X | /greeting:[string=Hello World!] | |
float | [float=X] | X | /pi=[float] | In all cases, if the user specifies no value for an option, that option is not sent as a command-line argument. |
input filename |
[inputfilename=X] | X | /C:[inputfilename=my default.cfg] | Specifies a file that the plugin will read |
output filename |
[outputfilename=X] | X | /debugout=[outputfilename=debug.txt] | Specifies a file that the plugin will write |
rectangle | [selection] | See notes | /s[selection] | The user-interface for this option is a checkbox, defaulting to
checked. When checked, the current selection in HDRShop will be sent to the plugin, in the format: 100,100,200,200 (that's top,left,bottom,right). If there is no selection, the size of the entire image is returned. |
multiple choice |
{String1|String2|...|StringN} | String1 | --algorithm:{|fast|accurate|weird} | Multiple selection from the given list of strings. The first value is the default. |
When the plugin is selected by the user, HDRShop will execute "sample_plugin --help" and parse the resulting text. HDRShop will then create a dialogue box where the user can enter the values of all the plugin options. When the user has selected the options and clicks "Execute," HDRShop will call the plugin again, this time with all of the options packaged as command line arguments. Options are passed to the plugin in the same format they are specified above. For example, if the user selects a "Blur Variance" value of 15, HDRshop will pass the command-line argument /V:15. If the user has selected the "Downsample" option, HDRShop will pass the argument /D, otherwise it will leave off the argument.
For plugins that manipulate images, HDRShop passes them as .pfm files. See below for details on how to parse these files. HDRShop writes the current image to a temporary .pfm file, which it passes the plugin. If the plug-in is supposed to return in image to HDRShop, HDRShop specifies the name of the temporary file that the plugin should save the .pfm file to.
Now lets get to the actual source code for the plugin:
int main(int argc, char *argv[])
{
char *inputfilename = 0;
char *outputfilename = 0;
int downsample = 0;
int variance = 10;
if (argc == 1) {
printHelp();
exit(0);
}
for (x = 1; x < argc; x++) {
if (argv[x][0] == '-') {
if (argv[x][1] == '-') {
if (strncmp("help", &argv[x][2], 4) == 0) {
printHelp();
exit(0);
}
}
}
else if (argv[x][0] == '/') {
switch(argv[x][1]) {
case '?':
printHelp();
exit(0);
break;
case 'V':
variance = atoi(argv[x]+3);
break;
case 'D':
downsample = 1;
break;
}
}
else {
if (inputfilename == 0)
inputfilename = argv[x];
else
outputfilename = argv[x];
}
}
...
This section parses the command line arguments. If the program is passed /? or --help, it calls printHelp() which prints the message detailed above to stderr and then exits. Otherwise, the program looks for the forward-slash flag to indicate command line options. If the option is ?, it prints the help message. Otherwise, if the option is V, it parses the remaining part of the string for the integer value of variance. If the option is D, it sets the downsample flag to true. Finally, if the command line argument is not an option, it is assumed to be the input filename. If the input filename has been read, it is assumed to be the output filename.
if (!inputfilename)The function doError() just prints an error string to stderr and then calls exit() with a nonzero value to indicate to HDRshop that an error occurred. HDRshop will display everything that was output to stderr to the user as an error message. The floatimage class is a utility class. It provides a number of useful functions like file i/o from various formats, antialiased pixel reads, bluring, convolution, and other utilities. The full source code for floatimage and this sample plug-in is availible for download here .
doError(1);
if (!outputfilename)
doError(2);
floatimage fimg;
if (!fimg.LoadPFM(inputfilename))
doError(3);
fimg.fast_gaussian_blur(variance);
if (downsample)
fimg.halfsize();
if (!fimg.SavePFM(outputfilename))
doError(4);
return 0;
}
Once the plug-in has been compiled into a working executable, it must
be placed in a subdirectoy called "plugins" that is in the same directory
as the HDRShop executable. The name of the plug-in will appear in the plugins
pulldown menu.
Return to the tutorials