X-Git-Url: https://git.llucax.com/z.facultad/75.06/jacu.git/blobdiff_plain/c85503d1a07d56f61d4fb85696212118c0c470cd..4620669a5d0ff5d3d07d1bec9d04f9b09a9cda16:/src/statichuff/statichuff.c diff --git a/src/statichuff/statichuff.c b/src/statichuff/statichuff.c index 7503511..e91a367 100644 --- a/src/statichuff/statichuff.c +++ b/src/statichuff/statichuff.c @@ -1,20 +1,51 @@ #include -typedef unsigned short int t_freq; +typedef unsigned long int t_freq; typedef struct t_freqnode { unsigned short int symbol; - unsigned short int freq; + t_freq freq; struct t_freqnode *lchild; struct t_freqnode *rchild; } HUFFNODE; typedef struct t_code { - unsigned short int code; + unsigned long int code; unsigned char codelength; } CODE; +void putbit(char bit, char restart, char flush, FILE *fp) +{ + static unsigned long int bits_buffer = 0; + static unsigned char bits_used = 0; + + /* me obligan a tirar el output */ + if ((flush == 1) && (bits_used > 0)) { + fwrite(&bits_buffer,sizeof(unsigned long int),1,fp); + bits_buffer = 0; + bits_used = 0; + return; + } + /* me indican que comienza un nuevo output */ + if (restart) { + bits_buffer = 0; + bits_used = 0; + } + /* inserto el bit en el buffer */ + bits_buffer = bits_buffer << 1; + bits_buffer |= bit; + bits_used++; + + /* lleno el buffer, escribo */ + if (bits_used == 32) { + fwrite(&bits_buffer,sizeof(unsigned long int),1,fp); + bits_buffer = 0; + bits_used = 0; + } + return; +} + void cpynode(HUFFNODE *node1, HUFFNODE *node2) { node1->symbol = node2->symbol; @@ -56,12 +87,12 @@ HUFFNODE *buildlist(t_freq *freqtable, int *nonzerofreqs) int rescalefreq(t_freq *freqtable) { int i; - int totalfreq = 0; + t_freq totalfreq = 0; /* Divido por la mitad las frecuencias, asegurando de no perder */ /* frequencias en 1, por ello le sumo 1 antes de partir */ for (i = 0; i < 256; i++) { - freqtable[i] = (freqtable[i]+1)/2; + freqtable[i] = (freqtable[i] << 2) | 1; totalfreq += freqtable[i]; } @@ -72,7 +103,7 @@ int scanfreq(char *inputfile, t_freq *freqtable) { /* Locals */ FILE *fp; - int sumfreq = 0,auxsum = 0; + t_freq sumfreq = 0; int i,symbol; /* Inicializamos la tabla de frecuencias */ @@ -89,7 +120,7 @@ int scanfreq(char *inputfile, t_freq *freqtable) ++sumfreq; /* Si llegue al tope de freq acumulada, halve em */ - if (sumfreq == 4181) + if (sumfreq == 14930352) sumfreq = rescalefreq(freqtable); } @@ -106,7 +137,7 @@ void printcodes(CODE *codetable,t_freq *freqtable) for (i = 0; i < 256; ++i) { if (codetable[i].codelength > 0) { auxcode = codetable[i].code; - printf("Symbol:%i Freq: %i Code:",i,freqtable[i]); + printf("Symbol:%i Freq: %li Code:",i,freqtable[i]); for (j = codetable[i].codelength-1; j >= 0; --j) { auxcode = codetable[i].code; auxcode = auxcode >> j; @@ -134,8 +165,7 @@ void buildcodes(CODE *table, HUFFNODE *node, int level, int code) if (node->symbol < 256) { /* Guardo el codigo en la tabla */ table[node->symbol].code = code; - table[node->symbol].codelength = level; - /*printf("Found symbol %i with freq %i at depth %i\n",node->symbol,node->freq,level);*/ + table[node->symbol].codelength = level; } else { code = code << 1; @@ -172,6 +202,37 @@ HUFFNODE *buildtree(HUFFNODE *list, int listcount) return lastsymbol; } +int encode(CODE *table, char* inputfile, char *outputfile) { + + FILE *fpsource,*fpdest; + int symbol,i; + char bit; + CODE symbolcode; + + /* Abrimos el file */ + if ((fpsource = fopen(inputfile,"rb")) == NULL) return 0; + if ((fpdest = fopen(outputfile,"wb")) == NULL) return 0; + + while (!feof(fpsource)) { + /* Levanto un symbolo (byte) */ + symbol = fgetc(fpsource); + if (symbol == EOF) continue; + + /* Cargamos el codigo y lo emitimos */ + symbolcode = table[symbol]; + for (i = symbolcode.codelength; i > 0; --i) { + bit = (symbolcode.code >> (i-1)) & 1; + putbit(bit,0,0,fpdest); + } + } + + /* Hacemos un flush de lo que haya quedado en el buffer de salida */ + putbit(0,0,1,fpdest); + fclose(fpsource); + fclose(fpdest); + return 1; +} + int main(int argc, char* argv[]) { /* Locals */ @@ -193,8 +254,7 @@ int main(int argc, char* argv[]) zerocodes(codetable); buildcodes(codetable,codetree,0,0); printcodes(codetable,freqtable); - /*encode(codetable)*/ + encode(codetable,argv[1],"output.dat"); return 0; - }