/src/libjxl/lib/jxl/dec_huffman.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) the JPEG XL Project Authors. All rights reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style |
4 | | // license that can be found in the LICENSE file. |
5 | | |
6 | | #include "lib/jxl/dec_huffman.h" |
7 | | |
8 | | #include <jxl/types.h> |
9 | | |
10 | | #include <cstdint> |
11 | | #include <cstring> /* for memset */ |
12 | | #include <vector> |
13 | | |
14 | | #include "lib/jxl/ans_params.h" |
15 | | #include "lib/jxl/base/bits.h" |
16 | | #include "lib/jxl/base/compiler_specific.h" |
17 | | #include "lib/jxl/dec_bit_reader.h" |
18 | | #include "lib/jxl/huffman_table.h" |
19 | | |
20 | | namespace jxl { |
21 | | |
22 | | static const int kCodeLengthCodes = 18; |
23 | | static const uint8_t kCodeLengthCodeOrder[kCodeLengthCodes] = { |
24 | | 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15, |
25 | | }; |
26 | | static const uint8_t kDefaultCodeLength = 8; |
27 | | static const uint8_t kCodeLengthRepeatCode = 16; |
28 | | |
29 | | JXL_BOOL ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths, |
30 | | int num_symbols, uint8_t* code_lengths, |
31 | 6.00k | BitReader* br) { |
32 | 6.00k | int symbol = 0; |
33 | 6.00k | uint8_t prev_code_len = kDefaultCodeLength; |
34 | 6.00k | int repeat = 0; |
35 | 6.00k | uint8_t repeat_code_len = 0; |
36 | 6.00k | int space = 32768; |
37 | 6.00k | HuffmanCode table[32]; |
38 | | |
39 | 6.00k | uint16_t counts[16] = {0}; |
40 | 114k | for (int i = 0; i < kCodeLengthCodes; ++i) { |
41 | 108k | ++counts[code_length_code_lengths[i]]; |
42 | 108k | } |
43 | 6.00k | if (!BuildHuffmanTable(table, 5, code_length_code_lengths, kCodeLengthCodes, |
44 | 6.00k | &counts[0])) { |
45 | 0 | return JXL_FALSE; |
46 | 0 | } |
47 | | |
48 | 4.68M | while (symbol < num_symbols && space > 0) { |
49 | 4.68M | const HuffmanCode* p = table; |
50 | 4.68M | uint8_t code_len; |
51 | 4.68M | br->Refill(); |
52 | 4.68M | p += br->PeekFixedBits<5>(); |
53 | 4.68M | br->Consume(p->bits); |
54 | 4.68M | code_len = static_cast<uint8_t>(p->value); |
55 | 4.68M | if (code_len < kCodeLengthRepeatCode) { |
56 | 4.67M | repeat = 0; |
57 | 4.67M | code_lengths[symbol++] = code_len; |
58 | 4.67M | if (code_len != 0) { |
59 | 4.46M | prev_code_len = code_len; |
60 | 4.46M | space -= 32768u >> code_len; |
61 | 4.46M | } |
62 | 4.67M | } else { |
63 | 12.3k | const int extra_bits = code_len - 14; |
64 | 12.3k | int old_repeat; |
65 | 12.3k | int repeat_delta; |
66 | 12.3k | uint8_t new_len = 0; |
67 | 12.3k | if (code_len == kCodeLengthRepeatCode) { |
68 | 4.04k | new_len = prev_code_len; |
69 | 4.04k | } |
70 | 12.3k | if (repeat_code_len != new_len) { |
71 | 4.63k | repeat = 0; |
72 | 4.63k | repeat_code_len = new_len; |
73 | 4.63k | } |
74 | 12.3k | old_repeat = repeat; |
75 | 12.3k | if (repeat > 0) { |
76 | 2.64k | repeat -= 2; |
77 | 2.64k | repeat <<= extra_bits; |
78 | 2.64k | } |
79 | 12.3k | repeat += static_cast<int>(br->ReadBits(extra_bits) + 3); |
80 | 12.3k | repeat_delta = repeat - old_repeat; |
81 | 12.3k | if (symbol + repeat_delta > num_symbols) { |
82 | 350 | return 0; |
83 | 350 | } |
84 | 11.9k | memset(&code_lengths[symbol], repeat_code_len, |
85 | 11.9k | static_cast<size_t>(repeat_delta)); |
86 | 11.9k | symbol += repeat_delta; |
87 | 11.9k | if (repeat_code_len != 0) { |
88 | 4.02k | space -= repeat_delta << (15 - repeat_code_len); |
89 | 4.02k | } |
90 | 11.9k | } |
91 | 4.68M | } |
92 | 5.65k | if (space != 0) { |
93 | 1.19k | return JXL_FALSE; |
94 | 1.19k | } |
95 | 4.46k | memset(&code_lengths[symbol], 0, static_cast<size_t>(num_symbols - symbol)); |
96 | 4.46k | return JXL_TRUE; |
97 | 5.65k | } |
98 | | |
99 | | static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br, |
100 | 6.72k | HuffmanCode* table) { |
101 | 6.72k | size_t max_bits = |
102 | 6.72k | (alphabet_size > 1u) ? FloorLog2Nonzero(alphabet_size - 1u) + 1 : 0; |
103 | | |
104 | 6.72k | size_t num_symbols = br->ReadFixedBits<2>() + 1; |
105 | | |
106 | 6.72k | uint16_t symbols[4] = {0}; |
107 | 23.4k | for (size_t i = 0; i < num_symbols; ++i) { |
108 | 16.7k | uint16_t symbol = br->ReadBits(max_bits); |
109 | 16.7k | if (symbol >= alphabet_size) { |
110 | 5 | return false; |
111 | 5 | } |
112 | 16.7k | symbols[i] = symbol; |
113 | 16.7k | } |
114 | | |
115 | 15.5k | for (size_t i = 0; i < num_symbols - 1; ++i) { |
116 | 24.3k | for (size_t j = i + 1; j < num_symbols; ++j) { |
117 | 15.5k | if (symbols[i] == symbols[j]) return false; |
118 | 15.5k | } |
119 | 9.59k | } |
120 | | |
121 | | // 4 symbols have to option to encode. |
122 | 5.91k | if (num_symbols == 4) num_symbols += br->ReadFixedBits<1>(); |
123 | | |
124 | 5.91k | const auto swap_symbols = [&symbols](size_t i, size_t j) { |
125 | 3.92k | uint16_t t = symbols[j]; |
126 | 3.92k | symbols[j] = symbols[i]; |
127 | 3.92k | symbols[i] = t; |
128 | 3.92k | }; |
129 | | |
130 | 5.91k | size_t table_size = 1; |
131 | 5.91k | switch (num_symbols) { |
132 | 1.73k | case 1: |
133 | 1.73k | table[0] = {0, symbols[0]}; |
134 | 1.73k | break; |
135 | 1.33k | case 2: |
136 | 1.33k | if (symbols[0] > symbols[1]) swap_symbols(0, 1); |
137 | 1.33k | table[0] = {1, symbols[0]}; |
138 | 1.33k | table[1] = {1, symbols[1]}; |
139 | 1.33k | table_size = 2; |
140 | 1.33k | break; |
141 | 2.11k | case 3: |
142 | 2.11k | if (symbols[1] > symbols[2]) swap_symbols(1, 2); |
143 | 2.11k | table[0] = {1, symbols[0]}; |
144 | 2.11k | table[2] = {1, symbols[0]}; |
145 | 2.11k | table[1] = {2, symbols[1]}; |
146 | 2.11k | table[3] = {2, symbols[2]}; |
147 | 2.11k | table_size = 4; |
148 | 2.11k | break; |
149 | 386 | case 4: { |
150 | 1.54k | for (size_t i = 0; i < 3; ++i) { |
151 | 3.47k | for (size_t j = i + 1; j < 4; ++j) { |
152 | 2.31k | if (symbols[i] > symbols[j]) swap_symbols(i, j); |
153 | 2.31k | } |
154 | 1.15k | } |
155 | 386 | table[0] = {2, symbols[0]}; |
156 | 386 | table[2] = {2, symbols[1]}; |
157 | 386 | table[1] = {2, symbols[2]}; |
158 | 386 | table[3] = {2, symbols[3]}; |
159 | 386 | table_size = 4; |
160 | 386 | break; |
161 | 0 | } |
162 | 354 | case 5: { |
163 | 354 | if (symbols[2] > symbols[3]) swap_symbols(2, 3); |
164 | 354 | table[0] = {1, symbols[0]}; |
165 | 354 | table[1] = {2, symbols[1]}; |
166 | 354 | table[2] = {1, symbols[0]}; |
167 | 354 | table[3] = {3, symbols[2]}; |
168 | 354 | table[4] = {1, symbols[0]}; |
169 | 354 | table[5] = {2, symbols[1]}; |
170 | 354 | table[6] = {1, symbols[0]}; |
171 | 354 | table[7] = {3, symbols[3]}; |
172 | 354 | table_size = 8; |
173 | 354 | break; |
174 | 0 | } |
175 | 0 | default: { |
176 | | // Unreachable. |
177 | 0 | return false; |
178 | 0 | } |
179 | 5.91k | } |
180 | | |
181 | 5.91k | const uint32_t goal_size = 1u << kHuffmanTableBits; |
182 | 45.8k | while (table_size != goal_size) { |
183 | 39.9k | memcpy(&table[table_size], &table[0], |
184 | 39.9k | static_cast<size_t>(table_size) * sizeof(table[0])); |
185 | 39.9k | table_size <<= 1; |
186 | 39.9k | } |
187 | | |
188 | 5.91k | return true; |
189 | 5.91k | } |
190 | | |
191 | | bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size, |
192 | 15.7k | BitReader* br) { |
193 | 15.7k | if (alphabet_size > (1 << PREFIX_MAX_BITS)) return false; |
194 | | |
195 | | /* simple_code_or_skip is used as follows: |
196 | | 1 for simple code; |
197 | | 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ |
198 | 15.7k | uint32_t simple_code_or_skip = br->ReadFixedBits<2>(); |
199 | 15.7k | if (simple_code_or_skip == 1u) { |
200 | 6.72k | table_.resize(1u << kHuffmanTableBits); |
201 | 6.72k | return ReadSimpleCode(alphabet_size, br, table_.data()); |
202 | 6.72k | } |
203 | | |
204 | 9.05k | std::vector<uint8_t> code_lengths(alphabet_size, 0); |
205 | 9.05k | uint8_t code_length_code_lengths[kCodeLengthCodes] = {0}; |
206 | 9.05k | int space = 32; |
207 | 9.05k | int num_codes = 0; |
208 | | /* Static Huffman code for the code length code lengths */ |
209 | 9.05k | static const HuffmanCode huff[16] = { |
210 | 9.05k | {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1}, |
211 | 9.05k | {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5}, |
212 | 9.05k | }; |
213 | 147k | for (size_t i = simple_code_or_skip; i < kCodeLengthCodes && space > 0; ++i) { |
214 | 138k | const int code_len_idx = kCodeLengthCodeOrder[i]; |
215 | 138k | const HuffmanCode* p = huff; |
216 | 138k | uint8_t v; |
217 | 138k | br->Refill(); |
218 | 138k | p += br->PeekFixedBits<4>(); |
219 | 138k | br->Consume(p->bits); |
220 | 138k | v = static_cast<uint8_t>(p->value); |
221 | 138k | code_length_code_lengths[code_len_idx] = v; |
222 | 138k | if (v != 0) { |
223 | 34.2k | space -= (32u >> v); |
224 | 34.2k | ++num_codes; |
225 | 34.2k | } |
226 | 138k | } |
227 | 9.05k | bool ok = |
228 | 9.05k | (num_codes == 1 || space == 0) && |
229 | 9.05k | FROM_JXL_BOOL(ReadHuffmanCodeLengths( |
230 | 9.05k | code_length_code_lengths, alphabet_size, code_lengths.data(), br)); |
231 | | |
232 | 9.05k | if (!ok) return false; |
233 | 4.46k | uint16_t counts[16] = {0}; |
234 | 48.0M | for (size_t i = 0; i < alphabet_size; ++i) { |
235 | 48.0M | ++counts[code_lengths[i]]; |
236 | 48.0M | } |
237 | 4.46k | table_.resize(alphabet_size + 376); |
238 | 4.46k | uint32_t table_size = |
239 | 4.46k | BuildHuffmanTable(table_.data(), kHuffmanTableBits, code_lengths.data(), |
240 | 4.46k | alphabet_size, &counts[0]); |
241 | 4.46k | table_.resize(table_size); |
242 | 4.46k | return (table_size > 0); |
243 | 9.05k | } |
244 | | |
245 | | } // namespace jxl |