OLD | NEW |
1 // Copyright 2011 Google Inc. All Rights Reserved. | 1 // Copyright 2011 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // This code is licensed under the same terms as WebM: | 3 // This code is licensed under the same terms as WebM: |
4 // Software License Agreement: http://www.webmproject.org/license/software/ | 4 // Software License Agreement: http://www.webmproject.org/license/software/ |
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ | 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ |
6 // ----------------------------------------------------------------------------- | 6 // ----------------------------------------------------------------------------- |
7 // | 7 // |
8 // Author: Jyrki Alakuijala (jyrki@google.com) | 8 // Author: Jyrki Alakuijala (jyrki@google.com) |
9 // | 9 // |
10 // Entropy encoding (Huffman) for webp lossless. | 10 // Entropy encoding (Huffman) for webp lossless. |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 // A comparer function for two Huffman trees: sorts first by 'total count' | 131 // A comparer function for two Huffman trees: sorts first by 'total count' |
132 // (more comes first), and then by 'value' (more comes first). | 132 // (more comes first), and then by 'value' (more comes first). |
133 static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { | 133 static int CompareHuffmanTrees(const void* ptr1, const void* ptr2) { |
134 const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; | 134 const HuffmanTree* const t1 = (const HuffmanTree*)ptr1; |
135 const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; | 135 const HuffmanTree* const t2 = (const HuffmanTree*)ptr2; |
136 if (t1->total_count_ > t2->total_count_) { | 136 if (t1->total_count_ > t2->total_count_) { |
137 return -1; | 137 return -1; |
138 } else if (t1->total_count_ < t2->total_count_) { | 138 } else if (t1->total_count_ < t2->total_count_) { |
139 return 1; | 139 return 1; |
140 } else { | 140 } else { |
141 if (t1->value_ < t2->value_) { | 141 assert(t1->value_ != t2->value_); |
142 return -1; | 142 return (t1->value_ < t2->value_) ? -1 : 1; |
143 } | |
144 if (t1->value_ > t2->value_) { | |
145 return 1; | |
146 } | |
147 return 0; | |
148 } | 143 } |
149 } | 144 } |
150 | 145 |
151 static void SetBitDepths(const HuffmanTree* const tree, | 146 static void SetBitDepths(const HuffmanTree* const tree, |
152 const HuffmanTree* const pool, | 147 const HuffmanTree* const pool, |
153 uint8_t* const bit_depths, int level) { | 148 uint8_t* const bit_depths, int level) { |
154 if (tree->pool_index_left_ >= 0) { | 149 if (tree->pool_index_left_ >= 0) { |
155 SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); | 150 SetBitDepths(&pool[tree->pool_index_left_], pool, bit_depths, level + 1); |
156 SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); | 151 SetBitDepths(&pool[tree->pool_index_right_], pool, bit_depths, level + 1); |
157 } else { | 152 } else { |
(...skipping 28 matching lines...) Expand all Loading... |
186 HuffmanTree* tree; | 181 HuffmanTree* tree; |
187 int tree_size_orig = 0; | 182 int tree_size_orig = 0; |
188 int i; | 183 int i; |
189 | 184 |
190 for (i = 0; i < histogram_size; ++i) { | 185 for (i = 0; i < histogram_size; ++i) { |
191 if (histogram[i] != 0) { | 186 if (histogram[i] != 0) { |
192 ++tree_size_orig; | 187 ++tree_size_orig; |
193 } | 188 } |
194 } | 189 } |
195 | 190 |
| 191 if (tree_size_orig == 0) { // pretty optimal already! |
| 192 return 1; |
| 193 } |
| 194 |
196 // 3 * tree_size is enough to cover all the nodes representing a | 195 // 3 * tree_size is enough to cover all the nodes representing a |
197 // population and all the inserted nodes combining two existing nodes. | 196 // population and all the inserted nodes combining two existing nodes. |
198 // The tree pool needs 2 * (tree_size_orig - 1) entities, and the | 197 // The tree pool needs 2 * (tree_size_orig - 1) entities, and the |
199 // tree needs exactly tree_size_orig entities. | 198 // tree needs exactly tree_size_orig entities. |
200 tree = (HuffmanTree*)WebPSafeMalloc(3ULL * tree_size_orig, sizeof(*tree)); | 199 tree = (HuffmanTree*)WebPSafeMalloc(3ULL * tree_size_orig, sizeof(*tree)); |
201 if (tree == NULL) return 0; | 200 if (tree == NULL) return 0; |
202 tree_pool = tree + tree_size_orig; | 201 tree_pool = tree + tree_size_orig; |
203 | 202 |
204 // For block sizes with less than 64k symbols we never need to do a | 203 // For block sizes with less than 64k symbols we never need to do a |
205 // second iteration of this loop. | 204 // second iteration of this loop. |
(...skipping 21 matching lines...) Expand all Loading... |
227 // Build the Huffman tree. | 226 // Build the Huffman tree. |
228 qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); | 227 qsort(tree, tree_size, sizeof(*tree), CompareHuffmanTrees); |
229 | 228 |
230 if (tree_size > 1) { // Normal case. | 229 if (tree_size > 1) { // Normal case. |
231 int tree_pool_size = 0; | 230 int tree_pool_size = 0; |
232 while (tree_size > 1) { // Finish when we have only one root. | 231 while (tree_size > 1) { // Finish when we have only one root. |
233 int count; | 232 int count; |
234 tree_pool[tree_pool_size++] = tree[tree_size - 1]; | 233 tree_pool[tree_pool_size++] = tree[tree_size - 1]; |
235 tree_pool[tree_pool_size++] = tree[tree_size - 2]; | 234 tree_pool[tree_pool_size++] = tree[tree_size - 2]; |
236 count = tree_pool[tree_pool_size - 1].total_count_ + | 235 count = tree_pool[tree_pool_size - 1].total_count_ + |
237 tree_pool[tree_pool_size - 2].total_count_; | 236 tree_pool[tree_pool_size - 2].total_count_; |
238 tree_size -= 2; | 237 tree_size -= 2; |
239 { | 238 { |
240 // Search for the insertion point. | 239 // Search for the insertion point. |
241 int k; | 240 int k; |
242 for (k = 0; k < tree_size; ++k) { | 241 for (k = 0; k < tree_size; ++k) { |
243 if (tree[k].total_count_ <= count) { | 242 if (tree[k].total_count_ <= count) { |
244 break; | 243 break; |
245 } | 244 } |
246 } | 245 } |
247 memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); | 246 memmove(tree + (k + 1), tree + k, (tree_size - k) * sizeof(*tree)); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 return 0; | 429 return 0; |
431 } | 430 } |
432 if (!GenerateOptimalTree(histogram, num_symbols, | 431 if (!GenerateOptimalTree(histogram, num_symbols, |
433 tree_depth_limit, tree->code_lengths)) { | 432 tree_depth_limit, tree->code_lengths)) { |
434 return 0; | 433 return 0; |
435 } | 434 } |
436 // Create the actual bit codes for the bit lengths. | 435 // Create the actual bit codes for the bit lengths. |
437 ConvertBitDepthsToSymbols(tree); | 436 ConvertBitDepthsToSymbols(tree); |
438 return 1; | 437 return 1; |
439 } | 438 } |
OLD | NEW |