decoration

Plug-in development

decoration

Development of external modules (plug-ins) for PhotoFiltre and PhotoFiltre Studio.
Date of document: April 2005

Contents of this document

  1. Introduction
  2. Module types:
    1. Modules of type Filter
    2. Modules of type Image
    3. Modules of type Import
    4. Modules of type Export
    5. Modules of type Tool
  3. Compilation requirements
  4. Exported functions
  5. Constants and structures
  6. Initialization functions
  7. Language functions
  8. Support functions
  9. Advice
  10. Appendix
    1. Delphi units
    2. Development license

Introduction

The external modules (plug-ins) are proprietary for PhotoFiltre and at the moment there is no compatibility with modules of other applications. They are stored with the '.pfl' (PhotoFiltre Library) extension in the subfolder 'Plugins'. They are simple DLLs, developed in Delphi, but the exported functions must follow certain rules. At each startup, PhotoFiltre scans that folder and loads all recognized modules.

Module types

PhotoFiltre knows various types of modules. Each type is placed in a different menu.

Modules of type Filter

They are only available in 16 million color mode (24 bit) without transparency and apply to the selection of the current image.

Rules:

Examples: Red eye reduction, automatic adjustments.

Modules of type Image

They are available whatever the number of colors and transparancy are and they apply to the entire current image. They are destined for functions that modify the size of the image, the transparency or the number of colors.

Rules:

Examples: Exterior frames with texture, copyright insertion.

Modules of type Import

They are meant for import functions and are always available (with or without image).

Rules:

Examples: Imports of digital photographs, JPEG2000, different formats.

Modules of type Export

They are meant for functions exporting the current image.

Rules:

Examples: JPEG2000, binary formats.

Modules of type Tool

They are meant for functions that can't be classified under the types above.

Rules:

Examples: Creation of images, Selection editor, lossless JPEG rotation, slideshow.

Compilation requirements

All procedures and functions have the 'stdcall' directive (standard API). All Integers are 32 bits in size. The type LongBool is a 32 bit boolean. All strings are passed by a PChar pointer and by buffers. Bitmap exchanges are in the internal PhotoFiltre 24 bit format.

Exported functions

function RegisterPluginHeader: PPluginHeader;

Returns a pointer to the address of the record for this entry (see below).

function RegisterPluginLanguage: PPluginLanguage;

Returns a pointer to the address of the language structure (see below). Allows a module to retrieve the language used by PhotoFiltre. This function is optional.

function RegisterPluginStruct: PPluginStruct;

Returns a pointer to the address of the execution structure (see below).

function RegisterCompatibility: Integer;

Allows managing the compatibility of modules. Modules developed in C++, C, ASM or anything else but Delphi 6 must return a compatibility equal to or above 2.

function RegisterApplication: PApplication;

Returns the address of the application of the module. It is optional if the module doesn't use a parameter entry form. If a function creates a form, it is obligatory, since it is required internally. (Modules in C++, C and ASM must manage this function themselves).

function RegisterPluginGlyph: HBitmap;

Returns a handle of the bitmap to be used in the Plug-ins bar. The bitmap must be 19x19 pixels in size.

function Execute: Integer;

Main function which executes the module. Returns 0 in case of an error or in case of a cancellation, and 1 in case of success. The return value is important for the management of the Undo/Redo functions.

procedure SetPointClick(Point: TPoint; Button: Integer);

For modules of the types doPreview and doColorPicker (see ShowForm). It is executed by PhotoFiltre at each click on the image and allows the module to retrieve the position and the button pressed.

Studio version: To get a position relative to the layer you must use the function GetLayerPos.

procedure SetColorPicker(Color: TColor);

For modules of type doColorPicker (see ShowForm). It is executed by PhotoFiltre on each click on the image and allows the module to retrieve the color under the cursor.

Constants and structures

const
  MaxLongStr = 256;
  MaxShortStr = 64;
  RGBColorCount = 256 * 256 * 256; // 16 million colors
  
