
merci

Voici mon implémentation de l'algorithme de compression Huffman (que je vais utiliser dans F-Zero) :
Quatres fichiers (deux .h et deux .c) pour la compression et la decompression On-Calc.
Le compresseur fait un peu moins de 2ko et le décompresseur un peu moins de 600 octets.
On ne peut pas compresser directement les fichiers car je travaille seulement avec des zones de mémoires (mais c'est possible en recuperant le pointeur avec les truc de vat.h).
Donc voilà je me demandais si quelqu'un pouvait trouver des optimisations en taille surtout pour le décompresseur ?
downloadez le projet complet : huff.zip
les sources pour ceux qui ont la flemme de downloader mais qui veulent juste voir a quoi ca ressemble (et oui c'est pas commenté et c'est illisible

main.c
// C Source File // Created 05/04/2005; 12:00:48 #include <tigcclib.h> #include "compress.h" #include "uncompress.h" unsigned char data[] = "test"; unsigned short size = 4; // Main Function void _main(void) { unsigned char * dataComp; unsigned short sizeComp; unsigned char * data2; unsigned short size2; dataComp = compress(data, size, &sizeComp); data2 = uncompress(dataComp, &size2); free(dataComp); free(data2); }
compress.h
// Header File // Created 16/04/2005; 21:18:10 unsigned char * compress(unsigned char * data, unsigned short size, unsigned short * sizeComp);
compress.c
// C Source File // Created 16/04/2005; 21:18:36 #include <tigcclib.h> #include "compress.h" typedef struct node { unsigned short nbocc; unsigned char isleaf; unsigned char l_id; unsigned char r_id; struct node * l_node; struct node * r_node; } node; typedef struct leaf { unsigned short nbocc; unsigned char isleaf; unsigned char id; } leaf; typedef struct code { unsigned char nbbit; unsigned char bits[16]; } code; CALLBACK short leaf_comp(const void *a, const void *b) { return ((leaf*)a)->nbocc - ((leaf*)b)->nbocc; } code lbit(code cod) { cod.bits[cod.nbbit >> 3] &= ~(0x80 >> (((cod.nbbit)++) & 0x7)); return cod; } code rbit(code cod) { cod.bits[cod.nbbit >> 3] |= (0x80 >> (((cod.nbbit)++) & 0x7)); return cod; } unsigned char * comp; unsigned char numbit; void wbit(unsigned char bit) { if(bit) *comp |= (0x80 >> numbit); else *comp &= ~(0x80 >> numbit); if(!((++numbit) & 0x7)) {++comp;numbit=0;} } void wid(unsigned char id) { unsigned short i; for(i=8;i--; ) wbit(id & 0x80), id<<=1; } void wcode(code cod) { unsigned short i; for(i=0; i<cod.nbbit; i++) wbit(cod.bits[i>>3] & 0x80>>(i&0x7)); } void btree_read(node * tree, code * codes, code cod) { wbit(0); if(!(tree->l_node)) codes[tree->l_id] = lbit(cod), wbit(1), wid(tree->l_id); else btree_read(tree->l_node, codes, lbit(cod)); if(!(tree->r_node)) codes[tree->r_id] = rbit(cod), wbit(1), wid(tree->r_id); else btree_read(tree->r_node, codes, rbit(cod)); } unsigned char * compress(unsigned char * data, unsigned short size, unsigned short * sizeComp) { unsigned char * dataComp; unsigned short nbleaf; code codes[256]; leaf leafs[256]; leaf *tableaf; unsigned short i; for(i=256;i--; ) codes[i].nbbit = 0; for(i=256;i--; ) { leafs[i].nbocc = 0; leafs[i].id = i; leafs[i].isleaf = 1; } for(i=size; i--; ) leafs[data[i]].nbocc++; qsort(leafs, 256, sizeof(leaf), leaf_comp); for(i=256; i-- && leafs[i].nbocc; ); tableaf = &leafs[256]; nbleaf = 255-i; node * nodes; node ** nodesptrs; if(nbleaf!=1) { nodes = (node*)calloc((nbleaf-1), sizeof(node)) + nbleaf-1; nodesptrs = (node **)malloc(sizeof(node *) * nbleaf); for(i=nbleaf; i--; ) *(nodesptrs++) = (node*)(--tableaf); nodesptrs -= nbleaf; for(i = nbleaf-1; i--; ) { (*(node*)(--nodes)).nbocc = (*(node**)(nodesptrs+i))->nbocc + (*(node**)(nodesptrs+i+1))->nbocc; if((*(node**)(nodesptrs+i))->isleaf) (*(node*)(nodes)).l_id = (*(leaf**)(nodesptrs+i))->id; else (*(node*)(nodes)).l_node = *(node**)(nodesptrs+i); if((*(node**)(nodesptrs+i+1))->isleaf) (*(node*)(nodes)).r_id = (*(leaf**)(nodesptrs+i+1))->id; else (*(node*)(nodes)).r_node = *(node**)(nodesptrs+i+1); unsigned short j; for(j=i;j--; ) if((*(node*)(nodes)).nbocc <= (*(node**)(nodesptrs+j))->nbocc) break; j++; memmove(nodesptrs+j+1,nodesptrs+j,(i-j)*sizeof(void*)); *(node**)(nodesptrs+j) = nodes; } free(nodesptrs); } else { nodes = (node*)calloc(1, sizeof(node)); nodes->l_id = leafs[255].id; nbleaf++; tableaf--; } unsigned short offset = ((nbleaf<<1)-1) + (nbleaf<<3) + 16; *sizeComp = (offset>>3) + ((offset & 0x7)?1:0); dataComp = (unsigned char *)malloc(sizeof(unsigned char) * (*sizeComp)); comp = dataComp+2; code cod; cod.nbbit = 0; numbit = 0; btree_read(nodes, codes, cod); unsigned long sum = 0; for(i=nbleaf; i--; ) sum += tableaf->nbocc * codes[tableaf->id].nbbit, tableaf++; *sizeComp = ((sum+offset)>>3) + (((sum+offset) & 0x7)?1:0); *(unsigned short*)dataComp = size; comp -= (long)dataComp; dataComp = (unsigned char *)realloc(dataComp, sizeof(unsigned char) * (*sizeComp)); comp += (long)dataComp; for(i=0; i<size; i++) wcode(codes[data[i]]); free(nodes); return dataComp; }
uncompress.h
// Header File // Created 18/04/2005; 16:15:38 unsigned char * uncompress(unsigned char * dataComp, unsigned short * size);
uncompress.c
// C Source File // Created 18/04/2005; 16:15:49 #include <tigcclib.h> #include "uncompress.h" typedef struct node { unsigned char l_id; unsigned char r_id; struct node * l_node; struct node * r_node; } node; unsigned char * comp; unsigned char numbit; node * nod; unsigned char rbit() { if(!((++numbit) & 0x7)) {++comp;numbit=0;} return *comp & (0x80 >> numbit); } unsigned char rid() { unsigned short i; unsigned char id=0; for(i=8;i--; ) id <<= 1, id |= (rbit()?1:0); return id; } node * mtree_read(unsigned char * id) { node * n = nod; if(rbit()) { *id = rid(); return NULL; } nod++; n->l_node = mtree_read(&(n->l_id)); n->r_node = mtree_read(&(n->r_id)); return n; } unsigned char rcode(node * n) { if(!rbit()) { if(!(n->l_node)) return n->l_id; else return rcode(n->l_node); } if(!(n->r_node)) return n->r_id; else return rcode(n->r_node); } unsigned char * uncompress(unsigned char * dataComp, unsigned short * size) { unsigned char * data; node nodes[255]; nod = nodes; comp = dataComp+1; numbit = 7; mtree_read(NULL); *size = *(unsigned short*)dataComp; data = (unsigned char *)malloc(sizeof(unsigned char) * (*size)); // gerer ca avec realloc etc.. unsigned short i; for(i=0;i<(*size);i++) data[i] = rcode(nodes); return data; }
Si vous voulez utiliser ce code, ben vous pouvez faire ce qui vous plait avec, c'est gratos
