Bug 1905042 - The AI Chat Sidebar stays open when the user disables the AI chat integ...
[gecko.git] / third_party / jpeg-xl / lib / jpegli / test_utils-inl.h
blob4fbcb721e4c61da3e907b66b1efe4dfaa079ded8
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 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 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 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 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 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 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 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 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 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 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 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 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 = static_cast<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(reinterpret_cast<void*>(cinfo->colormap),
198 3 * sizeof(JSAMPLE*));
199 for (int i = 0; i < kTestColorMapNumColors; ++i) {
200 cinfo->colormap[0][i] = (kTestColorMap[i] >> 16) & 0xff;
201 cinfo->colormap[1][i] = (kTestColorMap[i] >> 8) & 0xff;
202 cinfo->colormap[2][i] = (kTestColorMap[i] >> 0) & 0xff;
204 if (have_colormap) {
205 JPEG_API_FN(new_colormap)(cinfo);
207 } else if (sparams->color_quant_mode == CQUANT_REUSE) {
208 JXL_CHECK(cinfo->out_color_space == JCS_RGB);
209 JXL_CHECK(cinfo->colormap);
214 void SetDecompressParams(const DecompressParams& dparams,
215 j_decompress_ptr cinfo) {
216 cinfo->do_block_smoothing = dparams.do_block_smoothing ? 1 : 0;
217 cinfo->do_fancy_upsampling = dparams.do_fancy_upsampling ? 1 : 0;
218 if (dparams.output_mode == RAW_DATA) {
219 cinfo->raw_data_out = TRUE;
221 if (dparams.set_out_color_space) {
222 cinfo->out_color_space =
223 static_cast<J_COLOR_SPACE>(dparams.out_color_space);
224 if (dparams.out_color_space == JCS_UNKNOWN) {
225 cinfo->jpeg_color_space = JCS_UNKNOWN;
228 cinfo->scale_num = dparams.scale_num;
229 cinfo->scale_denom = dparams.scale_denom;
230 cinfo->quantize_colors = dparams.quantize_colors ? 1 : 0;
231 cinfo->desired_number_of_colors = dparams.desired_number_of_colors;
232 if (!dparams.scan_params.empty()) {
233 if (cinfo->buffered_image) {
234 for (const auto& sparams : dparams.scan_params) {
235 if (sparams.color_quant_mode == CQUANT_1PASS) {
236 cinfo->enable_1pass_quant = TRUE;
237 } else if (sparams.color_quant_mode == CQUANT_2PASS) {
238 cinfo->enable_2pass_quant = TRUE;
239 } else if (sparams.color_quant_mode == CQUANT_EXTERNAL) {
240 cinfo->enable_external_quant = TRUE;
243 SetScanDecompressParams(dparams, cinfo, 1);
244 } else {
245 SetScanDecompressParams(dparams, cinfo, kLastScan);
250 void CheckMarkerPresent(j_decompress_ptr cinfo, uint8_t marker_type) {
251 bool marker_found = false;
252 for (jpeg_saved_marker_ptr marker = cinfo->marker_list; marker != nullptr;
253 marker = marker->next) {
254 jxl::msan::UnpoisonMemory(marker, sizeof(*marker));
255 jxl::msan::UnpoisonMemory(marker->data, marker->data_length);
256 if (marker->marker == marker_type &&
257 marker->data_length == sizeof(kMarkerData) &&
258 memcmp(marker->data, kMarkerData, sizeof(kMarkerData)) == 0) {
259 marker_found = true;
262 JXL_CHECK(marker_found);
265 void VerifyHeader(const CompressParams& jparams, j_decompress_ptr cinfo) {
266 if (jparams.set_jpeg_colorspace) {
267 JXL_CHECK(cinfo->jpeg_color_space == jparams.jpeg_color_space);
269 if (jparams.override_JFIF >= 0) {
270 JXL_CHECK(cinfo->saw_JFIF_marker == jparams.override_JFIF);
272 if (jparams.override_Adobe >= 0) {
273 JXL_CHECK(cinfo->saw_Adobe_marker == jparams.override_Adobe);
275 if (jparams.add_marker) {
276 CheckMarkerPresent(cinfo, kSpecialMarker0);
277 CheckMarkerPresent(cinfo, kSpecialMarker1);
279 jxl::msan::UnpoisonMemory(
280 cinfo->comp_info, cinfo->num_components * sizeof(cinfo->comp_info[0]));
281 int max_h_samp_factor = 1;
282 int max_v_samp_factor = 1;
283 for (int i = 0; i < cinfo->num_components; ++i) {
284 jpeg_component_info* comp = &cinfo->comp_info[i];
285 if (!jparams.comp_ids.empty()) {
286 JXL_CHECK(comp->component_id == jparams.comp_ids[i]);
288 if (!jparams.h_sampling.empty()) {
289 JXL_CHECK(comp->h_samp_factor == jparams.h_sampling[i]);
291 if (!jparams.v_sampling.empty()) {
292 JXL_CHECK(comp->v_samp_factor == jparams.v_sampling[i]);
294 if (!jparams.quant_indexes.empty()) {
295 JXL_CHECK(comp->quant_tbl_no == jparams.quant_indexes[i]);
297 max_h_samp_factor = std::max(max_h_samp_factor, comp->h_samp_factor);
298 max_v_samp_factor = std::max(max_v_samp_factor, comp->v_samp_factor);
300 JXL_CHECK(max_h_samp_factor == cinfo->max_h_samp_factor);
301 JXL_CHECK(max_v_samp_factor == cinfo->max_v_samp_factor);
302 int referenced_tables[NUM_QUANT_TBLS] = {};
303 for (int i = 0; i < cinfo->num_components; ++i) {
304 jpeg_component_info* comp = &cinfo->comp_info[i];
305 JXL_CHECK(comp->width_in_blocks ==
306 DivCeil(cinfo->image_width * comp->h_samp_factor,
307 max_h_samp_factor * DCTSIZE));
308 JXL_CHECK(comp->height_in_blocks ==
309 DivCeil(cinfo->image_height * comp->v_samp_factor,
310 max_v_samp_factor * DCTSIZE));
311 referenced_tables[comp->quant_tbl_no] = 1;
313 for (const auto& table : jparams.quant_tables) {
314 JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[table.slot_idx];
315 if (!referenced_tables[table.slot_idx]) {
316 JXL_CHECK(quant_table == nullptr);
317 continue;
319 JXL_CHECK(quant_table != nullptr);
320 jxl::msan::UnpoisonMemory(quant_table, sizeof(*quant_table));
321 for (int k = 0; k < DCTSIZE2; ++k) {
322 JXL_CHECK(quant_table->quantval[k] == table.quantval[k]);
327 void VerifyScanHeader(const CompressParams& jparams, j_decompress_ptr cinfo) {
328 JXL_CHECK(cinfo->input_scan_number > 0);
329 if (cinfo->progressive_mode) {
330 JXL_CHECK(cinfo->Ss != 0 || cinfo->Se != 63);
331 } else {
332 JXL_CHECK(cinfo->Ss == 0 && cinfo->Se == 63);
334 if (jparams.progressive_mode > 2) {
335 JXL_CHECK(jparams.progressive_mode < 3 + kNumTestScripts);
336 const ScanScript& script = kTestScript[jparams.progressive_mode - 3];
337 JXL_CHECK(cinfo->input_scan_number <= script.num_scans);
338 const jpeg_scan_info& scan = script.scans[cinfo->input_scan_number - 1];
339 JXL_CHECK(cinfo->comps_in_scan == scan.comps_in_scan);
340 for (int i = 0; i < cinfo->comps_in_scan; ++i) {
341 JXL_CHECK(cinfo->cur_comp_info[i]->component_index ==
342 scan.component_index[i]);
344 JXL_CHECK(cinfo->Ss == scan.Ss);
345 JXL_CHECK(cinfo->Se == scan.Se);
346 JXL_CHECK(cinfo->Ah == scan.Ah);
347 JXL_CHECK(cinfo->Al == scan.Al);
349 if (jparams.restart_interval > 0) {
350 JXL_CHECK(cinfo->restart_interval == jparams.restart_interval);
351 } else if (jparams.restart_in_rows > 0) {
352 JXL_CHECK(cinfo->restart_interval ==
353 jparams.restart_in_rows * cinfo->MCUs_per_row);
355 if (jparams.progressive_mode == 0 && jparams.optimize_coding == 0) {
356 if (cinfo->jpeg_color_space == JCS_RGB) {
357 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
358 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 0);
359 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 0);
360 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
361 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 0);
362 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 0);
363 } else if (cinfo->jpeg_color_space == JCS_YCbCr) {
364 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
365 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 1);
366 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 1);
367 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
368 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 1);
369 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 1);
370 } else if (cinfo->jpeg_color_space == JCS_CMYK) {
371 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
372 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 0);
373 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 0);
374 JXL_CHECK(cinfo->comp_info[3].dc_tbl_no == 0);
375 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
376 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 0);
377 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 0);
378 JXL_CHECK(cinfo->comp_info[3].ac_tbl_no == 0);
379 } else if (cinfo->jpeg_color_space == JCS_YCCK) {
380 JXL_CHECK(cinfo->comp_info[0].dc_tbl_no == 0);
381 JXL_CHECK(cinfo->comp_info[1].dc_tbl_no == 1);
382 JXL_CHECK(cinfo->comp_info[2].dc_tbl_no == 1);
383 JXL_CHECK(cinfo->comp_info[3].dc_tbl_no == 0);
384 JXL_CHECK(cinfo->comp_info[0].ac_tbl_no == 0);
385 JXL_CHECK(cinfo->comp_info[1].ac_tbl_no == 1);
386 JXL_CHECK(cinfo->comp_info[2].ac_tbl_no == 1);
387 JXL_CHECK(cinfo->comp_info[3].ac_tbl_no == 0);
389 if (jparams.use_flat_dc_luma_code) {
390 JHUFF_TBL* tbl = cinfo->dc_huff_tbl_ptrs[0];
391 jxl::msan::UnpoisonMemory(tbl, sizeof(*tbl));
392 for (int i = 0; i < 15; ++i) {
393 JXL_CHECK(tbl->huffval[i] == i);
399 void UnmapColors(uint8_t* row, size_t xsize, int components,
400 JSAMPARRAY colormap, size_t num_colors) {
401 JXL_CHECK(colormap != nullptr);
402 std::vector<uint8_t> tmp(xsize * components);
403 for (size_t x = 0; x < xsize; ++x) {
404 JXL_CHECK(row[x] < num_colors);
405 for (int c = 0; c < components; ++c) {
406 tmp[x * components + c] = colormap[c][row[x]];
409 memcpy(row, tmp.data(), tmp.size());
412 void CopyCoefficients(j_decompress_ptr cinfo, jvirt_barray_ptr* coef_arrays,
413 TestImage* output) {
414 output->xsize = cinfo->image_width;
415 output->ysize = cinfo->image_height;
416 output->components = cinfo->num_components;
417 output->color_space = cinfo->out_color_space;
418 j_common_ptr comptr = reinterpret_cast<j_common_ptr>(cinfo);
419 for (int c = 0; c < cinfo->num_components; ++c) {
420 jpeg_component_info* comp = &cinfo->comp_info[c];
421 std::vector<JCOEF> coeffs(comp->width_in_blocks * comp->height_in_blocks *
422 DCTSIZE2);
423 for (size_t by = 0; by < comp->height_in_blocks; ++by) {
424 JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(comptr, coef_arrays[c],
425 by, 1, TRUE);
426 size_t stride = comp->width_in_blocks * sizeof(JBLOCK);
427 size_t offset = by * comp->width_in_blocks * DCTSIZE2;
428 memcpy(&coeffs[offset], ba[0], stride);
430 output->coeffs.emplace_back(std::move(coeffs));