/*  Grafx2 - The Ultimate 256-color bitmap paint program
    Copyright 2008 Yves Rizoud
    Copyright 2008 Franck Charlet
    Copyright 2007 Adrien Destugues
    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
    Grafx2 is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; version 2
    of the License.
    Grafx2 is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with Grafx2; if not, see  or
    write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#define _XOPEN_SOURCE
#if defined(__macosx__)
#define __no_pnglib__
#endif
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#ifndef __no_pnglib__
#include 
#endif
#include "const.h"
#include "struct.h"
#include "global.h"
#include "graph.h"
#include "divers.h"
#include "pages.h"
#include "op_c.h"
#include "boutons.h"
#include "erreurs.h"
#include "io.h"
#include "sdlscreen.h"
#include "windows.h"
#include "loadsave.h"
#define FILENAMESPACE 13
// -- PKM -------------------------------------------------------------------
void Test_PKM(void);
void Load_PKM(void);
void Save_PKM(void);
// -- LBM -------------------------------------------------------------------
void Test_LBM(void);
void Load_LBM(void);
void Save_LBM(void);
// -- GIF -------------------------------------------------------------------
void Test_GIF(void);
void Load_GIF(void);
void Save_GIF(void);
// -- PCX -------------------------------------------------------------------
void Test_PCX(void);
void Load_PCX(void);
void Save_PCX(void);
// -- BMP -------------------------------------------------------------------
void Test_BMP(void);
void Load_BMP(void);
void Save_BMP(void);
// -- IMG -------------------------------------------------------------------
void Test_IMG(void);
void Load_IMG(void);
void Save_IMG(void);
// -- SCx -------------------------------------------------------------------
void Test_SCx(void);
void Load_SCx(void);
void Save_SCx(void);
// -- CEL -------------------------------------------------------------------
void Test_CEL(void);
void Load_CEL(void);
void Save_CEL(void);
// -- KCF -------------------------------------------------------------------
void Test_KCF(void);
void Load_KCF(void);
void Save_KCF(void);
// -- PAL -------------------------------------------------------------------
void Test_PAL(void);
void Load_PAL(void);
void Save_PAL(void);
// -- PI1 -------------------------------------------------------------------
void Test_PI1(void);
void Load_PI1(void);
void Save_PI1(void);
// -- PC1 -------------------------------------------------------------------
void Test_PC1(void);
void Load_PC1(void);
void Save_PC1(void);
// -- PNG -------------------------------------------------------------------
#ifndef __no_pnglib__
void Test_PNG(void);
void Load_PNG(void);
void Save_PNG(void);
#endif
T_Format FormatFichier[NB_FORMATS_CONNUS] = {
  {"pkm", Test_PKM, Load_PKM, Save_PKM, 1, 1},
  {"lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0},
  {"gif", Test_GIF, Load_GIF, Save_GIF, 1, 1},
  {"bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0},
  {"pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0},
  {"img", Test_IMG, Load_IMG, Save_IMG, 1, 0},
  {"sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0},
  {"pi1", Test_PI1, Load_PI1, Save_PI1, 1, 0},
  {"pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0},
  {"cel", Test_CEL, Load_CEL, Save_CEL, 1, 0},
  {"kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0},
  {"pal", Test_PAL, Load_PAL, Save_PAL, 0, 0},
#ifndef __no_pnglib__
  {"png", Test_PNG, Load_PNG, Save_PNG, 1, 1}
#endif
};
// Cette variable est alimentée après chargement réussi d'une image.
// Actuellement seul le format PNG peut donner autre chose que PIXEL_SIMPLE.
enum PIXEL_RATIO Ratio_image_chargee=PIXEL_SIMPLE;
// Taille de fichier, en octets
int FileLength(FILE * Fichier)
{
        struct stat infos_fichier;
        fstat(fileno(Fichier),&infos_fichier);
        return infos_fichier.st_size;
}
// Chargement des pixels dans l'écran principal
void Pixel_Chargement_dans_ecran_courant(word Pos_X,word Pos_Y,byte Couleur)
{
  //if ((Pos_X>=0) && (Pos_Y>=0)) //Toujours vrai ?
  if ((Pos_X=0) && (Pos_Y>=0))
  if ((Pos_X=0) && (Pos_Y>=0))
  if ((Pos_X> 5) << 5) |
            ((V >> 5) << 2) |
            ((B >> 6));
    Pixel(Preview_Pos_X+(Pos_X/Preview_Facteur_X),
          Preview_Pos_Y+(Pos_Y/Preview_Facteur_Y),
          Couleur);
  }
}
// Création d'une palette fake
void Palette_fake_24b(T_Palette Palette)
{
  int Couleur;
  // Génération de la palette
  for (Couleur=0;Couleur<256;Couleur++)
  {
    Palette[Couleur].R=((Couleur & 0xE0)>>5)<<5;
    Palette[Couleur].V=((Couleur & 0x1C)>>2)<<5;
    Palette[Couleur].B=((Couleur & 0x03)>>0)<<6;
  }
}
// Supplément à faire lors de l'initialisation d'une preview dans le cas
// d'une image 24b
void Initialiser_preview_24b(int Largeur,int Hauteur)
{
  if (Pixel_de_chargement==Pixel_Chargement_dans_preview)
  {
    // Aiguillage du chargement 24b
    Pixel_Chargement_24b=Pixel_Chargement_dans_preview_24b;
    // Changement de palette
    Palette_fake_24b(Principal_Palette);
    Set_palette(Principal_Palette);
    Remapper_fileselect();
  }
  else
  {
    // Aiguillage du chargement 24b
    Pixel_Chargement_24b=Pixel_Chargement_dans_buffer_24b;
    // Allocation du buffer 24b
    Buffer_image_24b=
      (struct Composantes *)Emprunter_memoire_de_page(Largeur*Hauteur*sizeof(struct Composantes));
    if (!Buffer_image_24b)
    {
      // Afficher un message d'erreur
      // Pour être sûr que ce soit lisible.
      Calculer_couleurs_menu_optimales(Principal_Palette);
      Message_Memoire_insuffisante();
      if (Pixel_de_chargement==Pixel_Chargement_dans_ecran_courant)
        Erreur_fichier=1; // 1 => On n'a pas perdu l'image courante
      else
        Erreur_fichier=3; // 3 => Chargement de brosse échoué
    }
    else
      Image_24b=1;        // On a un buffer à traiter en fin de chargement
  }
}
void Initialiser_preview(short Largeur,short Hauteur,long Taille,int Format)
//
//   Cette procédure doit être appelée par les routines de chargement
// d'images.
//   Elle doit être appelée entre le moment où l'on connait la dimension de
// l'image (dimension réelle, pas dimension tronquée) et l'affichage du
// premier point.
//
{
  char  Chaine[256];
  int   Image_en_24b;
  Image_en_24b=Format & FORMAT_24B;
  Format      =Format & (~FORMAT_24B);
  if (Pixel_de_chargement==Pixel_Chargement_dans_preview)
  {
    // Préparation du chargement d'une preview:
    // Affichage des données "Image size:"
    if ((Largeur<10000) && (Hauteur<10000))
    {
      Num2str(Largeur,Chaine,4);
      Num2str(Hauteur,Chaine+5,4);
      Chaine[4]='x';
      Print_dans_fenetre(226,55,Chaine,CM_Noir,CM_Clair);
    }
    else
    {
      Print_dans_fenetre(226,55,"VERY BIG!",CM_Noir,CM_Clair);
    }
    // Affichage de la taille du fichier
    if (Taille<1048576)
    {
      // Le fichier fait moins d'un Mega, on affiche sa taille direct
      Num2str(Taille,Chaine,9);
      Print_dans_fenetre(226,63,Chaine,CM_Noir,CM_Clair);
    }
    else if ((Taille/1024)<10000000)
    {
      // Le fichier fait plus d'un Mega, on peut afficher sa taille en Ko
      Num2str(Taille/1024,Chaine,7);
      Chaine[7]='K';
      Chaine[8]='b';
      Print_dans_fenetre(226,63,Chaine,CM_Noir,CM_Clair);
    }
    else
    {
      // Le fichier fait plus de 10 Giga octets (cas très rare :))
      Print_dans_fenetre(226,63,"TOO BIG!!",CM_Noir,CM_Clair);
    }
    // Affichage du vrai format
    if (Format!=Principal_Format)
    {
      Print_dans_fenetre( 274,72,FormatFichier[Format-1].Extension,CM_Noir,CM_Clair);
    }
    // On efface le commentaire précédent
    Block(Fenetre_Pos_X+46*Menu_Facteur_X,Fenetre_Pos_Y+(175+FILENAMESPACE)*Menu_Facteur_Y,
          Menu_Facteur_X<<8,Menu_Facteur_Y<<3,CM_Clair);
    // Affichage du commentaire
    if (FormatFichier[Format-1].Commentaire)
      Print_dans_fenetre(46,175+FILENAMESPACE,Principal_Commentaire,CM_Noir,CM_Clair);
    // Calculs des données nécessaires à l'affichage de la preview:
    Preview_Facteur_X=Round_div_max(Largeur,122*Menu_Facteur_X);
    Preview_Facteur_Y=Round_div_max(Hauteur, 82*Menu_Facteur_Y);
    if ( (!Config.Maximize_preview) && (Preview_Facteur_X!=Preview_Facteur_Y) )
    {
      if (Preview_Facteur_X>Preview_Facteur_Y)
        Preview_Facteur_Y=Preview_Facteur_X;
      else
        Preview_Facteur_X=Preview_Facteur_Y;
    }
    Preview_Pos_X=Fenetre_Pos_X+180*Menu_Facteur_X;
    Preview_Pos_Y=Fenetre_Pos_Y+ (89+FILENAMESPACE)*Menu_Facteur_Y;
    // On nettoie la zone où va s'afficher la preview:
    Block(Preview_Pos_X,Preview_Pos_Y,
          Round_div_max(Largeur,Preview_Facteur_X),
          Round_div_max(Hauteur,Preview_Facteur_Y),
          CM_Noir);
  }
  else
  {
    if (Pixel_de_chargement==Pixel_Chargement_dans_ecran_courant)
    {
      if (Backup_avec_nouvelles_dimensions(0,Largeur,Hauteur))
      {
        // La nouvelle page a pu être allouée, elle est pour l'instant pleine
        // de 0s. Elle fait Principal_Largeur_image de large.
        // Normalement tout va bien, tout est sous contrôle...
      }
      else
      {
        // Afficher un message d'erreur
        // Pour être sûr que ce soit lisible.
        Calculer_couleurs_menu_optimales(Principal_Palette);
        Message_Memoire_insuffisante();
        Erreur_fichier=1; // 1 => On n'a pas perdu l'image courante
      }
    }
    else // chargement dans la brosse
    {
      free(Brosse);
      free(Smear_Brosse);
      Brosse=(byte *)malloc(Largeur*Hauteur);
      Brosse_Largeur=Largeur;
      Brosse_Hauteur=Hauteur;
      if (Brosse)
      {
        Smear_Brosse=(byte *)malloc(Largeur*Hauteur);
        if (!Smear_Brosse)
          Erreur_fichier=3;
      }
      else
        Erreur_fichier=3;
    }
  }
  if (!Erreur_fichier)
    if (Image_en_24b)
      Initialiser_preview_24b(Largeur,Hauteur);
}
void Dessiner_preview_palette(void)
{
  short Indice;
  short Preview_Pos_X=Fenetre_Pos_X+186*Menu_Facteur_X;
  short Preview_Pos_Y=Fenetre_Pos_Y+ (90+FILENAMESPACE)*Menu_Facteur_Y;
  if (Pixel_de_chargement==Pixel_Chargement_dans_preview)
    for (Indice=0; Indice<256; Indice++)
      Block(Preview_Pos_X+(((Indice>>4)*7)*Menu_Facteur_X),
            Preview_Pos_Y+(((Indice&15)*5)*Menu_Facteur_Y),
            5*Menu_Facteur_X,5*Menu_Facteur_Y,Indice);
  UpdateRect(
    Preview_Pos_X*Menu_Facteur_X,
  Preview_Pos_Y*Menu_Facteur_Y,
  5*Menu_Facteur_X*256,5*Menu_Facteur_Y*256);
}
// Calcul du nom complet du fichier
void Nom_fichier_complet(char * Nom_du_fichier, byte Sauve_Colorix)
{
    byte Pos;
    strcpy(Nom_du_fichier,Principal_Repertoire_fichier);
    //On va ajouter un séparateur à la fin du chemin s'il n'y est pas encore
    if (Nom_du_fichier[strlen(Nom_du_fichier)-1]!=SEPARATEUR_CHEMIN[0])
        strcat(Nom_du_fichier,SEPARATEUR_CHEMIN);
  // Si on est en train de sauvegarder une image Colorix, on calcule son ext.
  if (Sauve_Colorix)
  {
    Pos=strlen(Principal_Nom_fichier)-1;
    if (Principal_Nom_fichier[Pos]=='?')
    {
      if (Principal_Largeur_image<=320)
        Principal_Nom_fichier[Pos]='I';
      else
      {
        if (Principal_Largeur_image<=360)
          Principal_Nom_fichier[Pos]='Q';
        else
        {
          if (Principal_Largeur_image<=640)
            Principal_Nom_fichier[Pos]='F';
          else
          {
            if (Principal_Largeur_image<=800)
              Principal_Nom_fichier[Pos]='N';
            else
              Principal_Nom_fichier[Pos]='O';
          }
        }
      }
    }
  }
  strcat(Nom_du_fichier,Principal_Nom_fichier);
}
/////////////////////////////////////////////////////////////////////////////
//                    Gestion des lectures et écritures                    //
/////////////////////////////////////////////////////////////////////////////
void Lire_octet(FILE * Fichier, byte *Octet)
{
  // FIXME : Remplacer les appelants par read_bytes(), et gérer les retours d'erreur.
  read_byte(Fichier, Octet);
}
// --------------------------------------------------------------------------
byte * Tampon_ecriture;
word   Index_ecriture;
void Init_ecriture(void)
{
  Tampon_ecriture=(byte *)malloc(64000);
  Index_ecriture=0;
}
void Ecrire_octet(FILE *Fichier, byte Octet)
{
  Tampon_ecriture[Index_ecriture++]=Octet;
  if (Index_ecriture>=64000)
  {
    if (! write_bytes(Fichier,Tampon_ecriture,64000))
      Erreur_fichier=1;
    Index_ecriture=0;
  }
}
void Close_ecriture(FILE *Fichier)
{
  if (Index_ecriture)
    if (! write_bytes(Fichier,Tampon_ecriture,Index_ecriture))
      Erreur_fichier=1;
  free(Tampon_ecriture);
}
/////////////////////////////////////////////////////////////////////////////
// -------- Modifier la valeur du code d'erreur d'accès à un fichier --------
//   On n'est pas obligé d'utiliser cette fonction à chaque fois mais il est
// important de l'utiliser dans les cas du type:
//   if (!Erreur_fichier) *** else Erreur_fichier=***;
// En fait, dans le cas où l'on modifie Erreur_fichier alors qu'elle contient
// dèjà un code d'erreur.
void Modif_Erreur_fichier(int Nouvelle_valeur)
{
  if (Erreur_fichier>=0)
    Erreur_fichier=Nouvelle_valeur;
}
// -- Charger n'importe connu quel type de fichier d'image (ou palette) -----
void Charger_image(byte Image)
{
  int  Indice; // Indice de balayage des formats
  int  Format=0; // Format du fichier à charger
  // On place par défaut Erreur_fichier à vrai au cas où on ne sache pas
  // charger le format du fichier:
  Erreur_fichier=1;
  if (Principal_Format!=0)
  {
    FormatFichier[Principal_Format-1].Test();
    if (!Erreur_fichier)
      // Si dans le sélecteur il y a un format valide on le prend tout de suite
      Format=Principal_Format-1;
  }
  if (Erreur_fichier)
  {
    //  Sinon, on va devoir scanner les différents formats qu'on connait pour
    // savoir à quel format est le fichier:
    for (Indice=0;Indice0)
    {
      Erreur(0);
    }
    if (Image_24b)
    {
      // On vient de charger une image 24b
      if (!Erreur_fichier)
      {
        // Le chargement a réussi, on peut faire la conversion en 256 couleurs
        if (Pixel_de_chargement==Pixel_Chargement_dans_ecran_courant)
        {
          // Cas d'un chargement dans l'image
          if (Convert_bitmap_24B_to_256(Principal_Ecran,Buffer_image_24b,Principal_Largeur_image,Principal_Hauteur_image,Principal_Palette))
            Erreur_fichier=2;
        }
        else
        {
          // Cas d'un chargement dans la brosse
          if (Convert_bitmap_24B_to_256(Brosse,Buffer_image_24b,Brosse_Largeur,Brosse_Hauteur,Principal_Palette))
            Erreur_fichier=2;
        }
        //if (!Erreur_fichier)
        //  Palette_256_to_64(Principal_Palette);
        // Normalement plus besoin car 256 color natif, et c'etait probablement
        // un bug - yr
      }
      free(Buffer_image_24b);
    }
    if (Image)
    {
      if ( (Erreur_fichier!=1) && (FormatFichier[Format].Backup_done) )
      {
        // On considère que l'image chargée n'est plus modifiée
        Principal_Image_modifiee=0;
        // Et on documente la variable Principal_Format_fichier avec la valeur:
        Principal_Format_fichier=Format+1;
        // Correction des dimensions
        if (Principal_Largeur_image<1)
          Principal_Largeur_image=1;
        if (Principal_Hauteur_image<1)
          Principal_Hauteur_image=1;
      }
      else if (Erreur_fichier!=1)
      {
        // On considère que l'image chargée est encore modifiée
        Principal_Image_modifiee=1;
        // Et on documente la variable Principal_Format_fichier avec la valeur:
        Principal_Format_fichier=Format+1;
      }
      else
      {
        // Dans ce cas, on sait que l'image n'a pas changé, mais ses
        // paramètres (dimension, palette, ...) si. Donc on les restaures.
        Download_infos_page_principal(Principal_Backups->Pages);
      }
    }
  }
  else
    // Sinon, l'appelant sera au courant de l'échec grace à Erreur_fichier;
    // et si on s'apprêtait à faire un chargement définitif de l'image (pas
    // une preview), alors on flash l'utilisateur.
    if (Pixel_de_chargement!=Pixel_Chargement_dans_preview)
      Erreur(0);
}
// -- Sauver n'importe quel type connu de fichier d'image (ou palette) ------
void Sauver_image(byte Image)
{
  // On place par défaut Erreur_fichier à vrai au cas où on ne sache pas
  // sauver le format du fichier: (Est-ce vraiment utile??? Je ne crois pas!)
  Erreur_fichier=1;
  Lit_pixel_de_sauvegarde=(Image)?Lit_pixel_dans_ecran_courant:Lit_pixel_dans_brosse;
  FormatFichier[Principal_Format_fichier-1].Save();
  if (Erreur_fichier)
    Erreur(0);
  else
  {
    if ((Image) && (FormatFichier[Principal_Format_fichier-1].Backup_done))
      Principal_Image_modifiee=0;
  }
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// PAL ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// -- Tester si un fichier est au format PAL --------------------------------
void Test_PAL(void)
{
  FILE *Fichier;             // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  long Taille_du_fichier;   // Taille du fichier
  struct stat Informations_Fichier;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=1;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    stat(Nom_du_fichier,&Informations_Fichier);
    // Lecture de la taille du fichier
    Taille_du_fichier=Informations_Fichier.st_size;
    fclose(Fichier);
    // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets
    if (Taille_du_fichier==sizeof(T_Palette))
      Erreur_fichier=0;
  }
}
// -- Lire un fichier au format PAL -----------------------------------------
void Load_PAL(void)
{
  FILE *Fichier;              // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  //long  Taille_du_fichier;   // Taille du fichier
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    T_Palette Palette_64;
    // Initialiser_preview(???); // Pas possible... pas d'image...
    // Lecture du fichier dans Principal_Palette
    if (read_bytes(Fichier,Palette_64,sizeof(T_Palette)))
    {
      Palette_64_to_256(Palette_64);
      memcpy(Principal_Palette,Palette_64,sizeof(T_Palette));
      Set_palette(Principal_Palette);
      Remapper_fileselect();
      // On dessine une preview de la palette (si chargement=preview)
      Dessiner_preview_palette();
    }
    else
      Erreur_fichier=2;
    // Fermeture du fichier
    fclose(Fichier);
  }
  else
    // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
    Erreur_fichier=1;
}
// -- Sauver un fichier au format PAL ---------------------------------------
void Save_PAL(void)
{
  FILE *Fichier;             // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  //long Taille_du_fichier;   // Taille du fichier
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier,"wb")))
  {
    T_Palette Palette_64;
    memcpy(Palette_64,Principal_Palette,sizeof(T_Palette));
    Palette_256_to_64(Palette_64);
    // Enregistrement de Principal_Palette dans le fichier
    if (! write_bytes(Fichier,Palette_64,sizeof(T_Palette)))
    {
      Erreur_fichier=1;
      fclose(Fichier);
      remove(Nom_du_fichier);
    }
    else // Ecriture correcte => Fermeture normale du fichier
      fclose(Fichier);
  }
  else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
  {
    Erreur_fichier=1;
    fclose(Fichier);
    remove(Nom_du_fichier);
                     //   On se fout du résultat de l'opération car si ça
                     // renvoie 0 c'est que le fichier avait été partiel-
                     // -lement écrit, sinon pas du tout. Or dans tous les
                     // cas ça revient au même pour nous: Sauvegarde ratée!
  }
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// IMG ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct
{
  byte Filler1[6];
  word Largeur;
  word Hauteur;
  byte Filler2[118];
  T_Palette Palette;
} __attribute__((__packed__)) T_Header_IMG;
// -- Tester si un fichier est au format IMG --------------------------------
void Test_IMG(void)
{
  FILE *Fichier;              // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  T_Header_IMG IMG_Header;
  byte Signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0};
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=1;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    // Lecture et vérification de la signature
    if (read_bytes(Fichier,&IMG_Header,sizeof(T_Header_IMG)))
    {
      if ( (!memcmp(IMG_Header.Filler1,Signature,6))
        && IMG_Header.Largeur && IMG_Header.Hauteur)
        Erreur_fichier=0;
    }
    // Fermeture du fichier
    fclose(Fichier);
  }
}
// -- Lire un fichier au format IMG -----------------------------------------
void Load_IMG(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  byte * Buffer;
  FILE *Fichier;
  word Pos_X,Pos_Y;
  long Largeur_lue;
  long Taille_du_fichier;
  T_Header_IMG IMG_Header;
  struct stat Informations_Fichier;
  stat(Nom_du_fichier,&Informations_Fichier);
  
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    Taille_du_fichier=Informations_Fichier.st_size;
    if (read_bytes(Fichier,&IMG_Header,sizeof(T_Header_IMG)))
    {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    IMG_Header.Largeur = SDL_Swap16(IMG_Header.Largeur);
    IMG_Header.Hauteur = SDL_Swap16(IMG_Header.Hauteur);
#endif
      Buffer=(byte *)malloc(IMG_Header.Largeur);
      Initialiser_preview(IMG_Header.Largeur,IMG_Header.Hauteur,Taille_du_fichier,FORMAT_IMG);
      if (Erreur_fichier==0)
      {
        memcpy(Principal_Palette,IMG_Header.Palette,sizeof(T_Palette));
        Set_palette(Principal_Palette);
        Remapper_fileselect();
        Principal_Largeur_image=IMG_Header.Largeur;
        Principal_Hauteur_image=IMG_Header.Hauteur;
        Largeur_lue=IMG_Header.Largeur;
        for (Pos_Y=0;(Pos_YTAILLE_COMMENTAIRE)
                  {
                    Couleur=Octet;              // On se sert de Couleur comme
                    Octet=TAILLE_COMMENTAIRE;   // variable temporaire
                    Couleur-=TAILLE_COMMENTAIRE;
                  }
                  else
                    Couleur=0;
                  if (read_bytes(Fichier,Principal_Commentaire,Octet))
                  {
                    Indice+=Octet;
                    Principal_Commentaire[Octet]='\0';
                    if (Couleur)
                      if (fseek(Fichier,Couleur,SEEK_CUR))
                        Erreur_fichier=2;
                  }
                  else
                    Erreur_fichier=2;
                }
                else
                  Erreur_fichier=2;
                break;
              case 1 : // Dimensions de l'écran d'origine
                if (read_byte(Fichier,&Octet))
                {
                  if (Octet==4)
                  {
                    Indice+=4;
                    if ( ! read_word_le(Fichier,(word *) &Ecran_original_X)
                      || !read_word_le(Fichier,(word *) &Ecran_original_Y) )
                      Erreur_fichier=2;
                  }
                  else
                    Erreur_fichier=2;
                }
                else
                  Erreur_fichier=2;
                break;
              case 2 : // Couleur de transparence
                if (read_byte(Fichier,&Octet))
                {
                  if (Octet==1)
                  {
                    Indice++;
                    if (! read_byte(Fichier,&Back_color))
                      Erreur_fichier=2;
                  }
                  else
                    Erreur_fichier=2;
                }
                else
                  Erreur_fichier=2;
                break;
              default:
                if (read_byte(Fichier,&Octet))
                {
                  Indice+=Octet;
                  if (fseek(Fichier,Octet,SEEK_CUR))
                    Erreur_fichier=2;
                }
                else
                  Erreur_fichier=2;
            }
          }
          else
            Erreur_fichier=2;
        }
        if ( (!Erreur_fichier) && (Indice!=Head.Jump) )
          Erreur_fichier=2;
      }
      /*Init_lecture();*/
      if (!Erreur_fichier)
      {
        Initialiser_preview(Head.Largeur,Head.Hauteur,Taille_du_fichier,FORMAT_PKM);
        if (Erreur_fichier==0)
        {
          
          Principal_Largeur_image=Head.Largeur;
          Principal_Hauteur_image=Head.Hauteur;
          Taille_image=(dword)(Principal_Largeur_image*Principal_Hauteur_image);
          // Palette lue en 64
          memcpy(Principal_Palette,Head.Palette,sizeof(T_Palette));
          Palette_64_to_256(Principal_Palette);
          Set_palette(Principal_Palette);
          Remapper_fileselect();
          Compteur_de_donnees_packees=0;
          Compteur_de_pixels=0;
          Taille_pack=(Informations_Fichier.st_size)-sizeof(T_Header_PKM)-Head.Jump;
          // Boucle de décompression:
          while ( (Compteur_de_pixels>8);
      Ecrire_octet(Fichier,Hauteur_ecran&0xFF);
      Ecrire_octet(Fichier,Hauteur_ecran>>8);
      // Ecriture de la back-color
      Ecrire_octet(Fichier,2);
      Ecrire_octet(Fichier,1);
      Ecrire_octet(Fichier,Back_color);
      // Routine de compression PKM de l'image
      Taille_image=(dword)(Principal_Largeur_image*Principal_Hauteur_image);
      Compteur_de_pixels=0;
      Valeur_pixel=Lit_pixel_de_sauvegarde(0,0);
      while ( (Compteur_de_pixels=Taille_image) break;
          Valeur_pixel=Lit_pixel_de_sauvegarde(Compteur_de_pixels % Principal_Largeur_image,Compteur_de_pixels / Principal_Largeur_image);
        }
        if ( (Derniere_couleur!=Head.Recon1) && (Derniere_couleur!=Head.Recon2) )
        {
          if (Compteur_de_repetitions==1)
            Ecrire_octet(Fichier,Derniere_couleur);
          else
          if (Compteur_de_repetitions==2)
          {
            Ecrire_octet(Fichier,Derniere_couleur);
            Ecrire_octet(Fichier,Derniere_couleur);
          }
          else
          if ( (Compteur_de_repetitions>2) && (Compteur_de_repetitions<256) )
          { // RECON1/couleur/nombre
            Ecrire_octet(Fichier,Head.Recon1);
            Ecrire_octet(Fichier,Derniere_couleur);
            Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
          }
          else
          if (Compteur_de_repetitions>=256)
          { // RECON2/couleur/hi(nombre)/lo(nombre)
            Ecrire_octet(Fichier,Head.Recon2);
            Ecrire_octet(Fichier,Derniere_couleur);
            Ecrire_octet(Fichier,Compteur_de_repetitions>>8);
            Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
          }
        }
        else
        {
          if (Compteur_de_repetitions<256)
          {
            Ecrire_octet(Fichier,Head.Recon1);
            Ecrire_octet(Fichier,Derniere_couleur);
            Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
          }
          else
          {
            Ecrire_octet(Fichier,Head.Recon2);
            Ecrire_octet(Fichier,Derniere_couleur);
            Ecrire_octet(Fichier,Compteur_de_repetitions>>8);
            Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
          }
        }
      }
      Close_ecriture(Fichier);
    }
    else
      Erreur_fichier=1;
    fclose(Fichier);
  }
  else
  {
    Erreur_fichier=1;
    fclose(Fichier);
  }
  //   S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser
  // ce fichier pourri traîner... Ca fait pas propre.
  if (Erreur_fichier)
    remove(Nom_du_fichier);
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// LBM ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct
{
  word  Width;
  word  Height;
  word  Xorg;       // Inutile
  word  Yorg;       // Inutile
  byte  BitPlanes;
  byte  Mask;
  byte  Compression;
  byte  Pad1;       // Inutile
  word  Transp_col;
  byte  Xaspect;    // Inutile
  byte  Yaspect;    // Inutile
  word  Xscreen;
  word  Yscreen;
} __attribute__((__packed__)) T_Header_LBM;
byte * LBM_Buffer;
FILE *LBM_Fichier;
// -- Tester si un fichier est au format LBM --------------------------------
void Test_LBM(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  char  Format[4];
  char  Section[4];
  dword Dummy;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((LBM_Fichier=fopen(Nom_du_fichier, "rb")))
  {
    if (! read_bytes(LBM_Fichier,Section,4))
      Erreur_fichier=1;
    else
    if (memcmp(Section,"FORM",4))
      Erreur_fichier=1;
    else
    {
      read_dword_be(LBM_Fichier, &Dummy);
                   //   On aurait pu vérifier que ce long est égal à la taille
                   // du fichier - 8, mais ça aurait interdit de charger des
                   // fichiers tronqués (et déjà que c'est chiant de perdre
                   // une partie du fichier il faut quand même pouvoir en
                   // garder un peu... Sinon, moi je pleure :'( !!! )
      if (! read_bytes(LBM_Fichier,Format,4))
        Erreur_fichier=1;
      else
      if ( (memcmp(Format,"ILBM",4)) && (memcmp(Format,"PBM ",4)) )
        Erreur_fichier=1;
    }
    fclose(LBM_Fichier);
  }
  else
    Erreur_fichier=1;
}
// -- Lire un fichier au format LBM -----------------------------------------
  byte Image_HAM;
  // ---------------- Adapter la palette pour les images HAM ----------------
  void Adapter_Palette_HAM(void)
  {
    short I,J,Temp;
    byte  Couleur;
    if (Image_HAM==6)
    {
      for (I=1; I<=14; I++)
      {
        // On recopie a palette de base
        memcpy(Principal_Palette+(I<<4),Principal_Palette,48);
        // On modifie les teintes de cette palette
        for (J=0; J<16; J++)
        {
          Couleur=(I<<4)+J;
          if (I<=7)
          {
            if (I&1)
            {
              Temp=Principal_Palette[J].R+16;
              Principal_Palette[Couleur].R=(Temp<63)?Temp:63;
            }
            if (I&2)
            {
              Temp=Principal_Palette[J].V+16;
              Principal_Palette[Couleur].V=(Temp<63)?Temp:63;
            }
            if (I&4)
            {
              Temp=Principal_Palette[J].B+16;
              Principal_Palette[Couleur].B=(Temp<63)?Temp:63;
            }
          }
          else
          {
            if ((I-7)&1)
            {
              Temp=Principal_Palette[J].R-16;
              Principal_Palette[Couleur].R=(Temp>=0)?Temp:0;
            }
            if ((I-7)&2)
            {
              Temp=Principal_Palette[J].V-16;
              Principal_Palette[Couleur].V=(Temp>=0)?Temp:0;
            }
            if ((I-7)&4)
            {
              Temp=Principal_Palette[J].B-16;
              Principal_Palette[Couleur].B=(Temp>=0)?Temp:0;
            }
          }
        }
      }
      // Ici, il reste les 16 dernières couleurs à modifier
      for (I=240,J=0; J<16; I++,J++)
      {
        Temp=Principal_Palette[J].R+8;
        Principal_Palette[I].R=(Temp<63)?Temp:63;
        Temp=Principal_Palette[J].V+8;
        Principal_Palette[I].V=(Temp<63)?Temp:63;
        Temp=Principal_Palette[J].B+8;
        Principal_Palette[I].B=(Temp<63)?Temp:63;
      }
    }
    else if (Image_HAM==8)
    {
      for (I=1; I<=3; I++)
      {
        // On recopie la palette de base
        memcpy(Principal_Palette+(I<<6),Principal_Palette,192);
        // On modifie les teintes de cette palette
        for (J=0; J<64; J++)
        {
          Couleur=(I<<6)+J;
          switch (I)
          {
            case 1 :
              Temp=Principal_Palette[J].R+16;
              Principal_Palette[Couleur].R=(Temp<63)?Temp:63;
              break;
            case 2 :
              Temp=Principal_Palette[J].V+16;
              Principal_Palette[Couleur].V=(Temp<63)?Temp:63;
              break;
            default:
              Temp=Principal_Palette[J].B+16;
              Principal_Palette[Couleur].B=(Temp<63)?Temp:63;
          }
        }
      }
    }
    else // Image 64 couleurs sauvée en 32.
    {
      for (I=0; I<32; I++)
      {
        J=I+32;
        Principal_Palette[J].R=Principal_Palette[I].R>>1;
        Principal_Palette[J].V=Principal_Palette[I].V>>1;
        Principal_Palette[J].B=Principal_Palette[I].B>>1;
      }
    }
  }
  // ------------------------- Attendre une section -------------------------
  byte Wait_for(byte * Section_attendue)
  {
    // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur)
    dword Taille_section;
    byte Section_lue[4];
    if (! read_bytes(LBM_Fichier,Section_lue,4))
      return 0;
    while (memcmp(Section_lue,Section_attendue,4)) // Sect. pas encore trouvée
    {
      if (!read_dword_be(LBM_Fichier,&Taille_section))
        return 0;
      if (Taille_section&1)
        Taille_section++;
      if (fseek(LBM_Fichier,Taille_section,SEEK_CUR))
        return 0;
      if (! read_bytes(LBM_Fichier,Section_lue,4))
        return 0;
    }
    return 1;
  }
// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour
// en faire du chunky
byte Couleur_ILBM_line(word Pos_X, word Vraie_taille_ligne, byte HBPm1)
{
  // Renvoie la couleur du pixel (ILBM) en Pos_X.
  // CL sera le rang auquel on extrait les bits de la couleur
  byte cl = 7 - (Pos_X & 7);
  int ax,bh,dx;
  byte bl=0;
  for(dx=HBPm1;dx>=0;dx--)
  {
  //CIL_Loop
    ax = (Vraie_taille_ligne * dx + Pos_X) >> 3;
    bh = (LBM_Buffer[ax] >> cl) & 1;
    bl = (bl << 1) + bh;
  }
  return bl;
}
  // ----------------------- Afficher une ligne ILBM ------------------------
  void Draw_ILBM_line(short Pos_Y, short Vraie_taille_ligne)
  {
    byte  Couleur;
    byte  Rouge,Vert,Bleu;
    byte  Temp;
    short Pos_X;
    if (Image_HAM<=1)                                               // ILBM
    {
      for (Pos_X=0; Pos_X>2;
            Couleur=Meilleure_couleur(Rouge,Vert,Bleu);
            break;
          case 0x02: // Rouge
            Rouge=Temp>>2;
            Couleur=Meilleure_couleur(Rouge,Vert,Bleu);
            break;
          case 0x03: // Vert
            Vert=Temp>>2;
            Couleur=Meilleure_couleur(Rouge,Vert,Bleu);
            break;
          default:   // Nouvelle couleur
            Couleur=Temp;
            Rouge=Principal_Palette[Couleur].R;
            Vert =Principal_Palette[Couleur].V;
            Bleu =Principal_Palette[Couleur].B;
        }
        Pixel_de_chargement(Pos_X,Pos_Y,Couleur);
      }
    }
  }
