/*************************************************************************************************************************************/
/* */
/* C O D A G E D E H U F F M A N E T I N V E R S E : */
/* */
/* */
/* Author of '$xtc/HuffmanCoding.01$vv$I' : */
/* */
/* Jean-Francois COLONNA (LACTAMME, 20151223080449). */
/* */
/*************************************************************************************************************************************/
/*************************************************************************************************************************************/
/* */
/* D E F I N I T I O N G E N E R A L E S : */
/* */
/*************************************************************************************************************************************/
int HuffmanCoding_EditerFrequences=FAUX;
int HuffmanCoding_EditerArbre=FAUX;
int HuffmanCoding_EditerCodesDeHuffman=VRAI;
/* Indicateurs de controle des editions... */
#ifndef CHAR
# define CHAR \
unsigned char
#else
#endif
#define EntierCourt \
1
#define EntierLong \
2
#define Precision \
EntierLong
/* La Precision est soit 'EntierCourt' soit 'EntierLong'... */
/* */
/* ATTENTION : on notera que 'EntierCourt' et 'EntierLong' doivent etre defines a l'aide */
/* de valeurs entieres si l'on veut que le '#if' qui suit fonctionne correctement... */
#if (Precision==EntierCourt)
# define Entier \
int
# define For10 \
"d"
# define For16 \
"x"
#else
# define Entier \
long int
# define For10 \
"ld"
# define For16 \
"lx"
#endif
/* Types de donnees et Formats utiles... */
#define PREMIER_CARACTERE \
INDEX0
#define DERNIER_CARACTERE \
MASKO
#define NOMBRE_DE_CARACTERES \
((DERNIER_CARACTERE-PREMIER_CARACTERE)+1)
/*************************************************************************************************************************************/
/* */
/* S T R U C T U R E S F R E Q U E N T I E L L E S D E S C A R A C T E R E S : */
/* */
/*************************************************************************************************************************************/
Entier CodageDeHuffman_FrequencesDOccurenceDesCaracteres[NOMBRE_DE_CARACTERES];
Entier CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[NOMBRE_DE_CARACTERES];
Entier CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[NOMBRE_DE_CARACTERES];
Entier CodageDeHuffman_PremierCaractere=PREMIER_CARACTERE;
Entier CodageDeHuffman_DernierCaractere=DERNIER_CARACTERE;
/* On notera que tout est defini en 'int' afin d'eviter des debordements et des problemes */
/* de signe. On notera de plus que la definition des codes de caracteres n'est pas */
/* redondante avec les index d'acces a cause des permutations qui sont effectuees sur */
/* ces tableaux... */
#define SIZE_CodageDeHuffman_CodeBinaire \
((NOMBRE_DE_CARACTERES*(sizeof(CHAR)+sizeof(CHAR)+sizeof(Entier)))*NBITOC)
CHAR CodageDeHuffman_CaractereAssociesAuCodeBinaire[NOMBRE_DE_CARACTERES];
CHAR CodageDeHuffman_LongueurDuCodeBinaire[NOMBRE_DE_CARACTERES];
Entier CodageDeHuffman_CodeBinaire[NOMBRE_DE_CARACTERES];
/* Definition des codes entropiques de Huffman. */
Entier CodageDeHuffman_NombreDeBitsApresCodage;
Entier CodageDeHuffman_NombreDOctetsApresDecodage;
/* Afin de faciliter l'exploitation des resultats... */
#define NOEUD_INEXISTANT \
(INDEX0-1)
#define CARACTERE_INUTILISE \
0
#define CODE_DE_HUFFMAN_INUTILISE \
0
/*************************************************************************************************************************************/
/* */
/* A N A L Y S E F R E Q U E N T I E L L E D E S C A R A C T E R E S : */
/* */
/*************************************************************************************************************************************/
void CodageDeHuffman_GenerationFrequences(CHAR chaine[],Entier longueur)
{
Entier index;
for (index=INDEX0 ; index<=NombreVersIndex(longueur) ; index++)
{
CodageDeHuffman_FrequencesDOccurenceDesCaracteres[chaine[index]]++;
/* La "frequence" est obtenu par un simple comptage des caracteres... */
}
}
#define PERMUTATION(tableau,index1,index2) \
{ \
Entier SauvegardeTemporaire=tableau[index1]; \
tableau[index1] = tableau[index2]; \
tableau[index2] = SauvegardeTemporaire; \
}
void CodageDeHuffman_TriCroissantDesFrequencesDesCaracteres()
{
Entier index_de_fin;
for (index_de_fin=(CodageDeHuffman_DernierCaractere-1)
; index_de_fin>=CodageDeHuffman_PremierCaractere
; index_de_fin--
)
{
Entier index_de_debut;
for (index_de_debut=CodageDeHuffman_PremierCaractere ; index_de_debut<=index_de_fin ; index_de_debut++)
{
if (CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index_de_debut]
> CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index_de_debut+1]
)
{
PERMUTATION(CodageDeHuffman_FrequencesDOccurenceDesCaracteres
,index_de_debut
,index_de_debut+1
);
PERMUTATION(CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres
,index_de_debut
,index_de_debut+1
);
PERMUTATION(CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres
,index_de_debut
,index_de_debut+1
);
/* Cette echange conserve l'ordre des elements possedant la meme "clef"... */
}
else
{
}
}
}
for (index_de_fin=CodageDeHuffman_PremierCaractere ; index_de_fin<=CodageDeHuffman_DernierCaractere ; index_de_fin++)
{
if (CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index_de_fin] == CARACTERE_INUTILISE)
{
CodageDeHuffman_PremierCaractere = index_de_fin+1;
/* Afin de ne parcourir que les entrees utiles (dont les frequences sont donc differentes */
/* de 'CARACTERE_INUTILISE'...). On notera que 'DernierCaractere' ne bouge pas ; il vaut */
/* en effet toujours 'DERNIER_CARACTERE'... */
}
else
{
}
}
}
#define CARACTERE_INEXISTANT \
(PREMIER_CARACTERE-1)
#define PREMIER_CARACTERE_EDITABLE \
0x20
#define DERNIER_CARACTERE_EDITABLE \
0x7e
void CodageDeHuffman_EditionDesFrequencesDesCaracteres()
{
Entier index;
if (HuffmanCoding_EditerFrequences == VRAI)
{
printf("========================================\n");
for (index=CodageDeHuffman_PremierCaractere ; index<=CodageDeHuffman_DernierCaractere ; index++)
{
if (CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index] != CARACTERE_INUTILISE)
{
if (CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
> CARACTERE_INEXISTANT
)
{
if ( ((CHAR)CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
>= PREMIER_CARACTERE_EDITABLE
)
&& ((CHAR)CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
<= DERNIER_CARACTERE_EDITABLE
)
)
{
printf("caractere='%c' (0x%02"For16") frequence=%"For10" noeud=%"For10"\n"
,(CHAR)CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
,CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
,CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index]
,CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[index]
);
}
else
{
printf("caractere= (0x%02"For16") frequence=%"For10" noeud=%"For10"\n"
,CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index]
,CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index]
,CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[index]
);
}
/* Cas des "vrais" caracteres... */
}
else
{
printf("* frequence=%"For10" noeud=%"For10"\n"
,CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index]
,CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[index]
);
/* Cas des caracteres de type "cumul"... */
}
}
else
{
}
}
}
else
{
}
}
/*************************************************************************************************************************************/
/* */
/* G E S T I O N D E L ' A R B R E D E S C O D E S D E H U F F M A N : */
/* */
/*************************************************************************************************************************************/
#define NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE \
(2*NOMBRE_DE_CARACTERES)
#define PREMIER_NOEUD_DE_L_ARBRE \
INDEX0
#define DERNIER_NOEUD_DE_L_ARBRE \
NombreVersIndex(CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre)
#define SUIVANT_INEXISTANT \
(PREMIER_NOEUD_DE_L_ARBRE-1)
#define SIZE_CodageDeHuffman_Arbre \
((CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre*(sizeof(Entier)+sizeof(Entier)+sizeof(Entier)))*NBITOC) \
/* On notera que 'ArbreFrequenceDesNoeuds' est inutile pour la mesure de 'K'... */
Entier CodageDeHuffman_ArbreFrequenceDesNoeuds[NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE];
Entier CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE];
Entier CodageDeHuffman_ArbreChainageAGauche[NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE];
Entier CodageDeHuffman_ArbreChainageADroite[NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE];
#define SIZE_IdentiteDuNoeudCourantDeLArbre \
(sizeof(CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre)*NBITOC)
Entier CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre=PREMIER_NOEUD_DE_L_ARBRE;
Entier CodageDeHuffman_RacineDeLArbre;
/* Definition de l'arbre de codage... */
#define MISE_A_JOUR_ARBRE(frequence,caractere,ChainageAGauche,ChainageADroite) \
/* On notera qu'a GAUCHE se trouve la FREQUENCE MINIMALE... */ \
{ \
CodageDeHuffman_ArbreFrequenceDesNoeuds[CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre] = frequence; \
CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre] = caractere; \
CodageDeHuffman_ArbreChainageAGauche[CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre] = ChainageAGauche; \
CodageDeHuffman_ArbreChainageADroite[CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre] = ChainageADroite; \
\
if (CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre < NombreVersIndex(NOMBRE_MAXIMAL_DE_NOEUDS_DE_L_ARBRE)) \
{ \
CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre++; \
} \
else \
{ \
fprintf(stderr,"ERREUR(HuffmanCoding) : Debordement de l'arbre.\n"); \
} \
}
void CodageDeHuffman_GenerationDeLArbre()
{
Entier ItererLaGenerationDeLArbre=VRAI;
while (ItererLaGenerationDeLArbre == VRAI)
{
Entier index;
Entier IndexFrequenceMinimaleGauche,FrequenceMinimaleGauche,CaractereGauche,NoeudFilsGauche;
Entier IndexFrequenceMinimaleDroite,FrequenceMinimaleDroite,CaractereDroite,NoeudFilsDroite;
Entier SommeDesFrequencesEnUnNoeud=0;
CodageDeHuffman_TriCroissantDesFrequencesDesCaracteres();
CodageDeHuffman_EditionDesFrequencesDesCaracteres();
/* Tri destine a garantir l'ordre des frequences... */
index=CodageDeHuffman_PremierCaractere;
while ( (CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index] == CARACTERE_INUTILISE)
&& (index < CodageDeHuffman_DernierCaractere)
)
{
index++;
}
IndexFrequenceMinimaleGauche = index;
FrequenceMinimaleGauche= CodageDeHuffman_FrequencesDOccurenceDesCaracteres[IndexFrequenceMinimaleGauche];
CaractereGauche = CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[IndexFrequenceMinimaleGauche];
if (CaractereGauche != CARACTERE_INEXISTANT)
{
NoeudFilsGauche = CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre;
CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[IndexFrequenceMinimaleGauche]
= NoeudFilsGauche;
MISE_A_JOUR_ARBRE(FrequenceMinimaleGauche
,CaractereGauche
,SUIVANT_INEXISTANT
,SUIVANT_INEXISTANT
);
/* Creation d'une feuille de l'arbre (noeud donnant donc un caractere). */
}
else
{
NoeudFilsGauche
= CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[IndexFrequenceMinimaleGauche];
/* Cas d'un noeud de cumul de l'arbre deja genere. */
}
SommeDesFrequencesEnUnNoeud = SommeDesFrequencesEnUnNoeud + FrequenceMinimaleGauche;
CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[IndexFrequenceMinimaleGauche] = CARACTERE_INEXISTANT;
CodageDeHuffman_FrequencesDOccurenceDesCaracteres[IndexFrequenceMinimaleGauche] = CARACTERE_INUTILISE;
/* Ainsi, ce caractere dont la frequence va etre cumule un peu plus loin disparait en */
/* quelque sorte de la liste des caracteres a traiter (via donc une frequence nulle). */
index=CodageDeHuffman_PremierCaractere;
while ( (CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index] == CARACTERE_INUTILISE)
&& (index < CodageDeHuffman_DernierCaractere)
)
{
index++;
}
IndexFrequenceMinimaleDroite = index;
if (IndexFrequenceMinimaleGauche != IndexFrequenceMinimaleDroite)
{
FrequenceMinimaleDroite
= CodageDeHuffman_FrequencesDOccurenceDesCaracteres[IndexFrequenceMinimaleDroite];
CaractereDroite
= CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[IndexFrequenceMinimaleDroite];
if (FrequenceMinimaleGauche > FrequenceMinimaleDroite)
{
fprintf(stderr
,"ERREUR(HuffmanCoding) : FreqMinGauche=%"For10" > FreqMinDroite=%"For10"\n"
,FrequenceMinimaleGauche
,FrequenceMinimaleDroite
);
}
else
{
}
if (CaractereDroite != CARACTERE_INEXISTANT)
{
NoeudFilsDroite = CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre;
CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[IndexFrequenceMinimaleDroite]
= NoeudFilsDroite;
MISE_A_JOUR_ARBRE(FrequenceMinimaleDroite
,CaractereDroite
,SUIVANT_INEXISTANT
,SUIVANT_INEXISTANT
);
/* Creation d'une feuille de l'arbre (noeud donnant donc un caractere). */
}
else
{
NoeudFilsDroite
= CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[IndexFrequenceMinimaleDroite];
/* Cas d'un noeud de cumul de l'arbre deja genere. */
}
SommeDesFrequencesEnUnNoeud = SommeDesFrequencesEnUnNoeud + FrequenceMinimaleDroite;
CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[IndexFrequenceMinimaleDroite]
= CARACTERE_INEXISTANT;
CodageDeHuffman_FrequencesDOccurenceDesCaracteres[IndexFrequenceMinimaleDroite]
= SommeDesFrequencesEnUnNoeud;
/* Ainsi, ce caractere dont la frequence vient d'etre cumule est remplace par ce cumul... */
CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[IndexFrequenceMinimaleDroite]
= CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre;
MISE_A_JOUR_ARBRE(SommeDesFrequencesEnUnNoeud
,CARACTERE_INEXISTANT
,NoeudFilsGauche
,NoeudFilsDroite
);
/* Creation d'un noeud de cumul de l'arbre. */
}
else
{
ItererLaGenerationDeLArbre = FAUX;
}
}
CodageDeHuffman_RacineDeLArbre = CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre-1;
}
void CodageDeHuffman_EditionDeLArbre()
{
if (HuffmanCoding_EditerArbre == VRAI)
{
Entier index;
for (index=PREMIER_NOEUD_DE_L_ARBRE ; index<=DERNIER_NOEUD_DE_L_ARBRE ; index++)
{
printf("noeud=%04"For10" frequence=%08"For10""
,index
,CodageDeHuffman_ArbreFrequenceDesNoeuds[index]
);
if (CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[index] != CARACTERE_INEXISTANT)
{
printf(" caractere=0x%02"For16""
,CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[index]
);
}
else
{
printf(" * ");
}
if (CodageDeHuffman_ArbreChainageAGauche[index] != NOEUD_INEXISTANT)
{
printf(" ChainageAGauche=%04"For10""
,CodageDeHuffman_ArbreChainageAGauche[index]
);
}
else
{
}
if (CodageDeHuffman_ArbreChainageADroite[index] != NOEUD_INEXISTANT)
{
printf(" ChainageADroite=%04"For10""
,CodageDeHuffman_ArbreChainageADroite[index]
);
}
else
{
}
printf("\n");
}
}
else
{
}
}
#define GAUCHE \
1
#define DROITE \
0
#define BASE2 \
2
void CodageDeHuffman_ParcoursRecursifDeLArbre(Entier racine,Entier CodeBinaire,Entier LongueurCodeBinaire)
{
if (racine != NOEUD_INEXISTANT)
{
if ( (CodageDeHuffman_ArbreChainageAGauche[racine] != NOEUD_INEXISTANT)
&& (CodageDeHuffman_ArbreChainageADroite[racine] != NOEUD_INEXISTANT)
)
{
if (LongueurCodeBinaire < (NBITMO-1))
{
CodageDeHuffman_ParcoursRecursifDeLArbre(CodageDeHuffman_ArbreChainageAGauche[racine]
,(BASE2*CodeBinaire)+GAUCHE
,LongueurCodeBinaire+1
);
CodageDeHuffman_ParcoursRecursifDeLArbre(CodageDeHuffman_ArbreChainageADroite[racine]
,(BASE2*CodeBinaire)+DROITE
,LongueurCodeBinaire+1
);
}
else
{
fprintf(stderr,"ERREUR(HuffmanCoding) : Un code binaire est trop long.\n");
}
}
else
{
Entier caractere=CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[racine];
Entier longueur=COND((LongueurCodeBinaire == 0),1,LongueurCodeBinaire);
/* Le forcage de la longueur 1 est destine au cas ou l'arbre se reduit a sa racine, ce qui */
/* signifie que la chaine de caracteres ne possede qu'une suite de caracteres identiques. */
CodageDeHuffman_LongueurDuCodeBinaire[caractere] = longueur;
CodageDeHuffman_CodeBinaire[caractere] = CodeBinaire;
if (caractere != CodageDeHuffman_CaractereAssociesAuCodeBinaire[caractere])
{
fprintf(stderr,"ERREUR(HuffmanCoding) : Les tables de Huffman sont incoherentes.\n");
}
else
{
}
}
}
else
{
}
}
/*************************************************************************************************************************************/
/* */
/* I N T I A L I S A T I O N S D I V E R S E S : */
/* */
/*************************************************************************************************************************************/
void CodageDeHuffman_Initialisations()
{
Entier index;
CodageDeHuffman_PremierCaractere=PREMIER_CARACTERE;
CodageDeHuffman_DernierCaractere=DERNIER_CARACTERE;
CodageDeHuffman_IdentiteDuNoeudCourantDeLArbre=PREMIER_NOEUD_DE_L_ARBRE;
for (index=CodageDeHuffman_PremierCaractere ; index<=CodageDeHuffman_DernierCaractere ; index++)
{
CodageDeHuffman_FrequencesDOccurenceDesCaracteres[index] = CARACTERE_INUTILISE;
CodageDeHuffman_DefinitionRedondanteDesCodesDesCaracteres[index] = index;
CodageDeHuffman_NumerosDesNoeudsDeRangementDesCaracteres[index] = NOEUD_INEXISTANT;
CodageDeHuffman_CaractereAssociesAuCodeBinaire[index] = index;
CodageDeHuffman_LongueurDuCodeBinaire[index] = CODE_DE_HUFFMAN_INUTILISE;
CodageDeHuffman_CodeBinaire[index] = CODE_DE_HUFFMAN_INUTILISE;
}
}
/*************************************************************************************************************************************/
/* */
/* E D I T I O N D E S C O D E S D E H U F F M A N : */
/* */
/*************************************************************************************************************************************/
void CodageDeHuffman_EditionDesCodesDeHuffman()
{
if (HuffmanCoding_EditerCodesDeHuffman == VRAI)
{
Entier index_1;
printf("\n");
for (index_1=PREMIER_CARACTERE ; index_1<=DERNIER_CARACTERE ; index_1++)
{
Entier LongueurCodeBinaire=CodageDeHuffman_LongueurDuCodeBinaire[index_1];
if (LongueurCodeBinaire != CODE_DE_HUFFMAN_INUTILISE)
{
CHAR caractere=CodageDeHuffman_CaractereAssociesAuCodeBinaire[index_1];
Entier reste=CodageDeHuffman_CodeBinaire[index_1];
Entier PuissanceDe2=1;
Entier index_2;
if ( (caractere >= PREMIER_CARACTERE_EDITABLE)
&& (caractere <= DERNIER_CARACTERE_EDITABLE)
)
{
printf("'%c' (0x%02x) --> "
,caractere
,caractere
);
}
else
{
printf(" (0x%02x) --> "
,caractere
);
}
for (index_2=1 ; index_2<=LongueurCodeBinaire ; index_2++)
{
PuissanceDe2 = BASE2*PuissanceDe2;
}
for (index_2=1 ; index_2<=LongueurCodeBinaire ; index_2++)
{
PuissanceDe2 = PuissanceDe2/BASE2;
printf("%1"For10,reste/PuissanceDe2);
reste = reste%PuissanceDe2;
}
printf("\n");
}
else
{
}
}
}
else
{
}
}
/*************************************************************************************************************************************/
/* */
/* C O M P A C T A G E D ' U N E C H A I N E D E C A R A C T E R E S : */
/* */
/*************************************************************************************************************************************/
#define STORE_BIT(Bit,IndexBit,Chaine) \
{ \
Entier IndexBitDansChaine; \
CHAR Octet; \
CHAR MasqueRangementBit; \
Entier IndexBitDansOctet; \
\
IndexBitDansChaine = IndexBit/NBITOC; \
IndexBitDansOctet = IndexBit%NBITOC; \
\
Octet = Chaine[IndexBitDansChaine]; \
MasqueRangementBit = Bit << ((NBITOC-IndexBitDansOctet)-1); \
Chaine[IndexBitDansChaine] = Octet | MasqueRangementBit; \
}
Entier CodageDeHuffman_CompactageChaine(CHAR ChaineB[],CHAR ChaineA[],Entier longueurA)
{
Entier NombreDeBitsDansChaineB=0;
Entier IndexBitCourant=0;
Entier IndexDeChaineA;
for (IndexDeChaineA=INDEX0 ; IndexDeChaineA<=NombreVersIndex(longueurA) ; IndexDeChaineA++)
{
CHAR CaractereCourant=ChaineA[IndexDeChaineA];
Entier IndexCodageDeHuffman=PREMIER_CARACTERE;
Entier iterer=VRAI;
while (iterer == VRAI)
{
if (IndexCodageDeHuffman <= DERNIER_CARACTERE)
{
if (CaractereCourant
== CodageDeHuffman_CaractereAssociesAuCodeBinaire[IndexCodageDeHuffman]
)
{
/* Le caractere courant a ete retrouve dans les tables de codage entropique de Huffman : */
Entier LongueurCodeBinaire
=CodageDeHuffman_LongueurDuCodeBinaire[IndexCodageDeHuffman];
Entier reste=CodageDeHuffman_CodeBinaire[IndexCodageDeHuffman];
Entier IndexCodeBinaire;
Entier PuissanceDe2=1;
for (IndexCodeBinaire=1
; IndexCodeBinaire<=LongueurCodeBinaire
; IndexCodeBinaire++
)
{
PuissanceDe2 = BASE2*PuissanceDe2;
}
for (IndexCodeBinaire=1
; IndexCodeBinaire<=LongueurCodeBinaire
; IndexCodeBinaire++
)
{
Entier BitCourant;
PuissanceDe2 = PuissanceDe2/BASE2;
BitCourant = reste/PuissanceDe2;
reste = reste%PuissanceDe2;
STORE_BIT(BitCourant,IndexBitCourant,ChaineB);
/* Mise en place des bits codant le caractere courant 'CaractereCourant'... */
IndexBitCourant++;
NombreDeBitsDansChaineB++;
}
iterer=FAUX;
}
else
{
IndexCodageDeHuffman++;
/* Il faut poursuivre la recherche du caractere courant dans le code de Huffman... */
}
}
else
{
fprintf(stderr,"ERREUR(HuffmanCoding) : Le caractere '0x02x' n'est pas dans l'arbre.\n");
iterer=FAUX;
}
}
}
CodageDeHuffman_NombreDeBitsApresCodage = NombreDeBitsDansChaineB;
return(NombreDeBitsDansChaineB);
}
/*************************************************************************************************************************************/
/* */
/* D E C O M P A C T A G E D ' U N E C H A I N E D E C A R A C T E R E S : */
/* */
/*************************************************************************************************************************************/
#define LOAD_BIT(Bit,IndexBit,Chaine) \
{ \
Entier IndexBitDansChaine = IndexBit/NBITOC; \
Entier IndexBitDansOctet = IndexBit%NBITOC; \
Entier decalage; \
CHAR Octet; \
Entier MasqueExtractionBit; \
\
decalage = ((NBITOC-IndexBitDansOctet)-1); \
\
Octet = Chaine[IndexBitDansChaine]; \
MasqueExtractionBit = BIT << decalage; \
Bit = (Octet & MasqueExtractionBit) >> decalage; \
}
Entier CodageDeHuffman_DeCompactageChaine(CHAR ChaineR[],CHAR ChaineB[],Entier NombreDeBitsDansChaineB)
{
Entier NombreDOctetssDansChaineR=0;
Entier IndexBitCourant;
Entier IndexChaineR=INDEX0;
Entier NoeudCourantDeLArbre=CodageDeHuffman_RacineDeLArbre;
for (IndexBitCourant=INDEX0 ; IndexBitCourant<=NombreVersIndex(NombreDeBitsDansChaineB) ; IndexBitCourant++)
{
Entier BitCourant;
LOAD_BIT(BitCourant,IndexBitCourant,ChaineB);
if ( (CodageDeHuffman_ArbreChainageAGauche[NoeudCourantDeLArbre] == NOEUD_INEXISTANT)
&& (CodageDeHuffman_ArbreChainageADroite[NoeudCourantDeLArbre] == NOEUD_INEXISTANT)
)
{
/* Cas ou l'arbre n'a qu'un noeud (sa racine est une feuille), ce qui se rencontre dans */
/* le cas ou la chaine 'A' contient des caracteres tous identiques... */
}
else
{
switch (BitCourant)
/* La valeur du bit courant indique si l'on doit tourner a GAUCHE ou bien a DROITE... */
{
case GAUCHE:
{
NoeudCourantDeLArbre = CodageDeHuffman_ArbreChainageAGauche[NoeudCourantDeLArbre];
break;
}
case DROITE:
{
NoeudCourantDeLArbre = CodageDeHuffman_ArbreChainageADroite[NoeudCourantDeLArbre];
break;
}
default:
{
fprintf(stderr,"ERREUR(HuffmanCoding) : un bit vaut %"For10".\n",BitCourant);
}
}
}
if ( (CodageDeHuffman_ArbreChainageAGauche[NoeudCourantDeLArbre] == NOEUD_INEXISTANT)
&& (CodageDeHuffman_ArbreChainageADroite[NoeudCourantDeLArbre] == NOEUD_INEXISTANT)
)
{
ChaineR[IndexChaineR] = CodageDeHuffman_ArbreCaracteresEnChaqueNoeud[NoeudCourantDeLArbre];
/* Cas ou l'on est tombe sur une feuille de l'arbre : elle donne le caractere qui etait */
/* code par la suite courante de bits... */
IndexChaineR++;
NombreDOctetssDansChaineR++;
NoeudCourantDeLArbre = CodageDeHuffman_RacineDeLArbre;
/* Et on repart de la racine de l'arbre... */
}
else
{
}
}
CodageDeHuffman_NombreDOctetsApresDecodage = NombreDOctetssDansChaineR;
return(NombreDOctetssDansChaineR);
}
/*************************************************************************************************************************************/
/* */
/* V A L I D A T I O N D U D E C O M P A C T A G E / D E C O M P A C T A G E */
/* D ' U N E C H A I N E D E C A R A C T E R E S : */
/* */
/*************************************************************************************************************************************/
void CodageDeHuffman_Verifications(CHAR Chaine1[],Entier LongueurChaine1,CHAR Chaine2[],Entier LongueurChaine2)
{
Entier index;
if (LongueurChaine1 == LongueurChaine2)
{
for (index=INDEX0 ; index<=NombreVersIndex(MIN2(LongueurChaine1,LongueurChaine2)) ; index++)
{
if (Chaine1[index] != Chaine2[index])
{
fprintf(stderr,"ERREUR(HuffmanCoding) : '0x%02x' et '0x%02x' de rang %"For10" different.\n"
,Chaine1[index]
,Chaine2[index]
,index
);
}
else
{
}
}
}
else
{
fprintf(stderr
,"ERREUR(HuffmanCoding) : Les deux chaines n'ont pas la meme longueur (%"For10"#%"For10").\n"
,LongueurChaine1
,LongueurChaine2
);
}
}
/*************************************************************************************************************************************/
/* */
/* I N I T I A L I S A T I O N S A S S O C I E E S A C H A Q U E C H A I N E D E T E S T : */
/* */
/*************************************************************************************************************************************/
#ifndef CodageDeHuffman_FIN_DE_CHAINE
# define CodageDeHuffman_FIN_DE_CHAINE \
1 \
/* Le '+1' est destine a pouvoir introduire, si besoin est, une "fin de chaine"... */
#else
#endif
#define CodageDeHuffman_InitialisationChaines(ChaineB,ChaineR,ChaineA,LongueurChaineA) \
{ \
Entier index_1; \
Entier longueur=LongueurChaineA+CodageDeHuffman_FIN_DE_CHAINE; \
/* Le '+1' est destine a pouvoir introduire, si besoin est, une "fin de chaine"... */ \
\
ChaineB = malloc(longueur); \
ChaineR = malloc(longueur); \
\
for (index_1=1 ; index_1<=longueur ; index_1++) \
{ \
Entier index_2=NombreVersIndex(index_1); \
\
ChaineB[index_2] = 0; \
ChaineR[index_2] = 0; \
/* On notera que cela met donc implicitement une "fin de chaine" (0)... */ \
} \
}
#define CodageDeHuffman_DesinitialisationChaines(ChaineA1,ChaineA2) \
{ \
free(ChaineA1); \
free(ChaineA2); \
}