LIB TT
une librairie de prétraitement d'images astronomiques
version 20030413

Manuel du programmeur
Utiliser libTT dans un logiciel


1. Utilisation de la librairie

L'utilisation nécessite l'emploi des fichiers libtt.h, sysexp.h et le fichier de librairie libtt (suivi de l'extension .dll .so .sl .lib en fonction du système d'exploitation). Quelques fonctions d'accès directe aux routines de fitsio peuvent être accessibles en incluant libfiles.h (emploi lourd et peu recommandé).

L'adressage de la librairie TT exige au moins trois paramètres :

Les options de compilation en C et le prototypage pour appeler la librairie tt se trouvent dans le module libtt.h à inclure (#include "libtt.h") dans le source d'appel à la librairie (voir paragraphe précédent concernant la compilation). L'appel, se fait par la fonction  libtt_main. Par exemple :
   int msg;
   msg=libtt_main(TT_SCRIPT_2,1,texte);
TT_SCRIPT_2 est une définition (#define) de libtt.h et correspond au numéro de service associé à l'exécution d'un script. Le nombre 1 annonce qu'un seul paramètre va suivre. Le pointeur de la chaine de caractères texte (formatée C ANSI) est l'unique paramètre de la fonction.

La fonction libtt_main retourne toujours un entier de type (int) correspondant à un numéro d'erreur. L'exécution s'est passée sans problème si l'entier de retour vaut DLL_OK (zéro). Si une erreur est détectée, on peut traduire le numéro d'erreur en un message clair (en anglais) par le service TT_ERROR_MESSAGE. Dans le cas de l'utilisation du mode script, on peut lire des compléments sur la cause d'une erreur dans le fichier tt.err. Enfin, toujours dans le mode script, le fichier tt.log permet de tracer les différentes actions de la librairie TT.

On distingue deux types de services, le mode script et le mode pointeur. Le mode script a pour rôle d'effectuer des opérations sur des fichiers FITS en entrée et en sortie. Le mode pointeur permet d'effectuer des opérations entre des pointeurs et des fichiers FITS.

Les images sont au format flottant 4 octets (float) en mémoire de libtt afin de préserver les qualités photométriques lors des traitements.

1.2. Les services du mode script de TT

L'intérêt principal de la librairie TT est de pouvoir exécuter des commandes entrées sous la forme de script. Les numéros de service associés à ce mode sont : La syntaxe des scripts est détaillée dans le manuel de l'utilisateur.

1.3. Les services du mode pointeur de TT

Le mode pointeur permet de charger et de sauvergarder des images de fichiers FITS vers un pointeur en mémoire et d'effectuer quelques prétraitement d'image.

Dans une fonction qui va appeler la librairie libtt en mode pointeur, on définira les variables suivantes qui permettent de faire à peu près l'ensemble des opérations utiles :

   /* --- pour la description des caracteristiques de l'image ---*/
   int naxis1,naxis2,datatype,bitpix;
   char fullname[FLEN_FILENAME];
   /* --- pour la description generale d'une liste de mots cle ---*/
   int nbkeys,*datatypes;
   char **keynames,**values,**comments,**units;
   /* --- pour la description des statistiques ---*/
   double locut,hicut,maxi,mini,mean,sigma,bgmean,bgsigma,contrast;
Le mode pointeur utilise des noms de fichiers complet, c'est à dire que le nom inclus le répertoire et le suffixe. Ainsi : c:\toto\j.fit est un nom complet. Il existe une subtilité à cela qui permet d'abouter plusieurs images dans un même fichier FITS. Pour cela, il suffit de rajouter, au nom complet, un point virgule suivi du numéro d'unité d'entête-donnée (HDU) concernée. Par exemple :

c:\toto\j.fit;1 est l'image située dans le premier HDU du fichier c:\toto\j.fit
c:\toto\j.fit;2 est l'image située dans le deuxième HDU du fichier c:\toto\j.fit

Lorsque l'on va écrire l'image, il faut préciser derrière quel numéro de HDU on veut sauver. Ainsi, c:\toto\j.fit;4 signifie que l'on va insérer un nouveau HDU entre le HDU 4 et 5 actuel. Les HDU >=5 seront donc décalés d'une unité.

Lorsque l'on va lire une image, il faut juste préciser le numéro du HDU de l'image à lire.

Il est aussi possible d'utiliser la syntaxe des noms de fichiers étendus (Extended Filename Syntax) de Fitsio pour lire ou écrire une image. Se reporter à la documentation spécifique de Fitsio (http://heasarc.gsfc.nasa.gov/docs/software/fitsio/filters.html) pour cette utilisation.

1.3.1. Description des services du mode pointeur

1.3.1.1 Chargement d'une image FITS :

Le pointeur qui va accueillir l'image en mémoire peut être de n'importe quel type. Nous choisirons ici le cas d'un pointeur *p de type (short) :
   short *p;
   sprintf(fullname,"toto.fit");
   datatype=TSHORT;
   msg=libtt_main(TT_PTR_LOADIMA,5,fullname,&datatype,&p,&naxis1,&naxis2);
datatype contient le type du pointeur *p (voir la liste dans libtt.h). La zone mémoire associée au pointeur est allouée dans libtt par Fitsio. On pourra liberer la mémoire dans libtt en utilisant la fonction dédiée :
   msg=libtt_main(TT_PTR_FREEPTR,1,&p);

1.3.1.2 Chargement des mots clé d'une entête FITS :

Le chargement de l'ensemble des mots clé d'une entête FITS se fait de la façon suivante :
   sprintf(fullname,"toto.fit");
   msg=libtt_main(TT_PTR_LOADKEYS,7,fullname,&nbkeys,&keynames,&values,
                  &comments,&units,&datatypes);
Les pointeurs suivants vont accueillir la liste des mots clé et leurs paramètres : L'accès à la chaîne de caractères associée au kième mot clé est keynames[k]. La valeur correspondante est stockée dans values[k] et son type dans datatypes[k]. De même pour comments[k] et units[k].

La variable nbkeys contient le nombre de mots clé dans l'entête. Les zones mémoire associée aux pointeur est allouée dans libtt. On pourra liberer la mémoire dans libtt en utilisant la fonction dédiée :

   msg=libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,
                  &comments,&units,&datatypes);

1.3.1.3. Sauvegarde d'une image FITS

Le pointeur qui accueille l'image en mémoire peut être de n'importe quel type. Nous choisirons ici le cas d'un pointeur *p de type (float) et nous allons sauver l'image sous la forme de (short) :
   float *p;
   ...
   sprintf(fullname,"toto.fit");
   datatype=TFLOAT;
   bitpix=SHORT_IMG;
   msg=libtt_main(TT_PTR_SAVEIMA,5,fullname,p,&datatype,
                  &naxis1,&naxis2,&bitpix);
Dans ce cadre, une liste de mots clé minimale est crée automatiquement dans l'entête FITS de l'image. Il s'agit des mots clé : SIMPLE, BITPIX, NAXIS, NAXIS1, NAXIS2, EXTEND.

Si l'on souhaite sauver, en même temps la liste de mots clé, on ajoutera des paramètres :

   msg=libtt_main(TT_PTR_SAVEIMA,12,fullname,p,&datatype,&naxis1,
                  &naxis2,&bitpix,&nbkeys,keynames,values,
                  comments,units,datatypes);
Il s'agit de la même fonction, seul le nombre de paramètres change et l'on n'oubliera pas d'allouer, antérieurement, de la place mémoire pour les pointeurs des mots clés (fonction libtt_main(TT_PTR_ALLOKEYS,...)).

1.3.1.4. Création d'une liste de mots clés.

Il convient d'allouer de la mémoire pour les pointeurs de la liste de mots clé :
   msg=libtt_main(TT_PTR_ALLOKEYS,6,&nbkeys,&keynames,&values,
                  &comments,&units,&datatypes);
nbkey contient le nombre de mots clés à allouer. On peut ensuite remplir facilement la liste :
   sprintf(keynames[0],"MIPS-HI");
   sprintf(values[0],"%d",(int)(hicut));
   datatypes[0]=TINT;
   sprintf(comments[0],"High cut");
   sprintf(units[0],"ADU");
A la fin d'utilisation de la liste de mots clé, on pensera à libérer la mémoire :
   msg=libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,
                  &comments,&units,&datatypes);
