MagickCore (API C de bas niveau)
L'API MagickCore est une interface de bas niveau entre le langage de programmation C et les bibliothèques de traitement d'images ImageMagick, et elle est recommandée uniquement aux programmeurs de niveau expert. Contrairement à l'API C MagickWand, qui n'utilise que quelques types opaques et accesseurs, avec MagickCore vous accédez presque exclusivement aux membres de structure directement. Une description des méthodes publiques de MagickCore se trouve sur GitHub :
- Initialiser ou détruire l'environnement ImageMagick
- Constituer une image
- Composer une image
- Méthodes d'image
- Méthodes de canaux d'image
- Compter les couleurs d'une image
- Méthodes de palette de couleurs
- Méthodes d'espace colorimétrique
- Distorsions d'image
- Manipuler les calques d'image
- Manipuler les profils d'image
- Réduire le nombre de couleurs uniques d'une image
- Histogrammes d'image
- Segmenter une image par seuillage fuzzy c-Means
- Redimensionner une image
- Transformer une image
- Cisailler ou pivoter une image selon un angle arbitraire
- Améliorer une image
- Ajouter un effet
- Érosions, dilatations, ouvertures et fermetures morphologiques
- Ajouter un effet spécial
- Décorer une image
- Obtenir/définir un attribut d'image
- Obtenir/définir les propriétés d'image
- Obtenir les statistiques d'image
- Obtenir les caractéristiques d'image
- Annoter une image
- Peindre sur une image
- Dessiner sur une image
- Créer une vignette d'image
- Calculer la transformée de Fourier discrète (DFT)
- Comparer une image à une image reconstruite
- Vision par ordinateur
- Afficher et éditer une image de manière interactive
- Animer une séquence d'images de manière interactive
- Convertir vers et depuis des pixels chiffrés
- Travailler avec des listes d'images
- Méthodes de vue d'image
- Obtenir ou définir les pixels d'une image
- Travailler avec les vues de cache
- La FIFO de pixels
- Lire ou écrire des objets binaires volumineux (BLOB)
- Modules chargeables
- Calculer un condensé de message pour une image
- Le registre d'images
- Gérer les exceptions
- Allocation mémoire
- Surveiller ou limiter la consommation de ressources
- Surveiller la progression d'une opération sur image
- Obtenir la version et les droits d'auteur
- Méthodes MIME
- Méthodes obsolètes
- Codes d'erreur et d'avertissement
Après avoir écrit votre programme MagickCore, compilez-le ainsi :
cc `MagickCore-config --cflags --cppflags` -O2 -o core core.c `MagickCore-config --ldflags --libs`
Définissez la variable d'environnement PKG_CONFIG_PATH si ImageMagick n'est pas dans le chemin système par défaut :
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
Voici un exemple de programme qui utilise l'API MagickCore pour vous aider à démarrer, core.c. Il lit une image GIF, crée une vignette et l'écrit sur le disque au format d'image PNG.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <MagickCore/MagickCore.h>
int main(int argc,char **argv)
{
ExceptionInfo
*exception;
Image
*image,
*images,
*resize_image,
*thumbnails;
ImageInfo
*image_info;
if (argc != 3)
{
(void) fprintf(stdout,"Usage: %s image thumbnail\n",argv[0]);
exit(0);
}
/*
Initialize the image info structure and read an image.
*/
MagickCoreGenesis(*argv,MagickTrue);
exception=AcquireExceptionInfo();
image_info=CloneImageInfo((ImageInfo *) NULL);
(void) strcpy(image_info->filename,argv[1]);
images=ReadImage(image_info,exception);
if (exception->severity != UndefinedException)
CatchException(exception);
if (images == (Image *) NULL)
exit(1);
/*
Convert the image to a thumbnail.
*/
thumbnails=NewImageList();
while ((image=RemoveFirstImageFromList(&images)) != (Image *) NULL)
{
resize_image=ResizeImage(image,106,80,LanczosFilter,exception);
if (resize_image == (Image *) NULL)
MagickError(exception->severity,exception->reason,exception->description);
(void) AppendImageToList(&thumbnails,resize_image);
DestroyImage(image);
}
/*
Write the image thumbnail.
*/
(void) strcpy(thumbnails->filename,argv[2]);
WriteImage(image_info,thumbnails,exception);
/*
Destroy the image thumbnail and exit.
*/
thumbnails=DestroyImageList(thumbnails);
image_info=DestroyImageInfo(image_info);
exception=DestroyExceptionInfo(exception);
MagickCoreTerminus();
return(0);
}
Effectuons maintenant la même amélioration de contraste tout en tirant parti de notre système de traitement à double ou quadruple cœur en exécutant l'algorithme en parallèle à l'aide des vues de wand. Le module sigmoidal-contrast.c lit une image, applique un contrôle de contraste à non-linéarité sigmoïde et écrit le résultat sur le disque, tout comme le programme d'amélioration de contraste précédent, mais cette fois il effectue son travail en parallèle (suppose qu'ImageMagick est compilé avec la prise en charge d'OpenMP).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <MagickCore/MagickCore.h>
static MagickBooleanType SigmoidalContrast(ImageView *contrast_view,
const ssize_t y,const int id,void *context)
{
#define QuantumScale ((MagickRealType) 1.0/(MagickRealType) QuantumRange)
#define SigmoidalContrast(x) \
(QuantumRange*(1.0/(1+exp(10.0*(0.5-QuantumScale*x)))-0.0066928509)*1.0092503)
RectangleInfo
extent;
register IndexPacket
*indexes;
register PixelPacket
*pixels;
register ssize_t
x;
extent=GetImageViewExtent(contrast_view);
pixels=GetImageViewAuthenticPixels(contrast_view);
for (x=0; x < (ssize_t) (extent.width-extent.x); x++)
{
SetPixelRed(pixels,RoundToQuantum(SigmoidalContrast(GetPixelRed(pixels)));
SetPixelGreen(pixels,RoundToQuantum(SigmoidalContrast(GetPixelGreen(pixels)));
SetPixelBlue(pixels,RoundToQuantum(SigmoidalContrast(GetPixelBlue(pixels)));
SetPixelOpacity(pixels,RoundToQuantum(SigmoidalContrast(GetPixelOpacity(pixels)));
pixels++;
}
indexes=GetImageViewAuthenticIndexes(contrast_view);
if (indexes != (IndexPacket *) NULL)
for (x=0; x < (ssize_t) (extent.width-extent.x); x++)
SetPixelIndex(indexes+x,RoundToQuantum(SigmoidalContrast(GetPixelIndex(indexes+x))));
return(MagickTrue);
}
int main(int argc,char **argv)
{
#define ThrowImageException(image) \
{ \
\
CatchException(exception); \
if (contrast_image != (Image *) NULL) \
contrast_image=DestroyImage(contrast_image); \
exit(-1); \
}
#define ThrowViewException(view) \
{ \
char \
*description; \
\
ExceptionType \
severity; \
\
description=GetImageViewException(view,&severity); \
(void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \
description=DestroyString(description); \
exit(-1); \
}
ExceptionInfo
*exception;
Image
*contrast_image;
ImageInfo
*image_info;
ImageView
*contrast_view;
MagickBooleanType
status;
if (argc != 3)
{
(void) fprintf(stdout,"Usage: %s image sigmoidal-image\n",argv[0]);
exit(0);
}
/*
Read an image.
*/
MagickCoreGenesis(*argv,MagickTrue);
image_info=AcquireImageInfo();
(void) CopyMagickString(image_info->filename,argv[1],MaxTextExtent);
exception=AcquireExceptionInfo();
contrast_image=ReadImage(image_info,exception);
if (contrast_image == (Image *) NULL)
ThrowImageException(contrast_image);
/*
Sigmoidal non-linearity contrast control.
*/
contrast_view=NewImageView(contrast_image);
if (contrast_view == (ImageView *) NULL)
ThrowImageException(contrast_image);
status=UpdateImageViewIterator(contrast_view,SigmoidalContrast,(void *) NULL);
if (status == MagickFalse)
ThrowImageException(contrast_image);
contrast_view=DestroyImageView(contrast_view);
/*
Write the image then destroy it.
*/
status=WriteImages(image_info,contrast_image,argv[2],exception);
if (status == MagickFalse)
ThrowImageException(contrast_image);
contrast_image=DestroyImage(contrast_image);
exception=DestroyExceptionInfo(exception);
image_info=DestroyImageInfo(image_info);
MagickCoreTerminus();
return(0);
}
MagickCoreTerminus() est une fonction de la bibliothèque ImageMagick qui sert à nettoyer et libérer les ressources lors de l'arrêt d'une application utilisant ImageMagick. Cette fonction doit être appelée dans le thread principal du processus de l'application pendant la procédure d'arrêt. Il est crucial que cette fonction ne soit invoquée qu'après la terminaison de tous les threads qui utilisent des fonctions ImageMagick.
ImageMagick peut utiliser des threads en interne via OpenMP (une méthode de programmation parallèle). Par conséquent, il est important de s'assurer que tous les appels de fonctions vers ImageMagick sont terminés avant d'appeler MagickCoreTerminus(). Cela évite les problèmes de threads de travail OpenMP accédant à des ressources détruites par cette fonction de terminaison.
Si OpenMP est utilisé (à partir de la version 5.0), l'implémentation OpenMP gère elle-même le démarrage et l'arrêt des threads de travail ainsi que l'allocation et la libération des ressources avec ses propres méthodes. Cela signifie qu'après l'appel de MagickCoreTerminus(), certaines ressources OpenMP et certains threads de travail peuvent rester alloués. Pour y remédier, la fonction omp_pause_resource_all(omp_pause_hard) peut être invoquée. Cette fonction, introduite dans OpenMP version 5.0, garantit que toutes les ressources allouées par OpenMP (telles que les threads et la mémoire spécifique aux threads) sont libérées. Il est recommandé d'appeler cette fonction après que MagickCoreTerminus() a terminé son exécution.