var
  PluginErrorMsg: string = 'Error during the execution of the module!';
  
type
  PApplication = ^TApplication;
  
  PPluginHeader = ^TPluginHeader;
  TPluginHeader = packed record
    <list of fields>
  end;
  
  PPluginLanguage = ^TPluginLanguage;
  TPluginLanguage = packed record
    <list of fields>
  end;
  
  PPlgImage = ^TPlgImage;
  TPlgImage = packed record
    piSize: Integer; // Size of the structure
    piWidth: Integer; // Width in pixels
    piHeight: Integer; // Height in pixels
    piWidthSize: Integer; // X size in bytes (piWidth * piByteCount)
    piScanlineSize: Integer; // Complete scanline in bytes (32 bit alignment)
    piByteCount: Integer; // Number of bytes per pixel
    piDataSize: Integer; // Total size of buffer (piScanlineSize * piHeight)
    piBuffer: Pointer; // Address of transfer buffer
    piBitmap: TBitmap; // Pointer to a TBitmap object
    piHandle: HBitmap; // Windows bitmap handle 
  end;
  
  PPluginStruct = ^TPluginStruct;
  TPluginStruct = packed record
    <identifiers>
    <functions>
  end;
  
  EPluginException = class(Exception);

Initialization functions

They allow the description of the module, its type, its author and some other additional information. The functions are to be used by the function RegisterPluginHeader.

procedure SetHeaderAuthor(Author: string);

Name and copyright of the author. The length is truncated to MaxShortStr.

procedure SetHeaderCaption(Caption: string);

Name of the module. It is at the same time the title that appears in the PhotoFiltre menus.

Its length is truncated to 30 characters. The title can end on ellipses ('...') to indicate parameter entry.

procedure SetHeaderComment(Comment: string);

