Les premiers pas
Ce page explique le code de la bibliothèque GIF dans le répertoire «lib». Le code est collecté dans une bibliothèque de services étant utilisée dans tous les utilitaires de «util». Il peut être utilisé dans toute application devant lire/écrire le format de fichier GIF. Cette page n'explique pas le format de fichier GIF et suppose que vous le connaissez, au moins au niveau de la structure du fichier GIF.
Ses origines
Gershon a écrit : «Cette bibliothèque a été écrite parce que je n'ai rien trouvé de similaire et que j'en voulais une. J'ai été inspiré par la boîte à outils RLE Utah, que j'espérais porter sur un PC IBM, mais je l'ai trouvée trop spécifique à la machine et son taux de compression trop faible. J'ai fait un compromis sur le format GIF, mais je ne sais pas combien de temps 8 bits par pixel suffiront.»
Au cours de sa première période de maintenance entre 1989 et 1994, Eric S. Raymond (alias «ESR») a porté le code vers Unix, a écrit l'interface de haut niveau DGIfSlurp()/EGifSpew(), a rationalisé les structures de données internes et a fait beaucoup de nettoyage général et de refactorisation pour améliorer la qualité du code.
Entre 1994 et 2012, Toshio Kuratomi a corrigé divers bogues d'outils, des problèmes de recette de construction et des erreurs de segmentation rares. Il a partiellement démêlé la gestion des blocs d'extension quelque peu mal conçue dans les versions précédentes. Le code de base était très stable pendant cette période.
Au cours de sa deuxième période de maintenance, ESR a corrigé l'API d'extension, a rendu la bibliothèque réentrante et thread-safe, a écrit une suite de tests de régression, a grandement amélioré la documentation et a supprimé beaucoup de code obsolète.
Le descripteur GIF
Lorsqu'un fichier GIF est ouvert, un descripteur de fichier GIF est créé, étant un pointeur vers la structure GifFileType comme suit :
- typedef struct GifFileType {
- GifWord SWidth, SHeight; /* Taille de la toile virtuelle */
- GifWord SColorResolution; /* Combien de couleurs pouvons-nous générer ? */
- GifWord SBackGroundColor; /* Couleur d'arrière-plan pour la toile virtuelle */
- GifByteType AspectByte; /* Utilisé pour calculer le rapport hauteur/largeur des pixels */
- ColorMapObject *SColorMap; /* Carte de couleurs globale, NULL si inexistante. */
- int ImageCount; /* Numéro de l'image actuelle (les deux API) */
- GifImageDesc Image; /* Image actuelle (API de bas niveau) */
- SavedImage *SavedImages; /* Séquence d'images (API de haut niveau) */
- int ExtensionBlockCount; /* Compter les extensions au-delà de la dernière image */
- ExtensionBlock *ExtensionBlocks; /* Extensions au-delà de la dernière image */
- int Error; /* Dernière condition d'erreur signalée */
- void *UserData; /* crochet pour attacher les données utilisateur (TVT) */
- void *Private; /* Ne plaisantez pas avec ça ! */
- } GifFileType;
Cette structure a été copiée depuis gif_lib.h - le fichier d'entête de la bibliothèque GIF. Tout programme d'application utilisant la bibliothèque libgif.a doit l'inclure. Les membres commençant par S font référence à l'écran GIF; d'autres contiennent les propriétés de l'image actuelle (un fichier GIF peut avoir plusieurs images) ou pointent vers le magasin alloué utilisé par diverses routines.
L'utilisateur n'écrit presque jamais dans cette structure (exception : il peut parfois être utile de modifier des éléments dans le tableau SavedImages et le membre de fin), mais peut lire n'importe lequel de ces éléments à tout moment où il est valide (les informations sur l'image ne sont pas valides tant que la première image n'a pas été lue; elles sont lues ; les informations SavedImages ne sont valides qu'après un appel à DGifSlurp()).
Comme la bibliothèque doit conserver ses propres données internes, un pointeur privé vers des données cachées est inclus. Les applications doivent ignorer cela.
La bibliothèque alloue sa propre mémoire de manière dynamique, à l'ouverture des fichiers, et la libère une fois fermée. L'utilisateur n'est jamais obligé d'allouer de la mémoire pour aucune des fonctions de cette bibliothèque, et n'est presque jamais obligé de les libérer directement. Le «presque» dans la dernière clause est dû au fait qu'un appel manuel à free() peut être nécessaire en cas d'échec de la fermeture d'un fichier; consultez la documentation de DGifClose() et EGifClose() pour plus de détails.
Voici un résumé du module :
Fichier | Description |
---|---|
egif_lib.c | Routines d'encodage, toutes préfixées par E. |
dgif_lib.c | Routines de décodage, toutes préfixées par D. |
gifalloc.c | Routines pour la gestion des couleurs et l'allocation d'enregistrements GIF. |
gif_font.c | La table des polices 8x8 pour la police de caractères utilitaire GIF. |
La bibliothèque comprend un sixième fichier de code de fonction de hachage auquel on accède uniquement en interne.
La plupart des routines renvoient GIF_ERROR (voir gif_lib.h) si quelque chose s'est mal passé, GIF_OK sinon. Après un retour d'erreur, toutes les routines prenant un paramètre pointeur vers GifFileType définissent le membre Error avec un code pouvant être interprété dans une chaîne explicative avec la fonction GifErrorString() dans gif_err.c. (L'exception à cela est les routines DGifClose() et EGifClose(), désallouant cette structure et doivent donc renvoyer tout code d'erreur via un paramètre pointeur.)
Décodage (dgif_lib.c)
Les fonctions suivantes sont utilisées pour configurer l'entrée d'un GIF :
GifFileType *DGifOpenFileName(char *GifFileName, int *ErrorCode); |
Ouvrez un nouveau fichier GIF (en mode binaire, sous Windows) en utilisant le GifFileName donné et lisez ses informations d'écran.
Si une erreur se produit, NULL est renvoyé et ErrorCode est défini (si non NULL).
GifFileType *DGifOpenFileHandle(int FileHandle, int *ErrorCode) |
Ouvrez un nouveau fichier GIF à l'aide du FileHandle donné et lisez ses informations d'écran.
Si une erreur se produit, NULL est renvoyé et ErrorCode est défini (si non NULL).
Une fois que vous avez acquis un descripteur sur un GIF, la fonction de haut niveau :
int DGifSlurp(GifFileType) |
lit le reste d'un fichier GIF complet (éventuellement multi-images) à partir du descripteur de fichier indiqué dans les structures allouées dans le noyau. Il renvoie GIF_OK en cas de succès, GIF_ERROR en cas d'échec; en cas d'échec, le membre Error sera défini.
Une fois que vous avez fait cela, toutes les données d'image, de raster et de bloc d'extension du GIF sont accessibles dans le membre SavedImages (voir les structures dans gif_lib.h). Lorsque vous avez modifié l'image à votre goût, écrivez-la avec EGifSpew().
Un détail pouvant ne pas être clair en regardant simplement les structures est la façon dont les blocs d'extension et les sous-blocs sont entreposés. Chaque structure ExtensionBlock représente un bloc de données d'extension. Ceux avec un code de fonction nul représentent des blocs de données de continuation attachés à des blocs précédents avec des codes de fonction différents de zéro.
Vous pouvez lire à partir d'un fichier GIF via un crochet de fonction. Initialisez avec :
GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *ErrorCode) |
et consultez le fichier d'entête de la bibliothèque pour le type de InputFunc.
Il existe également un ensemble de fonctions obsolètes pour les entrées/sorties séquentielles, décrites dans une section ultérieure.
Encodage (egif_lib.c)
La fonction de haut niveau :
int EGifSpew(GifFileType *GifFile) |
écrit un fichier GIF complet (éventuellement multi-images) dans le descripteur de fichier indiqué à partir de structures allouées dans le noyau créées par une opération DGifSlurp() précédente ou des opérations équivalentes. Son argument est un descripteur de fichier GIF, pointant implicitement vers l'entreposage précédemment alloué par DGifSlurp().
Le fichier est écrit avec un tampon GIF87 à moins qu'il ne contienne l'un des quatre blocs d'extension spéciaux définis dans GIF89, auquel cas il est écrit avec un tampon GIF89.
EGifSpew() termine en fermant le GIF (en y écrivant un enregistrement de terminaison) et en libérant l'entreposage associé.
Vous pouvez écrire dans un fichier GIF via un crochet de fonction. Initialisez avec :
GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *ErrorCode) |
et consultez le fichier d'entête de la bibliothèque pour le type de OutputFunc.
Il existe également un ensemble de fonctions obsolètes pour les entrées/sorties séquentielles, décrites dans une section ultérieure.
Routines de gestion et d'allocation de cartes de couleurs
ColorMapObject *GifMakeMapObject(int ColorCount, GifColorType *ColorMap) |
Alloue de l'espace d'entreposage pour un objet de carte de couleurs avec le nombre donné d'emplacements de triplets RVB. Si le deuxième paramètre n'est pas NULL, initialise la partie de la table de couleurs de la nouvelle carte à partir de celui-ci. Renvoie NULL si la mémoire est épuisée ou si la taille n'est pas une puissance de 2 <= 256.
void GifFreeMapObject(ColorMapObject *Object) |
Libérez l'espace d'entreposage occupé par un objet ColorMap n'étant plus nécessaire.
ColorMapObject *GifUnionColorMap(ColorMapObject *ColorIn1, ColorMapObject *ColorIn2, GifPixelType ColorTransIn2[]) |
Crée l'union de deux cartes de couleurs données et la renvoie. Si le résultat ne rentre pas dans 256 couleurs, NULL est renvoyé, sinon l'union allouée. ColorIn1 est copié tel quel dans ColorUnion, tandis que les couleurs de ColorIn2 sont copiées si elles n'existaient pas auparavant. ColorTransIn2 cartographie l'ancien ColorIn2 dans la table de cartes de couleurs ColorUnion.
SavedImage *GifAttachImage(GifFileType *GifFile) |
Ajoutez un bloc d'image au tableau SavedImages. Le bloc d'image est initialement mis à zéro. Ce bloc d'image sera vu par tous les appels EGifSpew() suivants.
Gestion des extensions de contrôle graphique
GIF89 a ajouté un bloc d'extension de contrôle graphique, mais les versions de GIFLIB antérieures à 5.0 n'étaient pas d'une grande aide pour les lire ou les modifier. Ce manque a été comblé par la structure et les fonctions suivantes :
- typedef struct GraphicsControlBlock {
- int DisposalMode;
- #define DISPOSAL_UNSPECIFIED 0 /* Aucune élimination spécifiée. */
- #define DISPOSE_DO_NOT 1 /* Laisser l'image en place */
- #define DISPOSE_BACKGROUND 2 /* Définir la zone comme couleur d'arrière-plan */
- #define DISPOSE_PREVIOUS 3 /* Restaurer le contenu précédent */
- bool UserInputFlag; /* Confirmation de l'utilisateur requise avant l'élimination */
- int DelayTime; /* délai de pré-affichage en unités de 0,01 sec */
- int TransparentColor; /* Index de palette pour la transparence, -1 si aucun */
- #define NO_TRANSPARENT_COLOR -1
- } GraphicsControlBlock;
-
- int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex, GraphicsControlBlock *GCB);
- int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, GifFileType *GifFile, int ImageIndex);
Avec ces fonctions, vous pouvez extraire les données d'une extension de contrôle graphique associée à une image enregistrée dans un GraphicsControlBlock, le modifier et le réécrire. Notez que si l'image enregistrée spécifiée n'a pas d'extension de contrôle graphique, DGifSavedExtensionToGCB() remplira le GCB avec des valeurs par défaut et renverra GIF_ERROR (pouvant être ignoré); EGifGCBToSavedExtension() créera un nouveau bloc d'extension de début.
Gestion des erreurs (gif_err.c)
int GifErrorString(int ErrCode) |
Renvoie une chaîne décrivant le code d'erreur GIFLIB spécifié. Renvoie NULL si l'argument n'est pas un code d'erreur valide.
La police de caractères utilitaire GIF
La police de caractères utilitaire 8x8 utilisée dans les gifecho et gifcolor (obsolètes, plus installées) se trouve dans le module de bibliothèque gif_font.c, dans une table appelée GifAsciiTable. Le fichier d'entête de la bibliothèque inclut des extern et des définitions appropriés.
La prise en charge des polices utilitaires GIF inclut des points d'entrée pour dessiner des légendes sur des images intégrées, dessiner des boîtes et des rectangles et encadrer du texte. Ces points d'entrée sont les suivants :
void GifDrawText8x8(SavedImage *Image, const int x, const int y, const char *legend, const int color) |
Dessinez du texte à l'aide de la police utilitaire 8x8 sur l'image enregistrée. Le coin supérieur gauche du texte se trouve au pixel de l'image (x, y). Utilisez l'index de couleur spécifié.
void GifDrawBox(SavedImage *Image, const int x, const int y, const int w, const int h, const int color) |
Dessinez un cadre sur l'image enregistrée. Le coin supérieur gauche du cadre correspond aux pixels de l'image (x, y), la largeur est w, la hauteur est h. Utilisez l'index de couleur spécifié.
void GifDrawRectangle(SavedImage *Image, const int x, const int y, const int w, const int h, const int color) |
Dessinez un rectangle (rempli) sur l'image enregistrée. Le coin supérieur gauche de la boîte correspond aux pixels de l'image (x, y), la largeur est w, la hauteur est h. Utilisez l'index de couleur spécifié :
void GifDrawBoxedText8x8(SavedImage *Image, const int x, const int y, const char *legend, const int border, const int bg, const int fg) |
Dessiner du texte sur un rectangle rempli. Le rectangle sera dimensionné pour s'adapter au texte, avec le coin supérieur gauche à (x, y) sur l'image enregistrée. Le paramètre border spécifie une marge de pixels autour du texte. Le paramètre bg est l'index de la table des couleurs avec lequel remplir le rectangle; fg est l'index de la table des couleurs avec lequel dessiner le texte.
Cette fonction interprète spécialement certains caractères de la chaîne de légende. Une tabulation (\t) est interprétée comme une commande pour centrer le texte suivant dans la boîte. Un retour chariot (\r) est interprété comme une demande de saut de ligne.
Codes d'erreur
Les erreurs signalées par la bibliothèque GIFLIB sont divisées en deux catégories principales : l'encodeur (erreurs préfixées par E_GIF_ERR) et le décodeur (erreurs préfixées par D_GIF_ERR). Ce document les explique brièvement.
Erreurs d'encodage
Constante | Description |
---|---|
E_GIF_ERR_OPEN_FAILED | Message affiché à l'aide de PrintGifError : «Failed to open given file» Résultat d'erreur d'entrée/sortie lors de la tentative d'ouverture du fichier GIF donné. |
E_GIF_ERR_WRITE_FAILED | Message affiché à l'aide de PrintGifError : «Failed to Write to given file» Résultat d'erreur d'entrée/sortie lors d'une tentative d'écriture dans le fichier GIF donné. |
E_GIF_ERR_HAS_SCRN_DSCR | Message affiché avec PrintGifError : «Screen Descriptor already been set» Tentative d'écriture d'un deuxième descripteur d'écran dans le même fichier GIF. Le fichier GIF doit avoir exactement un descripteur d'écran qui doit être défini directement après l'ouverture du fichier. |
E_GIF_ERR_HAS_IMAG_DSCR | Message affiché avec PrintGifError : «Image Descriptor is still active» Le descripteur d'image doit être envoyé avant le vidage de l'image, et aucun deuxième descripteur d'image ne doit être envoyé avant la fin du vidage de l'image en cours. Cette erreur s'est probablement produite parce que l'image en cours n'était pas complète. |
E_GIF_ERR_NO_COLOR_MAP | Message affiché avec PrintGifError : «Neither Global Nor Local color map» Une image doit avoir une carte de couleurs globale (écran) ou locale (image). Aucune des deux n'a été fournie dans ce cas. |
E_GIF_ERR_DATA_TOO_BIG | Message affiché avec PrintGifError : «#Pixels bigger than Width * Height» Le nombre de pixels vidés pour cette image est supérieur à celui spécifié par la hauteur de l'image multipliée par la largeur de l'image. |
E_GIF_ERR_NOT_ENOUGH_MEM | Message affiché avec PrintGifError : «Fail to allocate required memory» Une fois qu'une tentative d'ouverture du fichier GIF est effectuée, des structures spéciales sont allouées pour contenir les données internes. Si l'allocation échoue, cette erreur est renvoyée. |
E_GIF_ERR_DISK_IS_FULL | Message imprimé avec PrintGifError : «Write failed (disk full?)» L'écriture des données codées a échoué. |
E_GIF_ERR_CLOSE_FAILED | Message affiché à l'aide de PrintGifError : «Failed to close given file» La fermeture du fichier a échoué. |
E_GIF_ERR_NOT_WRITEABLE | Message affiché avec PrintGifError : «Given file was not opened for write» Les fichiers GIF peuvent être ouverts à la fois en lecture (partie DGIF de la bibliothèque) et en écriture (partie EGIF de la bibliothèque). Cette erreur se produit lorsqu'un fichier ouvert en lecture (en utilisant DGIF) est donné à l'une des routines d'encodage (EGIF). |
Erreurs de décodage
Constante | Description |
---|---|
D_GIF_ERR_OPEN_FAILED | Message affiché à l'aide de PrintGifError : «Failed to open given file» Résultat d'erreur d'entrée/sortie lors de la tentative d'ouverture du fichier GIF donné. |
D_GIF_ERR_READ_FAILED | Message affiché à l'aide de PrintGifError : «Failed to read from given file» Résultat d'erreur d'entrée/sortie lors d'une tentative d'écriture dans le fichier GIF donné. |
D_GIF_ERR_NOT_GIF_FILE | Message affiché à l'aide de PrintGifError : «Data is not a GIF file» Les fichiers GIF doivent avoir un tampon spécial les identifiant comme tels. Si ce tampon n'est pas trouvé, cette erreur est émise. |
D_GIF_ERR_NO_SCRN_DSCR | Message affiché avec PrintGifError : «No screen descriptor detected» Chaque fichier GIF doit avoir un descripteur d'écran dans son entête. Cette erreur sera générée si aucun descripteur de ce type n'a été trouvé. |
D_GIF_ERR_NO_IMAG_DSCR | Message affiché avec PrintGifError : «No image descriptor detected» Chaque image doit avoir un descripteur d'image dans son en-tête. Cette erreur sera générée si aucun descripteur de ce type n'a été trouvé. |
D_GIF_ERR_NO_COLOR_MAP | Message affiché avec PrintGifError : «Neither global nor local color map» Une image doit avoir une carte de couleurs globale (écran) ou locale (image). Aucune des deux n'a été fournie dans ce cas. |
D_GIF_ERR_WRONG_RECORD | Message imprimé avec PrintGifError : «Wrong record type detected» Chaque enregistrement d'un fichier GIF possède un identifiant spécial dans son entête. Si l'enregistrement possède un identifiant non reconnu, cette erreur est générée. |
D_GIF_ERR_DATA_TOO_BIG | Message affiché avec PrintGifError : «Number of pixels bigger than width * height» Le nombre de pixels vidés pour cette image est supérieur à celui spécifié par la hauteur de l'image multipliée par la largeur de l'image. |
D_GIF_ERR_NOT_ENOUGH_MEM | Message affiché avec PrintGifError : «Failed to allocate required memory» Une fois qu'une tentative d'ouverture du fichier GIF est effectuée, des structures spéciales sont allouées pour contenir les données internes. Si l'allocation échoue, cette erreur est renvoyée. |
D_GIF_ERR_CLOSE_FAILED | Message affiché à l'aide de PrintGifError : «Failed to close given file» La fermeture du fichier a échoué. |
D_GIF_ERR_NOT_READABLE | Message affiché avec PrintGifError : «Given file was not opened for read» ??Les fichiers GIF peuvent être ouverts à la fois en lecture (partie DGIF de la bibliothèque) et en écriture (partie EGIF de la bibliothèque). Cette erreur se produit lorsqu'un fichier ouvert en écriture (en utilisant EGIF) est transmis à l'une des routines de décodage (DGIF). |
D_GIF_ERR_IMAGE_DEFECT | Message affiché avec PrintGifError : «Image is defective, decoding aborted» Cette erreur est générée une fois que le décodage a échoué - l'image est probablement défectueuse. |
D_GIF_ERR_EOF_TOO_SOON | Message affiché à l'aide de PrintGifError : «Image EOF detected, before image complete» Cette erreur est générée une fois que le nom d'erreur EOF est détecté dans l'image codée avant que tous les pixels (largeur * hauteur) n'aient été décodés. |
Bibliothèque de support des utilitaires
Ces fonctions ne font pas partie de la bibliothèque GIF principale. Elles font partie de la bibliothèque getarg prenant en charge les utilitaires.
Gestion des erreurs
void PrintGifError(void) |
Affiche un diagnostic d'une seule ligne sur la dernière erreur giflib sur stderr.
Analyse de la ligne de commande
bool GAGetArgs(int argc, char **argv, char *CtrlStr, ...) |
Routine principale de ce module. Étant donné argc et argv tels que reçus par la procédure principale, la ligne de commande CtrlStr et les adresses de tous les paramètres, analysez la ligne de commande et mettez à jour les paramètres.
La CtrlStr définit les types de variables devant suivre. Consultez le début de getarg.c pour une utilisation exacte.
Renvoie false en cas de succès, renvoie true en cas d'échec.
void GAPrintErrMsg(int Error) |
Si une erreur se produit dans GAGetARgs, cette routine peut être utilisée pour afficher une ligne de diagnostic sur stderr.
void GAPrintHowTo(char *CtrlStr) |
Étant donné le même CtrlStr que pour GAGetArgs, peut être utilisé pour afficher une ligne de «how to use».
Accès séquentiel
Si vous manipulez des images volumineuses sur une machine à mémoire extrêmement limitée, vous devrez peut-être utiliser les fonctions suivantes pour la lecture et l'écriture séquentielles. Il est préférable de les éviter et d'utiliser l'interface DGifSlurp()/EGifSpew() plus simple.
Lecture séquentielle
int DGifGetScreenDesc(GifFileType *GifFile) |
Lit les informations de l'écran dans la structure GifFile. Notez que cette routine est automatiquement appelée une fois qu'un fichier est ouvert et qu'il n'est donc généralement pas nécessaire de l'appeler explicitement.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType) |
Comme le fichier GIF peut contenir différents enregistrements dans un ordre arbitraire, cette routine doit être appelée une fois le fichier ouvert pour détecter le type d'enregistrement suivant et agir en conséquence. Elle peut renvoyer ces types dans GifType :
Constante | Description |
---|---|
UndefinedRecordType | Quelque chose ne va pas! |
ScreenDescRecordType | Informations sur l'écran. Comme les informations sur l'écran sont lues automatiquement lorsque le fichier est ouvert, cela ne devrait pas se produire. |
ImageDescRecordType | Le prochain enregistrement est un descripteur d'image. |
ExtensionRecordType | Le prochain enregistrement est le bloc d'extension. |
TrailerRecordType | Dernier enregistrement atteint, peut fermer le fichier. |
Les deux premiers types peuvent généralement être ignorés. La fonction renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK dans le cas contraire.
int DGifGetImageDesc(GifFileType *GifFile) |
Lit les informations de l'image dans la structure GifFile. Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetLine(GifFileType *GifFile, PixelType *GifLine, int GifLineLen) |
Charge un bloc de pixels à partir du fichier GIF. La ligne peut être de n'importe quelle longueur. De plus, cette routine peut être entrelacée avec DGifGetPixel jusqu'à ce que tous les pixels aient été lus.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetPixel(GifFileType *GifFile, PixelType GifPixel) |
Charge un pixel du fichier GIF. Cette routine peut être entrelacée avec DGifGetLine(), jusqu'à ce que tous les pixels soient lus. En raison de la surcharge par appel, l'utilisation de cette routine n'est pas recommandée.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetExtension(GifFileType *GifFile, int *GifExtCode, ByteType **GifExtension) |
Charge un bloc d'extension à partir du fichier GIF. Les blocs d'extension sont facultatifs dans les fichiers GIF. Cette routine doit être suivie de DGifGetExtensionNext.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetExtensionNext(GifFileType *GifFile, ByteType **GifExtension) |
Les extensions pouvant contenir plusieurs blocs, utilisez cette routine pour continuer après DGifGetExtension, jusqu'à ce que *GifExtension soit NULL.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetCode(GifFileType *GifFile, int *GifCodeSize, ByteType **GifCodeBlock) |
Il peut parfois être souhaitable de lire le code compressé tel quel sans le décoder. Cette routine fait exactement cela (avec DGifGetCodeNext) et peut être utilisée à la place de DGifGetLine.
Ces informations de code compressé peuvent être écrites à l'aide de la séquence EGifPutCode/EGifPutCodeNext (voir gifpos.c par exemple). Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifGetCodeNext(GifFileType *GifFile, ByteType **GifCodeBlock) |
Voir DGifGetCode ci-dessus.
int DGifGetLZCodes(GifFileType *GifFile, int *GifCode) |
Cette routine peut être appelée à la place de DGifGetLine/DGifGetPixel ou DGifGetCode/DGifGetCodeNext pour obtenir les codes LZ 12 bits des images. Elle sera principalement utilisée à des fins de débogage (voir GifText.c par exemple).
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) |
Écrivez un bloc de terminaison dans le fichier GIF, fermez le fichier GIF et libérez toute la mémoire allouée à sa gestion. GifFile ne doit pas être utilisé après l'appel de cette routine.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon. Lorsque GIF_ERROR est renvoyé, le code d'erreur de diagnostic est laissé dans ErrorCode. La structure GifFile est libérée sans condition.
(Remarque : dans les versions antérieures à 5.1.0, le paramètre ErrorCode était absent et la structure GifFile n'était pas libérée afin que le code d'erreur de diagnostic reste accessible dans GifFile->Error. Ce comportement a été modifié car il posait des problèmes pour l'implémentation des enveloppes de bibliothèque dans les langages dynamiques.)
const char * DGifGetGifVersion(GifFileType *GifFile) |
Récupérez la version GIF collectée lors de la lecture séquentielle. Ceci est pratique pour les utilisateurs d'API séquentielle souhaitant définir la version d'un encodeur à partir d'un décodeur (par exemple pour le redimensionnement des gif). Pour les utilisateurs tout-en-un, cela n'est pas nécessaire car l'encodeur gif inspecte tous les blocs d'extension, mais les utilisateurs séquentiels n'ont pas ce luxe.
Écriture séquentielle
Si vous manipulez des images volumineuses sur une machine à mémoire limitée, vous devrez peut-être utiliser les fonctions suivantes pour l'écriture séquentielle.
GifFileType *EGifOpenFileName(char *GifFileName, bool GifTestExistance, int *ErrorCode) |
Ouvrez un nouveau fichier GIF en utilisant le GifFileName donné (en mode binaire, sous Windows). Si GifTestExistance est TRUE et que le fichier existe, le fichier n'est pas détruit et NULL est renvoyé.
Si une erreur se produit, NULL est renvoyé et le ErrorCode est défini.
GifFileType *EGifOpenFileHandle(int GifFileHandle, int *ErrorCode) |
Ouvrez un nouveau fichier GIF à l'aide du GifFileHandle fourni.
Si une erreur se produit, NULL est renvoyé et ErrorCode est défini.
Le fichier est ouvert en mode binaire et sa taille de tampon est définie sur FILE_BUFFER_SIZE octets.
char *EGifGetGifVersion(GifFileType *GifFile) |
Ce calcul de version est disponible via cette fonction.
void EGifSetGifVersion(GifFileType *GifFile, bool gif89) |
Définissez le type GIF sur GIF89 si le paramètre est vrai et GIF87 s'il est faux. Le type par défaut est GIF87. Cette fonction peut être appelée après l'allocation de l'enregistrement GifFile mais avant EGifPutScreenDesc().
int EGifPutScreenDesc(GifFileType *GifFile, const int GifWidth, const GifHeight, const int GifColorRes, const int GifBackGround, ColorMapObject *GifColorMap) |
Mettre à jour les paramètres de l'écran GifFile, dans la structure GifFile et dans le fichier réel. En cas d'erreur, renvoie GIF_ERROR (voir gif_lib.h), sinon GIF_OK.
Cette routine doit être appelée immédiatement après l'ouverture du fichier GIF.
int EGifPutImageDesc(GifFileType *GifFile, const int GifLeft, const int GifTop, const int GifWidth, const GifHeight, const bool GifInterlace, ColorMapObject *GifColorMap) |
Mettre à jour les paramètres de l'image GifFile, dans la structure GifFile et dans le fichier réel. Si une erreur se produit, renvoie GIF_ERROR (voir gif_lib.h), sinon GIF_OK.
Cette routine doit être appelée chaque fois qu'une nouvelle image doit être vidée dans le fichier.
int EGifPutLine(GifFileType *GifFile, PixelType *GifLine, int GifLineLen) |
Déverse un bloc de pixels dans le fichier GIF. La tranche peut être de n'importe quelle longueur. De plus, cette routine peut être entrelacée avec EGifPutPixel(), jusqu'à ce que tous les pixels aient été envoyés.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutPixel(GifFileType *GifFile, const PixelType GifPixel) |
Dépose un pixel dans le fichier GIF. Cette routine peut être entrelacée avec EGifPutLine(), jusqu'à ce que tous les pixels aient été envoyés. En raison de la surcharge pour chaque appel, l'utilisation de cette routine n'est pas recommandée.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutComment(GifFileType *GifFile, char *GifComment) |
Utilise les enregistrements d'extension GIF pour enregistrer une chaîne en tant que commentaire dans le fichier. Le code d'extension est «C» (pour Commentaire).
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutExtension(GifFileType *GifFile, const int GifExtCode, const int GifExtLen, void *GifExtension) |
Dépose le bloc d'extension donné dans le fichier GIF. Les blocs d'extension sont facultatifs dans un fichier GIF. Les blocs d'extension de plus de 255 octets ou plus d'un bloc ne sont pas pris en charge dans cette fonction. Veuillez utiliser EGifPutExtensionFirst, EGifPutExtensionBlock et EGifPutExtensionTrailer si vos blocs d'extension peuvent entrer dans cette catégorie.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutExtensionLeader(GifFileType * GifFile, const int GifExtCode) |
Vide le début d'un bloc d'extension GIF dans un fichier GIF. Les blocs d'extension sont facultatifs dans les fichiers GIF. Cette fonction génère les informations de code de type nécessaires pour un bloc d'extension GIF.
Les autres blocs de l'extension GIF doivent être vidés à l'aide de EGifPutExtensionBlock. Une fois ce bloc d'extension terminé, EGifPutExtensionTrailer doit être appelé pour générer la fin du bloc.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutExtensionBlock(GifFileType * GifFile, const int GifExtLen, const VoidPtr GifExtension) |
Vide un sous-bloc d'une extension GIF dans un fichier GIF ; ne doit être utilisé qu'après un appel d'initialisation à EGifPutExtensionLeader(). Les blocs d'extension sont facultatifs dans les fichiers GIF. Cette fonction écrira les données d'extension de GifExtension dans le fichier en tant que sous-bloc du bloc d'extension précédent. Répétez l'appel de cette fonction jusqu'à ce que tous les sous-blocs de données aient été générés.
Notez que EGifPutExtensionLeader doit être appelé avant tout appel à cette fonction. EGifPutExtensionTrailer doit être appelé pour terminer le bloc d'extension une fois que tous les sous-blocs de données ont été générés.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutExtensionTrailer(GifFileType * GifFile, const VoidPtr GifExtension) |
Dépose le terminateur du bloc d'extension GIF dans un fichier GIF pour terminer le bloc d'extension actuel.
Notez qu'un appel à EGifPutExtensionLeader est nécessaire pour ouvrir le bloc d'extension GIF avant d'appeler cette fonction.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutCode(GifFileType *GifFile, int *GifCodeSize, ByteType **GifCodeBlock) |
Il peut parfois être souhaitable d'écrire le code compressé tel quel sans le décoder. Par exemple, un filtre pour un fichier GIF ne modifiant que la taille de l'écran (GifPos) n'a pas besoin des valeurs de pixels exactes. Envoyer l'image compressée telle quelle rend ce processus beaucoup plus rapide.
Cette routine fait exactement cela (avec EGifPutCodeNext) et peut être utilisée à la place d'EGifPutLine. Vous l'utiliserez généralement avec les routines DGifGetCode/DgifGetCodeNext, lisant le code compressé, tandis que EGifPutCode/EGifPutCodeNext l'écrivent. Voir gifpos.c par exemple.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon.
int EGifPutCodeNext(GifFileType *GifFile, ByteType **GifCodeBlock) |
Voir EGifPutCode ci-dessus.
int EGifCloseFile(GifFileType *GifFile) |
Écrivez un bloc de terminaison dans le fichier GIF, fermez le fichier GIF et libérez toute la mémoire allouée à sa gestion. GifFile ne doit pas être utilisé après l'appel de cette routine.
Renvoie GIF_ERROR si quelque chose s'est mal passé, GIF_OK sinon. Lorsque GIF_ERROR est renvoyé, le code d'erreur de diagnostic est laissé dans ErrorCode. La structure GifFile est libérée sans condition.
(Remarque : dans les versions antérieures à 5.1.0, le paramètre ErrorCode était absent et la structure GifFile n'était pas libérée afin que le code d'erreur de diagnostic reste accessible dans GifFile->Error. Ce comportement a été modifié car il posait des problèmes pour l'implémentation des enveloppes de bibliothèque dans les langages dynamiques.)
Compatibilité ascendante et descendante
À l'exception de quelques détails de gestion des blocs d'extension et de l'ajout de fonctions de lecture/écriture, l'interface DGifSlurp()/EGifSpew() est stable depuis 1990. Il est prévu qu'elle le reste.
Cependant, les signatures des fonctions d'ouverture de fichier ont été modifiées dans la version 5.0 afin de rendre la bibliothèque entièrement réentrante et thread-safe - les versions antérieures de la bibliothèque ne proposaient pas l'argument pointeur final vers le code d'erreur dans DGifOpen() et ses collègues. Pour la même raison, le stockage statique interrogé par GifLastError() dans les versions antérieures a disparu et cette fonction a été supprimée.
L'entête de la bibliothèque contient des définitions de version que vous pouvez utiliser si vous devez conditionner votre code afin qu'il puisse être compilé avec différentes versions de la bibliothèque.
Les versions jusqu'à 4.1.6 définissaient une macro GIF_LIB_VERSION étant une valeur de chaîne avec un format difficile à analyser. Cette macro a été retirée.
Les versions postérieures à la version 4.1.6 définissent des macros GIFLIB_MAJOR, GIFLIB_MINOR et GIFLIB_RELEASE à valeur entière pour les trois composantes de la version. Consultez le fichier NEWS dans la distribution GIFLIB pour suivre les modifications de l'API.
Les fonctions suivantes sont entièrement nouvelles :
- Les nouvelles fonctions DGifSavedExtensionToGCB() et EGifGCBToSavedExtension() facilitent la lecture et la modification des blocs de contrôle graphiques GIF89 dans les images enregistrées.
- La nouvelle fonction DGifGetGifVersion() est pratique pour les personnes effectuant des lectures séquentielles.
Quelques changements de comportement ont été introduits dans la version 5.0 :
Comportement général
- La bibliothèque est désormais entièrement réentrante et thread-safe.
- Toutes les fonctions exportées par cette bibliothèque ont désormais DGif, EGif ou Gif comme préfixe de nom.
- La version GIF par défaut à écrire est désormais calculée au moment de l'écriture à partir des types des blocs d'extension d'une image. (Auparavant, EGifSpew() se comportait de cette façon, mais pas le code d'écriture séquentielle.) Le résultat de ce calcul est disponible via la nouvelle fonction EGifGetGifVersion().
Dans les fonctions documentées :
- Les ouvreurs et les fermeurs de fichiers GIF - DGifOpenFileName(), DGifOpenFileHandle(), DGifOpen(), DGifClose(), EGifOpenFileName(), EGifOpenFileHandle(), EGifOpen() et EGifClose() - prennent désormais tous un paramètre d'adresse entier final. S'il n'est pas nul, il est utilisé pour renvoyer un code d'erreur lorsque la fonction renvoie NULL.
- EGifSlurp() et EGifSpew() lisent et écrivent les blocs d'extension qui suivent la dernière image, gèrent correctement les images entrelacées.
- EGifPutExtensionFirst() a été remplacé par EGifPutExtensionLeader(); la différence est que la nouvelle fonction ne prend pas de bloc facultatif, elle écrit simplement un début de bloc.
- EGifPutExtensionNext() a été remplacé par EGifPutExtensionBlock(); la différence est que la nouvelle fonction ne prend pas puis ne supprime pas un paramètre de code de fonction.
- EGifPutExtensionLast() a été remplacé par EGifPutExtensionTrailer(); tout ce qu'il fait est d'écrire le bloc de terminaison. Divisez vos anciens appels EGifPutExtensionLast() en EGifPutExtensionBlock() suivi de EGifPutExtensionTrailer().
Dans les fonctions non documentées :
- Certaines fonctions non documentées ont été renommées. AddExtensionBlock() est désormais GifAddExtensionBlock() et prend un paramètre de code de fonction supplémentaire. ApplyTranslation() est désormais GifApplyTranslation(); FreeExtension() est devenu GifFreeExtensions() et prend un type d'argument différent ; MakeSavedImage() est désormais GifMakeSavedImage(), FreeSavedImages() est désormais GifFreeSavedImages() et BitSize() est désormais GifBitSize().
- Trois fonctions documentées - MakeMapObject(), FreeMapObject() et UnionColorMap() - ont été renommées respectivement en GifMakeMapObject(), GifFreeMapObject() et GifUnionColorMap().
Gestion des erreurs :
- La gestion des erreurs de la bibliothèque n'utilise plus de cellule statique pour stocker le dernier code d'erreur enregistré; cela rendait la bibliothèque non sécurisée pour les processus léger.
- Pour les fonctions autres que les ouvreurs de fichiers GIF, le code d'erreur est désormais placé dans un membre Error de la structure GifFileType.
- Les fonctions GifError() et GifLastError() référençant cette cellule statique ont disparu, et la fonction GifErrorString() introduite dans la version 4.2 prend désormais un paramètre de code d'erreur explicite.
Squelettes de filtres GIF
Si vous développez sur un système d'exploitation à mémoire virtuelle comme la plupart des versions d'UNIX, ou si vous êtes sûr d'avoir suffisamment de mémoire pour conserver tous les GIF dont vous avez besoin pour fonctionner dans le noyau, l'écriture d'un filtre est triviale. Voir le fichier gifsponge.c dans util.
Un squelette de filtre séquentiel ressemblera généralement au fichier d'exemple giffilter.c dans util.
Veuillez consulter les utilitaires dans le répertoire util pour plus d'idées une fois que vous vous sentirez à l'aise avec ces squelettes. Essayez également de suivre les normes de codage de ce paquet si vous souhaitez que le mainteneur y ajoute officiellement votre nouvel utilitaire.
Fonctionnalités non implémentées
Certaines fonctionnalités de la spécification GIF originale n'ont pas résisté à l'épreuve du temps. Cette bibliothèque les ignore pour la plupart, mais elles sont décrites ici par souci d'exhaustivité.
La norme GIF ne parvient pas à être explicite sur un détail petit mais crucial : les champs entiers non signés de deux octets qu'elle contient sont de type little-endian.
Le format GIF semble avoir été conçu avec l'idée que les visualiseurs rendraient plusieurs images dans un GIF sur un canevas commun, donnant un effet semblable à celui d'un mur d'images. Le «bloc descripteur d'écran logique» (LSDB), 6 octets juste après le tampon GIF de 6 octets et l'entête de version au début d'un fichier GIF, comprend à la fois des champs de largeur et de hauteur de canevas de deux octets et une couleur d'arrière-plan de canevas. Chaque image, en plus de la hauteur et de la largeur, possède également des coordonnées «gauche» et «haut» spécifiant où elle doit être placée sur le canevas.
GIFLIB peut lire et définir ces champs; les utilitaires gifpos et giftool vous permettront d'écrire de tels changements. Mais les navigateurs et les visualiseurs d'images modernes les ignorent. De nos jours, les GIF à images multiples sont généralement utilisés soit comme animations dans lesquelles chaque sous-image est une trame, soit comme bibliothèques d'images, le client GIF gérant la composition dans un canevas sur lequel le format GIF ne contient aucune information.
Une autre fonctionnalité de la LSDB étant généralement ignorée est l'octet de rapport hauteur/largeur des pixels. Jusqu'à la version 5.0, GIFLIB ignorait cet indicateur en entrée et le mettait à zéro en sortie ; maintenant, il est lu et conservé s'il est présent. La norme GIF ne donne pas de justification à cela, mais il semble probable que les concepteurs l'aient prévu pour représenter des captures d'images de la télévision analogique de l'époque, ayant des équivalents de pixels rectangulaires.
Une autre fonctionnalité ignorée à la fois de la LSDB et des sous-images est l'indicateur de tri, qui est censé signaler si les couleurs de la carte de couleurs associée sont triées par ordre décroissant d'importance au cas où le périphérique d'affichage ne peut en afficher qu'un nombre limité. Cette fonctionnalité reflétait le coût élevé de la mémoire à double port au moment où la spécification GIF a été écrite à la fin des années 1980. Ce type de limite a disparu au milieu des années 1990. Jusqu'à la version 5.0, GIFLIB ignorait cet indicateur en entrée et le mettait à zéro en sortie ; il est désormais lu et conservé s'il est présent.
Enfin, le bloc d'extension en texte clair. Il s'agit d'un bloc d'extension contenant des instructions pour superposer des légendes de texte sur une image suivante. GIFLIB traite ces blocs comme des données brutes, sans tenter d'analyser l'emplacement et les données de texte.