Coverage Report

Created: 2025-06-16 07:00

/src/libjxl/lib/jxl/jpeg/jpeg_data.h
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
// Data structures that represent the non-pixel contents of a jpeg file.
7
8
#ifndef LIB_JXL_JPEG_JPEG_DATA_H_
9
#define LIB_JXL_JPEG_JPEG_DATA_H_
10
11
#include <array>
12
#include <cstddef>
13
#include <cstdint>
14
#include <vector>
15
16
#include "lib/jxl/base/status.h"
17
#include "lib/jxl/common.h"  // JPEGXL_ENABLE_TRANSCODE_JPEG
18
#include "lib/jxl/field_encodings.h"
19
#include "lib/jxl/fields.h"
20
#include "lib/jxl/frame_dimensions.h"
21
22
namespace jxl {
23
namespace jpeg {
24
25
constexpr int kMaxComponents = 4;
26
constexpr int kMaxQuantTables = 4;
27
constexpr int kMaxHuffmanTables = 4;
28
constexpr size_t kJpegHuffmanMaxBitLength = 16;
29
constexpr int kJpegHuffmanAlphabetSize = 256;
30
constexpr int kJpegDCAlphabetSize = 12;
31
constexpr int kMaxDHTMarkers = 512;
32
constexpr int kMaxDimPixels = 65535;
33
constexpr uint8_t kApp1 = 0xE1;
34
constexpr uint8_t kApp2 = 0xE2;
35
const uint8_t kIccProfileTag[12] = "ICC_PROFILE";
36
const uint8_t kExifTag[6] = "Exif\0";
37
const uint8_t kXMPTag[29] = "http://ns.adobe.com/xap/1.0/";
38
39
/* clang-format off */
40
constexpr uint32_t kJPEGNaturalOrder[80] = {
41
  0,   1,  8, 16,  9,  2,  3, 10,
42
  17, 24, 32, 25, 18, 11,  4,  5,
43
  12, 19, 26, 33, 40, 48, 41, 34,
44
  27, 20, 13,  6,  7, 14, 21, 28,
45
  35, 42, 49, 56, 57, 50, 43, 36,
46
  29, 22, 15, 23, 30, 37, 44, 51,
47
  58, 59, 52, 45, 38, 31, 39, 46,
48
  53, 60, 61, 54, 47, 55, 62, 63,
49
  // extra entries for safety in decoder
50
  63, 63, 63, 63, 63, 63, 63, 63,
51
  63, 63, 63, 63, 63, 63, 63, 63
52
};
53
54
constexpr uint32_t kJPEGZigZagOrder[64] = {
55
  0,   1,  5,  6, 14, 15, 27, 28,
56
  2,   4,  7, 13, 16, 26, 29, 42,
57
  3,   8, 12, 17, 25, 30, 41, 43,
58
  9,  11, 18, 24, 31, 40, 44, 53,
59
  10, 19, 23, 32, 39, 45, 52, 54,
60
  20, 22, 33, 38, 46, 51, 55, 60,
61
  21, 34, 37, 47, 50, 56, 59, 61,
62
  35, 36, 48, 49, 57, 58, 62, 63
63
};
64
/* clang-format on */
65
66
// Quantization values for an 8x8 pixel block.
67
struct JPEGQuantTable {
68
  std::array<int32_t, kDCTBlockSize> values;
69
  uint32_t precision = 0;
70
  // The index of this quantization table as it was parsed from the input JPEG.
71
  // Each DQT marker segment contains an 'index' field, and we save this index
72
  // here. Valid values are 0 to 3.
73
  uint32_t index = 0;
74
  // Set to true if this table is the last one within its marker segment.
75
  bool is_last = true;
76
};
77
78
// Huffman code and decoding lookup table used for DC and AC coefficients.
79
struct JPEGHuffmanCode {
80
  // Bit length histogram.
81
  std::array<uint32_t, kJpegHuffmanMaxBitLength + 1> counts = {};
82
  // Symbol values sorted by increasing bit lengths.
83
  std::array<uint32_t, kJpegHuffmanAlphabetSize + 1> values = {};
84
  // The index of the Huffman code in the current set of Huffman codes. For AC
85
  // component Huffman codes, 0x10 is added to the index.
86
  int slot_id = 0;
87
  // Set to true if this Huffman code is the last one within its marker segment.
88
  bool is_last = true;
89
};
90
91
// Huffman table indexes used for one component of one scan.
92
struct JPEGComponentScanInfo {
93
  uint32_t comp_idx;
94
  uint32_t dc_tbl_idx;
95
  uint32_t ac_tbl_idx;
96
};
97
98
// Contains information that is used in one scan.
99
struct JPEGScanInfo {
100
  // Parameters used for progressive scans (named the same way as in the spec):
101
  //   Ss : Start of spectral band in zig-zag sequence.
102
  //   Se : End of spectral band in zig-zag sequence.
103
  //   Ah : Successive approximation bit position, high.
104
  //   Al : Successive approximation bit position, low.
105
  uint32_t Ss;
106
  uint32_t Se;
107
  uint32_t Ah;
108
  uint32_t Al;
109
  uint32_t num_components = 0;
110
  std::array<JPEGComponentScanInfo, 4> components;
111
  // Last codestream pass that is needed to write this scan.
112
  uint32_t last_needed_pass = 0;
113
114
  // Extra information required for bit-precise JPEG file reconstruction.
115
116
  // Set of block indexes where the JPEG encoder has to flush the end-of-block
117
  // runs and refinement bits.
118
  std::vector<uint32_t> reset_points;
119
  // The number of extra zero runs (Huffman symbol 0xf0) before the end of
120
  // block (if nonzero), indexed by block index.
121
  // All of these symbols can be omitted without changing the pixel values, but
122
  // some jpeg encoders put these at the end of blocks.
123
  struct ExtraZeroRunInfo {
124
    uint32_t block_idx;
125
    uint32_t num_extra_zero_runs;
126
  };
127
  std::vector<ExtraZeroRunInfo> extra_zero_runs;
128
};
129
130
using coeff_t = int16_t;
131
132
// Represents one component of a jpeg file.
133
struct JPEGComponent {
134
  JPEGComponent()
135
0
      : id(0),
136
0
        h_samp_factor(1),
137
0
        v_samp_factor(1),
138
0
        quant_idx(0),
139
0
        width_in_blocks(0),
140
0
        height_in_blocks(0) {}
141
142
  // One-byte id of the component.
143
  uint32_t id;
144
  // Horizontal and vertical sampling factors.
145
  // In interleaved mode, each minimal coded unit (MCU) has
146
  // h_samp_factor x v_samp_factor DCT blocks from this component.
147
  int h_samp_factor;
148
  int v_samp_factor;
149
  // The index of the quantization table used for this component.
150
  uint32_t quant_idx;
151
  // The dimensions of the component measured in 8x8 blocks.
152
  uint32_t width_in_blocks;
153
  uint32_t height_in_blocks;
154
  // The DCT coefficients of this component, laid out block-by-block, divided
155
  // through the quantization matrix values.
156
  std::vector<coeff_t> coeffs;
157
};
158
159
enum class AppMarkerType : uint32_t {
160
  kUnknown = 0,
161
  kICC = 1,
162
  kExif = 2,
163
  kXMP = 3,
164
};
165
166
// Represents a parsed jpeg file.
167
struct JPEGData : public Fields {
168
  JPEGData()
169
0
      : width(0), height(0), restart_interval(0), has_zero_padding_bit(false) {}
170
171
  JXL_FIELDS_NAME(JPEGData)
172
#if JPEGXL_ENABLE_TRANSCODE_JPEG
173
  // Doesn't serialize everything - skips brotli-encoded data and what is
174
  // already encoded in the codestream.
175
  Status VisitFields(Visitor* visitor) override;
176
#else
177
  Status VisitFields(Visitor* /* visitor */) override {
178
    return JXL_UNREACHABLE("JPEG transcoding support not enabled");
179
  }
180
#endif  // JPEGXL_ENABLE_TRANSCODE_JPEG
181
182
  void CalculateMcuSize(const JPEGScanInfo& scan, int* MCUs_per_row,
183
                        int* MCU_rows) const;
184
185
  int width;
186
  int height;
187
  uint32_t restart_interval;
188
  std::vector<std::vector<uint8_t>> app_data;
189
  std::vector<AppMarkerType> app_marker_type;
190
  std::vector<std::vector<uint8_t>> com_data;
191
  std::vector<JPEGQuantTable> quant;
192
  std::vector<JPEGHuffmanCode> huffman_code;
193
  std::vector<JPEGComponent> components;
194
  std::vector<JPEGScanInfo> scan_info;
195
  std::vector<uint8_t> marker_order;
196
  std::vector<std::vector<uint8_t>> inter_marker_data;
197
  std::vector<uint8_t> tail_data;
198
199
  // Extra information required for bit-precise JPEG file reconstruction.
200
201
  bool has_zero_padding_bit;
202
  std::vector<uint8_t> padding_bits;
203
};
204
205
#if JPEGXL_ENABLE_TRANSCODE_JPEG
206
// Set ICC profile in jpeg_data.
207
Status SetJPEGDataFromICC(const std::vector<uint8_t>& icc,
208
                          jpeg::JPEGData* jpeg_data);
209
#else
210
static JXL_INLINE Status SetJPEGDataFromICC(
211
    const std::vector<uint8_t>& /* icc */, jpeg::JPEGData* /* jpeg_data */) {
212
  return JXL_UNREACHABLE("JPEG transcoding support not enabled");
213
}
214
#endif  // JPEGXL_ENABLE_TRANSCODE_JPEG
215
216
}  // namespace jpeg
217
}  // namespace jxl
218
219
#endif  // LIB_JXL_JPEG_JPEG_DATA_H_