| /* Copyright 2010 Google Inc. All Rights Reserved. | |
| Distributed under MIT license. | |
| See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | |
| */ | |
| /* Entropy encoding (Huffman) utilities. */ | |
| #ifndef BROTLI_ENC_ENTROPY_ENCODE_H_ | |
| #define BROTLI_ENC_ENTROPY_ENCODE_H_ | |
| #include "../common/types.h" | |
| #include "./port.h" | |
| #if defined(__cplusplus) || defined(c_plusplus) | |
| extern "C" { | |
| #endif | |
| /* A node of a Huffman tree. */ | |
| typedef struct HuffmanTree { | |
| uint32_t total_count_; | |
| int16_t index_left_; | |
| int16_t index_right_or_value_; | |
| } HuffmanTree; | |
| static BROTLI_INLINE void InitHuffmanTree(HuffmanTree* self, uint32_t count, | |
| int16_t left, int16_t right) { | |
| self->total_count_ = count; | |
| self->index_left_ = left; | |
| self->index_right_or_value_ = right; | |
| } | |
| /* Returns 1 is assignment of depths succeded, otherwise 0. */ | |
| BROTLI_INTERNAL BROTLI_BOOL BrotliSetDepth( | |
| int p, HuffmanTree* pool, uint8_t* depth, int max_depth); | |
| /* This function will create a Huffman tree. | |
| The (data,length) contains the population counts. | |
| The tree_limit is the maximum bit depth of the Huffman codes. | |
| The depth contains the tree, i.e., how many bits are used for | |
| the symbol. | |
| The actual Huffman tree is constructed in the tree[] array, which has to | |
| be at least 2 * length + 1 long. | |
| See http://en.wikipedia.org/wiki/Huffman_coding */ | |
| BROTLI_INTERNAL void BrotliCreateHuffmanTree(const uint32_t *data, | |
| const size_t length, | |
| const int tree_limit, | |
| HuffmanTree* tree, | |
| uint8_t *depth); | |
| /* Change the population counts in a way that the consequent | |
| Huffman tree compression, especially its rle-part will be more | |
| likely to compress this data more efficiently. | |
| length contains the size of the histogram. | |
| counts contains the population counts. | |
| good_for_rle is a buffer of at least length size */ | |
| BROTLI_INTERNAL void BrotliOptimizeHuffmanCountsForRle( | |
| size_t length, uint32_t* counts, uint8_t* good_for_rle); | |
| /* Write a Huffman tree from bit depths into the bitstream representation | |
| of a Huffman tree. The generated Huffman tree is to be compressed once | |
| more using a Huffman tree */ | |
| BROTLI_INTERNAL void BrotliWriteHuffmanTree(const uint8_t* depth, | |
| size_t num, | |
| size_t* tree_size, | |
| uint8_t* tree, | |
| uint8_t* extra_bits_data); | |
| /* Get the actual bit values for a tree of bit depths. */ | |
| BROTLI_INTERNAL void BrotliConvertBitDepthsToSymbols(const uint8_t *depth, | |
| size_t len, | |
| uint16_t *bits); | |
| /* Input size optimized Shell sort. */ | |
| typedef BROTLI_BOOL (*HuffmanTreeComparator)( | |
| const HuffmanTree*, const HuffmanTree*); | |
| static BROTLI_INLINE void SortHuffmanTreeItems(HuffmanTree* items, | |
| const size_t n, HuffmanTreeComparator comparator) { | |
| static const size_t gaps[] = {132, 57, 23, 10, 4, 1}; | |
| if (n < 13) { | |
| /* Insertion sort. */ | |
| size_t i; | |
| for (i = 1; i < n; ++i) { | |
| HuffmanTree tmp = items[i]; | |
| size_t k = i; | |
| size_t j = i - 1; | |
| while (comparator(&tmp, &items[j])) { | |
| items[k] = items[j]; | |
| k = j; | |
| if (!j--) break; | |
| } | |
| items[k] = tmp; | |
| } | |
| return; | |
| } else { | |
| /* Shell sort. */ | |
| int g = n < 57 ? 2 : 0; | |
| for (; g < 6; ++g) { | |
| size_t gap = gaps[g]; | |
| size_t i; | |
| for (i = gap; i < n; ++i) { | |
| size_t j = i; | |
| HuffmanTree tmp = items[i]; | |
| for (; j >= gap && comparator(&tmp, &items[j - gap]); j -= gap) { | |
| items[j] = items[j - gap]; | |
| } | |
| items[j] = tmp; | |
| } | |
| } | |
| } | |
| } | |
| #if defined(__cplusplus) || defined(c_plusplus) | |
| } /* extern "C" */ | |
| #endif | |
| #endif /* BROTLI_ENC_ENTROPY_ENCODE_H_ */ |