The reference document - Development of Plugins
Previous  Top  Next


Developing external mudules (plug-ins) for pour PhotoFiltre.
Date of this document: January 2004

(Note by the translator: This page is about 50% translated. Since I only have a marginal knowledge of both French and the Delphi programming language, some technical terms might be translated wrongly.
Just be cautious. -- Jeroen de Bruijn)
Contents of this document

I) Introduction
II) The different module types
A) Filter modules
B) Image modules
C) Import modules
D) Export modules
E) Tool modules
III) Library compilation options
IV) Export functions
V) Constants and variables
VI) Header initsialization functions
VII) User language functions
VIII) Interfacing functions
IX) Tips and tricks
X) Appendices
A) Delphi units
B) Authorization for plug-in development


I) Introduction

The extrenal modules (plug-ins) of photofiltre are very clean, but they are not directly compatible with any other application. The plug-ins are stored ina folder called "Plugins" and have the extention ".pfl" (PhotoFiltre Library). They are simple DLL's developed in Delphy, but they must comply with several rules for the results returned by functions. At the initsialization of PhotoFiltre, the application searches for plug-ins and loads all the recognized plug-ins.

Personally, I use the Delphi 6 PE edition to develop, but I don't think there are any problems if you use an other version of Delphi (I guess).

II) The different module types

PhotoFiltre uses several types of modules plusieurs types de modules. Each type is placed in a dedicated menu.

A) Filter modules

They are only aviable in 16 millions color mode (24 bits) without transparency and are applied to the selected part of the current image.

Rules :
- They should never change the current selection of the image.
- They should never modify the size of the image
- They should be able to cancel or undo their own changes to the image (cancel / undo)
- They will be placed in the menu Filter >> Other

Examples : Red eye reduction, Automatic adjustments

B) Image modules

These modules are aviable for every image (independent of the number of colors and transparency) and the effects will be applied over the whole current image (as opposite to only applicable to the selected part of the current image).

Rules :
- They should be able to cancel or undo their own changes to the image (cancel / undo)
- They will be placed in the menu Image >> Other

Examples : External frameworks with textures, insertion of copyright notice

C) Import modules

These modules are intended for import functions and are always aviable (with or without a current image).

Rules :
- They must create a new image
- They may not modify or delete the current immage (if aviable)
- They don't need to be able to cancel or undo their image creation (user can choose not save the image)
- They are aviable from the menu File >> Import

Examples : Import functions of misc camera's, JPEG2000, opening other image formats

D) Export modules

These modules are intended to export the current image.

Rules :
- They may never change current image
- They don't need to be able to cancel or undo their image creation
- They are aviable from the menu File >> Export

Examples : JPEG2000, Binary format.

E) Tool modules

These are all modules who can not be fit into any of the other classifications.

Rules :
- They may never modify any image in progress
- They don't need to be able to cancel or undo their image creation
- They are aviable from the menu Tools > Other.

Examples : Image creators, a selection editor, Lossless JPEG rotations, diaporama

III) Library compilation options

All procedures and functions have the instruction 'stdcall' (standard API).
Integers are 32 bits. The type LongBool is a 32 bits boolean. Character strings are passed by a PChar pointer and buffer. The changes in bitmaps are made with 24 bit RGB (Native PhotoFiltre format).

IV) Export functions

function RegisterPluginHeader: PPluginHeader;

graphic

Returns a pointer with the address of the header structure (see below)

function RegisterPluginLanguage: PPluginLanguage;
graphic

Returns a pointer with the address of the language construction.
Allows the module to know the language used by PhotoFiltre This is an optional function.

function RegisterPluginStruct: PPluginStruct;
graphic

Returns a pointer with the address of the main construct (See below)

function RegisterCompatibility: Integer;
graphic

Allows to manage the compatibility of the modules. At this moment, the function will return '1'.

function RegisterApplication: PApplication;
graphic

Will return the address of the module applications. It is optional if the module does not need to save parameters. If a module does save its parameters, this function is oliged, because it is used internally.

function Execute: Integer;
graphic

The main procedure that executes the module. Returns 0 in event of a failure or cancellation and returns 1 if the execution was successfull

