00001
00002
00003 #include "compressore.h"
00004 #include "listadoppia.h"
00005
00006
00007
00008
00009
00010
00011
00012
00013 int compressore::elevato (int a, int b)
00014 {
00015 if (a == 0) return 0;
00016 int app = 1;
00017 for (int i = 0; i < b; i++)
00018 app *= a;
00019 return app;
00020 }
00021
00022
00023
00024
00025 int compressore::traduci (char c)
00026 {
00027 int a = 0;
00028 for (int i = 0; i < 8; i++)
00029 a = a + ((c >> (i)) & 1) * elevato(2,i);
00030 return a;
00031 }
00032 #if DEBUG
00033 #include <iostream>
00034 #endif
00035 #if DEBUG
00036 namespace com
00037 {
00038 void preorder (node* tree)
00039 {
00040 if (tree == 0) return;
00041 cout << tree -> c << ' ' << tree -> freq << endl;
00042 preorder (tree -> left);
00043 preorder (tree -> right);
00044 }
00045 void postorder (node* tree)
00046 {
00047 if (tree == 0) return;
00048 postorder (tree -> left);
00049 postorder (tree -> right);
00050 cout << tree -> c << ' ' << tree -> freq << endl;
00051 }
00052 void inorder (node* tree)
00053 {
00054 if (tree == 0) return;
00055 inorder (tree -> left);
00056 cout << tree -> c << ' ' << tree -> freq << endl;
00057 inorder (tree -> right);
00058 }
00059 }
00060 #endif
00061
00062
00063 compressore::compressore(const char file[], const char fileo[])
00064 {
00065 #if DEBUG
00066 cout << "DEBUG" << endl;
00067 #endif
00068 stream.open (file, ios::in | ios::binary);
00069 if (!stream) throw "apertura";
00070 #if DEBUG
00071 cout << "apertura ultimata" << endl;
00072 system ("PAUSE");
00073 #endif
00074
00075 contaoccorrenze();
00076 #if DEBUG
00077 cout << "conteggio occorrenze terminato" << endl;
00078 for (int i = 0; i < 256; i++)
00079 cout << char(i) << ' ' << v[i] << endl;
00080 system ("PAUSE");
00081 #endif
00082
00083 int a = arrayfreq();
00084 num = a;
00085 delete[] v;
00086 v = 0;
00087 #if DEBUG
00088 cout << "vettorizzazione, stampo risultati" << endl;
00089 cout << "vettore pf:" << endl;
00090 for (int i = 0; i < a; i++)
00091 cout << pf[i]->c << ' ' << pf[i]->freq << endl;
00092 system ("PAUSE");
00093 #endif
00094
00095
00096 IOs out (fileo, pf, a);
00097 heap hp(pf, a);
00098 #if DEBUG
00099 cout << "generazione heap completata" << endl;
00100 for (int i = 0; i < a; i++)
00101 cout << hp.v[i] -> c << ' ' << hp.v[i]->freq << endl;
00102 system ("PAUSE");
00103 #endif
00104
00105
00106 int last = hp.lastn();
00107 root = huffman (hp, last);
00108 delete[] pf;
00109
00110 pf = 0;
00111 #if DEBUG
00112 cout << "costruzione albero ultimata" << endl;
00113 com::preorder (root);
00114 cout << "--------" << endl;
00115 com::postorder (root);
00116 cout << "--------" << endl;
00117 com::inorder (root);
00118 system ("PAUSE");
00119 #endif
00120
00121 c = new char*[256];
00122 if (c == 0) throw "memoria";
00123 for (int i = 0; i < 256; i++)
00124 c[i] = 0;
00125 char* app = new char[last+1];
00126 if (app == 0) throw "memoria";
00127 app[0] = '\0';
00128 if (root -> left == 0 && root -> right == 0)
00129 {
00130 int i = traduci(root -> c);
00131 c[i] = new char[2];
00132 if (c[i] == 0) throw "memoria";
00133 c[i][0] = '1';
00134 c[i][1] = '\0';
00135 }
00136 else
00137 linearizza(root, app);
00138
00139
00140 delete[] app;
00141 app = 0;
00142 cancella(root);
00143 #if DEBUG
00144 cout << "array di codifica ultimato" << endl;
00145 for (int i = 0; i < a; i++)
00146 cout << c[i].c << ' ' << c[i].codice << endl;
00147 system ("PAUSE");
00148 #endif
00149
00150 comprimi(file ,out);
00151 for (int i = 0; i < last + 1; i++)
00152 delete[] c[i];
00153 delete[] c;
00154
00155
00156 c = 0;
00157 stream.close();
00158 }
00159
00160 void compressore::cancella(node*& tree)
00161
00162 {
00163 if (tree==0) return;
00164 cancella (tree ->left);
00165 cancella (tree -> right);
00166 delete tree;
00167 tree = 0;
00168 }
00169
00170 void compressore::contaoccorrenze()
00171 {
00172 v = new int[256];
00173 if (!v) throw "memoria";
00174 for (int i = 0; i < 256; i++)
00175 v[i] = 0;
00176 int a;
00177 a = stream.get();
00178 while (stream)
00179 {
00180 v[a]++;
00181 a = stream.get();
00182 }
00183 }
00184
00185
00186
00187
00188
00189 int compressore::arrayfreq()
00190 {
00191 listadoppia l;
00192 for (int j = 0; j < 256; j++)
00193 if (v[j] > 0) l.inserisci(j);
00194 int n = l.numero();
00195 if (n == 0) throw "vuoto";
00196 pf = new frequenza* [n];
00197 if (!pf) throw "memoria";
00198 for (int i = 0; i < n; i++)
00199 {
00200 int e = l.estrai();
00201 pf[i] = new frequenza;
00202 if (!pf[i]) throw "memoria";
00203 pf[i] -> c = char(e);
00204 pf[i] -> freq = v[e];
00205 pf[i] -> left = pf[i] -> right = 0;
00206 }
00207 if (n == 0) throw "vuoto";
00208 return n;
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218 node* compressore::huffman (heap H, int last)
00219 {
00220 for(int i = 0; i < last; i++)
00221 {
00222 node* t = new node;
00223 if (t == 0) throw "memoria";
00224 t->left = H.estrai();
00225 t->right = H.estrai();
00226 t->freq= t->left->freq + t->right->freq;
00227 H.inserisci(t);
00228 }
00229 return H.estrai();
00230 }
00231
00232 void compressore::linearizza (node* tree, char* codice, int j)
00233 {
00234 if (tree == 0) return;
00235 if (tree -> left == 0 && tree -> right == 0)
00236 {
00237 int i = traduci (tree -> c);
00238
00239
00240 c[i] = new char[j+1];
00241 for (int a = 0; a < j+1; a++)
00242 c[i][a] = codice[a];
00243 return;
00244 }
00245 char* codices = new char[j+2];
00246 char* codiced = new char[j+2];
00247 strcpy (codices,codice);
00248 strcpy (codiced,codice);
00249 codices[j] = '0';
00250 codices[j+1] = '\0';
00251 codiced[j] = '1';
00252 codiced[j+1] = '\0';
00253 linearizza(tree->left,codices, j+1);
00254 linearizza(tree->right,codiced, j+1);
00255 delete[] codices;
00256 delete[] codiced;
00257 }
00258
00259 void compressore::comprimi(const char file[], IOs& out)
00260 {
00261
00262 char a;
00263 stream.clear();
00264 stream.close();
00265 stream.open(file, ios::in | ios::binary);
00266 a = char(stream.get());
00267 while (stream)
00268 {
00269 int i = traduci(a);
00270 if (c[i] == 0) throw "lettura";
00271 for (int j = 0; j < strlen(c[i]); j++)
00272 out.inserisci(int(c[i][j]) - int('0'));
00273 a = char(stream.get());
00274 }
00275 if (!stream.eof()) throw "compressione";
00276 out.svuota();
00277 }
00278