Home | History | Annotate | Download | only in utils
      1 // Copyright 2012 Google Inc. All Rights Reserved.
      2 //
      3 // This code is licensed under the same terms as WebM:
      4 //  Software License Agreement:  http://www.webmproject.org/license/software/
      5 //  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
      6 // -----------------------------------------------------------------------------
      7 //
      8 // Utilities for building and looking up Huffman trees.
      9 //
     10 // Author: Urvang Joshi (urvang (at) google.com)
     11 
     12 #include <assert.h>
     13 #include <stdlib.h>
     14 #include "./huffman.h"
     15 #include "../utils/utils.h"
     16 #include "webp/format_constants.h"
     17 
     18 #if defined(__cplusplus) || defined(c_plusplus)
     19 extern "C" {
     20 #endif
     21 
     22 #define NON_EXISTENT_SYMBOL (-1)
     23 
     24 static void TreeNodeInit(HuffmanTreeNode* const node) {
     25   node->children_ = -1;   // means: 'unassigned so far'
     26 }
     27 
     28 static int NodeIsEmpty(const HuffmanTreeNode* const node) {
     29   return (node->children_ < 0);
     30 }
     31 
     32 static int IsFull(const HuffmanTree* const tree) {
     33   return (tree->num_nodes_ == tree->max_nodes_);
     34 }
     35 
     36 static void AssignChildren(HuffmanTree* const tree,
     37                            HuffmanTreeNode* const node) {
     38   HuffmanTreeNode* const children = tree->root_ + tree->num_nodes_;
     39   node->children_ = (int)(children - node);
     40   assert(children - node == (int)(children - node));
     41   tree->num_nodes_ += 2;
     42   TreeNodeInit(children + 0);
     43   TreeNodeInit(children + 1);
     44 }
     45 
     46 static int TreeInit(HuffmanTree* const tree, int num_leaves) {
     47   assert(tree != NULL);
     48   if (num_leaves == 0) return 0;
     49   // We allocate maximum possible nodes in the tree at once.
     50   // Note that a Huffman tree is a full binary tree; and in a full binary tree
     51   // with L leaves, the total number of nodes N = 2 * L - 1.
     52   tree->max_nodes_ = 2 * num_leaves - 1;
     53   tree->root_ = (HuffmanTreeNode*)WebPSafeMalloc((uint64_t)tree->max_nodes_,
     54                                                  sizeof(*tree->root_));
     55   if (tree->root_ == NULL) return 0;
     56   TreeNodeInit(tree->root_);  // Initialize root.
     57   tree->num_nodes_ = 1;
     58   return 1;
     59 }
     60 
     61 void HuffmanTreeRelease(HuffmanTree* const tree) {
     62   if (tree != NULL) {
     63     free(tree->root_);
     64     tree->root_ = NULL;
     65     tree->max_nodes_ = 0;
     66     tree->num_nodes_ = 0;
     67   }
     68 }
     69 
     70 int HuffmanCodeLengthsToCodes(const int* const code_lengths,
     71                               int code_lengths_size, int* const huff_codes) {
     72   int symbol;
     73   int code_len;
     74   int code_length_hist[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
     75   int curr_code;
     76   int next_codes[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
     77   int max_code_length = 0;
     78 
     79   assert(code_lengths != NULL);
     80   assert(code_lengths_size > 0);
     81   assert(huff_codes != NULL);
     82 
     83   // Calculate max code length.
     84   for (symbol = 0; symbol < code_lengths_size; ++symbol) {
     85     if (code_lengths[symbol] > max_code_length) {
     86       max_code_length = code_lengths[symbol];
     87     }
     88   }
     89   if (max_code_length > MAX_ALLOWED_CODE_LENGTH) return 0;
     90 
     91   // Calculate code length histogram.
     92   for (symbol = 0; symbol < code_lengths_size; ++symbol) {
     93     ++code_length_hist[code_lengths[symbol]];
     94   }
     95   code_length_hist[0] = 0;
     96 
     97   // Calculate the initial values of 'next_codes' for each code length.
     98   // next_codes[code_len] denotes the code to be assigned to the next symbol
     99   // of code length 'code_len'.
    100   curr_code = 0;
    101   next_codes[0] = -1;  // Unused, as code length = 0 implies code doesn't exist.
    102   for (code_len = 1; code_len <= max_code_length; ++code_len) {
    103     curr_code = (curr_code + code_length_hist[code_len - 1]) << 1;
    104     next_codes[code_len] = curr_code;
    105   }
    106 
    107   // Get symbols.
    108   for (symbol = 0; symbol < code_lengths_size; ++symbol) {
    109     if (code_lengths[symbol] > 0) {
    110       huff_codes[symbol] = next_codes[code_lengths[symbol]]++;
    111     } else {
    112       huff_codes[symbol] = NON_EXISTENT_SYMBOL;
    113     }
    114   }
    115   return 1;
    116 }
    117 
    118 static int TreeAddSymbol(HuffmanTree* const tree,
    119                          int symbol, int code, int code_length) {
    120   HuffmanTreeNode* node = tree->root_;
    121   const HuffmanTreeNode* const max_node = tree->root_ + tree->max_nodes_;
    122   while (code_length-- > 0) {
    123     if (node >= max_node) {
    124       return 0;
    125     }
    126     if (NodeIsEmpty(node)) {
    127       if (IsFull(tree)) return 0;    // error: too many symbols.
    128       AssignChildren(tree, node);
    129     } else if (HuffmanTreeNodeIsLeaf(node)) {
    130       return 0;  // leaf is already occupied.
    131     }
    132     node += node->children_ + ((code >> code_length) & 1);
    133   }
    134   if (NodeIsEmpty(node)) {
    135     node->children_ = 0;      // turn newly created node into a leaf.
    136   } else if (!HuffmanTreeNodeIsLeaf(node)) {
    137     return 0;   // trying to assign a symbol to already used code.
    138   }
    139   node->symbol_ = symbol;  // Add symbol in this node.
    140   return 1;
    141 }
    142 
    143 int HuffmanTreeBuildImplicit(HuffmanTree* const tree,
    144                              const int* const code_lengths,
    145                              int code_lengths_size) {
    146   int symbol;
    147   int num_symbols = 0;
    148   int root_symbol = 0;
    149 
    150   assert(tree != NULL);
    151   assert(code_lengths != NULL);
    152 
    153   // Find out number of symbols and the root symbol.
    154   for (symbol = 0; symbol < code_lengths_size; ++symbol) {
    155     if (code_lengths[symbol] > 0) {
    156       // Note: code length = 0 indicates non-existent symbol.
    157       ++num_symbols;
    158       root_symbol = symbol;
    159     }
    160   }
    161 
    162   // Initialize the tree. Will fail for num_symbols = 0
    163   if (!TreeInit(tree, num_symbols)) return 0;
    164 
    165   // Build tree.
    166   if (num_symbols == 1) {  // Trivial case.
    167     const int max_symbol = code_lengths_size;
    168     if (root_symbol < 0 || root_symbol >= max_symbol) {
    169       HuffmanTreeRelease(tree);
    170       return 0;
    171     }
    172     return TreeAddSymbol(tree, root_symbol, 0, 0);
    173   } else {  // Normal case.
    174     int ok = 0;
    175 
    176     // Get Huffman codes from the code lengths.
    177     int* const codes =
    178         (int*)WebPSafeMalloc((uint64_t)code_lengths_size, sizeof(*codes));
    179     if (codes == NULL) goto End;
    180 
    181     if (!HuffmanCodeLengthsToCodes(code_lengths, code_lengths_size, codes)) {
    182       goto End;
    183     }
    184 
    185     // Add symbols one-by-one.
    186     for (symbol = 0; symbol < code_lengths_size; ++symbol) {
    187       if (code_lengths[symbol] > 0) {
    188         if (!TreeAddSymbol(tree, symbol, codes[symbol], code_lengths[symbol])) {
    189           goto End;
    190         }
    191       }
    192     }
    193     ok = 1;
    194  End:
    195     free(codes);
    196     ok = ok && IsFull(tree);
    197     if (!ok) HuffmanTreeRelease(tree);
    198     return ok;
    199   }
    200 }
    201 
    202 int HuffmanTreeBuildExplicit(HuffmanTree* const tree,
    203                              const int* const code_lengths,
    204                              const int* const codes,
    205                              const int* const symbols, int max_symbol,
    206                              int num_symbols) {
    207   int ok = 0;
    208   int i;
    209 
    210   assert(tree != NULL);
    211   assert(code_lengths != NULL);
    212   assert(codes != NULL);
    213   assert(symbols != NULL);
    214 
    215   // Initialize the tree. Will fail if num_symbols = 0.
    216   if (!TreeInit(tree, num_symbols)) return 0;
    217 
    218   // Add symbols one-by-one.
    219   for (i = 0; i < num_symbols; ++i) {
    220     if (codes[i] != NON_EXISTENT_SYMBOL) {
    221       if (symbols[i] < 0 || symbols[i] >= max_symbol) {
    222         goto End;
    223       }
    224       if (!TreeAddSymbol(tree, symbols[i], codes[i], code_lengths[i])) {
    225         goto End;
    226       }
    227     }
    228   }
    229   ok = 1;
    230  End:
    231   ok = ok && IsFull(tree);
    232   if (!ok) HuffmanTreeRelease(tree);
    233   return ok;
    234 }
    235 
    236 #if defined(__cplusplus) || defined(c_plusplus)
    237 }    // extern "C"
    238 #endif
    239