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;

Returns a pointer with the address of the header structure (see below)
function RegisterPluginLanguage: PPluginLanguage;

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;

Returns a pointer with the address of the main construct (See below)
function RegisterCompatibility: Integer;

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

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;

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);

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);

Name and compyright text of the author. Nom et copyright de l'auteur. The length is
truncated by MaxShortStr.
procedure SetHeaderCaption(Caption: string);

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);

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);

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);

type TPluginType = (ptFilter, ptImage, ptFileImport, ptFileExport, ptTool);
Sets the module type.
procedure SetHeaderVersion(Version: string);

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;

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

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);

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;

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;

Shows a message at the end of the execution of the filter in the status bar.
function EnumImages(EnumImageProc: TEnumImageProc): Boolean;

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;

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;

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;

Renvoie le nombre de couleurs de l'image en cours. Renvoie -1 si aucune image.
function GetExePath: string;

Renvoie le chemin de localisation du programme PhotoFiltre.
function GetImgFileName: string;

Renvoie le nom complet de l'image (avec chemin si l'image provient d'un fichier).
function GetImgHeight: Integer;

Renvoie la hauteur de l'image en cours. Renvoie 0 si aucune image.
function GetImgInfosByName(FileName: string; var ImageInfos: TImageInfos):
Boolean;

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;

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;

Renvoie la largeur de l'image en cours. Renvoie 0 si aucune image.
function GetIniFile: string;

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;

Renvoie le chemin en cours pour l'ouverture d'une image.
function GetPluginPath: string;

Renvoie le chemin de localisation des modules (plugins).
function GetSavePath: string;

Renvoie le chemin en cours pour l'enregistrement d'une image.
function GetSelBitmap(Bitmap: TBitmap): Boolean;

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;

Renvoie la hauteur de la sélection en cours. Renvoie 0 si aucune sélection.
function GetSelRect: TRect;

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;

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;

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;

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;

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;

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;

Renvoie vrai si au moins une image est ouverte.
procedure NewImage(Bitmap: TBitmap; FileName: string; Option: TImageOption;
ColorCount: Integer = RVBColorCount; TransColor: TColor = clNone);

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;

Renvoie vrai si une sélection est en cours dans l'image active.
function PluginManager: Integer;

Renvoie la version du gestionnaire de module interne de PhotoFiltre.
(pour des futurs tests de compatibilité)
procedure SetAlphaBlend(Alpha: TAlphaRange);

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;

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;

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;

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);

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;

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);

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;

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

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;

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).