home *** CD-ROM | disk | FTP | other *** search
- /* Fichier: codrle2.c
- Auteur: David Bourgin
- Date de creation: 1/2/94
- Date de derniere mise a jour: 24/7/95
- Dessein: Exemple de codage RLE type 2 avec comme donnees a compresser le contenu d'un fichier.
- */
-
- #include <stdio.h>
- /* Pour les routines printf,fgetc,fputc et rewind */
- #include <memory.h>
- /* Pour la routine memset */
- #include <stdlib.h>
- /* Pour la routine exit */
-
- /* Codes d'erreur renvoyes a l'appelant */
- #define NO_ERROR 0
- #define BAD_FILE_NAME 1
- #define BAD_ARGUMENT 2
-
- /* Constantes pratiques */
- #define FALSE 0
- #define TRUE 1
-
- /* Variables globales */
- FILE *f_source,*f_dest;
-
- /* Puisque fgetc=EOF uniquement apres un acces
- alors statut_octet_stocke vaut TRUE si un octet a ete engrange par fgetc
- ou FALSE s'il n'y aucun octet valide, deja lu et non traite dans val_octet_stocke */
- int statut_octet_stocke=FALSE;
- int val_octet_stocke;
-
- /* Pseudo procedures */
- #define debut_des_donnees() (statut_octet_stocke=FALSE,(void)rewind(f_source))
- #define fin_des_donnees() (statut_octet_stocke?FALSE:!(statut_octet_stocke=((val_octet_stocke=fgetc(f_source))!=EOF)))
- #define lire_octet() (statut_octet_stocke?statut_octet_stocke=FALSE,(unsigned char)val_octet_stocke:(unsigned char)fgetc(f_source))
- #define ecrire_octet(octet) ((void)fputc((octet),f_dest))
-
- void ecrire_reprle2(octet_repere,octet_repete,nombre_repetition)
- /* Parametres en sortie: Aucun
- Action: Ecrit dans le flux de sortie de compression le codage de nombre_repetition fois l'octet_repete.
- octet_repere fait office de marqueur comme defini par la methode RLE 2
- Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
- */
- unsigned char octet_repere,octet_repete;
- unsigned int nombre_repetition;
- { if (nombre_repetition<4)
- if (octet_repete==octet_repere)
- { ecrire_octet(octet_repere);
- ecrire_octet(nombre_repetition-1);
- }
- else { register unsigned int i;
-
- for (i=1;i<=nombre_repetition;i++)
- ecrire_octet(octet_repete);
- }
- else { ecrire_octet(octet_repere);
- ecrire_octet(nombre_repetition-1);
- ecrire_octet(octet_repete);
- }
- }
-
- void ecrire_non_reprle2(octet_repere,octet_non_repete)
- /* Parametres en sortie: Aucun
- Action: Ecrit dans le flux de sortie de compression l'octet_non_repete
- octet_repere fait office de marqueur comme defini par la methode RLE 2
- Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
- */
- unsigned char octet_repere,octet_non_repete;
- { if (octet_non_repete==octet_repere)
- { ecrire_octet(octet_repere);
- ecrire_octet(0);
- }
- else ecrire_octet(octet_non_repete);
- }
-
- void codagerle2()
- /* Parametres en sortie: Aucun
- Action: Compresse suivant la methode RLE type 2 tous les octets lus par la fonction lire_octet
- Erreurs: Une erreur d'entree/sortie peut perturber le deroulement de l'algorithme
- */
- { unsigned char octet1,octet2,octet_repere;
- unsigned int taille_trame;
- register unsigned int i;
- unsigned long int table_occurrences[256];
-
- if (!fin_des_donnees()) /* Y a-t-il au moins 1 octet a analyser? */
- { /* Initialiser le nombre d'occurrences de tous les octets a 0 */
- (void)memset((char *)table_occurrences,0,sizeof(table_occurrences));
- /* Ceci equivaut a remplir table_occurrences de 0.
- C'est plus rapide que boucler 256 fois */
- /* Valider les occurrences de table_occurrences en fonction des donnees a compresser */
- while (!fin_des_donnees())
- { octet1=lire_octet();
- table_occurrences[octet1]++;
- }
- octet_repere=0;
- for (i=1;i<=255;i++)
- if (table_occurrences[i]<table_occurrences[octet_repere])
- octet_repere=i;
- ecrire_octet(octet_repere);
- debut_des_donnees(); /* Nouvelle analyse des donnees */
- octet1=lire_octet();
- taille_trame=1;
- if (!fin_des_donnees())
- /* Y a-t-il au moins 2 octets a analyser? */
- { octet2=lire_octet();
- taille_trame=2;
- do { /* Debut de compression a proprement parle */
- if (octet1==octet2)
- /* N'a-t-on rencontre qu'une sequence d'octets identiques? */
- { while ((!fin_des_donnees())&&(octet1==octet2)&&(taille_trame<256))
- { octet2=lire_octet();
- taille_trame++;
- }
- if (octet1==octet2)
- { ecrire_reprle2(octet_repere,octet1,taille_trame);
- if (!fin_des_donnees())
- { octet1=lire_octet();
- taille_trame=1;
- }
- else taille_trame=0;
- }
- else { ecrire_reprle2(octet_repere,octet1,taille_trame-1);
- octet1=octet2;
- taille_trame=1;
- }
- }
- else { /* Non, alors ne pas prendre en compte le dernier octet */
- ecrire_non_reprle2(octet_repere,octet1);
- octet1=octet2;
- taille_trame=1;
- }
- if (!fin_des_donnees())
- { octet2=lire_octet();
- taille_trame=2;
- }
- }
- while ((!fin_des_donnees())||(taille_trame>=2));
- }
- if (taille_trame==1) /* Il restait un dernier octet a analyser */
- ecrire_non_reprle2(octet_repere,octet1);
- }
- }
-
- void aide()
- /* Parametres en sortie: Aucun
- Action: Affiche l'aide du programme et termine son execution
- Erreurs: Aucune
- */
- { printf("Cet utilitaire permet de compresser un fichier par la methode RLE type 2\n");
- printf("telle qu'elle est exposee dans 'La Video et Les Imprimantes sur PC'\n");
- printf("\nUsage: codrle2 source destination\n");
- printf("source: Nom du fichier a compresser\n");
- printf("destination: Nom du fichier compresse\n");
- }
-
- int main(argc,argv)
- /* Parametres en sortie: Renvoie un code d'erreur (0=Aucune)
- Action: Procedure principale
- Erreurs: Detectee, traitee et un code d'erreur est renvoye si necessaire
- */
- int argc;
- char *argv[];
- { if (argc!=3)
- { aide();
- exit(BAD_ARGUMENT);
- }
- else if ((f_source=fopen(argv[1],"rb"))==NULL)
- { aide();
- exit(BAD_FILE_NAME);
- }
- else if ((f_dest=fopen(argv[2],"wb"))==NULL)
- { aide();
- exit(BAD_FILE_NAME);
- }
- else { codagerle2();
- fclose(f_source);
- fclose(f_dest);
- }
- printf("Execution de codrle2 achevee.\n");
- return (NO_ERROR);
- }
-