Backed out 3 changesets (bug 1790375) for causing wd failures on fetch_error.py....
[gecko.git] / third_party / jpeg-xl / lib / jpegli / test_utils-inl.h
bloba4549171878c7b7fcec7c4f8df1386c1755ec735
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.
6 // This template file is included in both the libjpeg_test_util.cc and the
7 // test_utils.cc files with different JPEG_API_FN macros and possibly different
8 // include paths for the jpeg headers.
10 // Sequential non-interleaved.
11 static constexpr jpeg_scan_info kScript1[] = {
12 {1, {0}, 0, 63, 0, 0},
13 {1, {1}, 0, 63, 0, 0},
14 {1, {2}, 0, 63, 0, 0},
16 // Sequential partially interleaved, chroma first.
17 static constexpr jpeg_scan_info kScript2[] = {
18 {2, {1, 2}, 0, 63, 0, 0},
19 {1, {0}, 0, 63, 0, 0},
22 // Rest of the scan scripts are progressive.
24 static constexpr jpeg_scan_info kScript3[] = {
25 // Interleaved full DC.
26 {3, {0, 1, 2}, 0, 0, 0, 0},
27 // Full AC scans.
28 {1, {0}, 1, 63, 0, 0},
29 {1, {1}, 1, 63, 0, 0},
30 {1, {2}, 1, 63, 0, 0},
32 static constexpr jpeg_scan_info kScript4[] = {
33 // Non-interleaved full DC.
34 {1, {0}, 0, 0, 0, 0},
35 {1, {1}, 0, 0, 0, 0},
36 {1, {2}, 0, 0, 0, 0},
37 // Full AC scans.
38 {1, {0}, 1, 63, 0, 0},
39 {1, {1}, 1, 63, 0, 0},
40 {1, {2}, 1, 63, 0, 0},
42 static constexpr jpeg_scan_info kScript5[] = {
43 // Partially interleaved full DC, chroma first.
44 {2, {1, 2}, 0, 0, 0, 0},
45 {1, {0}, 0, 0, 0, 0},
46 // AC shifted by 1 bit.
47 {1, {0}, 1, 63, 0, 1},
48 {1, {1}, 1, 63, 0, 1},
49 {1, {2}, 1, 63, 0, 1},
50 // AC refinement scan.
51 {1, {0}, 1, 63, 1, 0},
52 {1, {1}, 1, 63, 1, 0},
53 {1, {2}, 1, 63, 1, 0},
55 static constexpr jpeg_scan_info kScript6[] = {
56 // Interleaved DC shifted by 2 bits.
57 {3, {0, 1, 2}, 0, 0, 0, 2},
58 // Interleaved DC refinement scans.
59 {3, {0, 1, 2}, 0, 0, 2, 1},
60 {3, {0, 1, 2}, 0, 0, 1, 0},
61 // Full AC scans.
62 {1, {0}, 1, 63, 0, 0},
63 {1, {1}, 1, 63, 0, 0},
64 {1, {2}, 1, 63, 0, 0},
67 static constexpr jpeg_scan_info kScript7[] = {
68 // Non-interleaved DC shifted by 2 bits.
69 {1, {0}, 0, 0, 0, 2},
70 {1, {1}, 0, 0, 0, 2},
71 {1, {2}, 0, 0, 0, 2},
72 // Non-interleaved DC first refinement scans.
73 {1, {0}, 0, 0, 2, 1},
74 {1, {1}, 0, 0, 2, 1},
75 {1, {2}, 0, 0, 2, 1},
76 // Non-interleaved DC second refinement scans.
77 {1, {0}, 0, 0, 1, 0},
78 {1, {1}, 0, 0, 1, 0},
79 {1, {2}, 0, 0, 1, 0},
80 // Full AC scans.
81 {1, {0}, 1, 63, 0, 0},
82 {1, {1}, 1, 63, 0, 0},
83 {1, {2}, 1, 63, 0, 0},
86 static constexpr jpeg_scan_info kScript8[] = {
87 // Partially interleaved DC shifted by 2 bits, chroma first
88 {2, {1, 2}, 0, 0, 0, 2},
89 {1, {0}, 0, 0, 0, 2},
90 // Partially interleaved DC first refinement scans.
91 {2, {0, 2}, 0, 0, 2, 1},
92 {1, {1}, 0, 0, 2, 1},
93 // Partially interleaved DC first refinement scans, chroma first.
94 {2, {1, 2}, 0, 0, 1, 0},
95 {1, {0}, 0, 0, 1, 0},
96 // Full AC scans.
97 {1, {0}, 1, 63, 0, 0},
98 {1, {1}, 1, 63, 0, 0},
99 {1, {2}, 1, 63, 0, 0},
102 static constexpr jpeg_scan_info kScript9[] = {
103 // Interleaved full DC.
104 {3, {0, 1, 2}, 0, 0, 0, 0},
105 // AC scans for component 0
106 // shifted by 1 bit, two spectral ranges
107 {1, {0}, 1, 6, 0, 1},
108 {1, {0}, 7, 63, 0, 1},
109 // refinement scan, full
110 {1, {0}, 1, 63, 1, 0},
111 // AC scans for component 1
112 // shifted by 1 bit, full
113 {1, {1}, 1, 63, 0, 1},
114 // refinement scan, two spectral ranges
115 {1, {1}, 1, 6, 1, 0},
116 {1, {1}, 7, 63, 1, 0},
117 // AC scans for component 2
118 // shifted by 1 bit, two spectral ranges
119 {1, {2}, 1, 6, 0, 1},
120 {1, {2}, 7, 63, 0, 1},
121 // refinement scan, two spectral ranges (but different from above)
122 {1, {2}, 1, 16, 1, 0},
123 {1, {2}, 17, 63, 1, 0},
126 static constexpr jpeg_scan_info kScript10[] = {
127 // Interleaved full DC.
128 {3, {0, 1, 2}, 0, 0, 0, 0},
129 // AC scans for spectral range 1..16
130 // shifted by 1
131 {1, {0}, 1, 16, 0, 1},
132 {1, {1}, 1, 16, 0, 1},
133 {1, {2}, 1, 16, 0, 1},
134 // refinement scans, two sub-ranges
135 {1, {0}, 1, 8, 1, 0},
136 {1, {0}, 9, 16, 1, 0},
137 {1, {1}, 1, 8, 1, 0},
138 {1, {1}, 9, 16, 1, 0},
139 {1, {2}, 1, 8, 1, 0},
140 {1, {2}, 9, 16, 1, 0},
141 // AC scans for spectral range 17..63
142 {1, {0}, 17, 63, 0, 1},
143 {1, {1}, 17, 63, 0, 1},
144 {1, {2}, 17, 63, 0, 1},
145 // refinement scans, two sub-ranges
146 {1, {0}, 17, 28, 1, 0},
147 {1, {0}, 29, 63, 1, 0},
148 {1, {1}, 17, 28, 1, 0},
149 {1, {1}, 29, 63, 1, 0},
150 {1, {2}, 17, 28, 1, 0},
151 {1, {2}, 29, 63, 1, 0},
154 struct ScanScript {
155 int num_scans;
156 const jpeg_scan_info* scans;
159 static constexpr ScanScript kTestScript[] = {
160 {ARRAY_SIZE(kScript1), kScript1}, {ARRAY_SIZE(kScript2), kScript2},
161 {ARRAY_SIZE(kScript3), kScript3}, {ARRAY_SIZE(kScript4), kScript4},
162 {ARRAY_SIZE(kScript5), kScript5}, {ARRAY_SIZE(kScript6), kScript6},
163 {ARRAY_SIZE(kScript7), kScript7}, {ARRAY_SIZE(kScript8), kScript8},
164 {ARRAY_SIZE(kScript9), kScript9}, {ARRAY_SIZE(kScript10), kScript10},
166 static constexpr int kNumTestScripts = ARRAY_SIZE(kTestScript);
168 void SetScanDecompressParams(const DecompressParams& dparams,
169 j_decompress_ptr cinfo, int scan_number) {
170 const ScanDecompressParams* sparams = nullptr;
171 for (const auto& sp : dparams.scan_params) {
172 if (scan_number <= sp.max_scan_number) {
173 sparams = &sp;
174 break;
177 if (sparams == nullptr) {
178 return;
180 if (dparams.quantize_colors) {
181 cinfo->dither_mode = (J_DITHER_MODE)sparams->dither_mode;
182 if (sparams->color_quant_mode == CQUANT_1PASS) {
183 cinfo->two_pass_quantize = FALSE;
184 cinfo->colormap = nullptr;
185 } else if (sparams->color_quant_mode == CQUANT_2PASS) {
186 JXL_CHECK(cinfo->out_color_space == JCS_RGB);
187 cinfo->two_pass_quantize = TRUE;
188 cinfo->colormap = nullptr;
189 } else if (sparams->color_quant_mode == CQUANT_EXTERNAL) {
190 JXL_CHECK(cinfo->out_color_space == JCS_RGB);
191 cinfo->two_pass_quantize = FALSE;
192 bool have_colormap = cinfo->colormap != nullptr;
193 cinfo->actual_number_of_colors = kTestColorMapNumColors;
194 cinfo->colormap = (*cinfo->mem->alloc_sarray)(
195 reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE,
196 cinfo->actual_number_of_colors, 3);
197 jxl::msan::UnpoisonMemory(cinfo->colormap, 3 * sizeof(JSAMPROW));
198 for (int i = 0; i < kTestColorMapNumColors; ++i) {
199 cinfo->colormap[0][i] = (kTestColorMap[i] >> 16) & 0xff;
200 cinfo->colormap[1][i] = (kTestColorMap[i] >> 8) & 0xff;
201 cinfo->colormap[2][i] = (kTestColorMap[i] >> 0) & 0xff;
203 if (have_colormap) {
204 JPEG_API_FN(new_colormap)(cinfo);
206 } else if (sparams->color_quant_mode == CQUANT_REUSE) {
207 JXL_CHECK(cinfo->out_color_space == JCS_RGB);
208 JXL_CHECK(cinfo->colormap);
213 void SetDecompressParams(const DecompressParams& dparams,
214 j_decompress_ptr cinfo) {
215 cinfo->do_block_smoothing = dparams.do_block_smoothing;
216 cinfo->do_fancy_upsampling = dparams.do_fancy_upsampling;
217 if (dparams.output_mode == RAW_DATA) {
218 cinfo->raw_data_out = TRUE;
220 if (dparams.set_out_color_space) {
221 cinfo->out_color_space = (J_COLOR_SPACE)dparams.out_color_space;
222 if (dparams.out_color_space == JCS_UNKNOWN) {
223 cinfo->jpeg_color_space = JCS_UNKNOWN;
226 cinfo->scale_num = dparams.scale_num;
227 cinfo->scale_denom = dparams.scale_denom;
228 cinfo->quantize_colors = dparams.quantize_colors;
229 cinfo->desired_number_of_colors = dparams.desired_number_of_colors;
230 if (!dparams.scan_params.empty()) {
231 if (cinfo->buffered_image) {
232 for (const auto& sparams : dparams.scan_params) {
233 if (sparams.color_quant_mode == CQUANT_1PASS) {
234 cinfo->enable_1pass_quant = TRUE;
235 } else if (sparams.color_quant_mode == CQUANT_2PASS) {
236 cinfo->enable_2pass_quant = TRUE;
237 } else if (sparams.color_quant_mode == CQUANT_EXTERNAL) {
238 cinfo->enable_external_quant = TRUE;
241 SetScanDecompressParams(dparams, cinfo, 1);
242 } else {
243 SetScanDecompressParams(dparams, cinfo, kLastScan);
248 void CheckMarkerPresent(j_decompress_ptr cinfo, uint8_t marker_type) {
249 bool marker_found = false;
250 for (jpeg_saved_marker_ptr marker = cinfo->marker_list; marker != nullptr;
251 marker = marker->next) {
252 jxl::msan::UnpoisonMemory(marker, sizeof(*marker));
253 jxl::msan::UnpoisonMemory(marker->data, marker->data_length);
254 if (marker->marker == marker_type &&
255 marker->data_length == sizeof(kMarkerData) &&
256 memcmp(marker->data, kMarkerData, sizeof(kMarkerData)) == 0) {
257 marker_found = true;
260 JXL_CHECK(marker_found);
263 void VerifyHeader(const CompressParams& jparams, j_decompress_ptr cinfo) {
264 if (jparams.set_jpeg_colorspace) {
265 JXL_CHECK(cinfo->jpeg_color_space == jparams.jpeg_color_space);
267 if (jparams.override_JFIF >= 0) {
268 JXL_CHECK(cinfo->saw_JFIF_marker == jparams.override_JFIF);
270 if (jparams.override_Adobe >= 0) {
271 JXL_CHECK(cinfo->saw_Adobe_marker == jparams.override_Adobe);
273 if (jparams.add_marker) {
274 CheckMarkerPresent(cinfo, kSpecialMarker0);
275 CheckMarkerPresent(cinfo, kSpecialMarker1);
277 jxl::msan::UnpoisonMemory(
278 cinfo->comp_info, cinfo->num_components * sizeof(cinfo->comp_info[0]));
279 int max_h_samp_factor = 1;
280 int max_v_samp_factor = 1;
281 for (int i = 0; i < cinfo->num_components; ++i) {
282 jpeg_component_info* comp = &cinfo->comp_info[i];
283 if (!jparams.comp_ids.empty()) {
284 JXL_CHECK(comp->component_id == jparams.comp_ids[i]);
286 if (!jparams.h_sampling.empty()) {
287 JXL_CHECK(comp->h_samp_factor == jparams.h_sampling[i]);
289 if (!jparams.v_sampling.empty()) {
290 JXL_CHECK(comp->v_samp_factor == jparams.v_sampling[i]);
292 if (!jparams.quant_indexes.empty()) {
293 JXL_CHECK(comp->quant_tbl_no == jparams.quant_indexes[i]);
295 max_h_samp_factor = std::max(max_h_samp_factor, comp->h_samp_factor);
296 max_v_samp_factor = std::max(max_v_samp_factor, comp->v_samp_factor);
298 JXL_CHECK(max_h_samp_factor == cinfo->max_h_samp_factor);
299 JXL_CHECK(max_v_samp_factor == cinfo->max_v_samp_factor);
300 int referenced_tables[NUM_QUANT_TBLS] = {};
301 for (int i = 0; i < cinfo->num_components; ++i) {
302 jpeg_component_info* comp = &cinfo->comp_info[i];
303 JXL_CHECK(comp->width_in_blocks ==
304 DivCeil(cinfo->image_width * comp->h_samp_factor,
305 max_h_samp_factor * DCTSIZE));
306 JXL_CHECK(comp->height_in_blocks ==
307 DivCeil(cinfo->image_height * comp->v_samp_factor,
308 max_v_samp_factor * DCTSIZE));
309 referenced_tables[comp->quant_tbl_no] = 1;
311 for (const auto& table : jparams.quant_tables) {
312 JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[table.slot_idx];
313 if (!referenced_tables[table.slot_idx]) {
314 JXL_CHECK(quant_table == nullptr);
315 continue;
317 JXL_CHECK(quant_table != nullptr);
318 jxl::msan::UnpoisonMemory(quant_table, sizeof(*quant_table));
319 for (int k = 0; k < DCTSIZE2; ++k) {
320 JXL_CHECK(quant_table->quantval[k] == table.quantval[k]);
325 void VerifyScanHeader(const CompressParams& jparams, j_decompress_ptr cinfo) {
326 JXL_CHECK(cinfo->input_scan_number > 0);
327 if (cinfo->progressive_mode) {
328 JXL_CHECK(cinfo->Ss != 0 || cinfo->Se != 63);
329 } else {
330 JXL_CHECK(cinfo->Ss == 0 && cinfo->Se == 63);
332 if (jparams.progressive_mode > 2) {
333 JXL_CHECK(jparams.progressive_mode < 3 + kNumTestScripts);
334 const ScanScript& script = kTestScript[jparams.progressive_mode - 3];
335 JXL_CHECK(cinfo->input_scan_number <= script.num_scans);
336 const jpeg_scan_info& scan = script.scans[cinfo->input_scan_number - 1];
337 JXL_CHECK(cinfo->comps_in_scan == scan.comps_in_scan);
338 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
339 JXL_CHECK(cinfo->cur_comp_info[i]->component_index ==
340 scan.component_index[i]);
342 JXL_CHECK(cinfo->Ss == scan.Ss);
343 JXL_CHECK(cinfo->Se == scan.Se);
344 JXL_CHECK(cinfo->Ah == scan.Ah);
345 JXL_CHECK(cinfo->Al == scan.Al);
347 if (jparams.restart_interval > 0) {
348 JXL_CHECK(cinfo->restart_interval == jparams.restart_interval);
349 } else if (jparams.restart_in_rows > 0) {
350 JXL_CHECK(cinfo->restart_interval ==
351 jparams.restart_in_rows * cinfo->MCUs_per_row);
353 if (jparams.progressive_mode == 0 && jparams.optimize_coding == 0) {
354 if (cinfo->jpeg_color_space == JCS_RGB) {
355 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
356 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 0);
357 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 0);
358 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
359 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 0);
360 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 0);
361 } else if (cinfo->jpeg_color_space == JCS_YCbCr) {
362 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
363 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 1);
364 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 1);
365 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
366 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 1);
367 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 1);
368 } else if (cinfo->jpeg_color_space == JCS_CMYK) {
369 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
370 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 0);
371 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 0);
372 JXL_CHECK(cinfo->comp_info[3].dc_tbl_no == 0);
373 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
374 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 0);
375 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 0);
376 JXL_CHECK(cinfo->comp_info[3].ac_tbl_no == 0);
377 } else if (cinfo->jpeg_color_space == JCS_YCCK) {
378 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
379 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 1);
380 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 1);
381 JXL_CHECK(cinfo->comp_info[3].dc_tbl_no == 0);
382 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
383 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 1);
384 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 1);
385 JXL_CHECK(cinfo->comp_info[3].ac_tbl_no == 0);
387 if (jparams.use_flat_dc_luma_code) {
388 JHUFF_TBL* tbl = cinfo->dc_huff_tbl_ptrs[0];
389 jxl::msan::UnpoisonMemory(tbl, sizeof(*tbl));
390 for (int i = 0; i < 15; ++i) {
391 JXL_CHECK(tbl->huffval[i] == i);
397 void UnmapColors(uint8_t* row, size_t xsize, int components,
398 JSAMPARRAY colormap, size_t num_colors) {
399 JXL_CHECK(colormap != nullptr);
400 std::vector<uint8_t> tmp(xsize * components);
401 for (size_t x = 0; x < xsize; ++x) {
402 JXL_CHECK(row[x] < num_colors);
403 for (int c = 0; c < components; ++c) {
404 tmp[x * components + c] = colormap[c][row[x]];
407 memcpy(row, tmp.data(), tmp.size());
410 void CopyCoefficients(j_decompress_ptr cinfo, jvirt_barray_ptr* coef_arrays,
411 TestImage* output) {
412 output->xsize = cinfo->image_width;
413 output->ysize = cinfo->image_height;
414 output->components = cinfo->num_components;
415 output->color_space = cinfo->out_color_space;
416 j_common_ptr comptr = reinterpret_cast<j_common_ptr>(cinfo);
417 for (int c = 0; c < cinfo->num_components; ++c) {
418 jpeg_component_info* comp = &cinfo->comp_info[c];
419 std::vector<JCOEF> coeffs(comp->width_in_blocks * comp->height_in_blocks *
420 DCTSIZE2);
421 for (size_t by = 0; by < comp->height_in_blocks; ++by) {
422 JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(comptr, coef_arrays[c],
423 by, 1, true);
424 size_t stride = comp->width_in_blocks * sizeof(JBLOCK);
425 size_t offset = by * comp->width_in_blocks * DCTSIZE2;
426 memcpy(&coeffs[offset], ba[0], stride);
428 output->coeffs.emplace_back(std::move(coeffs));