procedure SetColorPicker(Color: TColor);
graphic

For the moduels that use DM_COLOR_PICKER (see ShowForm). This is executed by PhotoFiltre on each click on an image to get the color underneat the cursor.
V) Constants and variables

const
MaxLongStr = 256;
MaxShortStr = 64;
RGBColorCount = 256 * 256 * 256; // 16 millions of colors

var
PluginErrorMsg: string = 'Error during the execution of the plug-in !';

type
PApplication = ^TApplication;

PPluginHeader = ^TPluginHeader;
TPluginHeader = packed record

end;

PPluginLanguage = ^TPluginLanguage;
TPluginLanguage = packed record

end;

PPluginStruct = ^TPluginStruct;
TPluginStruct = packed record


end;

EPluginException = class(Exception);

It is not usefull to describe these types in detail as the are only used internally in the Plugins.pas unit.

VI) Header initsialization functions

These functions are used to describe the module, its type, its author and other additional information. You need to use these functions within the RegisterPluginHeader function.

procedure SetHeaderAuthor(Author: string);
graphic

Name and compyright text of the author. Nom et copyright de l'auteur. The length is truncated by MaxShortStr.

procedure SetHeaderCaption(Caption: string);
graphic

Name of the module. It is also the name appearing in the menu of PhotoFiltre.
The length of the sting is truncated after 30 characters.
The name can end with '...' to indicate the user will get a screen with adjustable settings.

procedure SetHeaderComment(Comment: string);
graphic

Commments with a maximum of 3 lines (#13 to go to the next line).
The length of the string is truncated at MaxLongStr.

procedure SetHeaderMenuOptions(Options: TMenuOptions);
graphic

type
TMenuOption = (moRGBColors, moIndexdColors, moTransparent, moNoTransparent,
moSelected, moNotSelected, moNeedImage, moNeedMoreThanOneImage);
TMenuOptions = set of TMenuOption;

Allows to deactivate the PhotoFiltre menu if certain conditions are not met:

moRGBColors: the current image must be in 16 million colors
moIndexedColors: the current image must be in indexed colors mode
moTransparent: the current image must be transparent
moNoTransparent: the current image should not be transparent
moSelected: the current image must have a selection
moNotSelected: the current image should not have selection
moNeedImage: there has to be one image open atleast
moNeedMoreThanOneImage: at least two images must be open
moImageJpeg: the current image must be a JPEG image (jpg, JPEG, jpe, jfif)
moImageGif: the current image must be a GIF image
moImagePng: the current image must be a png image
moImageBmp: the current image must be a BMP image (bmp or rle)
moImageTiff: the current image must be a tiff (tif or tiff)
moImagePfs: the current image must be a PFS

procedure SetHeaderPluginType(PluginType: TPluginType);
graphic

type TPluginType = (ptFilter, ptImage, ptFileImport, ptFileExport, ptTool);

Sets the module type.

procedure SetHeaderVersion(Version: string);
graphic

Version and date of the module.
The string is truncated at MaxShortStr.

VII) User language functions.

These functions allow you to retrieve information about the language that is currently used in PhotoFiltre.
They might be used in RegisterPluginHeader and Execute in order to set the language for the module.
They are only aviable if the function RegisterPluginLanguage already has been called.

function GetLanguageCode: string;
graphic

Retrieves the language code (two characters) of the language used by Photofiltre
Examples : "FR", "EN", "DE", "NL"

function GetLanguageStr: string;
graphic

Retrieves the name of the language used by PhotoFiltre.
Examples : "Français", "English".

VIII) Les fonctions d'exécution

These functions allow PhotoFiltre to exchange data with the module.
These functions should be used in the exported Execute function.

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

Shows a message at the start of the execution of the filter in the status bar.
If Msg is a null string, the default message is used.
ChangeCursor indicates if the cursor should be set to the sandglass shape during execution.

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

Draw an outline (on the current image) in the shape of the current selection. No smoothing in indexed color mode. Aviable for modules of the image or filter type. Returns TRUE if the evens was succesfull.

procedure EndFilter;
graphic

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