Le surtypage de mots clés est possible mais n'est pas tenu en compte pour les mots clé réservés : SIMPLE, BITPIX, NAXIS, NAXIS1, NAXIS2, EXTEND.

1.3.1.5. Sauvegarde des mots clé d'une entête FITS

Si l'on souhaite enregistrer une liste mots clés à ajouter dans une entête d'un fichier FITS existant, on procède ainsi :
   msg=libtt_main(TT_PTR_SAVEKEYS,7,fullname,&nbkeys,keynames,values,
                  comments,units,datatypes);

1.3.1.6. Analyse statistique d'une image pointeur

Il est souvent utile de connaître les caractéritiques d'une image. TT possède une fonction statistique qui permet de déterminer rapidement les seuils de visualisation entre autres :
   msg=libtt_main(TT_PTR_STATIMA,13,p,&datatype,&naxis1,&naxis2,
                  &locut,&hicut,&maxi,&mini,&mean,&sigma,
                  &bgmean,&bgsigma,&contrast);
Dans ces paramètres (tous de type double), on trouvera :

1.3.1.7. Calcul des seuils de visualisation d'une image pointeur

Il est souvent utile de déterminer automatiquement les seuils d'une image. Cette fonction est un version plus rapide que TT_PTR_STATIMA car seuls les seuils sont calculés (cf. méthode de la fonction CUTS de IMA/SERIES) :
   msg=libtt_main(TT_PTR_CUTSIMA,6,p,&datatype,&naxis1,&naxis2,
                  &locut,&hicut);