void Load_LBM(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  T_Header_LBM Header;
  char  Format[4];
  char  Section[4];
  byte  Octet;
  short B256;
  dword Nb_couleurs;
  dword Taille_image;
  short Pos_X;
  short Pos_Y;
  short Compteur;
  short Taille_ligne;       // Taille d'une ligne en octets
  short Vraie_taille_ligne; // Taille d'une ligne en pixels
  byte  Couleur;
  long  Taille_du_fichier;
  struct stat Informations_Fichier;
  dword Dummy;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((LBM_Fichier=fopen(Nom_du_fichier, "rb")))
  {
      stat(Nom_du_fichier,&Informations_Fichier);
    Taille_du_fichier=Informations_Fichier.st_size;
    // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été)
    read_bytes(LBM_Fichier,Section,4);
    read_dword_be(LBM_Fichier,&Dummy);
    read_bytes(LBM_Fichier,Format,4);
    if (!Wait_for((byte *)"BMHD"))
      Erreur_fichier=1;
    read_dword_be(LBM_Fichier,&Dummy);
    // Maintenant on lit le header pour pouvoir commencer le chargement de l'image
    if ( (read_word_be(LBM_Fichier,&Header.Width))
      && (read_word_be(LBM_Fichier,&Header.Height))
      && (read_word_be(LBM_Fichier,&Header.Xorg))
      && (read_word_be(LBM_Fichier,&Header.Yorg))
      && (read_byte(LBM_Fichier,&Header.BitPlanes))
      && (read_byte(LBM_Fichier,&Header.Mask))
      && (read_byte(LBM_Fichier,&Header.Compression))
      && (read_byte(LBM_Fichier,&Header.Pad1))
      && (read_word_be(LBM_Fichier,&Header.Transp_col))
      && (read_byte(LBM_Fichier,&Header.Xaspect))
      && (read_byte(LBM_Fichier,&Header.Yaspect))
      && (read_word_be(LBM_Fichier,&Header.Xscreen))
      && (read_word_be(LBM_Fichier,&Header.Yscreen))
      && Header.Width && Header.Height)
    {
      if ( (Header.BitPlanes) && (Wait_for((byte *)"CMAP")) )
      {
        read_dword_be(LBM_Fichier,&Nb_couleurs);
        Nb_couleurs/=3;
        if (((dword)1< il faut copier les 32 coul.
          }              // sur les 32 suivantes et assombrir ces dernières.
          else
          {
            if ((Header.BitPlanes==6) || (Header.BitPlanes==8))
              Image_HAM=Header.BitPlanes;
            else
              /* Erreur_fichier=1;*/  /* C'est censé être incorrect mais j'ai */
              Image_HAM=0;            /* trouvé un fichier comme ça, alors... */
          }
        }
        else
          Image_HAM=0;
        if ( (!Erreur_fichier) && (Nb_couleurs>=2) && (Nb_couleurs<=256) )
        {
          HBPm1=Header.BitPlanes-1;
          if (Header.Mask==1)
            Header.BitPlanes++;
          // Deluxe paint le fait... alors on le fait...
          Back_color=Header.Transp_col;
          // On commence par passer la palette en 256 comme ça, si la nouvelle
          // palette a moins de 256 coul, la précédente ne souffrira pas d'un
          // assombrissement préjudiciable.
          if (Config.Clear_palette)
            memset(Principal_Palette,0,sizeof(T_Palette));
          else
            Palette_64_to_256(Principal_Palette);
          //   On peut maintenant charger la nouvelle palette
          if (read_bytes(LBM_Fichier,Principal_Palette,3*Nb_couleurs))
          {
            Palette_256_to_64(Principal_Palette);
            if (Image_HAM)
              Adapter_Palette_HAM();
            Palette_64_to_256(Principal_Palette);
            Set_palette(Principal_Palette);
            Remapper_fileselect();
            // On lit l'octet de padding du CMAP si la taille est impaire
            if (Nb_couleurs&1)
              if (read_byte(LBM_Fichier,&Octet))
                Erreur_fichier=2;
            if ( (Wait_for((byte *)"BODY")) && (!Erreur_fichier) )
            {
              read_dword_be(LBM_Fichier,&Taille_image);
              //swab((char *)&Header.Width ,(char *)&Principal_Largeur_image,2);
              //swab((char *)&Header.Height,(char *)&Principal_Hauteur_image,2);
              Principal_Largeur_image = Header.Width;
              Principal_Hauteur_image = Header.Height;
              //swab((char *)&Header.Xscreen,(char *)&Ecran_original_X,2);
              //swab((char *)&Header.Yscreen,(char *)&Ecran_original_Y,2);
              Ecran_original_X = Header.Xscreen;
              Ecran_original_Y = Header.Yscreen;
              Initialiser_preview(Principal_Largeur_image,Principal_Hauteur_image,Taille_du_fichier,FORMAT_LBM);
              if (Erreur_fichier==0)
              {
                if (!memcmp(Format,"ILBM",4))    // "ILBM": InterLeaved BitMap
                {
                  // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques)
                  if (Principal_Largeur_image & 15)
                  {
                    Vraie_taille_ligne=( (Principal_Largeur_image+16) >> 4 ) << 4;
                    Taille_ligne=( (Principal_Largeur_image+16) >> 4 )*(Header.BitPlanes<<1);
                  }
                  else
                  {
                    Vraie_taille_ligne=Principal_Largeur_image;
                    Taille_ligne=(Principal_Largeur_image>>3)*Header.BitPlanes;
                  }
                  if (!Header.Compression)
                  {                                           // non compressé
                    LBM_Buffer=(byte *)malloc(Taille_ligne);
                    for (Pos_Y=0; ((Pos_Y 127 alors il faut répéter 256-'Octet' fois la couleur de l'octet suivant
                        // Si Octet <= 127 alors il faut afficher directement les 'Octet' octets suivants
                        if (Octet>127)
                        {
                          Lire_octet(LBM_Fichier, &Couleur);
                          B256=(short)(256-Octet);
                          for (Compteur=0; Compteur<=B256; Compteur++)
                            if (Pos_X127)
                        {
                          Lire_octet(LBM_Fichier, &Couleur);
                          B256=256-Octet;
                          for (Compteur=0; Compteur<=B256; Compteur++)
                            Pixel_de_chargement(Pos_X++,Pos_Y,Couleur);
                        }
                        else
                          for (Compteur=0; Compteur<=Octet; Compteur++)
                          {
                            byte Lu=0;
                            Lire_octet(LBM_Fichier, &Lu);
                            Pixel_de_chargement(Pos_X++,Pos_Y,Lu);
                          }
                      }
                    }
                    /*Close_lecture();*/
                  }
                }
              }
            }
            else
              Modif_Erreur_fichier(2);
          }
          else
          {
            Erreur_fichier=1;
          }
        }
        else
          Modif_Erreur_fichier(1);
      }
      else
        Erreur_fichier=1;
    }
    else
      Erreur_fichier=1;
    fclose(LBM_Fichier);
  }
  else
    Erreur_fichier=1;
}
// -- Sauver un fichier au format LBM ---------------------------------------
  byte LBM_File_de_couleurs[129];
  word LBM_Taille_de_file;
  byte LBM_Mode_repetition;
  // ------------- Ecrire les couleurs que l'on vient de traiter ------------
  void Transferer_couleurs(void)
  {
    byte Indice;
    if (LBM_Taille_de_file>0)
    {
      if (LBM_Mode_repetition)
      {
        Ecrire_octet(LBM_Fichier,257-LBM_Taille_de_file);
        Ecrire_octet(LBM_Fichier,LBM_File_de_couleurs[0]);
      }
      else
      {
        Ecrire_octet(LBM_Fichier,LBM_Taille_de_file-1);
        for (Indice=0; Indice et on a 3 couleurs qui se suivent
          {
            LBM_Taille_de_file-=2;
            Transferer_couleurs();
            LBM_File_de_couleurs[0]=Couleur;
            LBM_File_de_couleurs[1]=Couleur;
            LBM_File_de_couleurs[2]=Couleur;
            LBM_Taille_de_file=3;
            LBM_Mode_repetition=1;
          }
        }
        else // La couleur n'est pas la même que la précédente
        {
          if (!LBM_Mode_repetition)                 // On conserve le mode...
          {
            LBM_File_de_couleurs[LBM_Taille_de_file++]=Couleur;
            if (LBM_Taille_de_file==128)
              Transferer_couleurs();
          }
          else                                        // On change de mode...
          {
            Transferer_couleurs();
            LBM_File_de_couleurs[LBM_Taille_de_file]=Couleur;
            LBM_Taille_de_file++;
          }
        }
    }
  }
void Save_LBM(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  T_Header_LBM Header;
  word Pos_X;
  word Pos_Y;
  byte Octet;
  word Vraie_largeur;
  struct stat Informations_Fichier;
  Erreur_fichier=0;
  Nom_fichier_complet(Nom_du_fichier,0);
  // Ouverture du fichier
  if ((LBM_Fichier=fopen(Nom_du_fichier,"wb")))
  {
    write_bytes(LBM_Fichier,"FORM",4);
    write_dword_be(LBM_Fichier,0); // On mettra la taille à jour à la fin
    write_bytes(LBM_Fichier,"PBM BMHD",8);
    write_dword_be(LBM_Fichier,20);
    // On corrige la largeur de l'image pour qu'elle soit multiple de 2
    Vraie_largeur=Principal_Largeur_image+(Principal_Largeur_image&1);
    //swab((byte *)&Vraie_largeur,(byte *)&Header.Width,2);
    Header.Width=Principal_Largeur_image;
    Header.Height=Principal_Hauteur_image;
    Header.Xorg=0;
    Header.Yorg=0;
    Header.BitPlanes=8;
    Header.Mask=0;
    Header.Compression=1;
    Header.Pad1=0;
    Header.Transp_col=Back_color;
    Header.Xaspect=1;
    Header.Yaspect=1;
    Header.Xscreen = Largeur_ecran;
    Header.Yscreen = Hauteur_ecran;
    write_word_be(LBM_Fichier,Header.Width);
    write_word_be(LBM_Fichier,Header.Height);
    write_word_be(LBM_Fichier,Header.Xorg);
    write_word_be(LBM_Fichier,Header.Yorg);
    write_bytes(LBM_Fichier,&Header.BitPlanes,1);
    write_bytes(LBM_Fichier,&Header.Mask,1);
    write_bytes(LBM_Fichier,&Header.Compression,1);
    write_bytes(LBM_Fichier,&Header.Pad1,1);
    write_word_be(LBM_Fichier,Header.Transp_col);
    write_bytes(LBM_Fichier,&Header.Xaspect,1);
    write_bytes(LBM_Fichier,&Header.Yaspect,1);
    write_word_be(LBM_Fichier,Header.Xscreen);
    write_word_be(LBM_Fichier,Header.Yscreen);
    write_bytes(LBM_Fichier,"CMAP",4);
    write_dword_be(LBM_Fichier,sizeof(T_Palette));
    write_bytes(LBM_Fichier,Principal_Palette,sizeof(T_Palette));
    write_bytes(LBM_Fichier,"BODY",4);
    write_dword_be(LBM_Fichier,0); // On mettra la taille à jour à la fin
    Init_ecriture();
    LBM_Taille_de_file=0;
    for (Pos_Y=0; ((Pos_Y on efface le fichier
      remove(Nom_du_fichier);
  }
  else
    Erreur_fichier=1;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// BMP ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct
{
    word Signature;   // ='BM' = 0x4D42
    uint32_t Taille_1;    // =Taille du fichier
    word Reserv_1;    // =0
    word Reserv_2;    // =0
    uint32_t Decalage;    // Nb octets avant les données bitmap
    uint32_t Taille_2;    // =40 
    uint32_t Largeur;
    uint32_t Hauteur;
    word Plans;       // =1
    word Nb_bits;     // =1,4,8 ou 24
    uint32_t Compression;
    uint32_t Taille_3;
    uint32_t XPM;
    uint32_t YPM;
    uint32_t Nb_Clr;
    uint32_t Clr_Imprt;
} __attribute__((__packed__)) T_BMP_Header;
// -- Tester si un fichier est au format BMP --------------------------------
void Test_BMP(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  T_BMP_Header Header;
  Erreur_fichier=1;
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    if (read_bytes(Fichier,&(Header.Signature),2) // "BM"
     && read_dword_le(Fichier,&(Header.Taille_1))
     && read_word_le(Fichier,&(Header.Reserv_1))
     && read_word_le(Fichier,&(Header.Reserv_2))
     && read_dword_le(Fichier,&(Header.Decalage))
     && read_dword_le(Fichier,&(Header.Taille_2))
     && read_dword_le(Fichier,&(Header.Largeur))
     && read_dword_le(Fichier,&(Header.Hauteur))
     && read_word_le(Fichier,&(Header.Plans))
     && read_word_le(Fichier,&(Header.Nb_bits))
     && read_dword_le(Fichier,&(Header.Compression))
     && read_dword_le(Fichier,&(Header.Taille_3))
     && read_dword_le(Fichier,&(Header.XPM))
     && read_dword_le(Fichier,&(Header.YPM))
     && read_dword_le(Fichier,&(Header.Nb_Clr))
     && read_dword_le(Fichier,&(Header.Clr_Imprt))
        )
     {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
      Header.Signature = SDL_Swap16(Header.Signature);
#endif
      if ( (Header.Signature==0x4D42) && (Header.Taille_2==40)
        && Header.Largeur && Header.Hauteur )
        Erreur_fichier=0;
     }
    fclose(Fichier);
  }
}
// -- Charger un fichier au format BMP --------------------------------------
void Load_BMP(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  T_BMP_Header Header;
  byte * Buffer;
  word  Indice;
  byte  Palette_locale[256][4]; // R,V,B,0
  word  Nb_Couleurs =  0;
  short Pos_X;
  short Pos_Y;
  word  Taille_ligne;
  byte  A,B,C=0;
  long  Taille_du_fichier;
  struct stat Informations_Fichier;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
      stat(Nom_du_fichier,&Informations_Fichier);
    Taille_du_fichier=Informations_Fichier.st_size;
    if (read_word_le(Fichier,&(Header.Signature))
     && read_dword_le(Fichier,&(Header.Taille_1))
     && read_word_le(Fichier,&(Header.Reserv_1))
     && read_word_le(Fichier,&(Header.Reserv_2))
     && read_dword_le(Fichier,&(Header.Decalage))
     && read_dword_le(Fichier,&(Header.Taille_2))
     && read_dword_le(Fichier,&(Header.Largeur))
     && read_dword_le(Fichier,&(Header.Hauteur))
     && read_word_le(Fichier,&(Header.Plans))
     && read_word_le(Fichier,&(Header.Nb_bits))
     && read_dword_le(Fichier,&(Header.Compression))
     && read_dword_le(Fichier,&(Header.Taille_3))
     && read_dword_le(Fichier,&(Header.XPM))
     && read_dword_le(Fichier,&(Header.YPM))
     && read_dword_le(Fichier,&(Header.Nb_Clr))
     && read_dword_le(Fichier,&(Header.Clr_Imprt))
    )
    {
      switch (Header.Nb_bits)
      {
        case 1 :
        case 4 :
        case 8 :
          if (Header.Nb_Clr)
            Nb_Couleurs=Header.Nb_Clr;
          else
            Nb_Couleurs=1<>3;
                Buffer=(byte *)malloc(Taille_ligne);
                for (Pos_Y=Principal_Hauteur_image-1; ((Pos_Y>=0) && (!Erreur_fichier)); Pos_Y--)
                {
                  if (read_bytes(Fichier,Buffer,Taille_ligne))
                    for (Pos_X=0; Pos_X>1] & 0xF);
                          else
                            Pixel_de_chargement(Pos_X,Pos_Y,Buffer[Pos_X>>1] >> 4 );
                          break;
                        case 1 :
                          if ( Buffer[Pos_X>>3] & (0x80>>(Pos_X&7)) )
                            Pixel_de_chargement(Pos_X,Pos_Y,1);
                          else
                            Pixel_de_chargement(Pos_X,Pos_Y,0);
                      }
                  else
                    Erreur_fichier=2;
                }
                free(Buffer);
                break;
              case 1 : // Compression RLE 8 bits
                Pos_X=0;
                Pos_Y=Principal_Hauteur_image-1;
                /*Init_lecture();*/
                Lire_octet(Fichier, &A);
                Lire_octet(Fichier, &B);
                while ( (!Erreur_fichier) && ((A)||(B!=1)) )
                {
                  if (A) // Encoded mode
                    for (Indice=1; Indice<=A; Indice++)
                      Pixel_de_chargement(Pos_X++,Pos_Y,B);
                  else   // Absolute mode
                    switch (B)
                    {
                      case 0 : // End of line
                        Pos_X=0;
                        Pos_Y--;
                        break;
                      case 1 : // End of bitmap
                        break;
                      case 2 : // Delta
                        Lire_octet(Fichier, &A);
                        Lire_octet(Fichier, &B);
                        Pos_X+=A;
                        Pos_Y-=B;
                        break;
                      default: // Nouvelle série
                        while (B)
                        {
                          Lire_octet(Fichier, &A);
                          Lire_octet(Fichier, &C);
                          Pixel_de_chargement(Pos_X++,Pos_Y,A);
                          if (--B)
                          {
                            Pixel_de_chargement(Pos_X++,Pos_Y,C);
                            B--;
                          }
                        }
                    }
                  Lire_octet(Fichier, &A);
                  Lire_octet(Fichier, &B);
                }
                /*Close_lecture();*/
                break;
              case 2 : // Compression RLE 4 bits
                Pos_X=0;
                Pos_Y=Principal_Hauteur_image-1;
                /*Init_lecture();*/
                Lire_octet(Fichier, &A);
                Lire_octet(Fichier, &B);
                while ( (!Erreur_fichier) && ((A)||(B!=1)) )
                {
                  if (A) // Encoded mode (A fois les 1/2 pixels de B)
                    for (Indice=1; Indice<=A; Indice++)
                    {
                      if (Indice & 1)
                        Pixel_de_chargement(Pos_X,Pos_Y,B>>4);
                      else
                        Pixel_de_chargement(Pos_X,Pos_Y,B&0xF);
                      Pos_X++;
                    }
                  else   // Absolute mode
                    switch (B)
                    {
                      case 0 : //End of line
                        Pos_X=0;
                        Pos_Y--;
                        break;
                      case 1 : // End of bitmap
                        break;
                      case 2 : // Delta
                        Lire_octet(Fichier, &A);
                        Lire_octet(Fichier, &B);
                        Pos_X+=A;
                        Pos_Y-=B;
                        break;
                      default: // Nouvelle série (B 1/2 pixels bruts)
                        for (Indice=1; ((Indice<=B) && (!Erreur_fichier)); Indice++,Pos_X++)
                        {
                          if (Indice&1)
                          {
                            Lire_octet(Fichier, &C);
                            Pixel_de_chargement(Pos_X,Pos_Y,C>>4);
                          }
                          else
                            Pixel_de_chargement(Pos_X,Pos_Y,C&0xF);
                        }
                        //   On lit l'octet rendant le nombre d'octets pair, si
                        // nécessaire. Encore un truc de crétin "made in MS".
                        if ( ((B&3)==1) || ((B&3)==2) )
                        {
                          byte Dummy;
                          Lire_octet(Fichier, &Dummy);
                        }
                    }
                  Lire_octet(Fichier, &A);
                  Lire_octet(Fichier, &B);
                }
                /*Close_lecture();*/
            }
            fclose(Fichier);
          }
          else
          {
            fclose(Fichier);
            Erreur_fichier=1;
          }
        }
      }
      else
      {
        // Image 24 bits!!!
        Erreur_fichier=0;
        Principal_Largeur_image=Header.Largeur;
        Principal_Hauteur_image=Header.Hauteur;
        Initialiser_preview(Header.Largeur,Header.Hauteur,Taille_du_fichier,FORMAT_BMP | FORMAT_24B);
        if (Erreur_fichier==0)
        {
          Taille_ligne=Principal_Largeur_image*3;
          Pos_X=(Taille_ligne % 4); // Pos_X sert de variable temporaire
          if (Pos_X>0)
            Taille_ligne+=(4-Pos_X);
          Buffer=(byte *)malloc(Taille_ligne);
          for (Pos_Y=Principal_Hauteur_image-1; ((Pos_Y>=0) && (!Erreur_fichier)); Pos_Y--)
          {
            if (read_bytes(Fichier,Buffer,Taille_ligne))
              for (Pos_X=0,Indice=0; Pos_X> 3)+1) << 3;
    else
      Taille_ligne=Principal_Largeur_image;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    Header.Signature  = 0x424D;
#else
    Header.Signature  = 0x4D42;
#endif
    Header.Taille_1   =(Taille_ligne*Principal_Hauteur_image)+1078;
    Header.Reserv_1   =0;
    Header.Reserv_2   =0;
    Header.Decalage   =1078;
    Header.Taille_2   =40;
    Header.Largeur    =Taille_ligne;
    Header.Hauteur    =Principal_Hauteur_image;
    Header.Plans      =1;
    Header.Nb_bits    =8;
    Header.Compression=0;
    Header.Taille_3   =0;
    Header.XPM        =0;
    Header.YPM        =0;
    Header.Nb_Clr     =0;
    Header.Clr_Imprt  =0;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
    Header.Taille_1   = SDL_Swap32( Header.Taille_1 );
    Header.Decalage   = SDL_Swap32( Header.Decalage );
    Header.Taille_2   = SDL_Swap32( Header.Taille_2 );
    Header.Largeur    = SDL_Swap32( Header.Largeur );
    Header.Hauteur    = SDL_Swap32( Header.Hauteur );
    Header.Plans      = SDL_Swap16( Header.Plans );
    Header.Nb_bits    = SDL_Swap16( Header.Nb_bits );
    // If you ever set any more fields to non-zero, please swap here!
#endif
    if (write_bytes(Fichier,&Header,sizeof(T_BMP_Header)))
    {
      //   Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre
      // inverse, et pour faire chier, on va les mettre sur une échelle de
      // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et
      // puis comme c'est pas assez débile, on va aussi y rajouter un octet
      // toujours à 0 pour forcer les gens à s'acheter des gros disques
      // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira
      // Windows 95." ...
      for (Indice=0; Indice<256; Indice++)
      {
        Palette_locale[Indice][0]=Principal_Palette[Indice].B;
        Palette_locale[Indice][1]=Principal_Palette[Indice].V;
        Palette_locale[Indice][2]=Principal_Palette[Indice].R;
        Palette_locale[Indice][3]=0;
      }
      if (write_bytes(Fichier,Palette_locale,1024))
      {
        Init_ecriture();
        // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez
        // les pixels dans l'ordre inverse, mais que sur les Y quand-même
        // parce que faut pas pousser."
        for (Pos_Y=Principal_Hauteur_image-1; ((Pos_Y>=0) && (!Erreur_fichier)); Pos_Y--)
          for (Pos_X=0; Pos_X>=Nb_bits_en_cours;
      Nb_bits_traites  +=Nb_bits_en_cours;
      Nb_bits_a_traiter-=Nb_bits_en_cours;
      GIF_Rest_bits    -=Nb_bits_en_cours;
    }
    return GIF_Code_actuel;
  }
  // -- Affiche un nouveau pixel --
  void GIF_Nouveau_pixel(byte Couleur)
  {
    Pixel_de_chargement(GIF_Pos_X,GIF_Pos_Y,Couleur);
    GIF_Pos_X++;
    if (GIF_Pos_X>=Principal_Largeur_image)
    {
      GIF_Pos_X=0;
      if (!GIF_Entrelacee)
        GIF_Pos_Y++;
      else
      {
        switch (GIF_Passe)
        {
          case 0 : GIF_Pos_Y+=8;
                   break;
          case 1 : GIF_Pos_Y+=8;
                   break;
          case 2 : GIF_Pos_Y+=4;
                   break;
          default: GIF_Pos_Y+=2;
        }
        if (GIF_Pos_Y>=Principal_Hauteur_image)
        {
          switch(++GIF_Passe)
          {
          case 1 : GIF_Pos_Y=4;
                   break;
          case 2 : GIF_Pos_Y=2;
                   break;
          case 3 : GIF_Pos_Y=1;
                   break;
          case 4 : GIF_Image_entrelacee_terminee=1;
          }
        }
      }
    }
  }
void Load_GIF(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  char Signature[6];
  word * Alphabet_Pile;     // Pile de décodage d'une chaîne
  word * Alphabet_Prefixe;  // Table des préfixes des codes
  word * Alphabet_Suffixe;  // Table des suffixes des codes
  word   Alphabet_Free;     // Position libre dans l'alphabet
  word   Alphabet_Max;      // Nombre d'entrées possibles dans l'alphabet
  word   Alphabet_Pos_pile; // Position dans la pile de décodage d'un chaîne
  T_LSDB LSDB;
  T_IDB IDB;
  word Nb_couleurs;       // Nombre de couleurs dans l'image
  word Indice_de_couleur; // Indice de traitement d'une couleur
  byte Taille_de_lecture; // Nombre de données à lire      (divers)
  //word Indice_de_lecture; // Indice de lecture des données (divers)
  byte Block_indicateur;  // Code indicateur du type de bloc en cours
  word Nb_bits_initial;   // Nb de bits au début du traitement LZW
  word Cas_special=0;       // Mémoire pour le cas spécial
  word Code_ancien=0;       // Code précédent
  word Read_byte;         // Sauvegarde du code en cours de lecture
  word Valeur_Clr;        // Valeur <=> Clear tables
  word Valeur_Eof;        // Valeur <=> Fin d'image
  long Taille_du_fichier;
  struct stat Informations_Fichier;
  int Nombre_LID; // Nombre d'images trouvées dans le fichier
  /////////////////////////////////////////////////// FIN DES DECLARATIONS //
  GIF_Pos_X=0;
  GIF_Pos_Y=0;
  GIF_Last_byte=0;
  GIF_Rest_bits=0;
  GIF_Rest_byte=0;
  Nombre_LID=0;
  
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((GIF_Fichier=fopen(Nom_du_fichier, "rb")))
  {
      stat(Nom_du_fichier,&Informations_Fichier);
    Taille_du_fichier=Informations_Fichier.st_size;
    if ( (read_bytes(GIF_Fichier,Signature,6)) &&
         ( (memcmp(Signature,"GIF87a",6)==0) ||
           (memcmp(Signature,"GIF89a",6)==0) ) )
    {
      // Allocation de mémoire pour les tables & piles de traitement:
      Alphabet_Pile   =(word *)malloc(4096*sizeof(word));
      Alphabet_Prefixe=(word *)malloc(4096*sizeof(word));
      Alphabet_Suffixe=(word *)malloc(4096*sizeof(word));
      if (read_word_le(GIF_Fichier,&(LSDB.Largeur))
      && read_word_le(GIF_Fichier,&(LSDB.Hauteur))
      && read_byte(GIF_Fichier,&(LSDB.Resol))
      && read_byte(GIF_Fichier,&(LSDB.Backcol))
      && read_byte(GIF_Fichier,&(LSDB.Aspect))
        )
      {
        // Lecture du Logical Screen Descriptor Block réussie:
        Ecran_original_X=LSDB.Largeur;
        Ecran_original_Y=LSDB.Hauteur;
        // Palette globale dispo = (LSDB.Resol  and $80)
        // Profondeur de couleur =((LSDB.Resol  and $70) shr 4)+1
        // Nombre de bits/pixel  = (LSDB.Resol  and $07)+1
        // Ordre de Classement   = (LSDB.Aspect and $80)
        Alphabet_Pos_pile=0;
        GIF_Last_byte    =0;
        GIF_Rest_bits    =0;
        GIF_Rest_byte    =0;
        Nb_couleurs=(1 << ((LSDB.Resol & 0x07)+1));
        Nb_bits_initial=(LSDB.Resol & 0x07)+2;
        if (LSDB.Resol & 0x80)
        {
          // Palette globale dispo:
          if (Config.Clear_palette)
            memset(Principal_Palette,0,sizeof(T_Palette));
          //   On peut maintenant charger la nouvelle palette:
          if (!(LSDB.Aspect & 0x80))
            // Palette dans l'ordre:
            for(Indice_de_couleur=0;Indice_de_couleurCaracteres_a_garder)
                        fseek(GIF_Fichier,Taille_de_lecture-Caracteres_a_garder,SEEK_CUR);
                    }
                    break;
                  case 0xF9: // Graphics Control Extension
                    // Prévu pour la transparence
                    
                  default:
                    // On saute le bloc:
                    fseek(GIF_Fichier,Taille_de_lecture,SEEK_CUR);
                    break;
                }
                // Lecture de la taille du bloc suivant:
                read_byte(GIF_Fichier,&Taille_de_lecture);
              }
            }
            break;
            case 0x2C: // Local Image Descriptor
            {
              // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort.
              if (Nombre_LID!=0)
              {
                Erreur_fichier=2;
                break;
              }
              Nombre_LID++;
              
              // lecture de 10 derniers octets
              if ( read_word_le(GIF_Fichier,&(IDB.Pos_X))
                && read_word_le(GIF_Fichier,&(IDB.Pos_Y))
                && read_word_le(GIF_Fichier,&(IDB.Largeur_image))
                && read_word_le(GIF_Fichier,&(IDB.Hauteur_image))
                && read_byte(GIF_Fichier,&(IDB.Indicateur))
                && read_byte(GIF_Fichier,&(IDB.Nb_bits_pixel))
                && IDB.Largeur_image && IDB.Hauteur_image)
              {
                Principal_Largeur_image=IDB.Largeur_image;
                Principal_Hauteur_image=IDB.Hauteur_image;
    
                Initialiser_preview(IDB.Largeur_image,IDB.Hauteur_image,Taille_du_fichier,FORMAT_GIF);
    
                // Palette locale dispo = (IDB.Indicateur and $80)
                // Image entrelacée     = (IDB.Indicateur and $40)
                // Ordre de classement  = (IDB.Indicateur and $20)
                // Nombre de bits/pixel = (IDB.Indicateur and $07)+1 (si palette locale dispo)
    
                if (IDB.Indicateur & 0x80)
                {
                  // Palette locale dispo
    
                  Nb_couleurs=(1 << ((IDB.Indicateur & 0x07)+1));
                  Nb_bits_initial=(IDB.Indicateur & 0x07)+2;
    
                  if (!(IDB.Indicateur & 0x40))
                    // Palette dans l'ordre:
                    for(Indice_de_couleur=0;Indice_de_couleurValeur_Clr)
                      {
                        Alphabet_Pile[Alphabet_Pos_pile++]=Alphabet_Suffixe[GIF_Code_actuel];
                        GIF_Code_actuel=Alphabet_Prefixe[GIF_Code_actuel];
                      }
    
                      Cas_special=Alphabet_Pile[Alphabet_Pos_pile++]=GIF_Code_actuel;
    
                      do
                        GIF_Nouveau_pixel(Alphabet_Pile[--Alphabet_Pos_pile]);
                      while (Alphabet_Pos_pile!=0);
    
                      Alphabet_Prefixe[Alphabet_Free  ]=Code_ancien;
                      Alphabet_Suffixe[Alphabet_Free++]=GIF_Code_actuel;
                      Code_ancien=Read_byte;
    
                      if (Alphabet_Free>Alphabet_Max)
                      {
                        if (GIF_Nb_bits<12)
                          Alphabet_Max      =((1 << (++GIF_Nb_bits))-1);
                      }
                    }
                    else // Code Clear rencontré
                    {
                      GIF_Nb_bits       =Nb_bits_initial;
                      Alphabet_Max      =((1 <<  GIF_Nb_bits)-1);
                      Alphabet_Free     =Nb_couleurs+2;
                      Cas_special       =GIF_Get_next_code();
                      Code_ancien       =GIF_Code_actuel;
                      GIF_Nouveau_pixel(GIF_Code_actuel);
                    }
                  }
                  else
                    Erreur_fichier=2;
                } // Code End-Of-Information ou erreur de fichier rencontré
    
                /*Close_lecture();*/
    
                if (Erreur_fichier>=0)
                if ( /* (GIF_Pos_X!=0) || */
                     ( ( (!GIF_Entrelacee) && (GIF_Pos_Y!=Principal_Hauteur_image) ) ||
                       (  (GIF_Entrelacee) && (!GIF_Image_entrelacee_terminee) )
                     ) )
                  Erreur_fichier=2;
              } // Le fichier contenait un IDB
              else
                Erreur_fichier=2;
            }
            default:
            break;
          }
          // Lecture du code de fonction suivant:
          read_byte(GIF_Fichier,&Block_indicateur);
        }
      } // Le fichier contenait un LSDB
      else
        Erreur_fichier=1;
      // Libération de la mémoire utilisée par les tables & piles de traitement:
      free(Alphabet_Suffixe);
      free(Alphabet_Prefixe);
      free(Alphabet_Pile);
    } // Le fichier contenait au moins la signature GIF87a ou GIF89a
    else
      Erreur_fichier=1;
    fclose(GIF_Fichier);
  } // Le fichier était ouvrable
  else
    Erreur_fichier=1;
}
// -- Sauver un fichier au format GIF ---------------------------------------
  int  GIF_Arret;         // "On peut arrêter la sauvegarde du fichier"
  byte GIF_Buffer[256];   // Buffer d'écriture de bloc de données compilées
  // -- Vider le buffer GIF dans le buffer KM --
  void GIF_Vider_le_buffer(void)
  {
    word Indice;
    if (GIF_Rest_byte)
    {
      GIF_Buffer[0]=GIF_Rest_byte;
      for (Indice=0;Indice<=GIF_Rest_byte;Indice++)
        Ecrire_octet(GIF_Fichier,GIF_Buffer[Indice]);
      GIF_Rest_byte=0;
    }
  }
  // -- Ecrit un code à GIF_Nb_bits --
  void GIF_Set_code(word Code)
  {
    word Nb_bits_a_traiter=GIF_Nb_bits;
    word Nb_bits_traites  =0;
    word Nb_bits_en_cours;
    while (Nb_bits_a_traiter)
    {
      Nb_bits_en_cours=(Nb_bits_a_traiter<=(8-GIF_Rest_bits))?Nb_bits_a_traiter:(8-GIF_Rest_bits);
      GIF_Last_byte|=(Code & ((1<>=Nb_bits_en_cours;
      GIF_Rest_bits    +=Nb_bits_en_cours;
      Nb_bits_traites  +=Nb_bits_en_cours;
      Nb_bits_a_traiter-=Nb_bits_en_cours;
      if (GIF_Rest_bits==8) // Il ne reste plus de bits à coder sur l'octet courant
      {
        // Ecrire l'octet à balancer:
        GIF_Buffer[++GIF_Rest_byte]=GIF_Last_byte;
        // Si on a atteint la fin du bloc de Raster Data
        if (GIF_Rest_byte==255)
          // On doit vider le buffer qui est maintenant plein
          GIF_Vider_le_buffer();
        GIF_Last_byte=0;
        GIF_Rest_bits=0;
      }
    }
  }
  // -- Lire le pixel suivant --
  byte GIF_Pixel_suivant(void)
  {
    byte Temp;
    Temp=Lit_pixel_de_sauvegarde(GIF_Pos_X,GIF_Pos_Y);
    if (++GIF_Pos_X>=Principal_Largeur_image)
    {
      GIF_Pos_X=0;
      if (++GIF_Pos_Y>=Principal_Hauteur_image)
        GIF_Arret=1;
    }
    return Temp;
  }
void Save_GIF(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  word * Alphabet_Prefixe;  // Table des préfixes des codes
  word * Alphabet_Suffixe;  // Table des suffixes des codes
  word * Alphabet_Fille;    // Table des chaînes filles (plus longues)
  word * Alphabet_Soeur;    // Table des chaînes soeurs (même longueur)
  word   Alphabet_Free;     // Position libre dans l'alphabet
  word   Alphabet_Max;      // Nombre d'entrées possibles dans l'alphabet
  word   Depart;            // Code précédent (sert au linkage des chaînes)
  int    Descente;          // Booléen "On vient de descendre"
  T_LSDB LSDB;
  T_IDB IDB;
  byte Block_indicateur;  // Code indicateur du type de bloc en cours
  word Chaine_en_cours;   // Code de la chaîne en cours de traitement
  byte Caractere;         // Caractère à coder
  word Indice;            // Indice de recherche de chaîne
  /////////////////////////////////////////////////// FIN DES DECLARATIONS //
  GIF_Pos_X=0;
  GIF_Pos_Y=0;
  GIF_Last_byte=0;
  GIF_Rest_bits=0;
  GIF_Rest_byte=0;
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((GIF_Fichier=fopen(Nom_du_fichier,"wb")))
  {
    // On écrit la signature du fichier
    if (write_bytes(GIF_Fichier,"GIF89a",6))
    {
      // La signature du fichier a été correctement écrite.
      // Allocation de mémoire pour les tables
      Alphabet_Prefixe=(word *)malloc(4096*sizeof(word));
      Alphabet_Suffixe=(word *)malloc(4096*sizeof(word));
      Alphabet_Fille  =(word *)malloc(4096*sizeof(word));
      Alphabet_Soeur  =(word *)malloc(4096*sizeof(word));
      // On initialise le LSDB du fichier
      if (Config.Taille_ecran_dans_GIF)
      {
        LSDB.Largeur=Largeur_ecran;
        LSDB.Hauteur=Hauteur_ecran;
      }
      else
      {
        LSDB.Largeur=Principal_Largeur_image;
        LSDB.Hauteur=Principal_Hauteur_image;
      }
      LSDB.Resol  =0x97;          // Image en 256 couleurs, avec une palette
      LSDB.Backcol=0;
      LSDB.Aspect =0;             // Palette normale
      // On sauve le LSDB dans le fichier
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
      LSDB.Largeur = SDL_Swap16(LSDB.Largeur);
      LSDB.Hauteur = SDL_Swap16(LSDB.Hauteur);
#endif
      if (write_bytes(GIF_Fichier,&LSDB,sizeof(T_LSDB)))
      {
        // Le LSDB a été correctement écrit.
        // On sauve la palette
        if (write_bytes(GIF_Fichier,Principal_Palette,768))
        {
          // La palette a été correctement écrite.
          //   Le jour où on se servira des blocks d'extensions pour placer
          // des commentaires, on le fera ici.
          // Ecriture de la transparence
          //write_bytes(GIF_Fichier,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8);
          // Ecriture du commentaire
          if (Principal_Commentaire[0])
          {
            write_bytes(GIF_Fichier,"\x21\xFE",2);
            write_byte(GIF_Fichier,strlen(Principal_Commentaire));
            write_bytes(GIF_Fichier,Principal_Commentaire,strlen(Principal_Commentaire)+1);
          }
                            
          
          // On va écrire un block indicateur d'IDB et l'IDB du fichier
          Block_indicateur=0x2C;
          IDB.Pos_X=0;
          IDB.Pos_Y=0;
          IDB.Largeur_image=Principal_Largeur_image;
          IDB.Hauteur_image=Principal_Hauteur_image;
          IDB.Indicateur=0x07;    // Image non entrelacée, pas de palette locale.
          IDB.Nb_bits_pixel=8; // Image 256 couleurs;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
          IDB.Largeur_image = SDL_Swap16(IDB.Largeur_image);
          IDB.Hauteur_image = SDL_Swap16(IDB.Hauteur_image);
#endif
          if ( write_bytes(GIF_Fichier,&Block_indicateur,1) &&
               write_bytes(GIF_Fichier,&IDB,sizeof(T_IDB)) )
          {
            //   Le block indicateur d'IDB et l'IDB ont étés correctements
            // écrits.
            Init_ecriture();
            Indice=4096;
            Erreur_fichier=0;
            GIF_Arret=0;
            // Réintialisation de la table:
            Alphabet_Free=258;
            GIF_Nb_bits  =9;
            Alphabet_Max =511;
            GIF_Set_code(256);
            for (Depart=0;Depart<4096;Depart++)
            {
              Alphabet_Fille[Depart]=4096;
              Alphabet_Soeur[Depart]=4096;
            }
            ////////////////////////////////////////////// COMPRESSION LZW //
            Depart=Chaine_en_cours=GIF_Pixel_suivant();
            Descente=1;
            do
            {
              Caractere=GIF_Pixel_suivant();
              //   On regarde si dans la table on aurait pas une chaîne
              // équivalente à Chaine_en_cours+Caractere
              while ( (Indice0xFFF)
                {
                  // Réintialisation de la table:
                  GIF_Set_code(256);
                  Alphabet_Free=258;
                  GIF_Nb_bits  =9;
                  Alphabet_Max =511;
                  for (Depart=0;Depart<4096;Depart++)
                  {
                    Alphabet_Fille[Depart]=4096;
                    Alphabet_Soeur[Depart]=4096;
                  }
                }
                else if (Alphabet_Free>Alphabet_Max+1)
                {
                  // On augmente le nb de bits
                  GIF_Nb_bits++;
                  Alphabet_Max=(1< 16c , 1 => 256c , ...
    word Bytes_per_plane_line;// Doit toujours être pair
    word Palette_info;       // 1 => Couleur , 2 => Gris (ignoré à partir de la version 4)
    word Screen_X;           // |_ Dimensions de
    word Screen_Y;           // |  l'écran d'origine
    byte Filler[54];         // Ca... J'adore!
  } __attribute__((__packed__)) T_PCX_Header;
T_PCX_Header PCX_Header;
// -- Tester si un fichier est au format PCX --------------------------------
void Test_PCX(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  Erreur_fichier=0;
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    if (read_byte(Fichier,&(PCX_Header.Manufacturer)) &&
        read_byte(Fichier,&(PCX_Header.Version)) &&
        read_byte(Fichier,&(PCX_Header.Compression)) &&
        read_byte(Fichier,&(PCX_Header.Depth)) &&
        read_word_le(Fichier,&(PCX_Header.X_min)) &&
        read_word_le(Fichier,&(PCX_Header.Y_min)) &&
        read_word_le(Fichier,&(PCX_Header.X_max)) &&
        read_word_le(Fichier,&(PCX_Header.Y_max)) &&
        read_word_le(Fichier,&(PCX_Header.X_dpi)) &&
        read_word_le(Fichier,&(PCX_Header.Y_dpi)) &&
        read_bytes(Fichier,&(PCX_Header.Palette_16c),48) &&        
        read_byte(Fichier,&(PCX_Header.Reserved)) &&
        read_byte(Fichier,&(PCX_Header.Plane)) &&
        read_word_le(Fichier,&(PCX_Header.Bytes_per_plane_line)) &&
        read_word_le(Fichier,&(PCX_Header.Palette_info)) &&
        read_word_le(Fichier,&(PCX_Header.Screen_X)) &&
        read_word_le(Fichier,&(PCX_Header.Screen_Y)) &&
        read_bytes(Fichier,&(PCX_Header.Filler),54) )
    {
    
      //   Vu que ce header a une signature de merde et peu significative, il
      // va falloir que je teste différentes petites valeurs dont je connais
      // l'intervalle. Grrr!
      if ( (PCX_Header.Manufacturer!=10)
        || (PCX_Header.Compression>1)
        || ( (PCX_Header.Depth!=1) && (PCX_Header.Depth!=2) && (PCX_Header.Depth!=4) && (PCX_Header.Depth!=8) )
        || ( (PCX_Header.Plane!=1) && (PCX_Header.Plane!=2) && (PCX_Header.Plane!=4) && (PCX_Header.Plane!=8) && (PCX_Header.Plane!=3) )
        || (PCX_Header.X_max>((Reduction_moins_1-(Pos_X%Reduction))*Depth)) & Masque;
      Pixel_de_chargement(Pos_X,Pos_Y,Couleur);
    }
  }
void Load_PCX(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  
  short Taille_ligne;
  short Vraie_taille_ligne; // Largeur de l'image corrigée
  short Largeur_lue;
  short Pos_X;
  short Pos_Y;
  byte  Octet1;
  byte  Octet2;
  byte  Indice;
  dword Nb_couleurs;
  long  Taille_du_fichier;
  byte  Palette_CGA[9]={ 84,252,252,  252, 84,252,  252,252,252};
  long  Position;
  long  Taille_image;
  byte * Buffer;
  struct stat Informations_Fichier;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
      stat(Nom_du_fichier,&Informations_Fichier);
    Taille_du_fichier=Informations_Fichier.st_size;
    /*
    if (read_bytes(Fichier,&PCX_Header,sizeof(T_PCX_Header)))
    {*/
    
    if (read_byte(Fichier,&(PCX_Header.Manufacturer)) &&
        read_byte(Fichier,&(PCX_Header.Version)) &&
        read_byte(Fichier,&(PCX_Header.Compression)) &&
        read_byte(Fichier,&(PCX_Header.Depth)) &&
        read_word_le(Fichier,&(PCX_Header.X_min)) &&
        read_word_le(Fichier,&(PCX_Header.Y_min)) &&
        read_word_le(Fichier,&(PCX_Header.X_max)) &&
        read_word_le(Fichier,&(PCX_Header.Y_max)) &&
        read_word_le(Fichier,&(PCX_Header.X_dpi)) &&
        read_word_le(Fichier,&(PCX_Header.Y_dpi)) &&
        read_bytes(Fichier,&(PCX_Header.Palette_16c),48) &&        
        read_byte(Fichier,&(PCX_Header.Reserved)) &&
        read_byte(Fichier,&(PCX_Header.Plane)) &&
        read_word_le(Fichier,&(PCX_Header.Bytes_per_plane_line)) &&
        read_word_le(Fichier,&(PCX_Header.Palette_info)) &&
        read_word_le(Fichier,&(PCX_Header.Screen_X)) &&
        read_word_le(Fichier,&(PCX_Header.Screen_Y)) &&
        read_bytes(Fichier,&(PCX_Header.Filler),54) )
    {
      
      Principal_Largeur_image=PCX_Header.X_max-PCX_Header.X_min+1;
      Principal_Hauteur_image=PCX_Header.Y_max-PCX_Header.Y_min+1;
      Ecran_original_X=PCX_Header.Screen_X;
      Ecran_original_Y=PCX_Header.Screen_Y;
      if (PCX_Header.Plane!=3)
      {
        Initialiser_preview(Principal_Largeur_image,Principal_Hauteur_image,Taille_du_fichier,FORMAT_PCX);
        if (Erreur_fichier==0)
        {
          // On prépare la palette à accueillir les valeurs du fichier PCX
          if (Config.Clear_palette)
            memset(Principal_Palette,0,sizeof(T_Palette));
          Nb_couleurs=(dword)(1<4)
            memcpy(Principal_Palette,PCX_Header.Palette_16c,48);
          else
          {
            Principal_Palette[1].R=0;
            Principal_Palette[1].V=0;
            Principal_Palette[1].B=0;
            Octet1=PCX_Header.Palette_16c[3]>>5;
            if (Nb_couleurs==4)
            { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :))
              memcpy(Principal_Palette+1,Palette_CGA,9);
              if (!(Octet1&2))
              {
                Principal_Palette[1].B=84;
                Principal_Palette[2].B=84;
                Principal_Palette[3].B=84;
              }
            } // Palette monochrome (on va dire que c'est du N&B)
            else
            {
              Principal_Palette[1].R=252;
              Principal_Palette[1].V=252;
              Principal_Palette[1].B=252;
            }
          }
          //   On se positionne à la fin du fichier - 769 octets pour voir s'il y
          // a une palette.
          if ( (PCX_Header.Depth==8) && (PCX_Header.Version>=5) && (Taille_du_fichier>(256*3)) )
          {
            fseek(Fichier,Taille_du_fichier-((256*3)+1),SEEK_SET);
            // On regarde s'il y a une palette après les données de l'image
            if (read_byte(Fichier,&Octet1))
              if (Octet1==12) // Lire la palette si c'est une image en 256 couleurs
              {
                int indice;
                // On lit la palette 256c que ces crétins ont foutue à la fin du fichier
                for(indice=0;indice<256;indice++)
                  if ( ! read_byte(Fichier,&Principal_Palette[indice].R)
                   || ! read_byte(Fichier,&Principal_Palette[indice].V)
                   || ! read_byte(Fichier,&Principal_Palette[indice].B) )
                  {
                    Erreur_fichier=2;
                    DEBUG("ERROR READING PCX PALETTE !",indice);
                    break;
                  }
              }
          }
          Set_palette(Principal_Palette);
          Remapper_fileselect();
          //   Maintenant qu'on a lu la palette que ces crétins sont allés foutre
          // à la fin, on retourne juste après le header pour lire l'image.
          fseek(Fichier,128,SEEK_SET);
          if (!Erreur_fichier)
          {
            Taille_ligne=PCX_Header.Bytes_per_plane_line*PCX_Header.Plane;
            Vraie_taille_ligne=(short)PCX_Header.Bytes_per_plane_line<<3;
            //   On se sert de données LBM car le dessin de ligne en moins de 256
            // couleurs se fait comme avec la structure ILBM.
            Image_HAM=0;
            HBPm1=PCX_Header.Plane-1;
            LBM_Buffer=(byte *)malloc(Taille_ligne);
            // Chargement de l'image
            if (PCX_Header.Compression)  // Image compressée
            {
              /*Init_lecture();*/
  
              Taille_image=(long)PCX_Header.Bytes_per_plane_line*Principal_Hauteur_image;
              if (PCX_Header.Depth==8) // 256 couleurs (1 plan)
              {
                for (Position=0; ((Position=Taille_ligne)
                      {
                        for (Pos_X=0; Pos_X=Taille_ligne)
                  {
                    for (Pos_X=0; Pos_X1) || (Last_pixel>=0xC0) )
            Ecrire_octet(Fichier,Compteur|0xC0);
          Ecrire_octet(Fichier,Last_pixel);
      
        }
      }
      
      // Ecriture de l'octet (12) indiquant que la palette arrive
      if (!Erreur_fichier)
        Ecrire_octet(Fichier,12);
      
      Close_ecriture(Fichier);
      
      // Ecriture de la palette
      if (!Erreur_fichier)
      {
        if (! write_bytes(Fichier,Principal_Palette,sizeof(T_Palette)))
          Erreur_fichier=1;
      }
    }
    else
      Erreur_fichier=1;
       
    fclose(Fichier);
       
    if (Erreur_fichier)
      remove(Nom_du_fichier);
       
  }    
  else 
    Erreur_fichier=1;
}      
       
       
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// CEL ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct
{
  word Width;              // Largeur de l'image
  word Height;             // Hauteur de l'image
} __attribute__((__packed__))  T_CEL_Header1;
typedef struct
{
  byte Signa[4];           // Signature du format
  byte Kind;               // Type de fichier ($10=PALette $20=BitMaP)
  byte Nbbits;             // Nombre de bits
  word Filler1;            // ???
  word Largeur;            // Largeur de l'image
  word Hauteur;            // Hauteur de l'image
  word Decalage_X;         // Decalage en X de l'image
  word Decalage_Y;         // Decalage en Y de l'image
  byte Filler2[16];        // ???
} __attribute__((__packed__))  T_CEL_Header2;
// -- Tester si un fichier est au format CEL --------------------------------
void Test_CEL(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  int  Taille;
  FILE *Fichier;
  T_CEL_Header1 Header1;
  T_CEL_Header2 Header2;
  struct stat Informations_Fichier;
  Erreur_fichier=0;
  if (!stat(Nom_du_fichier,&Informations_Fichier))
  {
    Erreur_fichier = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber
    return;
  }
  Nom_fichier_complet(Nom_du_fichier,0);
  if (! (Fichier=fopen(Nom_du_fichier, "rb")))
  {
    Erreur_fichier = 1;
    return;
  }
  if (read_word_le(Fichier,&Header1.Width) &&
      read_word_le(Fichier,&Header1.Height) )
  {
      //   Vu que ce header n'a pas de signature, il va falloir tester la
      // cohérence de la dimension de l'image avec celle du fichier.
      
      Taille=(Informations_Fichier.st_size)-sizeof(T_CEL_Header1);
      if ( (!Taille) || ( (((Header1.Width+1)>>1)*Header1.Height)!=Taille ) )
      {
        // Tentative de reconnaissance de la signature des nouveaux fichiers
        fseek(Fichier,0,SEEK_SET);        
        if (read_bytes(Fichier,&Header2.Signa,4) &&
            !memcmp(Header2.Signa,"KiSS",4) &&
            read_byte(Fichier,&Header2.Kind) &&
            (Header2.Kind==0x20) &&
            read_byte(Fichier,&Header2.Nbbits) &&
            read_word_le(Fichier,&Header2.Filler1) &&
            read_word_le(Fichier,&Header2.Largeur) &&
            read_word_le(Fichier,&Header2.Hauteur) &&
            read_word_le(Fichier,&Header2.Decalage_X) &&
            read_word_le(Fichier,&Header2.Decalage_Y) &&
            read_bytes(Fichier,&Header2.Filler2,16))
        {
          // ok
        }
        else
          Erreur_fichier=1;
      }
      else
        Erreur_fichier=1;
  }
  else
  {
    Erreur_fichier=1;
  }
  fclose(Fichier);    
}
// -- Lire un fichier au format CEL -----------------------------------------
void Load_CEL(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  T_CEL_Header1 Header1;
  T_CEL_Header2 Header2;
  short Pos_X;
  short Pos_Y;
  byte  Dernier_octet=0;
  long  Taille_du_fichier;
  struct stat Informations_Fichier;
  Erreur_fichier=0;
  stat(Nom_du_fichier,&Informations_Fichier);
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    if (read_bytes(Fichier,&Header1,sizeof(T_CEL_Header1)))
    {
      Taille_du_fichier=Informations_Fichier.st_size;
      if ( (Taille_du_fichier>(long int)sizeof(T_CEL_Header1))
        && ( (((Header1.Width+1)>>1)*Header1.Height)==(Taille_du_fichier-(long int)sizeof(T_CEL_Header1)) ) )
      {
        // Chargement d'un fichier CEL sans signature (vieux fichiers)
        Principal_Largeur_image=Header1.Width;
        Principal_Hauteur_image=Header1.Height;
        Ecran_original_X=Principal_Largeur_image;
        Ecran_original_Y=Principal_Hauteur_image;
        Initialiser_preview(Principal_Largeur_image,Principal_Hauteur_image,Taille_du_fichier,FORMAT_CEL);
        if (Erreur_fichier==0)
        {
          // Chargement de l'image
          /*Init_lecture();*/
          for (Pos_Y=0;((Pos_Y> 4));
              }
              else
                Pixel_de_chargement(Pos_X,Pos_Y,(Dernier_octet & 15));
          /*Close_lecture();*/
        }
      }
      else
      {
        // On réessaye avec le nouveau format
        fseek(Fichier,0,SEEK_SET);
        if (read_bytes(Fichier,&Header2,sizeof(T_CEL_Header2)))
        {
          // Chargement d'un fichier CEL avec signature (nouveaux fichiers)
          Principal_Largeur_image=Header2.Largeur+Header2.Decalage_X;
          Principal_Hauteur_image=Header2.Hauteur+Header2.Decalage_Y;
          Ecran_original_X=Principal_Largeur_image;
          Ecran_original_Y=Principal_Hauteur_image;
          Initialiser_preview(Principal_Largeur_image,Principal_Hauteur_image,Taille_du_fichier,FORMAT_CEL);
          if (Erreur_fichier==0)
          {
            // Chargement de l'image
            /*Init_lecture();*/
            if (!Erreur_fichier)
            {
              // Effacement du décalage
              for (Pos_Y=0;Pos_Y> 4));
                      }
                      else
                        Pixel_de_chargement(Pos_X+Header2.Decalage_X,Pos_Y+Header2.Decalage_Y,(Dernier_octet & 15));
                  break;
                case 8:
                  for (Pos_Y=0;((Pos_Y16 sont utilisées dans l'image
    for (Pos_X=16;((Pos_X<256) && (!Utilisation[Pos_X]));Pos_X++);
    if (Pos_X==256)
    {
      // Cas d'une image 16 couleurs (écriture à l'ancien format)
      Header1.Width =Principal_Largeur_image;
      Header1.Height=Principal_Hauteur_image;
      if (write_bytes(Fichier,&Header1,sizeof(T_CEL_Header1)))
      {
        // Sauvegarde de l'image
        Init_ecriture();
        for (Pos_Y=0;((Pos_Y>4)!=0)
            Erreur_fichier=1;
    }
    else
    {
      if (read_bytes(Fichier,&Header2,sizeof(T_CEL_Header2)))
      {
        if (memcmp(Header2.Signa,"KiSS",4)==0)
        {
          if (Header2.Kind!=0x10)
            Erreur_fichier=1;
        }
        else
          Erreur_fichier=1;
      }
      else
        Erreur_fichier=1;
    }
    fclose(Fichier);
  }
  else
    Erreur_fichier=1;
}
// -- Lire un fichier au format KCF -----------------------------------------
void Load_KCF(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  T_KCF_Header Buffer;
  T_CEL_Header2 Header2;
  byte Octet[3];
  int Indice_palette;
  int Indice_couleur;
  int Indice;
  long  Taille_du_fichier;
  Erreur_fichier=0;
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    Taille_du_fichier=FileLength(Fichier);
    if (Taille_du_fichier==sizeof(T_KCF_Header))
    {
      // Fichier KCF à l'ancien format
      if (read_bytes(Fichier,&Buffer,sizeof(T_KCF_Header)))
      {
        // Initialiser_preview(???); // Pas possible... pas d'image...
        if (Config.Clear_palette)
          memset(Principal_Palette,0,sizeof(T_Palette));
        // Chargement de la palette
        for (Indice_palette=0;Indice_palette<10;Indice_palette++)
          for (Indice_couleur=0;Indice_couleur<16;Indice_couleur++)
          {
            Indice=16+(Indice_palette*16)+Indice_couleur;
            Principal_Palette[Indice].R=((Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet1 >> 4) << 4);
            Principal_Palette[Indice].B=((Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet1 & 15) << 4);
            Principal_Palette[Indice].V=((Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet2 & 15) << 4);
          }
        for (Indice=0;Indice<16;Indice++)
        {
          Principal_Palette[Indice].R=Principal_Palette[Indice+16].R;
          Principal_Palette[Indice].V=Principal_Palette[Indice+16].V;
          Principal_Palette[Indice].B=Principal_Palette[Indice+16].B;
        }
        Set_palette(Principal_Palette);
        Remapper_fileselect();
      }
      else
        Erreur_fichier=1;
    }
    else
    {
      // Fichier KCF au nouveau format
      if (read_bytes(Fichier,&Header2,sizeof(T_CEL_Header2)))
      {
        // Initialiser_preview(???); // Pas possible... pas d'image...
        Indice=(Header2.Nbbits==12)?16:0;
        for (Indice_palette=0;Indice_palette> 4) << 4;
                 Principal_Palette[Indice].B=(Octet[0] & 15) << 4;
                 Principal_Palette[Indice].V=(Octet[1] & 15) << 4;
                 break;
               case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB
                 read_bytes(Fichier,Octet,3);
                 Principal_Palette[Indice].R=Octet[0];
                 Principal_Palette[Indice].V=Octet[1];
                 Principal_Palette[Indice].B=Octet[2];
             }
             Indice++;
           }
        }
        if (Header2.Nbbits==12)
          for (Indice=0;Indice<16;Indice++)
          {
            Principal_Palette[Indice].R=Principal_Palette[Indice+16].R;
            Principal_Palette[Indice].V=Principal_Palette[Indice+16].V;
            Principal_Palette[Indice].B=Principal_Palette[Indice+16].B;
          }
        Set_palette(Principal_Palette);
        Remapper_fileselect();
      }
      else
        Erreur_fichier=1;
    }
    fclose(Fichier);
  }
  else
    Erreur_fichier=1;
  if (!Erreur_fichier) Dessiner_preview_palette();
}
// -- Ecrire un fichier au format KCF ---------------------------------------
void Save_KCF(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
  FILE *Fichier;
  T_KCF_Header Buffer;
  T_CEL_Header2 Header2;
  byte Octet[3];
  int Indice_palette;
  int Indice_couleur;
  int Indice;
  dword Utilisation[256]; // Table d'utilisation de couleurs
  // On commence par compter l'utilisation de chaque couleurs
  Palette_Compter_nb_couleurs_utilisees(Utilisation);
  Erreur_fichier=0;
  Nom_fichier_complet(Nom_du_fichier,0);
  if ((Fichier=fopen(Nom_du_fichier,"wb")))
  {
    // Sauvegarde de la palette
    // On regarde si des couleurs >16 sont utilisées dans l'image
    for (Indice=16;((Indice<256) && (!Utilisation[Indice]));Indice++);
    if (Indice==256)
    {
      // Cas d'une image 16 couleurs (écriture à l'ancien format)
      for (Indice_palette=0;Indice_palette<10;Indice_palette++)
        for (Indice_couleur=0;Indice_couleur<16;Indice_couleur++)
        {
          Indice=16+(Indice_palette*16)+Indice_couleur;
          Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet1=((Principal_Palette[Indice].R>>4)<<4) | (Principal_Palette[Indice].B>>4);
          Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet2=Principal_Palette[Indice].V>>4;
        }
      if (! write_bytes(Fichier,&Buffer,sizeof(T_KCF_Header)))
        Erreur_fichier=1;
    }
    else
    {
      // Cas d'une image 256 couleurs (écriture au nouveau format)
      memcpy(Header2.Signa,"KiSS",4); // Initialisation de la signature
      Header2.Kind=0x10;              // Initialisation du type (PALette)
      Header2.Nbbits=24;              // Initialisation du nombre de bits
      Header2.Filler1=0;              // Initialisation du filler 1 (???)
      Header2.Largeur=256;            // Initialisation du nombre de couleurs
      Header2.Hauteur=1;              // Initialisation du nombre de palettes
      Header2.Decalage_X=0;           // Initialisation du décalage X
      Header2.Decalage_Y=0;           // Initialisation du décalage Y
      for (Indice=0;Indice<16;Indice++) // Initialisation du filler 2 (???)
        Header2.Filler2[Indice]=0;
      if (! write_bytes(Fichier,&Header2,sizeof(T_CEL_Header2)))
        Erreur_fichier=1;
      for (Indice=0;(Indice<256) && (!Erreur_fichier);Indice++)
      {
        Octet[0]=Principal_Palette[Indice].R;
        Octet[1]=Principal_Palette[Indice].V;
        Octet[2]=Principal_Palette[Indice].B;
        if (! write_bytes(Fichier,Octet,3))
          Erreur_fichier=1;
      }
    }
    fclose(Fichier);
    if (Erreur_fichier)
      remove(Nom_du_fichier);
  }
  else
    Erreur_fichier=1;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// SCx ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef struct
{
  byte Filler1[4];
  word Largeur;
  word Hauteur;
  byte Filler2;
  byte Plans;
} __attribute__((__packed__)) T_SCx_Header;
// -- Tester si un fichier est au format SCx --------------------------------
void Test_SCx(void)
{
  FILE *Fichier;              // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  //byte Signature[3];
  T_SCx_Header SCx_Header;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=1;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    // Lecture et vérification de la signature
    if ((read_bytes(Fichier,&SCx_Header,sizeof(T_SCx_Header))))
    {
      if ( (!memcmp(SCx_Header.Filler1,"RIX",3))
        && SCx_Header.Largeur && SCx_Header.Hauteur)
      Erreur_fichier=0;
    }
    // Fermeture du fichier
    fclose(Fichier);
  }
}
// -- Lire un fichier au format SCx -----------------------------------------
void Load_SCx(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  FILE *Fichier;
  word Pos_X,Pos_Y;
  long Taille,Vraie_taille;
  long Taille_du_fichier;
  T_SCx_Header SCx_Header;
  T_Palette SCx_Palette;
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    Taille_du_fichier=FileLength(Fichier);
    if ((read_bytes(Fichier,&SCx_Header,sizeof(T_SCx_Header))))
    {
      Initialiser_preview(SCx_Header.Largeur,SCx_Header.Hauteur,Taille_du_fichier,FORMAT_SCx);
      if (Erreur_fichier==0)
      {
        if (!SCx_Header.Plans)
          Taille=sizeof(T_Palette);
        else
          Taille=sizeof(struct Composantes)*(1<>3)*SCx_Header.Plans;
            Vraie_taille=(Taille/SCx_Header.Plans)<<3;
            LBM_Buffer=(byte *)malloc(Taille);
            HBPm1=SCx_Header.Plans-1;
            Image_HAM=0;
            for (Pos_Y=0;(Pos_Y>=1;
  }
}
//// CODAGE d'une partie d'IMAGE ////
void PI1_16p_to_8b(byte * Src,byte * Dst)
{
  int  i;           // Indice du pixel à calculer
  word masque;      // Masque de codage
  word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination
  masque=0x8000;
  w0=w1=w2=w3=0;
  for (i=0;i<16;i++)
  {
    // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit
    // correspondant à celui du masque
    w0|=(Src[i] & 0x01)?masque:0x00;
    w1|=(Src[i] & 0x02)?masque:0x00;
    w2|=(Src[i] & 0x04)?masque:0x00;
    w3|=(Src[i] & 0x08)?masque:0x00;
    masque>>=1;
  }
  Dst[0]=w0 >> 8;
  Dst[1]=w0 & 0x00FF;
  Dst[2]=w1 >> 8;
  Dst[3]=w1 & 0x00FF;
  Dst[4]=w2 >> 8;
  Dst[5]=w2 & 0x00FF;
  Dst[6]=w3 >> 8;
  Dst[7]=w3 & 0x00FF;
}
//// DECODAGE de la PALETTE ////
void PI1_Decoder_palette(byte * Src,byte * Pal)
{
  int i;  // Numéro de la couleur traitée
  int ip; // Indice dans la palette
  word w; // Word contenant le code
  // Schéma d'un word =
  //
  //    Low        High
  // VVVV RRRR | 0000 BBBB
  // 0321 0321 |      0321
  ip=0;
  for (i=0;i<16;i++)
  {
    w=((word)Src[(i*2)+1]<<8) | Src[(i*2)+0];
    // Traitement des couleurs rouge, verte et bleue:
    Pal[ip++]=(((w & 0x0007) <<  1) | ((w & 0x0008) >>  3)) << 4;
    Pal[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4;
    Pal[ip++]=(((w & 0x0700) >>  7) | ((w & 0x0800) >> 11)) << 4;
  }
}
//// CODAGE de la PALETTE ////
void PI1_Coder_palette(byte * Pal,byte * Dst)
{
  int i;  // Numéro de la couleur traitée
  int ip; // Indice dans la palette
  word w; // Word contenant le code
  // Schéma d'un word =
  //
  //    Low        High
  // VVVV RRRR | 0000 BBBB
  // 0321 0321 |      0321
  ip=0;
  for (i=0;i<16;i++)
  {
    // Traitement des couleurs rouge, verte et bleue:
    w =(((word)(Pal[ip]>>2) & 0x38) >> 3) | (((word)(Pal[ip]>>2) & 0x04) <<  1); ip++;
    w|=(((word)(Pal[ip]>>2) & 0x38) << 9) | (((word)(Pal[ip]>>2) & 0x04) << 13); ip++;
    w|=(((word)(Pal[ip]>>2) & 0x38) << 5) | (((word)(Pal[ip]>>2) & 0x04) <<  9); ip++;
    Dst[(i*2)+0]=w & 0x00FF;
    Dst[(i*2)+1]=(w>>8);
  }
}
// -- Tester si un fichier est au format PI1 --------------------------------
void Test_PI1(void)
{
  FILE * Fichier;              // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  int  Taille;              // Taille du fichier
  word Res;                 // Résolution de l'image
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=1;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    // Vérification de la taille
    Taille=FileLength(Fichier);
    if ((Taille==32034) || (Taille==32066))
    {
      // Lecture et vérification de la résolution
      if (read_word_le(Fichier,&Res))
      {
        if (Res==0x0000)
          Erreur_fichier=0;
      }
    }
    // Fermeture du fichier
    fclose(Fichier);
  }
}
// -- Lire un fichier au format PI1 -----------------------------------------
void Load_PI1(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  FILE *Fichier;
  word Pos_X,Pos_Y;
  byte * buffer;
  byte * ptr;
  byte pixels[320];
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    // allocation d'un buffer mémoire
    buffer=(byte *)malloc(32034);
    if (buffer!=NULL)
    {
      // Lecture du fichier dans le buffer
      if (read_bytes(Fichier,buffer,32034))
      {
        // Initialisation de la preview
        Initialiser_preview(320,200,FileLength(Fichier),FORMAT_PI1);
        if (Erreur_fichier==0)
        {
          // Initialisation de la palette
          if (Config.Clear_palette)
            memset(Principal_Palette,0,sizeof(T_Palette));
          PI1_Decoder_palette(buffer+2,(byte *)Principal_Palette);
          Set_palette(Principal_Palette);
          Remapper_fileselect();
          Principal_Largeur_image=320;
          Principal_Hauteur_image=200;
          // Chargement/décompression de l'image
          ptr=buffer+34;
          for (Pos_Y=0;Pos_Y<200;Pos_Y++)
          {
            for (Pos_X=0;Pos_X<(320>>4);Pos_X++)
            {
              PI1_8b_to_16p(ptr,pixels+(Pos_X<<4));
              ptr+=8;
            }
            for (Pos_X=0;Pos_X<320;Pos_X++)
              Pixel_de_chargement(Pos_X,Pos_Y,pixels[Pos_X]);
          }
        }
      }
      else
        Erreur_fichier=1;
      free(buffer);
    }
    else
      Erreur_fichier=1;
    fclose(Fichier);
  }
  else
    Erreur_fichier=1;
}
// -- Sauver un fichier au format PI1 ---------------------------------------
void Save_PI1(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  FILE *Fichier;
  short Pos_X,Pos_Y;
  byte * buffer;
  byte * ptr;
  byte pixels[320];
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier,"wb")))
  {
    // allocation d'un buffer mémoire
    buffer=(byte *)malloc(32066);
    // Codage de la résolution
    buffer[0]=0x00;
    buffer[1]=0x00;
    // Codage de la palette
    PI1_Coder_palette((byte *)Principal_Palette,buffer+2);
    // Codage de l'image
    ptr=buffer+34;
    for (Pos_Y=0;Pos_Y<200;Pos_Y++)
    {
      // Codage de la ligne
      memset(pixels,0,320);
      if (Pos_Y>4);Pos_X++)
      {
        PI1_16p_to_8b(pixels+(Pos_X<<4),ptr);
        ptr+=8;
      }
    }
    memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy
    if (write_bytes(Fichier,buffer,32066))
    {
      fclose(Fichier);
    }
    else // Erreur d'écriture (disque plein ou protégé)
    {
      fclose(Fichier);
      remove(Nom_du_fichier);
      Erreur_fichier=1;
    }
    // Libération du buffer mémoire
    free(buffer);
  }
  else
  {
    fclose(Fichier);
    remove(Nom_du_fichier);
    Erreur_fichier=1;
  }
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// PC1 ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// DECOMPRESSION d'un buffer selon la méthode PACKBITS ////
void PC1_Decompresser_PackBits(byte * Src,byte * Dst)
{
  int is,id; // Les indices de parcour des buffers
  int n;     // Octet de contrôle
  for (is=id=0;id<32000;)
  {
    n=Src[is++];
    if (n & 0x80)
    {
      // Recopier Src[is] -n+1 fois
      n=257-n;
      for (;(n>0) && (id<32000);n--)
        Dst[id++]=Src[is];
      is++;
    }
    else
    {
      // Recopier n+1 octets littéralement
      n=n+1;
      for (;(n>0) && (id<32000);n--)
        Dst[id++]=Src[is++];
    }
    // Contrôle des erreurs
    if (n>0)
      Erreur_fichier=1;
  }
}
//// COMPRESSION d'un buffer selon la méthode PACKBITS ////
void PC1_Compresser_PackBits(byte * Src,byte * Dst,int TailleS,int * TailleD)
{
  int is; // Indice dans la source
  int id; // Indice dans la destination
  int ir; // Indice de   la répétition
  int n;  // Taille des séquences
  int repet; // "Il y a répétition"
  for (is=id=0;is0;n--)
        Dst[id++]=Src[is++];
    }
    // On code la partie sans répétitions
    if (repet)
    {
      // On compte la quantité de fois qu'il faut répéter la valeur
      for (ir+=3;ir>=1;
    }
  }
}
//// CODAGE d'une partie d'IMAGE ////
// Transformation d'1 ligne de pixels en 4 plans de bits
void PC1_1lp_to_4pb(byte * Src,byte * Dst0,byte * Dst1,byte * Dst2,byte * Dst3)
{
  int  i,j;         // Compteurs
  int  ip;          // Indice du pixel à calculer
  byte masque;      // Masque de decodage
  byte b0,b1,b2,b3; // Les 4 octets des plans bits sources
  ip=0;
  // Pour chacun des 40 octets des plans de bits
  for (i=0;i<40;i++)
  {
    // Pour chacun des 8 bits des octets
    masque=0x80;
    b0=b1=b2=b3=0;
    for (j=0;j<8;j++)
    {
      b0|=(Src[ip] & 0x01)?masque:0x00;
      b1|=(Src[ip] & 0x02)?masque:0x00;
      b2|=(Src[ip] & 0x04)?masque:0x00;
      b3|=(Src[ip] & 0x08)?masque:0x00;
      ip++;
      masque>>=1;
    }
    Dst0[i]=b0;
    Dst1[i]=b1;
    Dst2[i]=b2;
    Dst3[i]=b3;
  }
}
// -- Tester si un fichier est au format PC1 --------------------------------
void Test_PC1(void)
{
  FILE *Fichier;              // Fichier du fichier
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  int  Taille;              // Taille du fichier
  word Res;                 // Résolution de l'image
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=1;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    // Vérification de la taille
    Taille=FileLength(Fichier);
    if ((Taille<=32066))
    {
      // Lecture et vérification de la résolution
      if (read_word_le(Fichier,&Res))
      {
        if (Res==0x0080)
          Erreur_fichier=0;
      }
    }
    // Fermeture du fichier
    fclose(Fichier);
  }
}
// -- Lire un fichier au format PC1 -----------------------------------------
void Load_PC1(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  FILE *Fichier;
  int  Taille;
  word Pos_X,Pos_Y;
  byte * buffercomp;
  byte * bufferdecomp;
  byte * ptr;
  byte pixels[320];
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  if ((Fichier=fopen(Nom_du_fichier, "rb")))
  {
    Taille=FileLength(Fichier);
    // allocation des buffers mémoire
    buffercomp=(byte *)malloc(Taille);
    bufferdecomp=(byte *)malloc(32000);
    if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) )
    {
      // Lecture du fichier dans le buffer
      if (read_bytes(Fichier,buffercomp,Taille))
      {
        // Initialisation de la preview
        Initialiser_preview(320,200,FileLength(Fichier),FORMAT_PC1);
        if (Erreur_fichier==0)
        {
          // Initialisation de la palette
          if (Config.Clear_palette)
            memset(Principal_Palette,0,sizeof(T_Palette));
          PI1_Decoder_palette(buffercomp+2,(byte *)Principal_Palette);
          Set_palette(Principal_Palette);
          Remapper_fileselect();
          Principal_Largeur_image=320;
          Principal_Hauteur_image=200;
          // Décompression du buffer
          PC1_Decompresser_PackBits(buffercomp+34,bufferdecomp);
          // Décodage de l'image
          ptr=bufferdecomp;
          for (Pos_Y=0;Pos_Y<200;Pos_Y++)
          {
            // Décodage de la scanline
            PC1_4pb_to_1lp(ptr,ptr+40,ptr+80,ptr+120,pixels);
            ptr+=160;
            // Chargement de la ligne
            for (Pos_X=0;Pos_X<320;Pos_X++)
              Pixel_de_chargement(Pos_X,Pos_Y,pixels[Pos_X]);
          }
        }
      }
      else
        Erreur_fichier=1;
      free(bufferdecomp);
      free(buffercomp);
    }
    else
    {
      Erreur_fichier=1;
      if (bufferdecomp) free(bufferdecomp);
      if (buffercomp)   free(buffercomp);
    }
    fclose(Fichier);
  }
  else
    Erreur_fichier=1;
}
// -- Sauver un fichier au format PC1 ---------------------------------------
void Save_PC1(void)
{
  char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
  FILE *Fichier;
  int   Taille;
  short Pos_X,Pos_Y;
  byte * buffercomp;
  byte * bufferdecomp;
  byte * ptr;
  byte pixels[320];
  Nom_fichier_complet(Nom_du_fichier,0);
  Erreur_fichier=0;
  // Ouverture du fichier
  if ((Fichier=fopen(Nom_du_fichier,"wb")))
  {
    // Allocation des buffers mémoire
    bufferdecomp=(byte *)malloc(32000);
    buffercomp  =(byte *)malloc(64066);
    // Codage de la résolution
    buffercomp[0]=0x80;
    buffercomp[1]=0x00;
    // Codage de la palette
    PI1_Coder_palette((byte *)Principal_Palette,buffercomp+2);
    // Codage de l'image
    ptr=bufferdecomp;
    for (Pos_Y=0;Pos_Y<200;Pos_Y++)
    {
      // Codage de la ligne
      memset(pixels,0,320);
      if (Pos_Ycolor_type;
              bit_depth = info_ptr->bit_depth;
              
              if (bit_depth <= 8 && (color_type == PNG_COLOR_TYPE_PALETTE || PNG_COLOR_TYPE_GRAY))
              {
                int num_text;
                png_text *text_ptr;
                
                int unit_type;
                png_uint_32 res_x;
                png_uint_32 res_y;
                // Commentaire (tEXt)
                Principal_Commentaire[0]='\0'; // On efface le commentaire
                if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL)))
                {
                  while (num_text--)
                  {
                    if (!strcmp(text_ptr[num_text].key,"Title"))
                    {
                      int Taille;
                      Taille = Min(text_ptr[num_text].text_length, TAILLE_COMMENTAIRE);
                      strncpy(Principal_Commentaire, text_ptr[num_text].text, Taille);
                      Principal_Commentaire[Taille]='\0';
                      break; // Pas besoin de vérifier les suivants
                    }
                  }
                }
                // Pixel Ratio (pHYs)
                if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type))
                {
                  // Ignore unit, and use the X/Y ratio as a hint for
                  // WIDE or TALL pixels
                  if (res_x>0 && res_y>0)
                  {
                    if (res_y/res_x>1)
                    {
                      Ratio_image_chargee=PIXEL_WIDE;
                    }
                    else if (res_x/res_y>1)
                    {
                      Ratio_image_chargee=PIXEL_TALL;
                    }
                  }
                }
                Initialiser_preview(info_ptr->width,info_ptr->height,Taille_du_fichier,FORMAT_PNG);
                if (Erreur_fichier==0)
                {
                  int x,y;
                  png_colorp palette;
                  int num_palette;
                                    
                  if (color_type == PNG_COLOR_TYPE_GRAY)
                  {
                    if (bit_depth < 8)
                      png_set_gray_1_2_4_to_8(png_ptr);
                    // palette de niveaux de gris
                    for (x=0;xwidth;
                  Principal_Hauteur_image=info_ptr->height;
                  Taille_image=(dword)(Principal_Largeur_image*Principal_Hauteur_image);
                
                  png_set_interlace_handling(png_ptr);
                  png_read_update_info(png_ptr, info_ptr);
                  /* read file */
                  if (!setjmp(png_jmpbuf(png_ptr)))
                  {
                    row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Principal_Hauteur_image);
                    for (y=0; yrowbytes);
                    png_read_image(png_ptr, row_pointers);
                    
                    for (y=0; y