/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 | 1.03k | BitReader* br) { |
32 | 1.03k | int symbol = 0; |
33 | 1.03k | uint8_t prev_code_len = kDefaultCodeLength; |
34 | 1.03k | int repeat = 0; |
35 | 1.03k | uint8_t repeat_code_len = 0; |
36 | 1.03k | int space = 32768; |
37 | 1.03k | HuffmanCode table[32]; |
38 | | |
39 | 1.03k | uint16_t counts[16] = {0}; |
40 | 19.5k | for (int i = 0; i < kCodeLengthCodes; ++i) { |
41 | 18.5k | ++counts[code_length_code_lengths[i]]; |
42 | 18.5k | } |
43 | 1.03k | if (!BuildHuffmanTable(table, 5, code_length_code_lengths, kCodeLengthCodes, |
44 | 1.03k | &counts[0])) { |
45 | 0 | return JXL_FALSE; |
46 | 0 | } |
47 | | |
48 | 1.98M | while (symbol < num_symbols && space > 0) { |
49 | 1.98M | const HuffmanCode* p = table; |
50 | 1.98M | uint8_t code_len; |
51 | 1.98M | br->Refill(); |
52 | 1.98M | p += br->PeekFixedBits<5>(); |
53 | 1.98M | br->Consume(p->bits); |
54 | 1.98M | code_len = static_cast<uint8_t>(p->value); |
55 | 1.98M | if (code_len < kCodeLengthRepeatCode) { |
56 | 1.97M | repeat = 0; |
57 | 1.97M | code_lengths[symbol++] = code_len; |
58 | 1.97M | if (code_len != 0) { |
59 | 1.50M | prev_code_len = code_len; |
60 | 1.50M | space -= 32768u >> code_len; |
61 | 1.50M | } |
62 | 1.97M | } else { |
63 | 5.25k | const int extra_bits = code_len - 14; |
64 | 5.25k | int old_repeat; |
65 | 5.25k | int repeat_delta; |
66 | 5.25k | uint8_t new_len = 0; |
67 | 5.25k | if (code_len == kCodeLengthRepeatCode) { |
68 | 2.01k | new_len = prev_code_len; |
69 | 2.01k | } |
70 | 5.25k | if (repeat_code_len != new_len) { |
71 | 1.62k | repeat = 0; |
72 | 1.62k | repeat_code_len = new_len; |
73 | 1.62k | } |
74 | 5.25k | old_repeat = repeat; |
75 | 5.25k | if (repeat > 0) { |
76 | 1.27k | repeat -= 2; |
77 | 1.27k | repeat <<= extra_bits; |
78 | 1.27k | } |
79 | 5.25k | repeat += static_cast<int>(br->ReadBits(extra_bits) + 3); |
80 | 5.25k | repeat_delta = repeat - old_repeat; |
81 | 5.25k | if (symbol + repeat_delta > num_symbols) { |
82 | 85 | return 0; |
83 | 85 | } |
84 | 5.17k | memset(&code_lengths[symbol], repeat_code_len, |
85 | 5.17k | static_cast<size_t>(repeat_delta)); |
86 | 5.17k | symbol += repeat_delta; |
87 | 5.17k | if (repeat_code_len != 0) { |
88 | 1.99k | space -= repeat_delta << (15 - repeat_code_len); |
89 | 1.99k | } |
90 | 5.17k | } |
91 | 1.98M | } |
92 | 945 | if (space != 0) { |
93 | 183 | return JXL_FALSE; |
94 | 183 | } |
95 | 762 | memset(&code_lengths[symbol], 0, static_cast<size_t>(num_symbols - symbol)); |
96 | 762 | return JXL_TRUE; |
97 | 945 | } |
98 | | |
99 | | static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br, |
100 | 1.58k | HuffmanCode* table) { |
101 | 1.58k | size_t max_bits = |
102 | 1.58k | (alphabet_size > 1u) ? FloorLog2Nonzero(alphabet_size - 1u) + 1 : 0; |
103 | | |
104 | 1.58k | size_t num_symbols = br->ReadFixedBits<2>() + 1; |
105 | | |
106 | 1.58k | uint16_t symbols[4] = {0}; |
107 | 5.57k | for (size_t i = 0; i < num_symbols; ++i) { |
108 | 4.01k | uint16_t symbol = br->ReadBits(max_bits); |
109 | 4.01k | if (symbol >= alphabet_size) { |
110 | 16 | return false; |
111 | 16 | } |
112 | 3.99k | symbols[i] = symbol; |
113 | 3.99k | } |
114 | | |
115 | 3.85k | for (size_t i = 0; i < num_symbols - 1; ++i) { |
116 | 6.45k | for (size_t j = i + 1; j < num_symbols; ++j) { |
117 | 4.16k | if (symbols[i] == symbols[j]) return false; |
118 | 4.16k | } |
119 | 2.36k | } |
120 | | |
121 | | // 4 symbols have to option to encode. |
122 | 1.49k | if (num_symbols == 4) num_symbols += br->ReadFixedBits<1>(); |
123 | | |
124 | 1.49k | const auto swap_symbols = [&symbols](size_t i, size_t j) { |
125 | 1.34k | uint16_t t = symbols[j]; |
126 | 1.34k | symbols[j] = symbols[i]; |
127 | 1.34k | symbols[i] = t; |
128 | 1.34k | }; |
129 | | |
130 | 1.49k | size_t table_size = 1; |
131 | 1.49k | switch (num_symbols) { |
132 | 458 | case 1: |
133 | 458 | table[0] = {0, symbols[0]}; |
134 | 458 | break; |
135 | 328 | case 2: |
136 | 328 | if (symbols[0] > symbols[1]) swap_symbols(0, 1); |
137 | 328 | table[0] = {1, symbols[0]}; |
138 | 328 | table[1] = {1, symbols[1]}; |
139 | 328 | table_size = 2; |
140 | 328 | break; |
141 | 217 | case 3: |
142 | 217 | if (symbols[1] > symbols[2]) swap_symbols(1, 2); |
143 | 217 | table[0] = {1, symbols[0]}; |
144 | 217 | table[2] = {1, symbols[0]}; |
145 | 217 | table[1] = {2, symbols[1]}; |
146 | 217 | table[3] = {2, symbols[2]}; |
147 | 217 | table_size = 4; |
148 | 217 | break; |
149 | 226 | case 4: { |
150 | 904 | for (size_t i = 0; i < 3; ++i) { |
151 | 2.03k | for (size_t j = i + 1; j < 4; ++j) { |
152 | 1.35k | if (symbols[i] > symbols[j]) swap_symbols(i, j); |
153 | 1.35k | } |
154 | 678 | } |
155 | 226 | table[0] = {2, symbols[0]}; |
156 | 226 | table[2] = {2, symbols[1]}; |
157 | 226 | table[1] = {2, symbols[2]}; |
158 | 226 | table[3] = {2, symbols[3]}; |
159 | 226 | table_size = 4; |
160 | 226 | break; |
161 | 0 | } |
162 | 261 | case 5: { |
163 | 261 | if (symbols[2] > symbols[3]) swap_symbols(2, 3); |
164 | 261 | table[0] = {1, symbols[0]}; |
165 | 261 | table[1] = {2, symbols[1]}; |
166 | 261 | table[2] = {1, symbols[0]}; |
167 | 261 | table[3] = {3, symbols[2]}; |
168 | 261 | table[4] = {1, symbols[0]}; |
169 | 261 | table[5] = {2, symbols[1]}; |
170 | 261 | table[6] = {1, symbols[0]}; |
171 | 261 | table[7] = {3, symbols[3]}; |
172 | 261 | table_size = 8; |
173 | 261 | break; |
174 | 0 | } |
175 | 0 | default: { |
176 | | // Unreachable. |
177 | 0 | return false; |
178 | 0 | } |
179 | 1.49k | } |
180 | | |
181 | 1.49k | const uint32_t goal_size = 1u << kHuffmanTableBits; |
182 | 11.4k | while (table_size != goal_size) { |
183 | 9.92k | memcpy(&table[table_size], &table[0], |
184 | 9.92k | static_cast<size_t>(table_size) * sizeof(table[0])); |
185 | 9.92k | table_size <<= 1; |
186 | 9.92k | } |
187 | | |
188 | 1.49k | return true; |
189 | 1.49k | } |
190 | | |
191 | | bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size, |
192 | 2.83k | BitReader* br) { |
193 | 2.83k | 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 | 2.83k | uint32_t simple_code_or_skip = br->ReadFixedBits<2>(); |
199 | 2.83k | if (simple_code_or_skip == 1u) { |
200 | 1.58k | table_.resize(1u << kHuffmanTableBits); |
201 | 1.58k | return ReadSimpleCode(alphabet_size, br, table_.data()); |
202 | 1.58k | } |
203 | | |
204 | 1.25k | std::vector<uint8_t> code_lengths(alphabet_size, 0); |
205 | 1.25k | uint8_t code_length_code_lengths[kCodeLengthCodes] = {0}; |
206 | 1.25k | int space = 32; |
207 | 1.25k | int num_codes = 0; |
208 | | /* Static Huffman code for the code length code lengths */ |
209 | 1.25k | static const HuffmanCode huff[16] = { |
210 | 1.25k | {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1}, |
211 | 1.25k | {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5}, |
212 | 1.25k | }; |
213 | 16.0k | for (size_t i = simple_code_or_skip; i < kCodeLengthCodes && space > 0; ++i) { |
214 | 14.8k | const int code_len_idx = kCodeLengthCodeOrder[i]; |
215 | 14.8k | const HuffmanCode* p = huff; |
216 | 14.8k | uint8_t v; |
217 | 14.8k | br->Refill(); |
218 | 14.8k | p += br->PeekFixedBits<4>(); |
219 | 14.8k | br->Consume(p->bits); |
220 | 14.8k | v = static_cast<uint8_t>(p->value); |
221 | 14.8k | code_length_code_lengths[code_len_idx] = v; |
222 | 14.8k | if (v != 0) { |
223 | 6.50k | space -= (32u >> v); |
224 | 6.50k | ++num_codes; |
225 | 6.50k | } |
226 | 14.8k | } |
227 | 1.25k | bool ok = |
228 | 1.25k | (num_codes == 1 || space == 0) && |
229 | 1.25k | FROM_JXL_BOOL(ReadHuffmanCodeLengths( |
230 | 1.25k | code_length_code_lengths, alphabet_size, code_lengths.data(), br)); |
231 | | |
232 | 1.25k | if (!ok) return false; |
233 | 762 | uint16_t counts[16] = {0}; |
234 | 5.73M | for (size_t i = 0; i < alphabet_size; ++i) { |
235 | 5.73M | ++counts[code_lengths[i]]; |
236 | 5.73M | } |
237 | 762 | table_.resize(alphabet_size + 376); |
238 | 762 | uint32_t table_size = |
239 | 762 | BuildHuffmanTable(table_.data(), kHuffmanTableBits, code_lengths.data(), |
240 | 762 | alphabet_size, &counts[0]); |
241 | 762 | table_.resize(table_size); |
242 | 762 | return (table_size > 0); |
243 | 1.25k | } |
244 | | |
245 | | } // namespace jxl |