Coverage Report

Created: 2025-07-16 07:53

/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
#include <string.h> /* for memset */
10
11
#include <vector>
12
13
#include "lib/jxl/ans_params.h"
14
#include "lib/jxl/base/bits.h"
15
#include "lib/jxl/huffman_table.h"
16
17
namespace jxl {
18
19
static const int kCodeLengthCodes = 18;
20
static const uint8_t kCodeLengthCodeOrder[kCodeLengthCodes] = {
21
    1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
22
};
23
static const uint8_t kDefaultCodeLength = 8;
24
static const uint8_t kCodeLengthRepeatCode = 16;
25
26
JXL_BOOL ReadHuffmanCodeLengths(const uint8_t* code_length_code_lengths,
27
                                int num_symbols, uint8_t* code_lengths,
28
4.75k
                                BitReader* br) {
29
4.75k
  int symbol = 0;
30
4.75k
  uint8_t prev_code_len = kDefaultCodeLength;
31
4.75k
  int repeat = 0;
32
4.75k
  uint8_t repeat_code_len = 0;
33
4.75k
  int space = 32768;
34
4.75k
  HuffmanCode table[32];
35
36
4.75k
  uint16_t counts[16] = {0};
37
90.3k
  for (int i = 0; i < kCodeLengthCodes; ++i) {
38
85.6k
    ++counts[code_length_code_lengths[i]];
39
85.6k
  }
40
4.75k
  if (!BuildHuffmanTable(table, 5, code_length_code_lengths, kCodeLengthCodes,
41
4.75k
                         &counts[0])) {
42
0
    return JXL_FALSE;
43
0
  }
44
45
99.4k
  while (symbol < num_symbols && space > 0) {
46
94.7k
    const HuffmanCode* p = table;
47
94.7k
    uint8_t code_len;
48
94.7k
    br->Refill();
49
94.7k
    p += br->PeekFixedBits<5>();
50
94.7k
    br->Consume(p->bits);
51
94.7k
    code_len = static_cast<uint8_t>(p->value);
52
94.7k
    if (code_len < kCodeLengthRepeatCode) {
53
88.2k
      repeat = 0;
54
88.2k
      code_lengths[symbol++] = code_len;
55
88.2k
      if (code_len != 0) {
56
62.5k
        prev_code_len = code_len;
57
62.5k
        space -= 32768u >> code_len;
58
62.5k
      }
59
88.2k
    } else {
60
6.48k
      const int extra_bits = code_len - 14;
61
6.48k
      int old_repeat;
62
6.48k
      int repeat_delta;
63
6.48k
      uint8_t new_len = 0;
64
6.48k
      if (code_len == kCodeLengthRepeatCode) {
65
242
        new_len = prev_code_len;
66
242
      }
67
6.48k
      if (repeat_code_len != new_len) {
68
250
        repeat = 0;
69
250
        repeat_code_len = new_len;
70
250
      }
71
6.48k
      old_repeat = repeat;
72
6.48k
      if (repeat > 0) {
73
4.10k
        repeat -= 2;
74
4.10k
        repeat <<= extra_bits;
75
4.10k
      }
76
6.48k
      repeat += static_cast<int>(br->ReadBits(extra_bits) + 3);
77
6.48k
      repeat_delta = repeat - old_repeat;
78
6.48k
      if (symbol + repeat_delta > num_symbols) {
79
0
        return 0;
80
0
      }
81
6.48k
      memset(&code_lengths[symbol], repeat_code_len,
82
6.48k
             static_cast<size_t>(repeat_delta));
83
6.48k
      symbol += repeat_delta;
84
6.48k
      if (repeat_code_len != 0) {
85
242
        space -= repeat_delta << (15 - repeat_code_len);
86
242
      }
87
6.48k
    }
88
94.7k
  }
89
4.75k
  if (space != 0) {
90
132
    return JXL_FALSE;
91
132
  }
92
4.62k
  memset(&code_lengths[symbol], 0, static_cast<size_t>(num_symbols - symbol));
93
4.62k
  return JXL_TRUE;
94
4.75k
}
95
96
static JXL_INLINE bool ReadSimpleCode(size_t alphabet_size, BitReader* br,
97
8.36k
                                      HuffmanCode* table) {
98
8.36k
  size_t max_bits =
99
8.36k
      (alphabet_size > 1u) ? FloorLog2Nonzero(alphabet_size - 1u) + 1 : 0;
100
101
8.36k
  size_t num_symbols = br->ReadFixedBits<2>() + 1;
102
103
8.36k
  uint16_t symbols[4] = {0};
104
31.8k
  for (size_t i = 0; i < num_symbols; ++i) {
105
23.4k
    uint16_t symbol = br->ReadBits(max_bits);
106
23.4k
    if (symbol >= alphabet_size) {
107
2
      return false;
108
2
    }
109
23.4k
    symbols[i] = symbol;
110
23.4k
  }
111
112
22.9k
  for (size_t i = 0; i < num_symbols - 1; ++i) {
113
37.0k
    for (size_t j = i + 1; j < num_symbols; ++j) {
114
22.5k
      if (symbols[i] == symbols[j]) return false;
115
22.5k
    }
116
14.8k
  }
117
118
  // 4 symbols have to option to encode.
119
8.07k
  if (num_symbols == 4) num_symbols += br->ReadFixedBits<1>();
120
121
8.07k
  const auto swap_symbols = [&symbols](size_t i, size_t j) {
122
7.46k
    uint16_t t = symbols[j];
123
7.46k
    symbols[j] = symbols[i];
124
7.46k
    symbols[i] = t;
125
7.46k
  };
126
127
8.07k
  size_t table_size = 1;
128
8.07k
  switch (num_symbols) {
129
557
    case 1:
130
557
      table[0] = {0, symbols[0]};
131
557
      break;
132
1.11k
    case 2:
133
1.11k
      if (symbols[0] > symbols[1]) swap_symbols(0, 1);
134
1.11k
      table[0] = {1, symbols[0]};
135
1.11k
      table[1] = {1, symbols[1]};
136
1.11k
      table_size = 2;
137
1.11k
      break;
138
6.06k
    case 3:
139
6.06k
      if (symbols[1] > symbols[2]) swap_symbols(1, 2);
140
6.06k
      table[0] = {1, symbols[0]};
141
6.06k
      table[2] = {1, symbols[0]};
142
6.06k
      table[1] = {2, symbols[1]};
143
6.06k
      table[3] = {2, symbols[2]};
144
6.06k
      table_size = 4;
145
6.06k
      break;
146
331
    case 4: {
147
1.32k
      for (size_t i = 0; i < 3; ++i) {
148
2.97k
        for (size_t j = i + 1; j < 4; ++j) {
149
1.98k
          if (symbols[i] > symbols[j]) swap_symbols(i, j);
150
1.98k
        }
151
993
      }
152
331
      table[0] = {2, symbols[0]};
153
331
      table[2] = {2, symbols[1]};
154
331
      table[1] = {2, symbols[2]};
155
331
      table[3] = {2, symbols[3]};
156
331
      table_size = 4;
157
331
      break;
158
0
    }
159
0
    case 5: {
160
0
      if (symbols[2] > symbols[3]) swap_symbols(2, 3);
161
0
      table[0] = {1, symbols[0]};
162
0
      table[1] = {2, symbols[1]};
163
0
      table[2] = {1, symbols[0]};
164
0
      table[3] = {3, symbols[2]};
165
0
      table[4] = {1, symbols[0]};
166
0
      table[5] = {2, symbols[1]};
167
0
      table[6] = {1, symbols[0]};
168
0
      table[7] = {3, symbols[3]};
169
0
      table_size = 8;
170
0
      break;
171
0
    }
172
0
    default: {
173
      // Unreachable.
174
0
      return false;
175
0
    }
176
8.07k
  }
177
178
8.07k
  const uint32_t goal_size = 1u << kHuffmanTableBits;
179
58.7k
  while (table_size != goal_size) {
180
50.6k
    memcpy(&table[table_size], &table[0],
181
50.6k
           static_cast<size_t>(table_size) * sizeof(table[0]));
182
50.6k
    table_size <<= 1;
183
50.6k
  }
184
185
8.07k
  return true;
186
8.07k
}
187
188
bool HuffmanDecodingData::ReadFromBitStream(size_t alphabet_size,
189
13.1k
                                            BitReader* br) {
190
13.1k
  if (alphabet_size > (1 << PREFIX_MAX_BITS)) return false;
191
192
  /* simple_code_or_skip is used as follows:
193
     1 for simple code;
194
     0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
195
13.1k
  uint32_t simple_code_or_skip = br->ReadFixedBits<2>();
196
13.1k
  if (simple_code_or_skip == 1u) {
197
8.36k
    table_.resize(1u << kHuffmanTableBits);
198
8.36k
    return ReadSimpleCode(alphabet_size, br, table_.data());
199
8.36k
  }
200
201
4.78k
  std::vector<uint8_t> code_lengths(alphabet_size, 0);
202
4.78k
  uint8_t code_length_code_lengths[kCodeLengthCodes] = {0};
203
4.78k
  int space = 32;
204
4.78k
  int num_codes = 0;
205
  /* Static Huffman code for the code length code lengths */
206
4.78k
  static const HuffmanCode huff[16] = {
207
4.78k
      {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 1},
208
4.78k
      {2, 0}, {2, 4}, {2, 3}, {3, 2}, {2, 0}, {2, 4}, {2, 3}, {4, 5},
209
4.78k
  };
210
50.8k
  for (size_t i = simple_code_or_skip; i < kCodeLengthCodes && space > 0; ++i) {
211
46.0k
    const int code_len_idx = kCodeLengthCodeOrder[i];
212
46.0k
    const HuffmanCode* p = huff;
213
46.0k
    uint8_t v;
214
46.0k
    br->Refill();
215
46.0k
    p += br->PeekFixedBits<4>();
216
46.0k
    br->Consume(p->bits);
217
46.0k
    v = static_cast<uint8_t>(p->value);
218
46.0k
    code_length_code_lengths[code_len_idx] = v;
219
46.0k
    if (v != 0) {
220
33.8k
      space -= (32u >> v);
221
33.8k
      ++num_codes;
222
33.8k
    }
223
46.0k
  }
224
4.78k
  bool ok =
225
4.78k
      (num_codes == 1 || space == 0) &&
226
4.78k
      FROM_JXL_BOOL(ReadHuffmanCodeLengths(
227
4.78k
          code_length_code_lengths, alphabet_size, code_lengths.data(), br));
228
229
4.78k
  if (!ok) return false;
230
4.62k
  uint16_t counts[16] = {0};
231
2.01M
  for (size_t i = 0; i < alphabet_size; ++i) {
232
2.01M
    ++counts[code_lengths[i]];
233
2.01M
  }
234
4.62k
  table_.resize(alphabet_size + 376);
235
4.62k
  uint32_t table_size =
236
4.62k
      BuildHuffmanTable(table_.data(), kHuffmanTableBits, code_lengths.data(),
237
4.62k
                        alphabet_size, &counts[0]);
238
4.62k
  table_.resize(table_size);
239
4.62k
  return (table_size > 0);
240
4.78k
}
241
242
// Decodes the next Huffman coded symbol from the bit-stream.
243
69.5M
uint16_t HuffmanDecodingData::ReadSymbol(BitReader* br) const {
244
69.5M
  size_t n_bits;
245
69.5M
  const HuffmanCode* table = table_.data();
246
69.5M
  table += br->PeekBits(kHuffmanTableBits);
247
69.5M
  n_bits = table->bits;
248
69.5M
  if (n_bits > kHuffmanTableBits) {
249
196k
    br->Consume(kHuffmanTableBits);
250
196k
    n_bits -= kHuffmanTableBits;
251
196k
    table += table->value;
252
196k
    table += br->PeekBits(n_bits);
253
196k
  }
254
69.5M
  br->Consume(table->bits);
255
69.5M
  return table->value;
256
69.5M
}
257
258
}  // namespace jxl