📄 codrle2.c
字号:
/* 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -