Coverage Report

Created: 2025-11-16 07:22

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