#include #include #include "compressor.h" struct node { unsigned char znak; int pocet; struct node *left; struct node *right; }; struct node* vytvor_node(unsigned char c, int p) { struct node* n = malloc(sizeof(struct node)); n->znak = c; n->pocet = p; n->left = NULL; n->right = NULL; return n; } int compress_file(char *input, char *output) { FILE *f = fopen(input, "rb"); if(!f) { printf("Neviem otvorit subor\n"); return 1; } fseek(f, 0, SEEK_END); long velkost = ftell(f); fseek(f, 0, SEEK_SET); unsigned char *data = malloc(velkost); fread(data, 1, velkost, f); fclose(f); int frekvencia[256]; int i; for(i=0;i<256;i++) frekvencia[i]=0; for(i=0;i0){ pole[n] = vytvor_node(i, frekvencia[i]); n++; } } for(i=0;ipocet > pole[j+1]->pocet){ struct node* tmp = pole[j]; pole[j] = pole[j+1]; pole[j+1] = tmp; } } } while(n>1){ struct node* left = pole[0]; struct node* right = pole[1]; struct node* parent = vytvor_node(0, left->pocet + right->pocet); parent->left = left; parent->right = right; for(i=0;ipocet < pole[i]->pocet){ for(int j=n;j>i;j--){ pole[j] = pole[j-1]; } pole[i] = parent; vlozene=1; break; } } if(!vlozene) pole[n] = parent; n++; } struct node* root = pole[0]; unsigned int kody[256]; unsigned char dlzky[256]; for(i=0;i<256;i++){ kody[i]=0; dlzky[i]=0; } struct node* zasobnik[512]; unsigned int kod_zasobnik[512]; unsigned char dlzka_zasobnik[512]; int top=0; zasobnik[top] = root; kod_zasobnik[top] = 0; dlzka_zasobnik[top] = 0; top++; while(top>0){ top--; struct node* aktualny = zasobnik[top]; unsigned int kod = kod_zasobnik[top]; unsigned char dlzka = dlzka_zasobnik[top]; if(!aktualny->left && !aktualny->right){ kody[aktualny->znak] = kod; dlzky[aktualny->znak] = dlzka>0 ? dlzka : 1; }else{ if(aktualny->left){ zasobnik[top] = aktualny->left; kod_zasobnik[top] = kod<<1; dlzka_zasobnik[top] = dlzka+1; top++; } if(aktualny->right){ zasobnik[top] = aktualny->right; kod_zasobnik[top] = (kod<<1)|1; dlzka_zasobnik[top] = dlzka+1; top++; } } } unsigned char* vystup = malloc(velkost*2); long pos=0; unsigned char bajt=0; int bit_pos=0; for(i=0;i=0;j--){ if((kod>>j)&1){ bajt |= (1<<(7-bit_pos)); } bit_pos++; if(bit_pos==8){ vystup[pos++] = bajt; bajt=0; bit_pos=0; } } } if(bit_pos>0) vystup[pos++]=bajt; FILE *fout = fopen(output, "wb"); fwrite(&velkost, sizeof(long), 1, fout); fwrite(frekvencia, sizeof(int), 256, fout); fwrite(vystup, 1, pos, fout); fclose(fout); printf("Komprimovane: %ld -> %ld\n", velkost, pos+sizeof(long)+256*sizeof(int)); free(data); free(vystup); return 0; } int decompress_file(char *input, char *output) { FILE *f = fopen(input, "rb"); if(!f){ printf("Neviem otvorit subor\n"); return 1; } long velkost; int frekvencia[256]; fread(&velkost, sizeof(long), 1, f); fread(frekvencia, sizeof(int), 256, f); struct node* pole[256]; int n=0; int i; for(i=0;i<256;i++){ if(frekvencia[i]>0){ pole[n] = vytvor_node(i, frekvencia[i]); n++; } } for(i=0;ipocet > pole[j+1]->pocet){ struct node* tmp = pole[j]; pole[j] = pole[j+1]; pole[j+1] = tmp; } } } while(n>1){ struct node* left = pole[0]; struct node* right = pole[1]; struct node* parent = vytvor_node(0, left->pocet + right->pocet); parent->left = left; parent->right = right; for(i=0;ipocet < pole[i]->pocet){ for(int j=n;j>i;j--){ pole[j] = pole[j-1]; } pole[i] = parent; vlozene=1; break; } } if(!vlozene) pole[n] = parent; n++; } struct node* root = pole[0]; fseek(f, 0, SEEK_END); long total = ftell(f); long komp_velkost = total - sizeof(long) - 256*sizeof(int); fseek(f, sizeof(long) + 256*sizeof(int), SEEK_SET); unsigned char *komp_data = malloc(komp_velkost); fread(komp_data, 1, komp_velkost, f); fclose(f); unsigned char *vystup = malloc(velkost); long vystup_pos=0; struct node* aktualny = root; for(i=0;i=0 && vystup_pos>bit)&1){ aktualny = aktualny->right; }else{ aktualny = aktualny->left; } if(!aktualny->left && !aktualny->right){ vystup[vystup_pos++] = aktualny->znak; aktualny = root; } } } FILE *fout = fopen(output, "wb"); fwrite(vystup, 1, velkost, fout); fclose(fout); printf("Dekomprimovane: %ld\n", velkost); free(komp_data); free(vystup); return 0; }