void encodeNode(HuffmanNode* node, obitstream& output) { if (node->isLeaf()) { output.writeBit(1); output.put(node->character); } else { output.writeBit(0); encodeNode(node->zero, output); encodeNode(node->one, output); } }
void encodeData(istream& input, const Map<int, string>& encodingMap, obitstream& output) { rewindStream(input); char c; while ((c = input.get()) != -1) { string s = encodingMap.get(c); for (int i = 0; i < s.length(); i++) output.writeBit(s[i] - '0'); } }
void addBiggerThanByte(map<int, int> freqTable, obitstream& output){ output.put('{'); for(map<int, int>::iterator it = freqTable.begin(); it != freqTable.end(); ++it){ int first = it->first; int second = it->second; string firstString = integerToString(first); while(firstString.size() > 0){ char tempFirst = firstString.front(); output.put(tempFirst); firstString.erase(firstString.begin()); } output.put(':'); string secondString = integerToString(second); while(secondString.size() > 0){ char tempSecond = secondString.front(); output.put(tempSecond); secondString.erase(secondString.begin()); } //Iterationen innan slutet för utskrift av kommatecken if(it != --freqTable.end()){ output.put(','); output.put(' '); } } output.put('}'); }
//Komprimerar headern genom att se om det finns tal i frekvenstabellen som är större än en byte (255) //Om så är fallet läggs den in i ouputen på samma sätt med en 1 först i filen för att markera det //Annars sätts 0 först i filen samt storleken på frekvenstabellen, alla karaktärer och frekvenser //Skrivs till ouput med .put() //Exempel för example.txt 08322973983991 EOF lägg inte in eftersom den är större än en byte void compress(istream& input, obitstream& output) { map<int, int> freqTable = buildFrequencyTable(input); HuffmanNode* priorityTree = buildEncodingTree(freqTable); map<int, string> encodingMap = buildEncodingMap(priorityTree); bool containsBiggerThanByte = false; vector<char> vectorForFreqTable; for(map<int,int>::iterator it = freqTable.begin(); it != freqTable.end(); ++it){ if(it->first == PSEUDO_EOF){ //Lägg inte till PSEUDO_EOF än break; } else if(!(it->first > PSEUDO_EOF) && !(it->second > PSEUDO_EOF)){ //Om frekvensen och karaktären tar mindre än en byte vectorForFreqTable.push_back(it->first); vectorForFreqTable.push_back(it->second); }else{ containsBiggerThanByte = true; break; } } if(containsBiggerThanByte){ output.put('1'); //Tal större än en byte finns addBiggerThanByte(freqTable,output); }else{ output.put('0'); //Inget tal större än en byte int freqTableSize = vectorForFreqTable.size(); output.put(freqTableSize); //tabellens storlek kommer användas för inmatningen for(int i = 0; i < freqTableSize; ++i){ int tempNum = vectorForFreqTable.at(i); output.put(tempNum); } } input.clear(); input.seekg(0, ios::beg); encodeData(input, encodingMap, output); freeTree(priorityTree); }
void encodeData(istream& input, const map<int, string> &encodingMap, obitstream& output) { while(input){ //Ta ut första byten int tempByte = input.get(); string tempCode; //Hämta ut bitsekvensen som hör till bokstaven if(tempByte == -1){ tempCode = encodingMap.at(PSEUDO_EOF); }else{ tempCode = encodingMap.at(tempByte); } while(tempCode.size() > 0){ //Ta ut första biten från sekvensen int tempBit = stringToInteger(string(1,tempCode.front())); //Skriv ut den till output output.writeBit(tempBit); //Ta bort den från sekvensen tempCode.erase(tempCode.begin()); } } }
void writeCode(string& code, obitstream& output) { for (size_t i = 0; i < code.size(); ++i) { (code[i] == '1') ? output.writeBit(1) : output.writeBit(0); } }
//Note: because there are 256+2(EOF_SIGN, INNER_SIGN) cases for a node, it takes 9 bits to store a node //below are helper function to handle 9 bits void output_9bit(obitstream & os, int x) { for (int i = 8; i >= 0; --i){ os.put_bit(x & (1 << i)); } }