Comment on a maximum of 3 lines (#13 for a line break).

The length is truncated to MaxLongStr.

type
  TMenuOption = (moRGBColors, moIndexedColors, moTransparent, 
    moNoTransparent, moSelected, moNotSelected, moNeedImage, 
    moNeedMoreThanOneImage, moLayered, moNotLayered, moRGBAColors, 
    moImageJpeg, moImageGif, moImagePng, moImageBmp, moImageTiff, 
    moImagePfs, moJpegExifData);
    
  TMenuOptions = set of TMenuOption;
  
procedure SetHeaderMenuOptions(Options: TMenuOptions);

Allows disabling the menu at the PhotoFiltre level if certain conditions are not met:

type
  TPluginType = (ptFilter, ptImage, ptFileImport, ptFileExport, ptTool);
  
procedure SetHeaderPluginType(PluginType: TPluginType);

Determines the type of the module.

procedure SetHeaderVersion(Version: string);

Version and date of the module.

The length is truncated to MaxShortStr.

Language functions

They allow you to retrieve information about the language used by PhotoFiltre. These functions can be used in RegisterPluginHeader and Execute in order to set the language for the module.

They are only available if the function RegisterPluginLanguage is exported.

function GetLanguageCode: string;

Returns the two-character code indicating the language used by PhotoFiltre.

Examples: "FR", "EN".

function GetLanguageStr: string;

Returns the language used by PhotoFiltre.

Examples: "Français", "English".

Support functions

They allow the communication of PhotoFiltre with the module.

These functions are to be used in the exported function Execute.

All levels of compatibility

See RegisterCompatibility for more information.

procedure BeginFilter(Msg: string = ''; ChangeCursor: Boolean = True);

Shows a message in the status bar at the start of the handling of the filter. If Msg is an empty string the default messsage is used. ChangeCursor indicates if the cursor should take the form of the sandglass during the handling.

procedure EndFilter;

Shows a message in the status bar at the end of the handling of the filter.

function MainHandle: HWND;

Returns the window handle of the main window of PhotoFiltre.

function ImageExists: Boolean;

Returns true is at least one image is open.

function XP_ThemesEnabled: Boolean;

Returns true if PhotoFiltre uses Windows XP themes for display (only under Windows XP).

function GetImgRect: TRect;

Returns the dimensions of the current image in the form of a rectangle (0, 0, Width, Height). Returns a zero rectangle if no image present.

function GetImgWidth: Integer;

Returns the width of the current image, or 0 if none present.

function GetImgHeight: Integer;

Returns the height of the current image, or 0 if none present.

function IsSelected: Boolean;

Returns true if there is a current selection in the active image.

function GetSelRect: TRect;

Returns the selection rectangle (maximum limits) of the current image. Equivalent to GetImgRect if there is no selection.

function GetSelWidth: Integer;

Returns the width of the current selection, or 0 if there is none. Equivalent to GetImgWidth if there is no selection.

function GetSelHeight: Integer;

Returns the height of the current selection, or 0 if there is none. Equivalent to GetImgHeight if there is no selection.

function GetBitmap(Bitmap: TBitmap): Boolean;

Returns a copy of the current image. The bitmap must be 24 bits and of the same size as the current image (see GetImgRect, GetImgWidth and GetImgHeight for the dimensions of the image).

The transparency and the number of colors are not copied, so, if necessary, you must use the functions GetTransparentColor and GetColorCount.

Returns True in case of success.

Studio version: Returns the flattened image if it contains several layers (white background in case of transparency or RGBA mode).

function SetBitmap(Bitmap: TBitmap): Boolean;

Modifies the current image. The bitmap must be 24 bits and of the same size as the current image (see GetImgRect, GetImgWidth and GetImgHeight for the dimensions of the image).

The transparency and the number of colors are not copied, so, if necessary, you must use the functions SetTransparentColor and SetColorCount.

Returns True in case of success.

Studio version: Only acts on the background. No redimensioning with DisableLayersPainting, no redimensioning in RGBA mode.

function GetSelBitmap(Bitmap: TBitmap): Boolean;

Returns a copy of the selected part of the image. The bitmap must be 24 bits and have the same size as the selection (see GetSelRect, GetSelWidth and GetSelHeight for the dimensions of the selection).

The transparency and the number of colors are not copied, so, if necessary, you'll have to use the functions GetTransparentColor and GetColorCount.

Returns True in case of success.

Studio version: Acts on the current layer (only of type image).

type
  TSelectionOption = (soAuto, soNone);
  
function SetSelBitmap(Bitmap: TBitmap; Option: TSelectionOption = soAuto);

Modifies the selected part of the image. The bitmap must be 24 bits and have the same size as the selection (see GetSelRect, GetSelWidth and GetSelHeight for the dimensions of the selection).

Applies the selection mask dependent on the value of Option:

Studio version: Action on the current layer (only of type image).

function GetSelSelMask(Bitmap: TBitmap): Boolean;

Returns the selection mask of the current image. The bitmap must be 24 bits and of an identical size as the current image (see GetImgRect, GetImgWidth et GetImgHeight for the dimensions of the image).

The selected part is white and the rest is black (the smoothing of the edge is on the gray level).

Returns True in case of success.

Studio version: Acts on the current layer (only of type image). Returns the intersection with the layer mask.

function GetColorCount: Integer;

Returns the number of colors of the current image, or -1 if there is no image.

Studio version: Doesn't work in layer mode nor in RGBA mode.

function SetColorCount(ColorCount: Integer): Integer;

modifies the number of colors of the current image. No verification about the format of the image.

Attention, this procedure modifies the entire current image. It should be used with care in modules of type Image.

Returns the number of colors of the image in case of success, or 0 in case of error.

Studio version: Doesn't work in layer mode nor in RGBA mode.

function GetTransparentColor: TColor;

Returns the transparent color of the current image, or clNone if there is no transparency available.

Studio version: Doesn't work in layer mode nor in RGBA mode.

function SetTransparentColor(Color: TColor): Boolean;

Allows the modification of the transparency of the current image. If Color is clNone, the transparency of the image is cancelled, otherwise the transparent color is modified and transparency is activated.

This functions is only available in indexed color modes (<= 256 colors).

Attention, this function modifies the entire current image. It should be used with care in modules of type Image.

Returns True in case of success.

Studio version: Doesn't work in layer mode nor in RGBA mode.

type
  TAlphaRange = 0..100;
      
procedure SetAlphaBlend(Alpha: TAlphaRange);

Restores a percentage of Bitmap Undo to create an effect of semi−transparence.

Available in 16 million color mode without transparency for modules of type Filter.

Studio version: Acts on the current layer (of type image only).

function DrawSelBorder(Width: Integer; Color: TColor; 
  Antialias: Boolean): Boolean;

Draws a border (on the current image) having the form of the selection.

No smoothing in indexed color mode. Available for the modules of type Image or Filter.

Returns True in case of success.

Studio version: also available in case of transparence.

procedure RestoreUndoBitmap;

Restores the current image using the last Undo version.

To be used in modules of type Filter with preview.

procedure ResetSaveMenu;

Deactivates the save menu and button to indicate a succeeded save.

To be used in modules of type Export

function GetImgFileName: string;

Returns the complete name of the image (with path, if the image comes from a file).

function SetImgFileName(FileName: string): Boolean;

Modifies the file name of the current image.

To be used in modules of type Export.

type
  TEnumImageProc = function (pFileName: PChar; Width, Height, NbColors: Integer;
    TransColor: TColor): LongBool; stdcall;
    
function EnumImages(EnumImageProc: TEnumImageProc): Boolean;

Traverses the list of images open in PhotoFiltre and executes EnumImageProc for each, with the following parameters:

Must be used before GetBitmapByName and GetThumbByName.

function GetBitmapByName(Bitmap: TBitmap; FileName: string): Boolean;

Returns a copy in 24 bit format of the image that corresponds to the file name.

The image must be open in PhotoFiltre. The bitmap must be 24 bits and of identical size as the image (see function EnumImages).

Returns True in case of success.

Studio version: Returns the flattened image if it contains multiple layers.

type
  TImageInfos = record
    FileName: string;
    Width, Height: Integer;
    ColorCount: Integer;
    TransparentColor: TColor;
  end;
  
function GetImgInfosByName(FileName: string; 
  var ImageInfos: TImageInfos): Boolean;

Allows the retrieval of information for an open image (see also EnumImages, GetBitmapByName and GetThumbByName).

function GetThumb(Bitmap: TBitmap; BkColor: TColor; 
  BorderSize, ShadowSize: Integer; ShadowBkColor: TColor; 
  var R: TRect): Boolean;

Returns a miniature (thumb) of the current image.

The bitmap must be 24 bits, its dimensions are not modified. The size of the thumb is calculated from that size, while maintaining the proportions.

Studio version: Returns a flattened miniature of the image if it contains several layers.

function GetThumbByName(Bitmap: TBitmap; FileName: string; BkColor: TColor;
  BorderSize, ShadowSize: Integer; ShadowBkColor: TColor; 
  var R: TRect): Boolean; 

Returns a miniature of the image that corresponds with the file name.

The image must be open in PhotoFiltre (see GetThumb).

Studio version: Returns a flattened miniature of the image if it contains several layers.

type 
  TImageOption = (ioCreate, ioFile);
  
procedure NewImage(Bitmap: TBitmap; FileName: string; Option: TImageOption; 
  ColorCount: Integer = RGBColorCount; TransColor: TColor = clNone);

Creates a new window containing the image passed in the parameter. The bitmap must be in 24 bit format.

If FileName is an empty string, the default value is used (name is 'Untitled n').

type
  TDialogOption = (doModal, doPreview, doColorPicker);
  
procedure ShowForm(Form: TForm; Option: TDialogOption;
  MainFormCenter: Boolean = True; CloseWaiting: Boolean = True);

Shows a parameter entry form of the module. One should never directly use the methods Show or ShowModal to avoid any conflicts with PhotoFiltre.

function GetExePath: string;

Returns the path where PhotoFiltre is located.

function GetIniFile: string;

Returns the complete name (with path) of the initialisation file. This way modules can avoid writing new initialisation files.

function GetOpenPath: string;

Returns the current path for opening an image.

function GetPluginPath: string;

Returns the path where modules (plug-ins) are located.

function GetSavePath: string;

Returns the current path for the saving of an image.

Functions only available for a compatibility above or equal to 2

(Development in C, ASM, ... see RegisterCompatibility for more information)

procedure PrepareDialog(Handle: HWND; Option: TDialogOption; MainFormCenter,
  CloseWaiting: Boolean);

Allows the preparation of a dialog window. See ShowForm for more details.

function CreateDBmp(pImg: PPlgImage): Boolean;

Tells PhotoFiltre to create a 24 bit bitmap. The fields piWidth and piHeight must be set before the call. The other fields are updated by PhotoFiltre.

Returns True in case of success.

function FreeDBmp(pImg: PPlgImage): Boolean;

Tells PhotoFiltre to free the bitmap associated with the structure.

Returns True in case of succes.

function ReleaseHandleDBmp(pImg: PPlgImage): Boolean;

In certain cases, it is necessary to free the associated bitmap handle before freeing the bitmap.

Returns true in case of success.

function GetScanLineDBmp(pImg: PPlgImage; Row: Integer): Pointer;

Returns a pointer to a scan line of the bitmap associated with the structure.

The field piBuffer is automatically updated with that value.

Functions only available for a compatibility above or equal to 3

(Additional for all versions of PhotoFiltre, see RegisterCompatibility)

function GetSelMask(Bitmap: TBitmap): Boolean;

Returns the selected part of the selection mask of the current image in 24 bit format.

The bitmap must be 24 bit and have the same size as the current image (see GetSelRect, GetSelWidth and GetSelHeight for the dimensions of the selection). The selected part is white and the rest black (the border smoothing is at the gray level).

Returns True in case of success.

Studio version: Action on the current layer (of type image only). Returns the intersection with the layer mask.

function GetImageDPI: Integer;

Returns the DPI number (pixels/inch) of the current image. The result is multiplied by 1000 to avoid floating point problems.

Returns 0 if no image.

function SetImageDPI(DPI: Integer): Integer;

Modifies the DPI number (pixels/inch) of the current image. The DPI value is divided by 1000 before taking effect, to avoid floating point problems.

Returns the DPI in case of success, or 0 in case of failure.

function SetSelMask(Bitmap: TBitmap; Flag: Integer): Boolean;

Modifies the current selection by forcing a bitmap mode (magic wand). Not the content is changed, but the form of the selection itself.

The mask must be in 24 bit format and have the same size as the background. Flag is ignored for versions other than Studio. (See GetImgRect, GetImgWidth and GetImgHeight for the dimensions of the image.)

Studio version: If Flags is 0, the mask is relative to the background and must respect the dimensions of the background, otherwise the mask is relative to the current layer and must respect the dimensions of the layer (see GetLayerRect, GetLayerWidth and GetLayerHeight for the dimensions of the layer).

function ResetUndoArea(R: TRect): TRect;

Allows the module to modify the undo/redo region in case the filter must spill over (e.g. outside the border of the selection).

Returns the really modified region.

type
  TApplicationState = (asMinimize, asRestore, asMaximize, 
    asHideForms, asShowForms);
  
function SetApplicationState(State: TApplicationState): Integer;

Allows the plug-in to modify the state of the application:

function GetSelShape(Points: PPoint): Integer;

Points is a pointer to a list of Windows type points.

If Points is nil, the function returns a code for the form of the current selection:

If Points is not nil and the selection is of type polygon, the function fills the table of points and returns the number of points. The buffer Points must be large enough to contain all the points. The coordinates of the points are relative to the selection rectangle.

Functions available only for a compatibility above or equal to 4

(PhotoFiltre Studio only, see RegisterCompatibility for more information.)

function IsStudioVersion: Boolean;

Returns True if the plug-in is executed by the Studio version.

function GetLayerRect: TRect;

Returns the bounding rectangle of the current layer (of the current image).

function GetLayerWidth: Integer;

Returns the width of the current layer (of the current image).

function GetLayerHeight: Integer;

Returns the height of the current layer (of the current image).

function GetLayerPos: TPoint;

Returns the top left position of the current layer (of the current image).

function GetLayerBitmap(Bitmap: TBitmap): Boolean;

Returns a copy of the current layer (of the current image).

The bitmap must be 24 bits and have the same size as the current layer (see GetLayerRect, GetLayerWidth and GetLayerHeight for the dimensions of the layer).

Returns True in case of success.

function SetLayerBitmap(Bitmap: TBitmap): Boolean;

Modifies the current layer (of the current image).

The bitmap must be 24 bits and have the same size as the current layer (see GetLayerRect, GetLayerWidth and GetLayerHeight for the dimensions of the layer).

Returns True in case of success.

function GetLayerAlpha(Bitmap: TBitmap): Boolean;

Returns a copy of the alpha channel of the current layer (of the current image).

The bitmap must be 24 bits and have the same size as the current layer (see GetLayerRect, GetLayerWidth and GetLayerHeight for the dimensions of the layer).

The result is a gray level bitmap (white for transparent pixels).

Returns True in case of success.

function SetLayerAlpha(Bitmap: TBitmap): Boolean;

Modifies the alpha channel of the current layer (of the current image).

The bitmap must be 24 bits and have the same size as the current layer (see GetLayerRect, GetLayerWidth and GetLayerHeight for the dimensions of the layer). The bitmap must be a gray level bitmap.

Returns True in case of success.

function GetSelAlpha(Bitmap: TBitmap): Boolean;

Returns a copy of the selected part of the alpha channel of the current layer.

The bitmap must be 24 bits and have the same size as the selection (see GetSelRect, GetSelWidth and GetSelHeight for the dimensions of the selection).

The result is a gray level bitmap (white for transparent pixels).

Returns True in case of success.

function SetSelAlpha(Bitmap: TBitmap): Boolean;

Modifies the selected part of the alpha channel of the current layer.

The bitmap must be 24 bits and have the same size as the selection (see GetSelRect, GetSelWidth and GetSelHeight for the dimensions of the selection).

Returns True in case of success.

function DisableLayersPainting(Disable: LongBool): Boolean;

Temporarily deactivates the display in layer mode to optimize the real update times. One must not forget to reactivate the normal showing at the end of execxution.

type
  TColorMode = (cmNone, cmIndexed, cmRGB, cmRGBLayered, cmRGBA);
  
function GetImageColorMode: TColorMode;

Returns the color mode of the current image. Returns cmNone if no image.

Advice

At first sight, the number of functions might look very high, but in reality each module type only needs a few functions.

For instance a module of type Filter is made up in the following way:

ShowForm (optional parameter entry form) BeginFilter GetSelBitmap <handling> SetSelBitmap EndFilter

Modules of type Import are even simpler:

ShowForm (optional parameter entry form or dialog box) BeginFilter <opening and handling> NewImage SetColorCount and SetTransparentColor if necessary

For modules of type Export:

ShowForm (optional parameter entry form or dialog box) BeginFilter GetBitmap GetColorCount and GetTransparentColor if necessary <saving> ResetSaveMenu (optional to indicate the image was saved) EndFilter

Only modules of type Image are more complicated so the number of functions may be more important for the effect handling (format change, transparency, ...).

Appendix

Delphi units

The unit 'PlgInt.pas' is the base interface to make PhotoFiltre talk to modules. It is conform to the Windows API but is rather awkward to use. For that reason, I implemented the unit 'Plugin.pas', which is much more Delphi oriented. It performs type conversions (PChar, Integer, ...) in order to simplify the use of the functions. These two units must be present in your projects.

Development license

The development for free modules (freeware) is free and does not require any special authorization, but the following rules must be respected:

On the other hand, the development of commercial modules (shareware) is forbidden without explicit authorisation from my part (Antonio Da Cruz).