#define _XOPEN_SOURCE #include "const.h" #include "struct.h" #include "global.h" #include "graph.h" #include "divers.h" #include "pages.h" #include "op_c.h" #include #include #include #include #include #include #include "boutons.h" // On d‚clare m‚chamment le prototype de Erreur pour ‚viter de faire un // fichier "main.h": void Erreur(int Code); // Chargement des pixels dans l'‚cran principal void Pixel_Chargement_dans_ecran_courant(short Pos_X,short Pos_Y,byte Couleur) { if ((Pos_X>=0) && (Pos_Y>=0)) 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)<<3; Palette[Couleur].V=((Couleur & 0x1C)>>2)<<3; Palette[Couleur].B=((Couleur & 0x03)>>0)<<4; } } // 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( 27,74,"but is:",CM_Fonce,CM_Clair); Print_dans_fenetre( 83,74,Format_Extension[Format-1],CM_Noir,CM_Clair); } // On efface le commentaire pr‚c‚dent Block(Fenetre_Pos_X+46*Menu_Facteur_X,Fenetre_Pos_Y+176*Menu_Facteur_Y, Menu_Facteur_X<<8,Menu_Facteur_Y<<3,CM_Clair); // Affichage du commentaire if (Format_Commentaire[Format-1]) Print_dans_fenetre(46,176,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*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*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); } // 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); if (Nom_du_fichier[strlen(Nom_du_fichier)-1]!='\\') strcat(Nom_du_fichier,"\\"); // 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 // ///////////////////////////////////////////////////////////////////////////// byte * Tampon_lecture; word Index_lecture; void Init_lecture(void) { Tampon_lecture=(byte *)malloc(64000); Index_lecture=64000; } byte Lire_octet(int Fichier) { if (++Index_lecture>=64000) { if (read(Fichier,Tampon_lecture,64000)<=0) Erreur_fichier=2; Index_lecture=0; } return Tampon_lecture[Index_lecture]; } void Close_lecture(void) { free(Tampon_lecture); } // -------------------------------------------------------------------------- byte * Tampon_ecriture; word Index_ecriture; void Init_ecriture(void) { Tampon_ecriture=(byte *)malloc(64000); Index_ecriture=0; } void Ecrire_octet(int Fichier, byte Octet) { Tampon_ecriture[Index_ecriture++]=Octet; if (Index_ecriture>=64000) { if (write(Fichier,Tampon_ecriture,64000)==-1) Erreur_fichier=1; Index_ecriture=0; } } void Close_ecriture(int Fichier) { if (Index_ecriture) if (write(Fichier,Tampon_ecriture,Index_ecriture)==-1) Erreur_fichier=1; free(Tampon_ecriture); } ///////////////////////////////////////////////////////////////////////////// void (/*__interrupt __near*/ *Ancien_handler_clavier)(void); void /*__interrupt __near*/ Nouveau_handler_clavier(void) { /* A revoir ... _disable(); if (!Erreur_fichier) Erreur_fichier=-1; _enable(); _chain_intr(Ancien_handler_clavier); */ ; } // -------- 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; // 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) { Format_Test[Principal_Format-1](); 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); } free(Buffer_image_24b); } if (Image) { if ( (Erreur_fichier!=1) && (Format_Backup_done[Format]) ) { // 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 grƒce … 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; Format_Save[Principal_Format_fichier-1](); if (Erreur_fichier) Erreur(0); else { if ((Image) && (Format_Backup_done[Principal_Format_fichier-1])) Principal_Image_modifiee=0; } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// PAL //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format PAL -------------------------------- void Test_PAL(void) { int Fichier; // Handle du fichier char Nom_du_fichier[256]; // Nom complet du fichier long Taille_du_fichier; // Taille du fichier struct stat* Informations_Fichier=NULL; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=1; // Ouverture du fichier Fichier=open(Nom_du_fichier,O_RDONLY); if (Fichier!=-1) { stat(Nom_du_fichier,Informations_Fichier); // Lecture de la taille du fichier Taille_du_fichier=Informations_Fichier->st_size; close(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) { int Handle; // Handle du fichier char Nom_du_fichier[256]; // Nom complet du fichier long Taille_du_fichier; // Taille du fichier Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; // Ouverture du fichier Handle=open(Nom_du_fichier,O_RDONLY); if (Handle!=-1) { // Initialiser_preview(???); // Pas possible... pas d'image... // Lecture du fichier dans Principal_Palette if (read(Handle,Principal_Palette,sizeof(T_Palette))==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 close(Handle); } 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) { int Fichier; // Handle du fichier char Nom_du_fichier[256]; // Nom complet du fichier long Taille_du_fichier; // Taille du fichier Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; // Ouverture du fichier Fichier=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP); if (Fichier!=-1) { // Enregistrement de Principal_Palette dans le fichier if (write(Fichier,Principal_Palette,sizeof(T_Palette))==-1) { Erreur_fichier=1; close(Fichier); remove(Nom_du_fichier); } else // Ecriture correcte => Fermeture normale du fichier close(Fichier); } else // Si on n'a pas r‚ussi … ouvrir le fichier, alors il y a eu une erreur { Erreur_fichier=1; close(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 //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format IMG -------------------------------- void Test_IMG(void) { int Handle; // Handle du fichier char Nom_du_fichier[256]; // Nom complet du fichier struct Header { byte Filler1[6]; word Largeur; word Hauteur; byte Filler2[118]; T_Palette Palette; } IMG_Header; byte Signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0}; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=1; // Ouverture du fichier Handle=open(Nom_du_fichier,O_RDONLY); if (Handle!=-1) { // Lecture et v‚rification de la signature if ((read(Handle,&IMG_Header,sizeof(struct Header)))==sizeof(struct Header)) { if ( (!memcmp(IMG_Header.Filler1,Signature,6)) && IMG_Header.Largeur && IMG_Header.Hauteur) Erreur_fichier=0; } // Fermeture du fichier close(Handle); } } // -- Lire un fichier au format IMG ----------------------------------------- void Load_IMG(void) { char Nom_du_fichier[256]; // Nom complet du fichier byte * Buffer; int Fichier; word Pos_X,Pos_Y; long Largeur_lue; long Taille_du_fichier; struct Header { byte Filler1[6]; word Largeur; word Hauteur; byte Filler2[118]; T_Palette Palette; } IMG_Header; struct stat* Informations_Fichier=NULL; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { stat(Nom_du_fichier,Informations_Fichier); Taille_du_fichier=Informations_Fichier->st_size; if (read(Fichier,&IMG_Header,sizeof(struct Header))==sizeof(struct Header)) { Buffer=(byte *)malloc(IMG_Header.Largeur); Initialiser_preview(IMG_Header.Largeur,IMG_Header.Hauteur,Taille_du_fichier,FORMAT_IMG); if (Erreur_fichier==0) { // 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. Palette_64_to_256(Principal_Palette); // On peut maintenant transf‚rer la nouvelle palette memcpy(Principal_Palette,IMG_Header.Palette,sizeof(T_Palette)); Palette_256_to_64(Principal_Palette); Set_palette(Principal_Palette); Remapper_fileselect(); Principal_Largeur_image=IMG_Header.Largeur; Principal_Hauteur_image=IMG_Header.Hauteur; for (Pos_Y=0;(Pos_Yst_size; if (read(Fichier,&Head,sizeof(struct Header))==sizeof(struct Header)) { Principal_Commentaire[0]='\0'; // On efface le commentaire if (Head.Jump) { Indice=0; while ( (IndiceTAILLE_COMMENTAIRE) { Couleur=Octet; // On se sert de Couleur comme Octet=TAILLE_COMMENTAIRE; // variable temporaire Couleur-=TAILLE_COMMENTAIRE; } else Couleur=0; if (read(Fichier,Principal_Commentaire,Octet)==Octet) { Indice+=Octet; Principal_Commentaire[Octet]='\0'; if (Couleur) if (lseek(Fichier,Couleur,SEEK_CUR)==-1) Erreur_fichier=2; } else Erreur_fichier=2; } else Erreur_fichier=2; break; case 1 : // Dimensions de l'‚cran d'origine if (read(Fichier,&Octet,1)==1) { if (Octet==4) { Indice+=4; if ( (read(Fichier,&Ecran_original_X,2)!=2) || (read(Fichier,&Ecran_original_Y,2)!=2) ) Erreur_fichier=2; } else Erreur_fichier=2; } else Erreur_fichier=2; break; case 2 : // Couleur de transparence if (read(Fichier,&Octet,1)==1) { if (Octet==1) { Indice++; if (read(Fichier,&Back_color,1)!=1) Erreur_fichier=2; } else Erreur_fichier=2; } else Erreur_fichier=2; break; default: if (read(Fichier,&Octet,1)==1) { Indice+=Octet; if (lseek(Fichier,Octet,SEEK_CUR)==-1) 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); memcpy(Principal_Palette,Head.Palette,sizeof(T_Palette)); Set_palette(Principal_Palette); Remapper_fileselect(); Compteur_de_donnees_packees=0; Compteur_de_pixels=0; Taille_pack=(Informations_Fichier->st_size)-sizeof(struct Header)-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_pixels2) && (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; close(Fichier); } else { Erreur_fichier=1; close(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 //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format LBM -------------------------------- int LBM_Fichier; // ------------ Lire et traduire une valeur au format Motorola ------------ dword Lire_long(void) { dword Temp; dword Valeur; if (read(LBM_Fichier,&Valeur,4)!=4) Erreur_fichier=1; swab((char *)&Valeur,(char *)&Temp,4); return ((Temp>>16)+(Temp<<16)); } void Test_LBM(void) { char Nom_du_fichier[256]; char Format[4]; char Section[4]; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((LBM_Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { if (read(LBM_Fichier,Section,4)!=4) Erreur_fichier=1; else if (memcmp(Section,"FORM",4)) Erreur_fichier=1; else { Lire_long(); // 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(LBM_Fichier,Format,4)!=4) Erreur_fichier=1; else if ( (memcmp(Format,"ILBM",4)) && (memcmp(Format,"PBM ",4)) ) Erreur_fichier=1; } close(LBM_Fichier); } else Erreur_fichier=1; } // -- Lire un fichier au format LBM ----------------------------------------- byte * LBM_Buffer; byte Image_HAM; byte HBPm1; // Header.BitPlanes-1 // ---------------- 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(LBM_Fichier,Section_lue,4)!=4) return 0; while (memcmp(Section_lue,Section_attendue,4)) // Sect. pas encore trouv‚e { Taille_section=Lire_long(); if (Erreur_fichier) return 0; if (Taille_section&1) Taille_section++; if (lseek(LBM_Fichier,Taille_section,SEEK_CUR)==-1) return 0; if (read(LBM_Fichier,Section_lue,4)!=4) return 0; } return 1; } // ----------------------- 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[256]; int Fichier; struct Header_LBM { word Width; word Height; short Xorg; // Inutile short Yorg; // Inutile byte Bit_planes; byte Mask; byte Compression; byte Pad1; // Inutile word Transp_col; byte Xaspect; // Inutile byte Yaspect; // Inutile short Xscreen; short Yscreen; } 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=NULL; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((LBM_Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { 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(LBM_Fichier,Section,4); Lire_long(); read(LBM_Fichier,Format,4); if (!Wait_for("BMHD")) Erreur_fichier=1; Lire_long(); // Maintenant on lit le header pour pouvoir commencer le chargement de l'image if ( (read(LBM_Fichier,&Header,sizeof(struct Header_LBM))==sizeof(struct Header_LBM)) && Header.Width && Header.Height) { if ( (Header.Bit_planes) && (Wait_for("CMAP")) ) { Nb_couleurs=Lire_long()/3; if (((int)1< il faut copier les 32 coul. } // sur les 32 suivantes et assombrir ces derniŠres. else { if ((Header.Bit_planes==6) || (Header.Bit_planes==8)) Image_HAM=Header.Bit_planes; 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.Bit_planes-1; if (Header.Mask==1) Header.Bit_planes++; // 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(LBM_Fichier,Principal_Palette,3*Nb_couleurs)==(3*Nb_couleurs)) { Palette_256_to_64(Principal_Palette); if (Image_HAM) Adapter_Palette_HAM(); 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(LBM_Fichier,&Octet,1)==1) Erreur_fichier=2; if ( (Wait_for("BODY")) && (!Erreur_fichier) ) { Taille_image=Lire_long(); swab((char *)&Header.Width ,(char *)&Principal_Largeur_image,2); swab((char *)&Header.Height,(char *)&Principal_Hauteur_image,2); swab((char *)&Header.Xscreen,(char *)&Ecran_original_X,2); swab((char *)&Header.Yscreen,(char *)&Ecran_original_Y,2); 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.Bit_planes<<1); } else { Vraie_taille_ligne=Principal_Largeur_image; Taille_ligne=(Principal_Largeur_image>>3)*Header.Bit_planes; } if (!Header.Compression) { // non compress‚ LBM_Buffer=(byte *)malloc(Taille_ligne); for (Pos_Y=0; ((Pos_Y127) { Couleur=Lire_octet(LBM_Fichier); B256=(short)(256-Octet); for (Compteur=0; Compteur<=B256; Compteur++) if (Pos_X127) { Couleur=Lire_octet(LBM_Fichier); B256=256-Octet; for (Compteur=0; Compteur<=B256; Compteur++) Pixel_de_chargement(Pos_X++,Pos_Y,Couleur); } else for (Compteur=0; Compteur<=Octet; Compteur++) Pixel_de_chargement(Pos_X++,Pos_Y,Lire_octet(LBM_Fichier)); } } Close_lecture(); } } } } else Modif_Erreur_fichier(2); } else { // On restore l'ancienne palette en cas d'erreur... Palette_256_to_64(Principal_Palette); // ... ce qui permet de ne renvoyer qu'une erreur 1 (pas de modif) Erreur_fichier=1; } } else Modif_Erreur_fichier(1); } else Erreur_fichier=1; } else Erreur_fichier=1; close(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; // ----------- Traduire et ‚crire une valeur au format Motorola ----------- void Ecrire_long(dword Valeur) { dword Temp; swab((char *)&Valeur,(char *)&Temp,4); Valeur=(Temp>>16)+(Temp<<16); if (write(LBM_Fichier,&Valeur,4)==-1) Erreur_fichier=1; } // ------------- 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[256]; struct Header_LBM { word Width; word Height; short Xorg; // Inutile short Yorg; // Inutile byte BitPlanes; byte Mask; byte Compression; byte Pad1; // Inutile word Transp_col; // Inutile byte Xaspect; // Inutile byte Yaspect; // Inutile short Xscreen; short Yscreen; } Header; word Pos_X; word Pos_Y; byte Octet; word Vraie_largeur; struct stat* Informations_Fichier=NULL; Erreur_fichier=0; Nom_fichier_complet(Nom_du_fichier,0); // Ouverture du fichier LBM_Fichier=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP); if (LBM_Fichier!=-1) { write(LBM_Fichier,"FORM",4); Ecrire_long(0); // On mettra la taille … jour … la fin write(LBM_Fichier,"PBM BMHD",8); Ecrire_long(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); swab((byte *)&Principal_Largeur_image,(byte *)&Header.Width,2); swab((byte *)&Principal_Hauteur_image,(byte *)&Header.Height,2); 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; swab((byte *)&Largeur_ecran,(byte *)&Header.Xscreen,2); swab((byte *)&Hauteur_ecran,(byte *)&Header.Yscreen,2); write(LBM_Fichier,&Header,sizeof(struct Header_LBM)); write(LBM_Fichier,"CMAP",4); Ecrire_long(sizeof(T_Palette)); Palette_64_to_256(Principal_Palette); write(LBM_Fichier,Principal_Palette,sizeof(T_Palette)); Palette_256_to_64(Principal_Palette); write(LBM_Fichier,"BODY",4); Ecrire_long(0); // On mettra la taille … jour … la fin Init_ecriture(); LBM_Taille_de_file=0; for (Pos_Y=0; ((Pos_Yst_size)-824); if (!Erreur_fichier) { lseek(LBM_Fichier,4,SEEK_SET); // Si la taille de la section de l'image (taille fichier-8) est // impaire, on rajoute un 0 (Padding) … la fin. if ((Informations_Fichier->st_size) & 1) { Ecrire_long((Informations_Fichier->st_size)-7); lseek(LBM_Fichier,0,SEEK_END); Octet=0; if (write(LBM_Fichier,&Octet,1)==-1) Erreur_fichier=1; } else Ecrire_long((Informations_Fichier->st_size)-8); close(LBM_Fichier); if (Erreur_fichier) remove(Nom_du_fichier); } else { Erreur_fichier=1; close(LBM_Fichier); remove(Nom_du_fichier); } } else // Il y a eu une erreur lors du compactage => on efface le fichier remove(Nom_du_fichier); } else Erreur_fichier=1; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// BMP //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format BMP -------------------------------- void Test_BMP(void) { char Nom_du_fichier[256]; int Fichier; struct BMP_Header { word Signature; // ='BM' = 0x4D42 long Taille_1; // =Taille du fichier word Reserv_1; // =0 word Reserv_2; // =0 long Decalage; // Nb octets avant les donn‚es bitmap long Taille_2; // =40 long Largeur; long Hauteur; word Plans; // =1 word Nb_bits; // =1,4,8 ou 24 long Compression; long Taille_3; long XPM; long YPM; long Nb_Clr; long Clr_Imprt; } Header; Erreur_fichier=1; Nom_fichier_complet(Nom_du_fichier,0); if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { if (read(Fichier,&Header,sizeof(struct BMP_Header))==sizeof(struct BMP_Header)) if ( (Header.Signature==0x4D42) && (Header.Taille_2==40) && Header.Largeur && Header.Hauteur ) Erreur_fichier=0; close(Fichier); } } // -- Charger un fichier au format BMP -------------------------------------- void Load_BMP(void) { char Nom_du_fichier[256]; int Fichier; struct BMP_Header { word Signature; // ='BM' = 0x4D42 long Taille_1; // =Taille du fichier word Reserv_1; // =0 word Reserv_2; // =0 long Decalage; // Nb octets avant les donn‚es bitmap long Taille_2; // =40 long Largeur; long Hauteur; word Plans; // =1 word Nb_bits; // =1,4,8 ou 24 long Compression; long Taille_3; long XPM; long YPM; long Nb_Clr; long Clr_Imprt; } Header; byte * Buffer; word Indice; byte Palette_locale[256][4]; // R,V,B,0 word Nb_Couleurs; short Pos_X; short Pos_Y; word Taille_ligne; byte A,B,C=0; long Taille_du_fichier; struct stat* Informations_Fichier=NULL; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { stat(Nom_du_fichier,Informations_Fichier); Taille_du_fichier=Informations_Fichier->st_size; if (read(Fichier,&Header,sizeof(struct BMP_Header))==sizeof(struct BMP_Header)) { 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(Fichier,Buffer,Taille_ligne)==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(); A=Lire_octet(Fichier); B=Lire_octet(Fichier); 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 A=Lire_octet(Fichier); B=Lire_octet(Fichier); Pos_X+=A; Pos_Y-=B; break; default: // Nouvelle s‚rie while (B) { A=Lire_octet(Fichier); C=Lire_octet(Fichier); Pixel_de_chargement(Pos_X++,Pos_Y,A); if (--B) { Pixel_de_chargement(Pos_X++,Pos_Y,C); B--; } } } A=Lire_octet(Fichier); B=Lire_octet(Fichier); } Close_lecture(); break; case 2 : // Compression RLE 4 bits Pos_X=0; Pos_Y=Principal_Hauteur_image-1; Init_lecture(); A=Lire_octet(Fichier); B=Lire_octet(Fichier); 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 A=Lire_octet(Fichier); B=Lire_octet(Fichier); 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) { C=Lire_octet(Fichier); 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) ) Lire_octet(Fichier); } A=Lire_octet(Fichier); B=Lire_octet(Fichier); } Close_lecture(); } close(Fichier); } else { close(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(Fichier,Buffer,Taille_ligne)==Taille_ligne) for (Pos_X=0,Indice=0; Pos_X> 3)+1) << 3; else Taille_ligne=Principal_Largeur_image; Header.Signature =0x4D42; 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 (write(Fichier,&Header,sizeof(struct BMP_Header))!=-1) { // 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." ... Palette_64_to_256(Principal_Palette); 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; } Palette_256_to_64(Principal_Palette); if (write(Fichier,Palette_locale,1024)!=-1) { 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[256]; 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 struct Type_LSDB { word Largeur; // Largeur de l'‚cran virtuel word Hauteur; // Hauteur de l'‚cran virtuel byte Resol; // Informations sur la r‚solution (et autres) byte Backcol; // Couleur de fond byte Aspect; // Informations sur l'aspect ratio (et autres) } LSDB; // Logical Screen Descriptor Block struct Type_IDB { word Pos_X; // Abscisse o— devrait ˆtre affich‚e l'image word Pos_Y; // Ordonn‚e o— devrait ˆtre affich‚e l'image word Largeur_image; // Largeur de l'image word Hauteur_image; // Hauteur de l'image byte Indicateur; // Informations diverses sur l'image byte Nb_bits_pixel; // Nb de bits par pixel } IDB; // Image Descriptor Block word Nb_couleurs; // Nombre de couleurs dans l'image word Indice_de_couleur; // Indice de traitement d'une couleur word 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=NULL; /////////////////////////////////////////////////// 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=open(Nom_du_fichier,O_RDONLY))!=-1) { stat(Nom_du_fichier,Informations_Fichier); Taille_du_fichier=Informations_Fichier->st_size; if ( (read(GIF_Fichier,Signature,6)==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(GIF_Fichier,&LSDB,sizeof(struct Type_LSDB))==sizeof(struct Type_LSDB)) { // 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: // 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 (!(LSDB.Aspect & 0x80)) // Palette dans l'ordre: read(GIF_Fichier,Principal_Palette,Nb_couleurs*3); else { // Palette tri‚e par composantes: 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; } // Le fichier contenait une image else Erreur_fichier=2; } // 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; close(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[256]; 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" struct Type_LSDB { word Largeur; // Largeur de l'‚cran virtuel |_ Dimensions de l'image si 1 word Hauteur; // Hauteur de l'‚cran virtuel | seule image dans le fichier (ce qui est notre cas) byte Resol; // Informations sur la r‚solution (et autres) byte Backcol; // Couleur de fond byte Aspect; // Informations sur l'aspect ratio (et autres) } LSDB; // Logical Screen Descriptor Block struct Type_IDB { word Pos_X; // Abscisse o— devrait ˆtre affich‚e l'image word Pos_Y; // Ordonn‚e o— devrait ˆtre affich‚e l'image word Largeur_image; // Largeur de l'image word Hauteur_image; // Hauteur de l'image byte Indicateur; // Informations diverses sur l'image byte Nb_bits_pixel; // Nb de bits par pixel } IDB; // Image Descriptor Block 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); GIF_Fichier=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP); if (GIF_Fichier!=-1) { // On ‚crit la signature du fichier if (write(GIF_Fichier,"GIF87a",6)==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 (write(GIF_Fichier,&LSDB,sizeof(struct Type_LSDB))==sizeof(struct Type_LSDB)) { // Le LSDB a ‚t‚ correctement ‚crit. // On sauve la palette Palette_64_to_256(Principal_Palette); if (write(GIF_Fichier,Principal_Palette,768)==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. // 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 ( (write(GIF_Fichier,&Block_indicateur,1)==1) && (write(GIF_Fichier,&IDB,sizeof(struct Type_IDB))==sizeof(struct Type_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! } Header; // Je hais ce header! Erreur_fichier=0; Nom_fichier_complet(Nom_du_fichier,0); if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { if (read(Fichier,&Header,sizeof(struct PCX_Header))==sizeof(struct PCX_Header)) { // 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 ( (Header.Manufacturer!=10) || (Header.Compression>1) || ( (Header.Depth!=1) && (Header.Depth!=2) && (Header.Depth!=4) && (Header.Depth!=8) ) || ( (Header.Plane!=1) && (Header.Plane!=2) && (Header.Plane!=4) && (Header.Plane!=8) && (Header.Plane!=3) ) || (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[256]; int Fichier; struct PCX_Header { byte Manufacturer; // |_ Il font chier ces cons! Ils auraient pu byte Version; // | mettre une vraie signature! byte Compression; // L'image est-elle compress‚e? byte Depth; // Nombre de bits pour coder un pixel (inutile puisqu'on se sert de Plane) word X_min; // |_ Coin haut-gauche | word Y_min; // | de l'image |_ (Cr‚tin!) word X_max; // |_ Coin bas-droit | word Y_max; // | de l'image | word X_dpi; // |_ Densit‚ de |_ (Presque inutile parce que word Y_dpi; // | l'image | aucun moniteur n'est pareil!) byte Palette_16c[48]; // Palette 16 coul (inutile pour 256c) (d‚bile!) byte Reserved; // Ca me plait ‡a aussi! byte Plane; // 4 => 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! } Header; // Je hais ce header! 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 =NULL; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { stat(Nom_du_fichier,Informations_Fichier); Taille_du_fichier=Informations_Fichier->st_size; if (read(Fichier,&Header,sizeof(struct PCX_Header))==sizeof(struct PCX_Header)) { Principal_Largeur_image=Header.X_max-Header.X_min+1; Principal_Hauteur_image=Header.Y_max-Header.Y_min+1; Ecran_original_X=Header.Screen_X; Ecran_original_Y=Header.Screen_Y; if (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)); else Palette_64_to_256(Principal_Palette); Nb_couleurs=(dword)(1<4) memcpy(Principal_Palette,Header.Palette_16c,48); else { Principal_Palette[1].R=0; Principal_Palette[1].V=0; Principal_Palette[1].B=0; Octet1=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 ( (Header.Depth==8) && (Header.Version>=5) && (Taille_du_fichier>sizeof(T_Palette)) ) { lseek(Fichier,Taille_du_fichier-(sizeof(T_Palette)+1),SEEK_SET); // On regarde s'il y a une palette aprŠs les donn‚es de l'image if (read(Fichier,&Octet1,1)==1) if (Octet1==12) // Lire la palette si c'est une image en 256 couleurs { // On lit la palette 256c que ces cr‚tins ont foutue … la fin du fichier if (read(Fichier,Principal_Palette,sizeof(T_Palette))!=sizeof(T_Palette)) Erreur_fichier=2; } } Palette_256_to_64(Principal_Palette); 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. lseek(Fichier,sizeof(struct PCX_Header),SEEK_SET); if (!Erreur_fichier) { Taille_ligne=Header.Bytes_per_plane_line*Header.Plane; Vraie_taille_ligne=(short)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=Header.Plane-1; LBM_Buffer=(byte *)malloc(Taille_ligne); // Chargement de l'image if (Header.Compression) // Image compress‚e { Init_lecture(); Taille_image=(long)Header.Bytes_per_plane_line*Principal_Hauteur_image; if (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(Fichier,Principal_Palette,sizeof(T_Palette))==-1) Erreur_fichier=1; } } else Erreur_fichier=1; close(Fichier); if (Erreur_fichier) remove(Nom_du_fichier); // On remet la palette … son ‚tat normal Palette_256_to_64(Principal_Palette); } else Erreur_fichier=1; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// CEL //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format CEL -------------------------------- void Test_CEL(void) { char Nom_du_fichier[256]; int Taille; int Fichier; struct CEL_Header1 { word Width; // Largeur de l'image word Height; // Hauteur de l'image } Header1; struct CEL_Header2 { 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]; // ??? } Header2; struct stat* Informations_Fichier =NULL; Erreur_fichier=0; Nom_fichier_complet(Nom_du_fichier,0); if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { if (read(Fichier,&Header1,sizeof(struct CEL_Header1))==sizeof(struct CEL_Header1)) { // 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. stat(Nom_du_fichier,Informations_Fichier); Taille=(Informations_Fichier->st_size)-sizeof(struct CEL_Header1); if ( (!Taille) || ( (((Header1.Width+1)>>1)*Header1.Height)!=Taille ) ) { // Tentative de reconnaissance de la signature des nouveaux fichiers lseek(Fichier,0,SEEK_SET); if (read(Fichier,&Header2,sizeof(struct CEL_Header2))==sizeof(struct CEL_Header2)) { if (memcmp(Header2.Signa,"KiSS",4)==0) { if (Header2.Kind!=0x20) Erreur_fichier=1; } else Erreur_fichier=1; } else Erreur_fichier=1; } } else Erreur_fichier=1; close(Fichier); } else Erreur_fichier=1; } // -- Lire un fichier au format CEL ----------------------------------------- void Load_CEL(void) { char Nom_du_fichier[256]; int Fichier; struct CEL_Header1 { word Width; // Largeur de l'image word Height; // Hauteur de l'image } Header1; struct CEL_Header2 { 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]; // ??? } Header2; short Pos_X; short Pos_Y; byte Dernier_octet=0; long Taille_du_fichier; struct stat* Informations_Fichier=NULL; Erreur_fichier=0; Nom_fichier_complet(Nom_du_fichier,0); if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { if (read(Fichier,&Header1,sizeof(struct CEL_Header1))==sizeof(struct CEL_Header1)) { stat(Nom_du_fichier,Informations_Fichier); Taille_du_fichier=Informations_Fichier->st_size; if ( (Taille_du_fichier>sizeof(struct CEL_Header1)) && ( (((Header1.Width+1)>>1)*Header1.Height)==(Taille_du_fichier-sizeof(struct 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 lseek(Fichier,0,SEEK_SET); if (read(Fichier,&Header2,sizeof(struct CEL_Header2))==sizeof(struct 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(Fichier,&Header1,sizeof(struct CEL_Header1))!=-1) { // Sauvegarde de l'image Init_ecriture(); for (Pos_Y=0;((Pos_Y>4)!=0) Erreur_fichier=1; } else { if (read(Fichier,&Header2,sizeof(struct CEL_Header2))==sizeof(struct CEL_Header2)) { if (memcmp(Header2.Signa,"KiSS",4)==0) { if (Header2.Kind!=0x10) Erreur_fichier=1; } else Erreur_fichier=1; } else Erreur_fichier=1; } close(Fichier); } else Erreur_fichier=1; } // -- Lire un fichier au format KCF ----------------------------------------- void Load_KCF(void) { char Nom_du_fichier[256]; int Fichier; struct KCF_Header { struct { struct { byte Octet1; byte Octet2; } Couleur[16]; } Palette[10]; } Buffer; struct CEL_Header2 { 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 ou nb de couleurs d‚finies word Hauteur; // Hauteur de l'image ou nb de palettes d‚finies word Decalage_X; // Decalage en X de l'image word Decalage_Y; // Decalage en Y de l'image byte Filler2[16]; // ??? } 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=open(Nom_du_fichier,O_RDONLY))!=-1) { Taille_du_fichier=filelength(Fichier); if (Taille_du_fichier==sizeof(struct KCF_Header)) { // Fichier KCF … l'ancien format if (read(Fichier,&Buffer,sizeof(struct KCF_Header))==sizeof(struct 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) << 2); Principal_Palette[Indice].B=((Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet1 & 15) << 2); Principal_Palette[Indice].V=((Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet2 & 15) << 2); } 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(Fichier,&Header2,sizeof(struct CEL_Header2))==sizeof(struct CEL_Header2)) { // Initialiser_preview(???); // Pas possible... pas d'image... Indice=(Header2.Nbbits==12)?16:0; for (Indice_palette=0;Indice_palette> 4) << 2; Principal_Palette[Indice].B=(Octet[0] & 15) << 2; Principal_Palette[Indice].V=(Octet[1] & 15) << 2; break; case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB read(Fichier,Octet,3); Principal_Palette[Indice].R=Octet[0]>>2; Principal_Palette[Indice].V=Octet[1]>>2; Principal_Palette[Indice].B=Octet[2]>>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; } close(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[256]; int Fichier; struct KCF_Header { struct { struct { byte Octet1; byte Octet2; } Couleur[16]; } Palette[10]; } Buffer; struct CEL_Header2 { 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 ou nb de couleurs d‚finies word Hauteur; // Hauteur de l'image ou nb de palettes d‚finies word Decalage_X; // Decalage en X de l'image word Decalage_Y; // Decalage en Y de l'image byte Filler2[16]; // ??? } 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=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP))!=-1) { // 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>>2)<<4) | (Principal_Palette[Indice].B>>2); Buffer.Palette[Indice_palette].Couleur[Indice_couleur].Octet2=Principal_Palette[Indice].V>>2; } if (write(Fichier,&Buffer,sizeof(struct KCF_Header))!=sizeof(struct 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(Fichier,&Header2,sizeof(struct CEL_Header2))!=sizeof(struct CEL_Header2)) Erreur_fichier=1; for (Indice=0;(Indice<256) && (!Erreur_fichier);Indice++) { Octet[0]=Principal_Palette[Indice].R<<2; Octet[1]=Principal_Palette[Indice].V<<2; Octet[2]=Principal_Palette[Indice].B<<2; if (write(Fichier,Octet,3)!=3) Erreur_fichier=1; } } close(Fichier); if (Erreur_fichier) remove(Nom_du_fichier); } else Erreur_fichier=1; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////// SCx //////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // -- Tester si un fichier est au format SCx -------------------------------- void Test_SCx(void) { int Handle; // Handle du fichier char Nom_du_fichier[256]; // Nom complet du fichier byte Signature[3]; struct Header { byte Filler1[4]; word Largeur; word Hauteur; byte Filler2; byte Plans; } SCx_Header; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=1; // Ouverture du fichier Handle=open(Nom_du_fichier,O_RDONLY); if (Handle!=-1) { // Lecture et v‚rification de la signature if ((read(Handle,&SCx_Header,sizeof(struct Header)))==sizeof(struct Header)) { if ( (!memcmp(SCx_Header.Filler1,"RIX",3)) && SCx_Header.Largeur && SCx_Header.Hauteur) Erreur_fichier=0; } // Fermeture du fichier close(Handle); } } // -- Lire un fichier au format SCx ----------------------------------------- void Load_SCx(void) { char Nom_du_fichier[256]; // Nom complet du fichier int Fichier; word Pos_X,Pos_Y; long Taille,Vraie_taille; long Taille_du_fichier; struct Header { byte Filler1[4]; word Largeur; word Hauteur; byte Filler2; byte Plans; } SCx_Header; T_Palette SCx_Palette; Nom_fichier_complet(Nom_du_fichier,0); Erreur_fichier=0; if ((Fichier=open(Nom_du_fichier,O_RDONLY))!=-1) { Taille_du_fichier=filelength(Fichier); if ((read(Fichier,&SCx_Header,sizeof(struct Header)))==sizeof(struct 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)) << 2; Pal[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 2; Pal[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 2; } } //// 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] & 0x38) >> 3) | (((word)Pal[ip] & 0x04) << 1); ip++; w|=(((word)Pal[ip] & 0x38) << 9) | (((word)Pal[ip] & 0x04) << 13); ip++; w|=(((word)Pal[ip] & 0x38) << 5) | (((word)Pal[ip] & 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) { int Handle; // Handle du fichier char Nom_du_fichier[256]; // 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 Handle=open(Nom_du_fichier,O_RDONLY); if (Handle!=-1) { // V‚rification de la taille Taille=filelength(Handle); if ((Taille==32034) || (Taille==32066)) { // Lecture et v‚rification de la r‚solution if ((read(Handle,&Res,2))==2) { if (Res==0x0000) Erreur_fichier=0; } } // Fermeture du fichier close(Handle); } } // -- Lire un fichier au format PI1 ----------------------------------------- void Load_PI1(void) { char Nom_du_fichier[256]; // Nom complet du fichier int 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=open(Nom_du_fichier,O_RDONLY))!=-1) { // allocation d'un buffer m‚moire buffer=(byte *)malloc(32034); if (buffer!=NULL) { // Lecture du fichier dans le buffer if (read(Fichier,buffer,32034)==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; close(Fichier); } else Erreur_fichier=1; } // -- Sauver un fichier au format PI1 --------------------------------------- void Save_PI1(void) { char Nom_du_fichier[256]; // Nom complet du fichier int 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 Fichier=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP); if (Fichier!=-1) { // allocation d'un buffer m‚moire buffer=(byte *)malloc(32034); // 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; } } if (write(Fichier,buffer,32034)==32034) { close(Fichier); } else // Erreur d'‚criture (disque plein ou prot‚g‚) { close(Fichier); remove(Nom_du_fichier); Erreur_fichier=1; } // Lib‚ration du buffer m‚moire free(buffer); } else { close(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) { int Handle; // Handle du fichier char Nom_du_fichier[256]; // 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 Handle=open(Nom_du_fichier,O_RDONLY); if (Handle!=-1) { // V‚rification de la taille Taille=filelength(Handle); if ((Taille<=32066)) { // Lecture et v‚rification de la r‚solution if ((read(Handle,&Res,2))==2) { if (Res==0x0080) Erreur_fichier=0; } } // Fermeture du fichier close(Handle); } } // -- Lire un fichier au format PC1 ----------------------------------------- void Load_PC1(void) { char Nom_du_fichier[256]; // Nom complet du fichier int 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=open(Nom_du_fichier,O_RDONLY))!=-1) { 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(Fichier,buffercomp,Taille)==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); } close(Fichier); } else Erreur_fichier=1; } // -- Sauver un fichier au format PC1 --------------------------------------- void Save_PC1(void) { char Nom_du_fichier[256]; // Nom complet du fichier int 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 Fichier=open(Nom_du_fichier,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP); if (Fichier!=-1) { // 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_Y