Dans ces paramètres (tous de type double), on trouvera : Enfin, le calcul des seuils par analyse de l'histogramme fournit la valeur du mode. Il est possible de récupérer la valeur du mode de la façon suivante :
   msg=libtt_main(TT_PTR_CUTSIMA,7,p,&datatype,&naxis1,&naxis2,
                  &locut,&hicut,&mode);
La variable mode est de type (double).

1.3.1.8. Sauvegarde d'une image JPEG noir & blanc

La fonction de sauvgarde au format JPEG contient des paramètres identiques à une sauvegarde FITS à cela près qu'il faut ajouter les seuil bas et haut.
   int quality=75;
   sprintf(fullname,"toto.jpg");
   msg=libtt_main(TT_PTR_SAVEJPG,8,fullname,p,&datatype,
                  &naxis1,&naxis2,&locut,&hicut,&quality);
Quality (de type int) est un paramètre qui fixe le critère de dégradation de l'image. Zéro pour une image complètement dégradée et 100 pour une compression sans perte. A noter que libTT limite la valeur minimale de quality à 5. Les seuils sont de type (double).

A noter que la librairie libtt n'a pas pour vocation de lire des formats JPEG.

1.3.1.9. Sauvegarde d'une image JPEG couleur

La fonction de sauvegarde au format JPEG couleur nécessite trois pointeurs (RGB) :
   sprintf(fullname,"toto.jpg");
   msg=libtt_main(TT_PTR_SAVEJPGCOLOR,14,fullname,pr,pg,pb,&datatype,
                  &naxis1,&naxis2,&locutr,&hicutr,&locutg,&hicutg,
                  &locutb,&hicutb,&quality);
 Les seuils sont de type (double). La variable quality est de type (int).

1.3.1.10. Traitement d'une image de type pointeur

Il est possible d'accéder à l'ensemble des fonctions de traitement d'image de type IMA/SERIES pour une seule image représentée par son pointeur. Dans ce cas, l'exemple ci-dessous illustre l'utilisation de ce type de traitement.
   msg=libtt_main(TT_PTR_IMASERIES,7,
                  &p,&datatype,&naxis1,&naxis2,&p,&datatype,
                  "OFFSET offset=1000");