function EnumImages(EnumImageProc: TEnumImageProc): Boolean;
graphic

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

Cycles trought the opened images list and executes the EnumImageProc action with the following parameters:
pFileName : Name of the image (Management of the buffer is handled by PhotoFiltre)
Width : width of the image
Height : height of the image
NbColors : number of colors used in the image
TransColor : The color number if the image has tranparency or clNone if there is no transparency.

Must be used before GetBitmapByName and GetThumbByName.

function GetBitmap(Bitmap: TBitmap): Boolean;
graphic

Renvoie une copie au format 24 bits de l'image en cours.
Le bitmap doit être en 24 bits et de taille identique à l'image en cours.
(voir GetImgRect, GetImgWidth et GetImgHeight pour les dimensions de l'image)
La transparence et le nombre de couleurs ne sont pas gérés, il faut utiliser les fonctions
GetTransparentColor et GetColorCount si nécessaire.
Renvoie vrai en cas de réussite.

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

Renvoie une copie au format 24 bits de l'image correspondant au nom de fichier.
Cette image doit être ouverte dans PhotoFiltre.
Le bitmap doit être en 24 bits et de taille identique à l'image (voir la fonction EnumImages).
Renvoie vrai en cas de réussite.

function GetColorCount: Integer;
graphic

Renvoie le nombre de couleurs de l'image en cours. Renvoie -1 si aucune image.

function GetExePath: string;
graphic

Renvoie le chemin de localisation du programme PhotoFiltre.

function GetImgFileName: string;
graphic

Renvoie le nom complet de l'image (avec chemin si l'image provient d'un fichier).

function GetImgHeight: Integer;
graphic

Renvoie la hauteur de l'image en cours. Renvoie 0 si aucune image.

function GetImgInfosByName(FileName: string; var ImageInfos: TImageInfos): Boolean;
graphic

type
TImageInfos = record
FileName: string;
Width, Height: Integer;
ColorCount: Integer;
TransparentColor: TColor;
end;

Permet de Récupérer les informations sur une image ouverte.
(Voir également EnumImages, GetBitmapByName et GetThumbByName)

function GetImgRect: TRect;
graphic

Renvoie les dimensions de l'image en cours sous forme d'un rectangle (0, 0, Largeur, Hauteur).
Renvoie un rectangle nul si aucune image.

function GetImgWidth: Integer;
graphic

Renvoie la largeur de l'image en cours. Renvoie 0 si aucune image.

function GetIniFile: string;
graphic

Renvoie le nom complet (avec chemin) du fichier d'initialisation.
Permet d'éviter la création d'un nouveau fichier d'initialisation pour le module.

function GetOpenPath: string;
graphic

Renvoie le chemin en cours pour l'ouverture d'une image.

function GetPluginPath: string;
graphic

Renvoie le chemin de localisation des modules (plugins).

function GetSavePath: string;
graphic

Renvoie le chemin en cours pour l'enregistrement d'une image.

function GetSelBitmap(Bitmap: TBitmap): Boolean;
graphic

Renvoie une copie au format 24 bits de la partie de l'image sélectionnée.
Le bitmap doit être en 24 bits et de taille identique à la sélection.
(voir GetSelRect, GetSelWidth et GetSelHeight pour les dimensions de la sélection)
La transparence et le nombre de couleurs ne sont pas gérés, il faut utiliser les fonctions
GetTransparentColor et GetColorCount si nécessaire.
Renvoie vrai en cas de réussite.

function GetSelHeight: Integer;
graphic

Renvoie la hauteur de la sélection en cours. Renvoie 0 si aucune sélection.

function GetSelRect: TRect;
graphic

Renvoie le rectangle de sélection (limites maximum) de l'image en cours.
Renvoie un rectangle nul si aucune sélection.function

GetSelMask(Bitmap: TBitmap): Boolean;
graphic

Renvoie le masque de sélection de l'image en cours au format 24 bits.
Le bitmap doit être en 24 bits et de taille identique à l'image en cours.
(voir GetImgRect, GetImgWidth et GetImgHeight pour les dimensions de l'image)
La partie sélectionnée est en blanc et le reste en noir.
Renvoie vrai en cas de réussite.

function GetSelWidth: Integer;
graphic

Renvoie la largeur de la sélection en cours. Renvoie 0 si aucune sélection.

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

Renvoie une miniature (vignette) de l'image en cours.
Le bitmap doit être au format 24 bits, ses dimensions ne sont pas modifiées.
La taille de la vignette est calculée en fonction de cette taille tout en conservant les proportions.
BkColor : couleur du fond (zone non affichée)
BorderSize
: Taille de la marge (comprise entre 1 et 50 pixels)
ShadowSize : Taille de l'ombrage (comprise entre 1 et 10 pixels)
ShadowBkColor : couleur du fond utilisée par l'ombre pour simuler l'opacité
R : récupère la région dans la quelle la vignette est affichée (sans les bords ni l'ombre)

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

Renvoie la miniature de l'image correspondant au nom du fichier.
L'image doit être ouverte dans PhotoFiltre (voir GetThumb et EnumImages)

function GetTransparentColor: TColor;
graphic

Renvoie la couleur de transparence de l'image en cours.
Renvoie clNone si la transparence de l'image n'est pas disponible.

function ImageExists: Boolean;
graphic

Renvoie vrai si au moins une image est ouverte.

procedure NewImage(Bitmap: TBitmap; FileName: string; Option: TImageOption;
ColorCount: Integer = RVBColorCount; TransColor: TColor = clNone);
graphic

type TImageOption = (ioCreate, ioFile);

Crée une nouvelle fenêtre contenant l'image passée en paramètre. Le bitmap doit être au format 24 bits.
Si FileName est une chaîne vide, une valeur par défaut sera affectée (du type 'Sans titre n').
Les valeurs possibles pour Option sont les suivantes:
ioCreate :la source est une image créée ou importée. Les fonctions d'enregistrement sont activées.
ioFile : la source provient d'un fichier. Les fonctions d'enregistrement sont désactivées.
ColorCount : nombre de couleurs de l'image (aucune vérification)
TransColor : Active une couleur de transparence si la valeur est différente de clNone.

function IsSelected: Boolean;
graphic

Renvoie vrai si une sélection est en cours dans l'image active.

function PluginManager: Integer;
graphic

Renvoie la version du gestionnaire de module interne de PhotoFiltre.
(pour des futurs tests de compatibilité)

procedure SetAlphaBlend(Alpha: TAlphaRange);
graphic

type TAlphaRange = 0..100;

Restaure un pourcentage du Bitmap Undo pour créer un effet de semi-transparence.
Disponible en mode 16 millions de couleurs sans transparence pour les modules de type Filtre.
Renvoie vrai en cas de réussite.

function SetBitmap(Bitmap: TBitmap): Boolean;
graphic

Modifie l'image en cours (contenu et taille). Le bitmap doit être au format 24 bits.
En cas de modification de la couleur de transparence ou du nombre de couleurs, il faut utiliser les fonctions SetTransparentColor et SetColorCount pour la mise à jour.
Renvoie vrai en cas de réussite.

function SetColorCount(ColorCount: Integer): Integer;
graphic

Modifie le nombre de couleurs de l'image en cours.
Aucune vérification quand au format de l'image.
Attention, cette procédure modifie toute l'image en cours. Elle doit être utilisée avec prudence dans les modules de type Image.
Renvoie le nombre de couleurs de l'image en cas de réussite, 0 en cas d'échec.

function SetImgFileName(FileName: string): Boolean;
graphic

Modifie le nom du fichier de l'image en cours.
A utiliser dans les modules de type Exportation.

function SetSelBitmap(Bitmap: TBitmap; Option: TSelectionOption = soAuto);
graphic

type TSelectionOption = (soAuto, soNone);

Modifie la partie de l'image sélectionnée.
Le bitmap doit être en 24 bits et de taille identique à la sélection.
(voir GetSelRect, GetSelWidth et GetSelHeight pour les dimensions de la sélection)
Applique le masque de sélection en fonction de la valeur de Option :
soAuto : lissage automatique
soNone : aucun lissage (pour dessiner un contour par exemple)

function SetTransparentColor(Color: TColor): Boolean;
graphic

Permet de modifier la transparence de l'image en cours.
Si Color vaut clNone, la transparence de l'image est annulée, sinon la couleur de transparence est modifiée et la transparence est activée.
Cette fonction est disponible en mode couleurs idexées uniquement (<= 256 couleurs).
Attention, cette procédure modifie toute l'image en cours. Elle doit être utilisée avec prudence dans les modules de type Image.
Renvoie vrai en cas de réussite.

procedure ShowForm(Form: TForm; Option: TDialogOption;
MainFormCenter: Boolean = True;
CloseWaiting: Boolean = True);
graphic

type TDialogOption = (doModal, doPreview, doColorPicker);

Affiche une fiche de paramétrage du module. Il ne faut jamais utiliser directement les méthodes
Show ou ShowModal pour éviter les conflits avec PhotoFiltre.
Les valeurs possibles pour Option sont les suivantes:
doModal : la fenêtre principale et la palette d'outils sont désactivées
(ceci implique tous les menus et tous les boutons)
doPreview et doColorPicker = les boutons de zoom restent actifs pour un aperçu
doColorPicker : le mode pipette est activé et la fonction exportée SetDialogColor est appelée en cas de clique sur l'image.
doPreview et doColorPicker sont appliquables seulement si une image est ouverte, sinon la valeur
doModal est utilisée par défaut.
MainFormCenter : centre la fiche dans la fenêtre principale.
CloseWaiting : attend que la fiche se ferme avant de rendre la main.

procedure ResetSaveMenu;
graphic

Désactive le menu et bouton d'enregistrement pour simuler un enregistrement réussi.
A utiliser dans les modules de type Exportation.

procedure RestoreUndoBitmap;
graphic

Restaure l'image en cours en utilisant la dernière version Undo.
A utiliser dans les modules de type Filtre avec aperçu.

function XP_ThemesEnabled: Boolean;
graphic

Renvoie vrai si PhotoFiltre utilise les thèmes Windows XP pour l'affichage.
(Sous Windows XP uniquement)


IX) Conseils

A première vue, le nombre de fonctions peut sembler élevé mais en réalité chaque type de module nécessite très peu de fonctions.

Par exemple un module de type Filtre se compose de la façon suivante:
ShowForm (fiche de paramétrage facultatif)
BeginFilter
GetSelBitmap

SetSelBitmap
EndFilter

Les modules de type Importation sont encore plus simple:
ShowForm (fiche de paramétrage ou Boîte de dialogue)
BeginFilter

NewImage
SetColorCount et SetTransparentColor si nécessaire.

Pour les modules de type Exportation:
ShowForm (fiche de paramétrage ou Boîte de dialogue)
BeginFilter
GetBitmap
GetColorCount et GetTransparentColor si nécessaire.

ResetSaveMenu (facultatif pour indiquer que l'image est déjà enregistrée)
EndFilter

Seuls les modules de type Image sont plus compliqués car le nombre de fonctions peut être plus important en fonction des traitements à effectuer (changement de format, transparence,
redimensionnement de l'image, ...).

X) Annexes

A) Unités Delphi pour le développement des modules

L'unité 'PlgInt.pas' est l'interface de base pour faire dialoguer PhotoFiltre avec les modules. Elle est conforme aux API Windows mais est assez lourde à manipuler. Pour cette raison, j'ai implémenté l'unité 'Plugin.pas' plus orientée Delphi. Elle gère les conversions de type (PChar, Integer, ...) afin de simplifier l'utilisation des fonctions. Les deux unités doivent être présentes dans vos projets.

B) Autorisation de développement

Le développement des modules de type gratuiciel (freeware) est libre et ne nécessite aucune
autorisation particulière, mais il faut respecter les règles suivantes:
- pas de publicité quelque soit sa forme (bandeau, image, texte, message subliminal, ...)
- un lien vers le site officiel de l'auteur est autorisé (utilisez de préférence la boîte 'A propos')
- le développeur m'informe dans la mesure du possible de ses projets

Par contre, le développement des modules de type commercial (shareware et autres) est interdit sans autorisation explicite de ma part (Antonio DA CRUZ).