PDA

Visualizza la versione completa : [C++] Compressione dati con algoritmo Huffman non funziona con dati binari


zeno3083
28-06-2007, 12:06
Salve a tutti
Io ho scritto un programma di compressione dati che utilizza l'agoritmo di huffman, il problema e che il programma funziona benissimo con i txt ma non con altri formati, vi spiego come avviene implementazione:
Leggo il file lo inserisco in uno stream di dati leggo un byte alla volta e verifico le ricorrenze, poi utilizzo il metodo di huffman per dare ai caratteri più ricorrenti una codifica di pochi bit.
La mia domanda è quando inserisco un file immagine nello stream sono sempre byte è posso trattarli come dei char?

MItaly
28-06-2007, 18:36
Originariamente inviato da zeno3083
La mia domanda è quando inserisco un file immagine nello stream sono sempre byte è posso trattarli come dei char?
Certamente.

zeno3083
28-06-2007, 19:21
Allora non riesco a capireperchè non va con formati diversi dal txt.

MItaly
28-06-2007, 20:06
Come apri e leggi il file?

zeno3083
28-06-2007, 23:20
lo metto su uno stream di input per leggere, e uno di output per scrivere.

MItaly
29-06-2007, 13:09
Posta il codice.

zeno3083
29-06-2007, 15:43
Ti posto il programma di compressione



#include <iostream>

#include <fstream>

#include <string>

#include <map>

#include <vector>

#include <queue>

#include "TreeHuffman.h"







int main (int argc, char * const argv[]) {

char nomefile[30];

char nomefilescrittura[30]; //nome del file

ifstream lettura;

ifstream lettura2; //creo un oggetto ifstream(lettura dei dati da un file sequenziale)

ofstream scrittura;

ofstream structfile;



map<const char, int > freqMap; //map(chiave,valore)

map<const char, int > ::iterator it; //iteratore map

priority_queue< TreeHuffman, vector<TreeHuffman>, greater<TreeHuffman> > q;//coda di priorità(elemento,chiave,???)

TreeHuffman *hNode;//nodo



char ch;



cout << " Inserisci il nome del File da comprimere. \n";

cin >> nomefile;

lettura.open(nomefile);//inserisce il file nello stream

cout << "Inserisci il nome del nuovo file compresso. \n";

cin >> nomefilescrittura;



if (lettura.fail()){ //verfica se c'è un errore nell'apertura del file

cout << "Errore nell'apertura del file \n";

exit(1);

}



lettura.get(ch);//legge un byte alla volta

while( !lettura.eof()) { //verifica se siamo alla fine del file

it = freqMap.find(ch);//cerca il carattere e restituisce iteratore

if (it == freqMap.end())//verifica che non siamo alla fine della mappa

freqMap[ch] = 1;

else

freqMap[ch]++;

lettura.get(ch);

}



it = freqMap.begin();

structfile.open("map.dat");

//copia i valore della map nella coda di priorità

while(it != freqMap.end()){

hNode = new TreeHuffman(it->first, it->second);//inizializzo l'oggetto Nodo

q.push(*hNode);//prende il puntatore al nodo e lo inserisce nella coda di priorità cosi da creare una coda di alberi

it++;//va all'elemento successivo

}

/*Prendo gli alberi con frequenza minore li sommo e creo il nuovo albero

lo inserisco di nuovo nella coda di priorità, prendo di nuovo i due alberi

con frequenza minore li sommo di nuovo e procedo cosi fin quando non mi rimane

un solo elemeto nella coda di priorità che è il puntatore all'albero di huffmann*/

while ( q.size() > 1 ) {

TreeHuffman *left = new TreeHuffman( q.top() );

q.pop();

TreeHuffman *right = new TreeHuffman( q.top() );

q.pop();

q.push( TreeHuffman( left, right ) );

}

/*Ora che l'albero è stato creato non mi resta che crearmi il mio file compresso*/

lettura2.open(nomefile);

lettura2.get(ch);

scrittura.open(nomefilescrittura);

*hNode=q.top();

char control=ch;

while( !lettura2.eof()) { //verifica se siamo alla fine del file

string codice=hNode->trovacodifica(ch);

scrittura<<codice;

lettura2.get(ch);

}

it=freqMap.begin();

while(it!=freqMap.end()){

ch=it->first;

string codice=hNode->trovacodifica(ch);

structfile<<(int)ch<<'§'<<codice<<'§';

cout<<"carattere "<<(int)ch<<"codifica "<<codice<<endl;

it++;

}







scrittura.close();

return 0;



}


e qui quello di decompressione


#include <iostream>

#include <fstream>

#include <string>

#include <map>

#include <vector>

#include <queue>

#include "TreeHuffman.h"









int main (int argc, char * const argv[]) {

char nomefile[30];

char nomefilescrittura[30]; //nome del file

ifstream recupero; //creo un oggetto ifstream(lettura dei dati da un file sequenziale)

ifstream lettura;

ofstream scrittura;



map<const string, char > freqMap; //map(chiave,valore)

map<const string, char > ::iterator it; //iteratore map



recupero.open("map.dat");



cout << " Inserisci il nome del File da decomprimere. \n";

cin >> nomefile;

cout << "Inserisci il nome del nuovo file compresso. \n";

cin >> nomefilescrittura;

lettura.open(nomefile);//inserisce il file nello stream

scrittura.open(nomefilescrittura);



char ch;

char x;

string ch1="";

string x1="";

//scrittura.open(nomefilescrittura);



while( !recupero.eof()) { //verifica se siamo alla fine del file

recupero.get(x);

while(x!='§'){

x1+=x;

recupero.get(x);

}

if(x1=="")

x1=x;

recupero.get(ch);

while(ch!='§'){

ch1+=ch;

recupero.get(ch);

}

if(ch1=="")

ch1=ch;

int y=atoi(x1.c_str());

freqMap[ch1]=(char)y;

ch1="";

x1="";

}

lettura.get(ch);

x1=ch;

it=freqMap.begin();

while(!lettura.eof()){

while(freqMap.find(x1)==freqMap.end()){

lettura.get(ch);

x1+=ch;

}

scrittura<<freqMap[x1];

lettura.get(ch);

x1=ch;

}



scrittura.close();

return 0;



}

MItaly
29-06-2007, 20:25
Nella parte di scrittura del file compresso prova a sostituire


scrittura<<codice;

con


scrittura.put(codice);
.

zeno3083
30-06-2007, 10:24
Scusa non vorrei sbagliarmi ma ".put" mi permette di scrivere caratteri mentre "codice" è una stringa, potrei utilizzare ".write", però non capisco dove sta la differenza.

MItaly
30-06-2007, 11:14
Scusa, hai più che ragione. Tuttavia mi era venuto in mente che poteva darsi che lo stream di output, usando i metodi per l'output formattato, effettuasse qualche genere di traduzione di caratteri indesiderata. Forse il problema invece sta nello stream di input... :master:

Loading