Les quatre premiers paramètres sont associés à l'image d'entrée. Les deux paramètres suivants sont associés à l'image de sortie qui peut donc être redirigée vers un autre pointeur. S'il s'agit du même pointeur en entrée et en sortie et que ses dimensions (naxis1 et naxis2) ont changé alors le pointeur sera redimensionné A la fin du traitement, les valeurs de naxis1 et naxis2 sont donc éventuellement changées.

La chaîne de caractère ("OFFSET offset=1000" dans l'exemple) contient la syntaxe de la fonction de traitement et de ses paramètres optionnels tels que décrits dans la liste des fonctions.

Certaines fonctions de type IMA/SERIES ont besoin de paramètres présents dans l'entête FITS de l'image pour effectuer le traitement (CATCHART ou ASTROMETRY par exemple). Il convient de passer la liste des mots clés de l'entête préalablement chargée. Dans ce cas, il y a 13 arguments à passer. Les 7 premiers sont ceux définis précédemment, et les suivants correspondent au nombre de mots clé (nbkeys) de l'entête et des arguments (nom, valeur, commentaire, unité, type de données) de la liste :

   msg=libtt_main(TT_PTR_IMASERIES,13,
                  &p,&datatype,&naxis1,&naxis2,&p,&datatype,
                  "OFFSET offset=1000",
                  &nbkeys,&keynames,&values,&comments,&units,&datatypes);
A la fin du traitement, le contenu de la liste aura augmenté en fonction de l'historique du traitement (une réallocation mémoire est donc effectuée).

1.3.1.11. Chargement d'une image FITS à 3 axes (NAXIS=3) :

Le pointeur qui va accueillir l'image en mémoire peut être de n'importe quel type. Nous choisirons ici le cas d'un pointeur *p de type (short) :
   short *p;
int iaxis3;
   sprintf(fullname,"toto.fit");
   datatype=TSHORT;
iaxis3=10;
   msg=libtt_main(TT_PTR_LOADIMA3D,7,fullname,&datatype,&iaxis3,&p,&naxis1,&naxis2,&naxis3);
datatype contient le type du pointeur *p (voir la liste dans libtt.h). La valeur de iaxis3 prend la valeur du plan image à charger (on ne charge qu'un plan image par rapport aux NAXIS3 disponibles). La zone mémoire associée au pointeur est allouée dans libtt par Fitsio. On pourra liberer la mémoire dans libtt en utilisant la fonction dédiée :
   msg=libtt_main(TT_PTR_FREEPTR,1,&p);

1.3.1.12. Sauvegarde d'une image FITS à 3 axes (image "cube")

Le pointeur qui accueille l'image en mémoire peut être de n'importe quel type et représente un cube d'images. Nous choisirons ici le cas d'un pointeur *p de type (float) et nous allons sauver l'image sous la forme de (short) :
   float *p;
   ...
   sprintf(fullname,"toto.fit");
   datatype=TFLOAT;
   bitpix=SHORT_IMG;
   msg=libtt_main(TT_PTR_SAVEIMA3D,6,fullname,p,&datatype,
                  &naxis1,&naxis2,&naxis3,&bitpix);
Dans ce cadre, une liste de mots clé minimale est crée automatiquement dans l'entête FITS de l'image. Il s'agit des mots clé : SIMPLE, BITPIX, NAXIS, NAXIS1, NAXIS2, NAXIS3, EXTEND.

Si l'on souhaite sauver, en même temps la liste de mots clé, on ajoutera des paramètres :

   msg=libtt_main(TT_PTR_SAVEIMA3D,13,fullname,p,&datatype,&naxis1,
                  &naxis2,&naxis3,&bitpix,&nbkeys,keynames,values,
                  comments,units,datatypes);
Il s'agit de la même fonction, seul le nombre de paramètres change et l'on n'oubliera pas d'allouer, antérieurement, de la place mémoire pour les pointeurs des mots clés (fonction libtt_main(TT_PTR_ALLOKEYS,...)).

1.3.2. Exemple de programme utilisant le mode pointeur

Le listing ci dessous a pour but d'illustrer l'utilisation de libtt pour generer une image, la sauver en FITS et en JPEG, la recharger, et faire des opérations sur les mots clé de l"entête FITS et effectuer un traitement de l'image. Ce listing est extrait du fichier essai.c du package libtt.
/***************************************************************************/
/* Ce programme a pour role de montrer l'utilisation des appels aux        */
/* fonctions de la librairie 'libtt'.                                      */
/*                                                                         */
/* La librairie 'libtt' ne comporte qu'une seule fonction d'entree :       */
/* int libtt_main(int service, ...);                                       */
/* Le service est un numero de fonction de la librairie. Le numero de      */
/* service sera avantageusement remplace par son identificateur defini     */
/* dans les #define de libtt.h                                             */
/* ... est une suite de pointeurs (parametres passes a chaque service),    */
/* La valeur de retour est un code d'erreur. Zero si aucun probleme.       */
/*                                                                         */
/*                                                                         */
/* Les exemples ci-apres ont pour mission d'eclaircir tout cela...         */
/***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

                       /****************************************/
#include "libtt.h"     /* pour beneficier des #define de libtt */
                       /****************************************/

int main();
int essai_pointer(void);

void print(char *texte);    /* imprime un texte a l'ecran           */
void print_erreur(int msg); /* imprime le numero d'erreur a l'ecran */

int open_libtt(void);  /* pour charger la librairie libtt */
int close_libtt(void); /* pour fermer la librairie libtt  */
#ifdef OS_WIN32
   /* chargement de la librairie dynamique pour Windows */
   #include <windows.h>
   HINSTANCE dll_tt;
   typedef int __stdcall LIBTT(int,...);
   LIBTT *libtt_main;
   #define LIBTT_MAIN "_libtt_main"
   #define LIBTT_NAME "libtt.dll"
#endif
#ifdef __linux__
   /* chargement de la librairie dynamique pour Linux */
   #include <dlfcn.h>
   void *so_tt;
   typedef int LIBTT(int,...);
   LIBTT *libtt_main;
   #define LIBTT_MAIN "libtt_main"
   #define LIBTT_NAME "libtt.so"
#endif

/***************************************************************************/
/* main :                                                                  */
/***************************************************************************/
int main() {
   int msg;
   open_libtt();
   if ((msg=essai_pointer())!=0) {print_erreur(msg);}
   close_libtt();

   return(msg);
}

/***************************************************************************/
/* open_libtt :                                                            */
/***************************************************************************/
/* charge la librairie dynamique libtt en memoire                          */
/* Valeurs de retour :                                                     */
/* =0 : librairie et point d'entree bien charges.                          */
/* =1 : ne trouve pas la librairie.                                        */
/* =2 : librairie bien chargee mais point d'entree non trouve.             */
/***************************************************************************/
int open_libtt(void)
{
#ifdef OS_WIN32
   dll_tt = LoadLibrary(LIBTT_NAME);
   if((dll_tt!=NULL)) {
      libtt_main = (LIBTT*)GetProcAddress(dll_tt,LIBTT_MAIN);
      if(libtt_main==NULL) {
         return(2);
      }
   } else {
      return(1);
   }
#endif
#ifdef __linux__
   so_tt=dlopen(LIBTT_NAME,RTLD_LAZY);
   if (so_tt!=NULL) {
      libtt_main=dlsym(so_tt,LIBTT_MAIN);
      if(libtt_main==NULL) {
         return(2);
      }
   } else {
      return(1);
   }
#endif
   return(0);
}

/***************************************************************************/
/* close_libtt :                                                           */
/***************************************************************************/
/* ferme la librairie dynamique libtt en memoire                           */
/***************************************************************************/
int close_libtt(void)
{
#ifdef OS_WIN32
   FreeLibrary(dll_tt);
#endif
#ifdef __linux__
   dlclose(so_tt);
#endif
   return 0;
}

/***************************************************************************/
/* essai_pointer                                                           */
/***************************************************************************/
/* On montre ici la facon d'appeler libtt pour effectuer des operations    */
/* entre un fichier FITS et un pointeur d'image.                           */
/* On gere les mots cles de l'entete.                                      */
/***************************************************************************/
int essai_pointer(void)
{
   int msg;
   int k,k1,k2;
   char texte[256];
 
   /* --- pour la description d'une image de type unsigned short ---*/
   unsigned short *p;

   /* --- pour la description des caracteristiques de l'image ---*/
   int naxis1,naxis2,datatype,bitpix;
   /* FLEN_FILENAME est defini dans libtt.h */
   char fullname[FLEN_FILENAME];
   /* --- pour la description generale d'une liste de mots cle ---*/
   int nbkeys;         /* nombre de mots cles dans la liste */
   char **keynames;    /* liste mots cles */
   char **values;      /* liste de valeurs associees aux mots cle */
   char **comments;    /* liste de commentaires associes aux mots cle */
   char **units;       /* liste des unites physiques a ajouter aux commentaires */
   int *datatypes;     /* liste de datatype associe a chaque values */

   /* --- pour la description des statistiques ---*/
   double locut,hicut,maxi,mini,mean,sigma,bgmean,bgsigma,contrast;

   /* --- on commence par creer une image dans un pointeur ---*/
   naxis1=50;
   naxis2=100;
   datatype=TUSHORT;
   /* datatype doit obligatoirement etre du type de *p */
   p=(unsigned short*)calloc(naxis1*naxis2,sizeof(unsigned short));
   for (k1=0;k1<naxis1;k1++) {
      for (k2=0;k2<naxis2;k2++) {
         p[naxis2*k1+k2]=40000+naxis2*k1+k2;
      }
   }

   /* --- on effectue une analyse statistique du pointeur ---*/
   if ((msg=libtt_main(TT_PTR_STATIMA,13,p,&datatype,&naxis1,&naxis2,
    &locut,&hicut,&maxi,&mini,&mean,&sigma,&bgmean,&bgsigma,&contrast))!=0) {
      free(p);
      return(msg);
   }
   /* --- affiche les parametres statistiques ---*/
   sprintf(texte,"%f %f %f %f %f %f %f %f %f",
    locut,hicut,maxi,mini,mean,sigma,bgmean,bgsigma,contrast);
   print(texte);
   /* --- on cree une liste de nbkeys mots cles pour l'entete ---*/
   nbkeys=3;
   /* allocation memoire des la liste */
   if ((msg=libtt_main(TT_PTR_ALLOKEYS,6,&nbkeys,&keynames,&values,
    &comments,&units,&datatypes))!=0) {
      free(p);
      return(msg);
   }

   /* --- remplissage des valeurs du premier mot cle --- */
   sprintf(keynames[0],"MIPS-HI");
   sprintf(values[0],"%d",(int)(hicut));
   datatypes[0]=TINT;
   sprintf(comments[0],"High cut");
   sprintf(units[0],"ADU");
   /* --- remplissage des valeurs du deuxieme mot cle --- */
   sprintf(keynames[1],"MIPS-LO");
   sprintf(values[1],"%d",(int)(locut));
   datatypes[1]=TINT;
   sprintf(comments[1],"Low cut");
   sprintf(units[1],"ADU");

   /* --- remplissage des valeurs du troisieme mot cle --- */
   sprintf(keynames[2],"CHAINE");
   sprintf(values[2],"salut les filles");
   datatypes[2]=TSTRING;
   sprintf(comments[2],"On rigole un peu");
   sprintf(units[2],"");

   /* --- on sauve l'image avec l'entete ---*/
   sprintf(fullname,"toto.fit");
   bitpix=USHORT_IMG;
   /* le bitpix=USOHRT_IMG genere un bitpix=16 mais adapte les bzero */
   /* et bscale de facon a stocker des entiers 16 bits non signes.   */
   if ((msg=libtt_main(TT_PTR_SAVEIMA,12,fullname,p,&datatype,&naxis1,
    &naxis2,&bitpix,&nbkeys,keynames,values,comments,units,datatypes))!=0) {
      free(p);
      libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,&comments,&units,&datatypes);
      return(msg);
   }

   /* --- on libere la memoire de la liste de mots cles ---*/
   libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,&comments,&units,&datatypes);

   /* --- on sauve l'image jpeg ---*/
   sprintf(fullname,"toto.jpg");
   if ((msg=libtt_main(TT_PTR_SAVEJPG,7,fullname,p,&datatype,&naxis1,
    &naxis2,&locut,&hicut))!=0) {
      free(p);
      return(msg);
   }

   /* --- on libere la memoire du pointeur image ---*/
   free(p);

   /* --- on charge l'image en memoire sans les mots cles ---*/
   sprintf(fullname,"toto.fit");
   naxis1=0;
   naxis2=0;
   datatype=TUSHORT;

   /* quelque soit la valeur de BITPIX, on contraint, avec datatype, */
   /* le type du pointeur image qu'il faut dimensionner et remplir.  */
   if ((msg=libtt_main(TT_PTR_LOADIMA,5,fullname,&datatype,&p,&naxis1,
    &naxis2))!=0) {
      return(msg);
   }

   /* --- on imprime a l'ecran quelques carateristiques de l'image ---*/
   sprintf(texte,"naxis1=%d",naxis1); print(texte);
   sprintf(texte,"naxis2=%d",naxis2); print(texte);
   sprintf(texte,"pixel(2,3)=%d (il faut trouver 40203)",p[naxis2*2+3]); print(texte);

   /* --- on charge maintenant la liste de mots cles ---*/
   if ((msg=libtt_main(TT_PTR_LOADKEYS,7,fullname,&nbkeys,&keynames,&values,
    &comments,&units,&datatypes))!=0) {
      free(p);
      return(msg);
   }

   /* --- on imprime a l'ecran la liste des mots cles ---*/
   for (k=0;k<nbkeys;k++) {
      sprintf(texte,"%s=%s <%s> [%s] type=%d",keynames[k],values[k],comments[k],units[k],datatypes[k]);
      print(texte);
   }

   /* --- on effectue un offset sur le pointeur de l'image ---*/
   sprintf(texte,"nbkeys=%d avant l'offset\n",nbkeys); print(texte);
   if ((msg=libtt_main(TT_PTR_IMASERIES,13,
    &p,&datatype,&naxis1,&naxis2,&p,&datatype,
    "OFFSET offset=1000",
    &nbkeys,&keynames,&values,&comments,&units,&datatypes))!=0) {
      libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,&comments,&units,&datatypes);
      free(p);
      return(msg);
   }
   sprintf(texte,"nbkeys=%d apres l'offset\n",nbkeys); print(texte);

   /* --- on libere la memoire de la liste de mots cles ---*/
   libtt_main(TT_PTR_FREEKEYS,5,&keynames,&values,&comments,&units,&datatypes);

   /* --- on libere la memoire du pointeur image ---*/
   free(p);

   return(0);
}

/***************************************************************************/
/* Permet d'afficher un message a l'ecran.                                 */
/* A remplacer par l'envoi du texte sur une boite de message pour les      */
/* environnements a fenetres.                                              */
/***************************************************************************/
void print(char *texte)
{
   printf("%s\n",texte);
}

/***************************************************************************/
/* Permet d'afficher les messages d'erreur provenant de la librairie libtt */
/***************************************************************************/
void print_erreur(int msg)
{
   char texte[256];
   /* --- ecrit le numero d'erreur ---*/
   sprintf(texte,"Erreur (%d) detectee dans libtt",msg);
   print(texte);
   /* --- ecrit le message d'erreur en clair ---*/
   libtt_main(TT_ERROR_MESSAGE,2,&msg,texte);
   print(texte);
}