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