Octane v1.01.20 - The Open Compression Toolkit for C++ http://octane.sourceforge.net/
Homepage | Main | Modules | Class Hierarchy | Compound List | File List | Compound Members | Related Pages

coders/coder_huffman/huffmancoder.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 //---------------------------------------------------------------------------
00010 
00011 //---------------------------------------------------------------------------
00012 // application includes
00013 #include "huffmancoder.hpp"
00014 // system includes
00015 #include <assert.h>
00016 //---------------------------------------------------------------------------
00017 
00018 
00019 
00020 
00021 
00022 
00023 //---------------------------------------------------------------------------
00024 // Functions from OCTANE PUBLIC API
00025 void HuffmanCoder::ShowDebuggingInfo()
00026 {
00027         // show bit strings
00028         ShowBitStrings();
00029         // show memory used by priority queue
00030         std::cout << " Memory used by Huffman Coder:         " << GetMemoryUsed() << " bytes.\n";
00031 }
00032 
00033 unsigned int HuffmanCoder::GetMemoryUsed()
00034 {
00035         // approximate memory usage of the priority queue
00036         unsigned int memoryused=0;
00037         memoryused+=sizeof(symbolsetpq);
00038         if (symbolsetpq.size()!=0)
00039                 memoryused+=(symbolsetpq.top())->get_memoryused();
00040         memoryused+=sizeof(symbolvector);
00041         if (symbolvector.size()!=0)
00042                 memoryused+=(unsigned int)(symbolvector.capacity()*sizeof(HuffNode_Leaf*));
00043 
00044         return memoryused;
00045 }
00046 //---------------------------------------------------------------------------
00047 
00048 
00049 
00050 
00051 
00052 //---------------------------------------------------------------------------
00053 // Functions from CODER PUBLIC API
00054 bool HuffmanCoder::WriteSymbolBits(int symbolnum,bitwriter &bw)
00055 {
00056         // write bits for symbol number - this is easy because we've precomputed the bitvectors for every symbol
00057         assert(symbolnum<(int)(symbolvector.size()));
00058         return symbolvector[symbolnum]->AddBitsToBitWriter(bw);
00059 }
00060 
00061 bool HuffmanCoder::DecodeSymbolFromInput(int &symbolnum, bitreader &br)
00062 {
00063         // decode a symbol from the input, and set symbolnum to symbol number
00064         // return false on no symbols left in stream
00065         HuffNode* nodep;
00066         bool bitvalue;
00067         
00068         // now walk through the input bits      
00069         nodep = symbolsetpq.top();
00070         while (!br.empty())
00071                 {
00072                 // grab a bit
00073                 bitvalue = br.get_bit();
00074 
00075                 // traverse down tree
00076                 if (bitvalue==false)
00077                         nodep=nodep->get_child0();
00078                 else
00079                         nodep=nodep->get_child1();
00080                 if (nodep==NULL)
00081                         {
00082                         cerr << "ERROR: Internal error traversing huffman tree in huffmancoder.cpp, in HuffmanCoder::DecodeSymbolFromInput()." << endl;
00083                         break;
00084                         }
00085 
00086                 // if its leaf we got our symbol
00087                 if (nodep->isleaf())
00088                         {
00089                         // we hit a leaf, so this is our decoded symbol - return its number
00090                         symbolnum=((HuffNode_Leaf*)nodep)->get_symbolid();
00091                         return true;
00092                         }
00093                 else
00094                         {
00095                         // just a middle node, so keep traversing
00096                         }
00097                 }
00098         
00099         // no symbols to read
00100         return false;
00101 }
00102 //---------------------------------------------------------------------------
00103 
00104 
00105 
00106 
00107         
00108 //---------------------------------------------------------------------------
00109 // Helpers
00110 void  HuffmanCoder::ShowBitStrings()
00111 {
00112         // show bitstrings for debugging
00113         string bitset_string;
00114         THuffmanNodeWeight symbolweight;
00115         int symbolid;
00116 
00117         // show the dictionary sorted alphabetically
00118         if (symbolsetpq.size()>0)
00119                 {
00120                 cout << "SymbolSet Huffman Codes ("<<(unsigned int)(symbolvector.size())<<" entries)\n";
00121                 cout << " " << setiosflags(ios::left) << setw(10) << "symbolid" << " " << setw(16) << "weight" << " " << "bitstring\n";
00122                 cout << " " << setiosflags(ios::left) << setw(10) << "--------" << " " << setw(16) << "------" << " " << "----------\n";
00123                 for (symbolvector_pos=symbolvector.begin();symbolvector_pos!=symbolvector.end();++symbolvector_pos)
00124                         {
00125                         symbolid=(*symbolvector_pos)->get_symbolid();
00126                         symbolweight = (*symbolvector_pos)->get_weight();
00127                         bitset_string=(*symbolvector_pos)->get_bitcode_string();
00128                         cout << " " << setiosflags(ios::left) << setw(10) << symbolid << " " << setw(16) << symbolweight << " " << bitset_string <<"\n";
00129                         }
00130                 cout << "\n";
00131                 }
00132 }
00133 //---------------------------------------------------------------------------
00134 
00135 
00136 
00137 
00138 //---------------------------------------------------------------------------
00139 // Building and managing the priority queue (huffman tree)
00140 
00141 bool HuffmanCoder::BuildUpdateHuffmanTreeAndBitcodes(OctaneModeler *modelerp)
00142 {
00143         // the SymbolSet is ready to be processed into a priority queue and for us to generate bitcodes
00144         // this can safely be called multiple times, so you can engage in a series
00145         // of pruning symbol set, generating bitcodes, and repeating the process to reduce bitcode lengths
00146         HuffNode *topmostp;
00147         HuffNode_Leaf *symbolleafp;
00148 
00149         // Free any priority queue
00150         FreeSymbols();
00151 
00152         // Loop through all symbols in modeler and add them as new leaf symbols in a priority queue and fast lookup vector
00153         int symbolcount=modelerp->GetSymbolCount();
00154         for (int index=0;index<symbolcount;++index)
00155                 {
00156                 // create symbol as new leaf to priority queue, recording its index in vector with a two-way link
00157                 symbolleafp = new HuffNode_Leaf(index,modelerp->GetWeightVectorItem(index));
00158                 // add symbol as leaf in priority queue
00159                 symbolsetpq.push(symbolleafp);
00160                 // add symbol leaf to vector (note this will never change, its for fast indexed lookup since pq nodes move around)
00161                 symbolvector.push_back(symbolleafp);
00162                 }
00163 
00164         // Build Priority Queue.  This loop removes the two smallest HuffNodes from the queue.
00165         //  It creates a new internal HuffNode that has those two HuffNodes as children. The new internal HuffNode is then inserted into the priority queue.
00166         //  When there is only one HuffNode in the priority queue, the tree is complete.
00167         while ( symbolsetpq.size() > 1 )
00168                 {
00169                 // pop topmost but save it so we can add it as left child
00170                 topmostp=symbolsetpq.top();
00171                 HuffNode *child0 = topmostp;
00172                 symbolsetpq.pop();
00173                 // pop next topmost but save it so we can add it as left child
00174                 topmostp=symbolsetpq.top();
00175                 HuffNode *child1 = topmostp;
00176                 symbolsetpq.pop();
00177                 // now make a new parent node with these two children
00178                 symbolsetpq.push(new HuffNode_Middle(child0,child1));
00179                 }
00180 
00181         // Traverse_buildbitcodes tree and build bit codes (create a bitset big enough to hold largest code length)
00182         TraverseHuffmanTreeBuildBitcodes();
00183 
00184         // now a test, show debugging info
00185         // ShowDebuggingInfo();
00186 
00187         // return success
00188         return true;
00189 }
00190 
00191 
00192 void HuffmanCoder::TraverseHuffmanTreeBuildBitcodes()
00193         {
00194         // begin recursive traverse of the huffman tree, used for building bitcodes
00195         bitset<DEF_HUFFMANPQ_MAXFUNCBITS> current_bitset;
00196         (symbolsetpq.top())->traverse_buildbitcodes(current_bitset,0);
00197         }
00198 
00199 
00200 void HuffmanCoder::FreeSymbols()
00201 {
00202         // free the priority queue
00203         HuffNode* topmostp;
00204         while ( symbolsetpq.size() >= 1 )
00205                 {
00206                 // grab topmost and delete all of its children, then it (there really should be only 1 at top after building huffman tree)
00207                 topmostp=symbolsetpq.top();
00208                 // note we tell the node to delete itself and all its children
00209                 topmostp->recursive_freechildren();
00210                 delete topmostp;
00211                 // now pop it off
00212                 symbolsetpq.pop();
00213                 }
00214         // now free the symbol vector
00215         symbolvector.clear();
00216 }
00217 //---------------------------------------------------------------------------
00218 
 
Generated on 20 May 2004 by doxygen 1.3.3