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