/*************************************************************************************************************************************/
/* */
/* C O M P R E S S I O N " R U N - L E N G T H E N C O D I N G " E T I N V E R S E : */
/* */
/* */
/* Nota : */
/* */
/* Ce programme est inspire de 'v $xtc/CompressionDecompression_RLE_1D.01$c'. */
/* Il y a une petite difference au sujet du compte des repetitions : */
/* */
/* */
/* $xtc/CompressionDecompression_RLE_1D.01$c */
/* */
/* Kc --> K */
/* - */
/* */
/* KKc --> KK */
/* -- */
/* */
/* KKKc --> KKK */
/* --- */
/* */
/* KKKKc --> KKKK[4] */
/* ---- */
/* */
/* KKKKKc --> KKKK[5] */
/* ---- */
/* */
/* KKKKKKc --> KKKK[6] */
/* ---- */
/* */
/* (...) */
/* */
/* KKKKK(...)K --> KKKK[255] */
/* ---- */
/* ----------- */
/* /|\ */
/* | */
/* | */
/* ------------- il n'y a que 255 caracteres 'K'. */
/* */
/* */
/* alors que : */
/* */
/* $KrC/CompressionDeCompressionRunLengthEncoding.11$vv$I */
/* */
/* Kc --> K */
/* - */
/* */
/* KKc --> KK */
/* -- */
/* */
/* KKKc --> KKK */
/* --- */
/* */
/* KKKKc --> KKKK[0] */
/* ---- */
/* */
/* KKKKKc --> KKKK[1] */
/* ---- */
/* */
/* KKKKKKc --> KKKK[2] */
/* */
/* (...) */
/* */
/* KKKKK(...)K --> KKKK[255] */
/* ---- */
/* ----------- */
/* /|\ */
/* | */
/* | */
/* ------------- il y a au total 4+255=259 caracteres 'K'. */
/* */
/* */
/* (ou [n] represente un octet contenant en binaire */
/* la valeur n comprise entre 0 et 255) ce qui est donc */
/* plus optimise. Enfin, 'c' represente un caractere */
/* different de 'K' (on notera au passage que ce caractere */
/* 'c' n'apparait pas apres une chaine de 'K's de longueur */
/* maximale car, en effet, le caractere suivant le dernier */
/* 'K' peut etre un autre caractere 'K'...). */
/* */
/* */
/* Author of '$xtc/RunLengthEncoding.11$vv$I' : */
/* */
/* Jean-Francois COLONNA (LACTAMME, 20151223082146). */
/* */
/*************************************************************************************************************************************/
/*************************************************************************************************************************************/
/* */
/* D E F I N I T I O N G E N E R A L E S : */
/* */
/*************************************************************************************************************************************/
int RunLengthEncoding_EditerLesChaines=VRAI;
int RunLengthEncoding_EditionsHexaDecimalesDesChaines=VRAI;
/* Indicateurs de controle des editions... */
#define INFINI \
2000000000
#define QUE_FAIRE(x) \
(0)
#define NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS \
(1)
#define BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS \
(256)
#define BORNE_INFERIEURE_DE_REPETITIONS \
((4)+QUE_FAIRE(NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS))
#define BORNE_SUPERIEURE_DE_REPETITIONS \
(BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS-1)
/* Definitions des bornes : */
/* */
/* INFERIEUR a partir de laquelle on compacte, */
/* SUPERIEUR limite superieure du compactage a cause de la capacite d'un octet. */
/* */
/* On notera que si l'on utilise plus d'un octet pour stocker les nombres de repetitions, */
/* la borne inferieure doit etre augmentee, mais comment et de combien ? */
#ifndef CHAR
# define CHAR \
unsigned char \
/* Afin que tous les tests effectues fonctionnent correctement et que les relations */ \
/* d'odre soient bien celles que l'on attend, il est a priori necessaire que les */ \
/* caracteres soient non signes... */
#else
#endif
#ifndef FORMAT_CARACTERE
# define FORMAT_CARACTERE \
COND((RunLengthEncoding_EditionsHexaDecimalesDesChaines == VRAI),"%02x ","%c") \
/* Format d'edition des caracteres des chaines... */
#else
#endif
#define RunLengthEncoding_INDEXN \
NombreVersIndex(RunLengthEncoding_LongueurChainesNonCompressees)
int RunLengthEncoding_LongueurChainesNonCompressees;
/* On notera qu'a priori, aucune des chaines utilisees n'a de caractere de fin. Cela */
/* vient du fait que ces chaines peuvent contenir 256 codes differents et qu'alors le */
/* code '0x00' habituel ne peut etre utilise. La fin d'une chaine est donc reperee via */
/* son dernier caractere d'index 'INDEXN'... */
#ifndef ACCES_CHAINE
# define ACCES_CHAINE(Chaine,IndexCaractere) \
*(Chaine+IndexCaractere) \
/* Acces a une chaine quelconque... */
#else
#endif
CHAR *RunLengthEncoding_ChaineACompresser;
/* Definition de la chaine Argument a permuter... */
CHAR *RunLengthEncoding_ChaineCompressee;
int RunLengthEncoding_LongueurDeChaineCompressee;
/* Definition de la version permutee de 'ChaineACompresser'... */
CHAR *RunLengthEncoding_ChaineDecompressee;
/* Definition de la chaine "depermutee" qui doit donc etre identique a 'ChaineACompresser'. */
/*************************************************************************************************************************************/
/* */
/* E D I T I O N S D I V E R S E S : */
/* */
/*************************************************************************************************************************************/
#define RunLengthEncoding_EDITION_D_UNE_CHAINE(ChaineA,IndexDernierCaractereChaineA) \
{ \
if (RunLengthEncoding_EditerLesChaines == VRAI) \
{ \
int IndexCaractere; \
\
for (IndexCaractere=INDEX0 ; IndexCaractere <= IndexDernierCaractereChaineA ; IndexCaractere++) \
{ \
printf(FORMAT_CARACTERE,ACCES_CHAINE(ChaineA,IndexCaractere)); \
} \
\
printf("\n"); \
} \
else \
{ \
} \
}
/*************************************************************************************************************************************/
/* */
/* I N I T I A L I S A T I O N D E L A C H A I N E A T R A I T E R : */
/* */
/*************************************************************************************************************************************/
#define RunLengthEncoding_InitialisationChaineATraiter(ChaineR,ChaineA,LongueurChaineA) \
{ \
int IndexCaractere; \
\
RunLengthEncoding_LongueurChainesNonCompressees = LongueurChaineA; \
/* ATTENTION : en toute generalite dans 'ChaineA' les 256 codes possibles peuvent */ \
/* etre presents et donc 'strlen(...)' ne peut pas fonctionner systematiquement. C'est */ \
/* pourquoi un pramatre de longueur 'LongueurChaineA' doit apparaitre explicitement... */ \
\
ChaineR = malloc(RunLengthEncoding_LongueurChainesNonCompressees); \
\
for (IndexCaractere=INDEX0 ; IndexCaractere <= RunLengthEncoding_INDEXN ; IndexCaractere++) \
{ \
ACCES_CHAINE(ChaineR,IndexCaractere) = ChaineA[IndexCaractere]; \
} \
}
#define RunLengthEncoding_DesinitialisationChaineATraiter(ChaineA) \
{ \
free(ChaineA); \
}
/*************************************************************************************************************************************/
/* */
/* C O M P R E S S I O N D ' U N E C H A I N E : */
/* */
/*************************************************************************************************************************************/
#define LONGUEUR_MAXIMALE_DES_BUFFERS(longueur) \
(2*longueur)
#define STORE_COMPRESSION_11(ChaineR,IndexChaineR,valeur,LongueurChaineR,LongueurChaineA) \
{ \
ACCES_CHAINE(ChaineR,IndexChaineR) = (valeur); \
\
if (IndexChaineR < NombreVersIndex(LONGUEUR_MAXIMALE_DES_BUFFERS(LongueurChaineA))) \
{ \
IndexChaineR++; \
} \
else \
{ \
fprintf(stderr,"Erreur de compression/decompression (debordement de capacite) -1-\n"); \
} \
\
LongueurChaineR++; \
}
#define STORE_REPETITION_11(Chaine,IndexChaine,nombre,LongueurChaineR,LongueurChaineA) \
{ \
int compteur; \
int quotient=(nombre); \
int reste; \
\
for (compteur=1 ; compteur<=NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS ; compteur++) \
{ \
reste = quotient % BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS; \
quotient = quotient / BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS; \
\
STORE_COMPRESSION_11(Chaine,IndexChaine,(CHAR)reste,LongueurChaineR,LongueurChaineA); \
} \
\
if (quotient != 0) \
{ \
fprintf(stderr,"Erreur de compression (debordement de capacite de repetition) -1-\n"); \
} \
else \
{ \
} \
}
#define RunLengthEncoding_InitialisationTransformationDirecte(ChaineR) \
{ \
ChaineR=malloc(LONGUEUR_MAXIMALE_DES_BUFFERS(RunLengthEncoding_LongueurChainesNonCompressees)); \
}
#define RunLengthEncoding_TransformationDirecte(ChaineR,ChaineA) \
{ \
CHAR CaracterePrecedent=0; \
int CaracterePrecedentExiste=FAUX; \
int CompteurDeRepetitions=1; \
int IndexChaineA; \
int IndexChaineR=INDEX0; \
int LongueurChaineR = 0; \
\
for (IndexChaineA=INDEX0 \
; IndexChaineA<=NombreVersIndex(RunLengthEncoding_LongueurChainesNonCompressees) \
; IndexChaineA++ \
) \
{ \
CHAR CaractereCourant=ACCES_CHAINE(ChaineA,IndexChaineA); \
\
if (CaracterePrecedentExiste == FAUX) \
{ \
CaracterePrecedent = CaractereCourant; \
CaracterePrecedentExiste = VRAI; \
\
STORE_COMPRESSION_11(ChaineR,IndexChaineR \
,CaractereCourant \
,LongueurChaineR \
,RunLengthEncoding_LongueurChainesNonCompressees \
); \
} \
else \
{ \
if ( (CaractereCourant == CaracterePrecedent) \
&& (CompteurDeRepetitions \
< (BORNE_SUPERIEURE_DE_REPETITIONS+BORNE_INFERIEURE_DE_REPETITIONS) \
) \
) \
{ \
CompteurDeRepetitions++; \
\
if ( (CompteurDeRepetitions > 1) \
&& (CompteurDeRepetitions <= BORNE_INFERIEURE_DE_REPETITIONS) \
) \
{ \
STORE_COMPRESSION_11(ChaineR,IndexChaineR \
,CaractereCourant \
,LongueurChaineR \
,RunLengthEncoding_LongueurChainesNonCompressees \
); \
} \
else \
{ \
} \
\
if ( (CompteurDeRepetitions >= BORNE_INFERIEURE_DE_REPETITIONS) \
&& (IndexChaineA \
== NombreVersIndex(RunLengthEncoding_LongueurChainesNonCompressees)) \
) \
{ \
STORE_REPETITION_11(ChaineR,IndexChaineR \
,CompteurDeRepetitions-BORNE_INFERIEURE_DE_REPETITIONS \
,LongueurChaineR \
,RunLengthEncoding_LongueurChainesNonCompressees \
); \
} \
else \
{ \
} \
} \
else \
{ \
if (CompteurDeRepetitions >= BORNE_INFERIEURE_DE_REPETITIONS) \
{ \
STORE_REPETITION_11(ChaineR,IndexChaineR \
,CompteurDeRepetitions-BORNE_INFERIEURE_DE_REPETITIONS \
,LongueurChaineR \
,RunLengthEncoding_LongueurChainesNonCompressees \
); \
} \
else \
{ \
} \
\
STORE_COMPRESSION_11(ChaineR,IndexChaineR \
,CaractereCourant \
,LongueurChaineR \
,RunLengthEncoding_LongueurChainesNonCompressees \
); \
\
CaracterePrecedent = CaractereCourant; \
CompteurDeRepetitions = 1; \
} \
} \
} \
\
RunLengthEncoding_LongueurDeChaineCompressee = LongueurChaineR; \
\
RunLengthEncoding_EDITION_D_UNE_CHAINE(ChaineR,NombreVersIndex(LongueurChaineR)); \
}
#define RunLengthEncoding_DesinitialisationsTransformationDirecte() \
{ \
}
/*************************************************************************************************************************************/
/* */
/* D E C O M P R E S S I O N D ' U N E C H A I N E : */
/* */
/*************************************************************************************************************************************/
#define STORE_DECOMPRESSION_11(ChaineR,IndexChaineR,valeur) \
{ \
ACCES_CHAINE(ChaineR,IndexChaineR)=valeur; \
\
IndexChaineR++; \
}
#define GET_REPETITION_11(ChaineA,IndexChaineA,NombreDeCaracteres) \
{ \
int compteur; \
int facteur=1; \
\
NombreDeCaracteres=0; \
\
for (compteur=1 ; compteur<=NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS ; compteur++) \
{ \
CHAR caractere=ACCES_CHAINE(ChaineA,IndexChaineA); \
NombreDeCaracteres = NombreDeCaracteres+(caractere*facteur); \
facteur = BASE_DE_NUMERATION_DES_NOMBRES_DE_REPETITIONS*facteur; \
\
if (compteur < NOMBRE_D_OCTETS_POUR_LES_NOMBRES_DE_REPETITIONS) \
{ \
IndexChaineA++; \
} \
else \
{ \
} \
} \
}
#define REPEAT_STORE_DECOMPRESSION_11(ChaineR,IndexChaineR,ChaineA,IndexChaineA,valeur) \
{ \
int nombre; \
int NombreDeCaracteres_ADupliquer; \
\
GET_REPETITION_11(ChaineA,IndexChaineA,NombreDeCaracteres_ADupliquer); \
\
for (nombre=1 ; nombre <= NombreDeCaracteres_ADupliquer ; nombre++) \
{ \
STORE_DECOMPRESSION_11(ChaineR,IndexChaineR,valeur); \
} \
}
#define CARACTERE_PRECEDENT_INDEFINI \
INFINI
\
#define RunLengthEncoding_InitialisationTransformationInverse(ChaineA) \
{ \
ChaineA=malloc(RunLengthEncoding_LongueurChainesNonCompressees); \
}
#define RunLengthEncoding_TransformationInverse(ChaineR,ChaineA) \
{ \
int iterer=VRAI; \
int CaracterePrecedent=CARACTERE_PRECEDENT_INDEFINI; \
/* ATTENTION : doit etre un 'int' et non pas un 'CHAR' a cause de la valeur 'INFINI'... */ \
int CompteurDeRepetitions=1; \
int DimensionImageEffective=0; \
int IndexChaineA=INDEX0; \
int IndexChaineR=INDEX0; \
\
while (iterer == VRAI) \
{ \
CHAR CaractereCourant=ACCES_CHAINE(ChaineA,IndexChaineA); \
\
if (CompteurDeRepetitions <= BORNE_INFERIEURE_DE_REPETITIONS) \
{ \
if (CompteurDeRepetitions == BORNE_INFERIEURE_DE_REPETITIONS) \
{ \
REPEAT_STORE_DECOMPRESSION_11(ChaineR,IndexChaineR \
,ChaineA,IndexChaineA \
,CaracterePrecedent \
); \
CaracterePrecedent = CARACTERE_PRECEDENT_INDEFINI; \
CompteurDeRepetitions = 1; \
} \
else \
{ \
if (CaractereCourant == CaracterePrecedent) \
{ \
CompteurDeRepetitions++; \
} \
else \
{ \
CaracterePrecedent = CaractereCourant; \
CompteurDeRepetitions = 1; \
} \
\
STORE_DECOMPRESSION_11(ChaineR,IndexChaineR,CaractereCourant); \
} \
} \
else \
{ \
fprintf(stderr,"Erreur de decompression -1-\n"); \
} \
\
IndexChaineA++; \
\
if (IndexChaineA<=NombreVersIndex(RunLengthEncoding_LongueurDeChaineCompressee)) \
{ \
} \
else \
{ \
iterer = FAUX; \
} \
} \
}
#define RunLengthEncoding_DesinitialisationsTransformationInverse(ChaineA1,ChaineA2) \
{ \
free(ChaineA1); \
free(ChaineA2); \
}
/*************************************************************************************************************************************/
/* */
/* V E R I F I C A T I O N D U P R O C E S S U S C O M P L E T : */
/* */
/*************************************************************************************************************************************/
void RunLengthEncoding_Verifications(CHAR *ChaineA1,CHAR *ChaineA2)
{
int IndexCaractere;
for (IndexCaractere=INDEX0 ; IndexCaractere <= RunLengthEncoding_INDEXN ; IndexCaractere++)
{
if (ACCES_CHAINE(ChaineA1,IndexCaractere) != ACCES_CHAINE(ChaineA2,IndexCaractere))
{
fprintf(stderr
,"ERREUR(RunLengthEncoding) : chaine retablie ('0x%02x') # chaine a traiter ('0x%02x').\n"
,ACCES_CHAINE(ChaineA1,IndexCaractere)
,ACCES_CHAINE(ChaineA2,IndexCaractere)
);
}
else
{
}
}
RunLengthEncoding_EDITION_D_UNE_CHAINE(ChaineA1,RunLengthEncoding_INDEXN);
RunLengthEncoding_EDITION_D_UNE_CHAINE(ChaineA2,RunLengthEncoding_INDEXN);
}