1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use crabby_avif::decoder::track::RepetitionCount;
16 use crabby_avif::decoder::CompressionFormat;
17 use crabby_avif::decoder::ImageContentType;
18 use crabby_avif::image::*;
19 use crabby_avif::reformat::rgb;
20 use crabby_avif::*;
21
22 #[path = "./mod.rs"]
23 mod tests;
24
25 use std::cell::RefCell;
26 use std::rc::Rc;
27 use tests::*;
28
29 // From avifalphanoispetest.cc
30 #[test]
alpha_no_ispe()31 fn alpha_no_ispe() {
32 // See https://github.com/AOMediaCodec/libavif/pull/745.
33 let mut decoder = get_decoder("alpha_noispe.avif");
34 // By default, non-strict files are refused.
35 assert!(matches!(
36 decoder.settings.strictness,
37 decoder::Strictness::All
38 ));
39 let res = decoder.parse();
40 assert!(matches!(res, Err(AvifError::BmffParseFailed(_))));
41 // Allow this kind of file specifically.
42 decoder.settings.strictness =
43 decoder::Strictness::SpecificExclude(vec![decoder::StrictnessFlag::AlphaIspeRequired]);
44 let res = decoder.parse();
45 assert!(res.is_ok());
46 let image = decoder.image().expect("image was none");
47 assert!(image.alpha_present);
48 assert!(!image.image_sequence_track_present);
49 if !HAS_DECODER {
50 return;
51 }
52 let res = decoder.next_image();
53 assert!(res.is_ok());
54 let image = decoder.image().expect("image was none");
55 let alpha_plane = image.plane_data(Plane::A);
56 assert!(alpha_plane.is_some());
57 assert!(alpha_plane.unwrap().row_bytes > 0);
58 }
59
60 #[test]
alpha_premultiplied()61 fn alpha_premultiplied() {
62 let mut decoder = get_decoder("alpha_premultiplied.avif");
63 let res = decoder.parse();
64 assert!(res.is_ok());
65 let image = decoder.image().expect("image was none");
66 assert!(image.alpha_present);
67 assert!(image.alpha_premultiplied);
68 if !HAS_DECODER {
69 return;
70 }
71 let res = decoder.next_image();
72 assert!(res.is_ok());
73 let image = decoder.image().expect("image was none");
74 assert!(image.alpha_present);
75 assert!(image.alpha_premultiplied);
76 let alpha_plane = image.plane_data(Plane::A);
77 assert!(alpha_plane.is_some());
78 assert!(alpha_plane.unwrap().row_bytes > 0);
79 }
80
81 // From avifanimationtest.cc
82 #[test_case::test_case("colors-animated-8bpc.avif")]
83 #[test_case::test_case("colors-animated-8bpc-audio.avif")]
animated_image(filename: &str)84 fn animated_image(filename: &str) {
85 let mut decoder = get_decoder(filename);
86 let res = decoder.parse();
87 assert!(res.is_ok());
88 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
89 let image = decoder.image().expect("image was none");
90 assert!(!image.alpha_present);
91 assert!(image.image_sequence_track_present);
92 assert_eq!(decoder.image_count(), 5);
93 assert_eq!(decoder.repetition_count(), RepetitionCount::Finite(0));
94 for i in 0..5 {
95 assert_eq!(decoder.nearest_keyframe(i), 0);
96 }
97 if !HAS_DECODER {
98 return;
99 }
100 for _ in 0..5 {
101 assert!(decoder.next_image().is_ok());
102 }
103 }
104
105 // From avifanimationtest.cc
106 #[test_case::test_case("colors-animated-8bpc.avif")]
107 #[test_case::test_case("colors-animated-8bpc-audio.avif")]
animated_image_with_source_set_to_primary_item(filename: &str)108 fn animated_image_with_source_set_to_primary_item(filename: &str) {
109 let mut decoder = get_decoder(filename);
110 decoder.settings.source = decoder::Source::PrimaryItem;
111 let res = decoder.parse();
112 assert!(res.is_ok());
113 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
114 let image = decoder.image().expect("image was none");
115 assert!(!image.alpha_present);
116 // This will be reported as true irrespective of the preferred source.
117 assert!(image.image_sequence_track_present);
118 // imageCount is expected to be 1 because we are using primary item as the
119 // preferred source.
120 assert_eq!(decoder.image_count(), 1);
121 assert_eq!(decoder.repetition_count(), RepetitionCount::Finite(0));
122 if !HAS_DECODER {
123 return;
124 }
125 // Get the first (and only) image.
126 assert!(decoder.next_image().is_ok());
127 // Subsequent calls should not return anything since there is only one
128 // image in the preferred source.
129 assert!(decoder.next_image().is_err());
130 }
131
132 // From avifanimationtest.cc
133 #[test]
animated_image_with_alpha_and_metadata()134 fn animated_image_with_alpha_and_metadata() {
135 let mut decoder = get_decoder("colors-animated-8bpc-alpha-exif-xmp.avif");
136 let res = decoder.parse();
137 assert!(res.is_ok());
138 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
139 let image = decoder.image().expect("image was none");
140 assert!(image.alpha_present);
141 assert!(image.image_sequence_track_present);
142 assert_eq!(decoder.image_count(), 5);
143 assert_eq!(decoder.repetition_count(), RepetitionCount::Infinite);
144 assert_eq!(image.exif.len(), 1126);
145 assert_eq!(image.xmp.len(), 3898);
146 if !HAS_DECODER {
147 return;
148 }
149 for _ in 0..5 {
150 assert!(decoder.next_image().is_ok());
151 }
152 }
153
154 #[test]
animated_image_with_depth_and_metadata()155 fn animated_image_with_depth_and_metadata() {
156 // Depth map data is not supported and should be ignored.
157 let mut decoder = get_decoder("colors-animated-8bpc-depth-exif-xmp.avif");
158 let res = decoder.parse();
159 assert!(res.is_ok());
160 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
161 let image = decoder.image().expect("image was none");
162 assert!(!image.alpha_present);
163 assert!(image.image_sequence_track_present);
164 assert_eq!(decoder.image_count(), 5);
165 assert_eq!(decoder.repetition_count(), RepetitionCount::Infinite);
166 assert_eq!(image.exif.len(), 1126);
167 assert_eq!(image.xmp.len(), 3898);
168 if !HAS_DECODER {
169 return;
170 }
171 for _ in 0..5 {
172 assert!(decoder.next_image().is_ok());
173 }
174 }
175
176 #[test]
animated_image_with_depth_and_metadata_source_set_to_primary_item()177 fn animated_image_with_depth_and_metadata_source_set_to_primary_item() {
178 // Depth map data is not supported and should be ignored.
179 let mut decoder = get_decoder("colors-animated-8bpc-depth-exif-xmp.avif");
180 decoder.settings.source = decoder::Source::PrimaryItem;
181 let res = decoder.parse();
182 assert!(res.is_ok());
183 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
184 let image = decoder.image().expect("image was none");
185 assert!(!image.alpha_present);
186 // This will be reported as true irrespective of the preferred source.
187 assert!(image.image_sequence_track_present);
188 // imageCount is expected to be 1 because we are using primary item as the
189 // preferred source.
190 assert_eq!(decoder.image_count(), 1);
191 assert_eq!(decoder.repetition_count(), RepetitionCount::Finite(0));
192 if !HAS_DECODER {
193 return;
194 }
195 // Get the first (and only) image.
196 assert!(decoder.next_image().is_ok());
197 // Subsequent calls should not return anything since there is only one
198 // image in the preferred source.
199 assert!(decoder.next_image().is_err());
200 }
201
202 // From avifkeyframetest.cc
203 #[test]
keyframes()204 fn keyframes() {
205 let mut decoder = get_decoder("colors-animated-12bpc-keyframes-0-2-3.avif");
206 let res = decoder.parse();
207 assert!(res.is_ok());
208 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
209 let image = decoder.image().expect("image was none");
210 assert!(image.image_sequence_track_present);
211 assert_eq!(decoder.image_count(), 5);
212
213 // First frame is always a keyframe.
214 assert!(decoder.is_keyframe(0));
215 assert_eq!(decoder.nearest_keyframe(0), 0);
216
217 assert!(!decoder.is_keyframe(1));
218 assert_eq!(decoder.nearest_keyframe(1), 0);
219
220 assert!(decoder.is_keyframe(2));
221 assert_eq!(decoder.nearest_keyframe(2), 2);
222
223 assert!(decoder.is_keyframe(3));
224 assert_eq!(decoder.nearest_keyframe(3), 3);
225
226 assert!(!decoder.is_keyframe(4));
227 assert_eq!(decoder.nearest_keyframe(4), 3);
228
229 // Not an existing frame.
230 assert!(!decoder.is_keyframe(15));
231 assert_eq!(decoder.nearest_keyframe(15), 3);
232 }
233
234 // From avifdecodetest.cc
235 #[test]
color_grid_alpha_no_grid()236 fn color_grid_alpha_no_grid() {
237 // Test case from https://github.com/AOMediaCodec/libavif/issues/1203.
238 let mut decoder = get_decoder("color_grid_alpha_nogrid.avif");
239 let res = decoder.parse();
240 assert!(res.is_ok());
241 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
242 let image = decoder.image().expect("image was none");
243 assert!(image.alpha_present);
244 assert!(!image.image_sequence_track_present);
245 if !HAS_DECODER {
246 return;
247 }
248 let res = decoder.next_image();
249 assert!(res.is_ok());
250 let image = decoder.image().expect("image was none");
251 let alpha_plane = image.plane_data(Plane::A);
252 assert!(alpha_plane.is_some());
253 assert!(alpha_plane.unwrap().row_bytes > 0);
254 }
255
256 // From avifprogressivetest.cc
257 #[test_case::test_case("progressive_dimension_change.avif", 2, 256, 256; "progressive_dimension_change")]
258 #[test_case::test_case("progressive_layered_grid.avif", 2, 512, 256; "progressive_layered_grid")]
259 #[test_case::test_case("progressive_quality_change.avif", 2, 256, 256; "progressive_quality_change")]
260 #[test_case::test_case("progressive_same_layers.avif", 4, 256, 256; "progressive_same_layers")]
261 #[test_case::test_case("tiger_3layer_1res.avif", 3, 1216, 832; "tiger_3layer_1res")]
262 #[test_case::test_case("tiger_3layer_3res.avif", 3, 1216, 832; "tiger_3layer_3res")]
progressive(filename: &str, layer_count: u32, width: u32, height: u32)263 fn progressive(filename: &str, layer_count: u32, width: u32, height: u32) {
264 let mut filename_with_prefix = String::from("progressive/");
265 filename_with_prefix.push_str(filename);
266 let mut decoder = get_decoder(&filename_with_prefix);
267
268 decoder.settings.allow_progressive = false;
269 let res = decoder.parse();
270 assert!(res.is_ok());
271 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
272 let image = decoder.image().expect("image was none");
273 assert!(matches!(
274 image.progressive_state,
275 decoder::ProgressiveState::Available
276 ));
277
278 decoder.settings.allow_progressive = true;
279 let res = decoder.parse();
280 assert!(res.is_ok());
281 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
282 let image = decoder.image().expect("image was none");
283 assert!(matches!(
284 image.progressive_state,
285 decoder::ProgressiveState::Active
286 ));
287 assert_eq!(image.width, width);
288 assert_eq!(image.height, height);
289 assert_eq!(decoder.image_count(), layer_count);
290 if !HAS_DECODER {
291 return;
292 }
293 for _i in 0..decoder.image_count() {
294 let res = decoder.next_image();
295 assert!(res.is_ok());
296 let image = decoder.image().expect("image was none");
297 assert_eq!(image.width, width);
298 assert_eq!(image.height, height);
299 }
300 }
301
302 // From avifmetadatatest.cc
303 #[test]
decoder_parse_icc_exif_xmp()304 fn decoder_parse_icc_exif_xmp() {
305 // Test case from https://github.com/AOMediaCodec/libavif/issues/1086.
306 let mut decoder = get_decoder("paris_icc_exif_xmp.avif");
307
308 decoder.settings.ignore_xmp = true;
309 decoder.settings.ignore_exif = true;
310 let res = decoder.parse();
311 assert!(res.is_ok());
312 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
313 let image = decoder.image().expect("image was none");
314
315 assert_eq!(image.icc.len(), 596);
316 assert_eq!(image.icc[0], 0);
317 assert_eq!(image.icc[1], 0);
318 assert_eq!(image.icc[2], 2);
319 assert_eq!(image.icc[3], 84);
320
321 assert!(image.exif.is_empty());
322 assert!(image.xmp.is_empty());
323
324 decoder.settings.ignore_xmp = false;
325 decoder.settings.ignore_exif = false;
326 let res = decoder.parse();
327 assert!(res.is_ok());
328 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
329 let image = decoder.image().expect("image was none");
330
331 assert_eq!(image.exif.len(), 1126);
332 assert_eq!(image.exif[0], 73);
333 assert_eq!(image.exif[1], 73);
334 assert_eq!(image.exif[2], 42);
335 assert_eq!(image.exif[3], 0);
336
337 assert_eq!(image.xmp.len(), 3898);
338 assert_eq!(image.xmp[0], 60);
339 assert_eq!(image.xmp[1], 63);
340 assert_eq!(image.xmp[2], 120);
341 assert_eq!(image.xmp[3], 112);
342 }
343
344 // From avifgainmaptest.cc
345 #[test]
color_grid_gainmap_different_grid()346 fn color_grid_gainmap_different_grid() {
347 let mut decoder = get_decoder("color_grid_gainmap_different_grid.avif");
348 decoder.settings.image_content_to_decode = ImageContentType::All;
349 let res = decoder.parse();
350 assert!(res.is_ok());
351 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
352 let image = decoder.image().expect("image was none");
353 // Color+alpha: 4x3 grid of 128x200 tiles.
354 assert_eq!(image.width, 128 * 4);
355 assert_eq!(image.height, 200 * 3);
356 assert_eq!(image.depth, 10);
357 // Gain map: 2x2 grid of 64x80 tiles.
358 assert!(decoder.gainmap_present());
359 assert_eq!(decoder.gainmap().image.width, 64 * 2);
360 assert_eq!(decoder.gainmap().image.height, 80 * 2);
361 assert_eq!(decoder.gainmap().image.depth, 8);
362 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 6);
363 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.1, 2);
364 if !HAS_DECODER {
365 return;
366 }
367 let res = decoder.next_image();
368 assert!(res.is_ok());
369 assert!(decoder.gainmap().image.row_bytes[0] > 0);
370 }
371
372 // From avifgainmaptest.cc
373 #[test]
color_grid_alpha_grid_gainmap_nogrid()374 fn color_grid_alpha_grid_gainmap_nogrid() {
375 let mut decoder = get_decoder("color_grid_alpha_grid_gainmap_nogrid.avif");
376 decoder.settings.image_content_to_decode = ImageContentType::All;
377 let res = decoder.parse();
378 assert!(res.is_ok());
379 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
380 let image = decoder.image().expect("image was none");
381 // Color+alpha: 4x3 grid of 128x200 tiles.
382 assert_eq!(image.width, 128 * 4);
383 assert_eq!(image.height, 200 * 3);
384 assert_eq!(image.depth, 10);
385 // Gain map: single image of size 64x80.
386 assert!(decoder.gainmap_present());
387 assert_eq!(decoder.gainmap().image.width, 64);
388 assert_eq!(decoder.gainmap().image.height, 80);
389 assert_eq!(decoder.gainmap().image.depth, 8);
390 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 6);
391 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.1, 2);
392 if !HAS_DECODER {
393 return;
394 }
395 let res = decoder.next_image();
396 assert!(res.is_ok());
397 assert!(decoder.gainmap().image.row_bytes[0] > 0);
398 }
399
400 // From avifgainmaptest.cc
401 #[test]
color_nogrid_alpha_nogrid_gainmap_grid()402 fn color_nogrid_alpha_nogrid_gainmap_grid() {
403 let mut decoder = get_decoder("color_nogrid_alpha_nogrid_gainmap_grid.avif");
404 decoder.settings.image_content_to_decode = ImageContentType::All;
405 let res = decoder.parse();
406 assert!(res.is_ok());
407 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
408 let image = decoder.image().expect("image was none");
409 // Color+alpha: single image of size 128x200.
410 assert_eq!(image.width, 128);
411 assert_eq!(image.height, 200);
412 assert_eq!(image.depth, 10);
413 // Gain map: 2x2 grid of 64x80 tiles.
414 assert!(decoder.gainmap_present());
415 assert_eq!(decoder.gainmap().image.width, 64 * 2);
416 assert_eq!(decoder.gainmap().image.height, 80 * 2);
417 assert_eq!(decoder.gainmap().image.depth, 8);
418 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 6);
419 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.1, 2);
420 if !HAS_DECODER {
421 return;
422 }
423 let res = decoder.next_image();
424 assert!(res.is_ok());
425 assert!(decoder.gainmap().image.row_bytes[0] > 0);
426 }
427
428 // From avifgainmaptest.cc
429 #[test]
gainmap_oriented()430 fn gainmap_oriented() {
431 let mut decoder = get_decoder("gainmap_oriented.avif");
432 decoder.settings.image_content_to_decode = ImageContentType::All;
433 let res = decoder.parse();
434 assert!(res.is_ok());
435 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
436 let image = decoder.image().expect("image was none");
437 assert_eq!(image.irot_angle, Some(1));
438 assert_eq!(image.imir_axis, Some(0));
439 assert!(decoder.gainmap_present());
440 assert_eq!(decoder.gainmap().image.irot_angle, None);
441 assert_eq!(decoder.gainmap().image.imir_axis, None);
442 }
443
444 // The two test files should produce the same results:
445 // One has an unsupported 'version' field, the other an unsupported
446 // 'minimum_version' field, but the behavior of these two files is the same.
447 // From avifgainmaptest.cc
448 #[test_case::test_case("unsupported_gainmap_version.avif")]
449 #[test_case::test_case("unsupported_gainmap_minimum_version.avif")]
decode_unsupported_version(filename: &str)450 fn decode_unsupported_version(filename: &str) {
451 // Parse with various settings.
452 let mut decoder = get_decoder(filename);
453 let res = decoder.parse();
454 assert!(res.is_ok());
455 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
456 // Gain map marked as not present because the metadata is not supported.
457 assert!(!decoder.gainmap_present());
458 assert_eq!(decoder.gainmap().image.width, 0);
459 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 0);
460 assert_eq!(decoder.gainmap().metadata.alternate_hdr_headroom.0, 0);
461
462 decoder = get_decoder(filename);
463 decoder.settings.image_content_to_decode = ImageContentType::All;
464 let res = decoder.parse();
465 assert!(res.is_ok());
466 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
467 // Gainmap not found: its metadata is not supported.
468 assert!(!decoder.gainmap_present());
469 assert_eq!(decoder.gainmap().image.width, 0);
470 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 0);
471 assert_eq!(decoder.gainmap().metadata.alternate_hdr_headroom.0, 0);
472 }
473
474 // From avifgainmaptest.cc
475 #[test]
decode_unsupported_writer_version_with_extra_bytes()476 fn decode_unsupported_writer_version_with_extra_bytes() {
477 let mut decoder = get_decoder("unsupported_gainmap_writer_version_with_extra_bytes.avif");
478 let res = decoder.parse();
479 assert!(res.is_ok());
480 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
481 // Decodes successfully: there are extra bytes at the end of the gain map
482 // metadata but that's expected as the writer_version field is higher
483 // that supported.
484 assert!(decoder.gainmap_present());
485 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.0, 6);
486 assert_eq!(decoder.gainmap().metadata.base_hdr_headroom.1, 2);
487 }
488
489 // From avifgainmaptest.cc
490 #[test]
decode_supported_writer_version_with_extra_bytes()491 fn decode_supported_writer_version_with_extra_bytes() {
492 let mut decoder = get_decoder("supported_gainmap_writer_version_with_extra_bytes.avif");
493 let res = decoder.parse();
494 // Fails to decode: there are extra bytes at the end of the gain map metadata
495 // that shouldn't be there.
496 assert!(matches!(res, Err(AvifError::InvalidToneMappedImage(_))));
497 }
498
499 // From avifgainmaptest.cc
500 #[test]
decode_ignore_gain_map_but_read_metadata()501 fn decode_ignore_gain_map_but_read_metadata() {
502 let mut decoder = get_decoder("seine_sdr_gainmap_srgb.avif");
503
504 let res = decoder.parse();
505 assert!(res.is_ok());
506 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
507 decoder.image().expect("image was none");
508 // Gain map not decoded.
509 assert!(decoder.gainmap_present());
510 // ... but not decoded because enableDecodingGainMap is false by default.
511 assert_eq!(decoder.gainmap().image.width, 0);
512 assert_eq!(decoder.gainmap().image.row_bytes[0], 0);
513 // Check that the gain map metadata WAS populated.
514 assert_eq!(decoder.gainmap().metadata.alternate_hdr_headroom.0, 13);
515 assert_eq!(decoder.gainmap().metadata.alternate_hdr_headroom.1, 10);
516 }
517
518 // From avifgainmaptest.cc
519 #[test]
decode_ignore_color_and_alpha()520 fn decode_ignore_color_and_alpha() {
521 let mut decoder = get_decoder("seine_sdr_gainmap_srgb.avif");
522 decoder.settings.image_content_to_decode = ImageContentType::GainMap;
523
524 let res = decoder.parse();
525 assert!(res.is_ok());
526 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
527
528 let image = decoder.image().expect("image was none");
529 // Main image metadata is available.
530 assert_eq!(image.width, 400);
531 // The gain map metadata is available.
532 assert!(decoder.gainmap_present());
533 assert_eq!(decoder.gainmap().image.width, 400);
534 assert_eq!(decoder.gainmap().metadata.alternate_hdr_headroom.0, 13);
535
536 if !HAS_DECODER {
537 return;
538 }
539 let res = decoder.next_image();
540 let image = decoder.image().expect("image was none");
541 assert!(res.is_ok());
542 // Main image pixels are not available.
543 assert_eq!(image.row_bytes[0], 0);
544 // Gain map pixels are available.
545 assert!(decoder.gainmap().image.row_bytes[0] > 0);
546 }
547
548 // From avifgainmaptest.cc
549 #[test_case::test_case("paris_icc_exif_xmp.avif")]
550 #[test_case::test_case("sofa_grid1x5_420.avif")]
551 #[test_case::test_case("color_grid_alpha_nogrid.avif")]
552 #[test_case::test_case("seine_sdr_gainmap_srgb.avif")]
decode_ignore_all(filename: &str)553 fn decode_ignore_all(filename: &str) {
554 let mut decoder = get_decoder(filename);
555 // Ignore both the main image and the gain map.
556 decoder.settings.image_content_to_decode = ImageContentType::None;
557 // But do read the gain map metadata
558
559 let res = decoder.parse();
560 assert!(res.is_ok());
561 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
562 let image = decoder.image().expect("image was none");
563 // Main image metadata is available.
564 assert!(image.width > 0);
565 // But trying to access the next image should give an error because both
566 // ignoreColorAndAlpha and enableDecodingGainMap are set.
567 let res = decoder.next_image();
568 assert!(res.is_err());
569 }
570
571 // From avifcllitest.cc
572 #[test_case::test_case("clli_0_0.avif", 0, 0; "clli_0_0")]
573 #[test_case::test_case("clli_0_1.avif", 0, 1; "clli_0_1")]
574 #[test_case::test_case("clli_0_65535.avif", 0, 65535; "clli_0_65535")]
575 #[test_case::test_case("clli_1_0.avif", 1, 0; "clli_1_0")]
576 #[test_case::test_case("clli_1_1.avif", 1, 1; "clli_1_1")]
577 #[test_case::test_case("clli_1_65535.avif", 1, 65535; "clli_1_65535")]
578 #[test_case::test_case("clli_65535_0.avif", 65535, 0; "clli_65535_0")]
579 #[test_case::test_case("clli_65535_1.avif", 65535, 1; "clli_65535_1")]
580 #[test_case::test_case("clli_65535_65535.avif", 65535, 65535; "clli_65535_65535")]
clli(filename: &str, max_cll: u16, max_pall: u16)581 fn clli(filename: &str, max_cll: u16, max_pall: u16) {
582 let mut filename_with_prefix = String::from("clli/");
583 filename_with_prefix.push_str(filename);
584 let mut decoder = get_decoder(&filename_with_prefix);
585 let res = decoder.parse();
586 assert!(res.is_ok());
587 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
588 let image = decoder.image().expect("image was none");
589 if max_cll == 0 && max_pall == 0 {
590 assert!(image.clli.is_none());
591 } else {
592 assert!(image.clli.is_some());
593 let clli = image.clli.as_ref().unwrap();
594 assert_eq!(clli.max_cll, max_cll);
595 assert_eq!(clli.max_pall, max_pall);
596 }
597 }
598
599 #[test]
raw_io()600 fn raw_io() {
601 let data =
602 std::fs::read(get_test_file("colors-animated-8bpc.avif")).expect("Unable to read file");
603 let mut decoder = decoder::Decoder::default();
604 let _ = unsafe {
605 decoder
606 .set_io_raw(data.as_ptr(), data.len())
607 .expect("Failed to set IO")
608 };
609 assert!(decoder.parse().is_ok());
610 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
611 assert_eq!(decoder.image_count(), 5);
612 if !HAS_DECODER {
613 return;
614 }
615 for _ in 0..5 {
616 assert!(decoder.next_image().is_ok());
617 }
618 }
619
620 struct CustomIO {
621 data: Vec<u8>,
622 available_size_rc: Rc<RefCell<usize>>,
623 }
624
625 impl decoder::IO for CustomIO {
read(&mut self, offset: u64, max_read_size: usize) -> AvifResult<&[u8]>626 fn read(&mut self, offset: u64, max_read_size: usize) -> AvifResult<&[u8]> {
627 let available_size = self.available_size_rc.borrow();
628 let start = usize::try_from(offset).unwrap();
629 let end = start + max_read_size;
630 if start > self.data.len() || end > self.data.len() {
631 return Err(AvifError::IoError);
632 }
633 let mut ssize = max_read_size;
634 if ssize > self.data.len() - start {
635 ssize = self.data.len() - start;
636 }
637 let end = start + ssize;
638 if *available_size < end {
639 return Err(AvifError::WaitingOnIo);
640 }
641 Ok(&self.data[start..end])
642 }
643
size_hint(&self) -> u64644 fn size_hint(&self) -> u64 {
645 self.data.len() as u64
646 }
647
persistent(&self) -> bool648 fn persistent(&self) -> bool {
649 false
650 }
651 }
652
653 #[test]
custom_io()654 fn custom_io() {
655 let data =
656 std::fs::read(get_test_file("colors-animated-8bpc.avif")).expect("Unable to read file");
657 let mut decoder = decoder::Decoder::default();
658 let available_size_rc = Rc::new(RefCell::new(data.len()));
659 let io = Box::new(CustomIO {
660 available_size_rc: available_size_rc.clone(),
661 data,
662 });
663 decoder.set_io(io);
664 assert!(decoder.parse().is_ok());
665 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
666 assert_eq!(decoder.image_count(), 5);
667 if !HAS_DECODER {
668 return;
669 }
670 for _ in 0..5 {
671 assert!(decoder.next_image().is_ok());
672 }
673 }
674
expected_min_decoded_row_count( height: u32, cell_height: u32, cell_columns: u32, available_size: usize, size: usize, grid_cell_offsets: &Vec<usize>, ) -> u32675 fn expected_min_decoded_row_count(
676 height: u32,
677 cell_height: u32,
678 cell_columns: u32,
679 available_size: usize,
680 size: usize,
681 grid_cell_offsets: &Vec<usize>,
682 ) -> u32 {
683 if available_size >= size {
684 return height;
685 }
686 let mut cell_index: Option<usize> = None;
687 for (index, offset) in grid_cell_offsets.iter().enumerate().rev() {
688 if available_size >= *offset {
689 cell_index = Some(index);
690 break;
691 }
692 }
693 if cell_index.is_none() {
694 return 0;
695 }
696 let cell_index = cell_index.unwrap() as u32;
697 let cell_row = cell_index / cell_columns;
698 let cell_column = cell_index % cell_columns;
699 let cell_rows_decoded = if cell_column == cell_columns - 1 { cell_row + 1 } else { cell_row };
700 cell_rows_decoded * cell_height
701 }
702
703 #[test]
expected_min_decoded_row_count_computation()704 fn expected_min_decoded_row_count_computation() {
705 let grid_cell_offsets: Vec<usize> = vec![3258, 10643, 17846, 22151, 25409, 30000];
706 let cell_height = 154;
707 assert_eq!(
708 0,
709 expected_min_decoded_row_count(770, cell_height, 1, 1000, 30000, &grid_cell_offsets)
710 );
711 assert_eq!(
712 1 * cell_height,
713 expected_min_decoded_row_count(770, cell_height, 1, 4000, 30000, &grid_cell_offsets)
714 );
715 assert_eq!(
716 2 * cell_height,
717 expected_min_decoded_row_count(770, cell_height, 1, 12000, 30000, &grid_cell_offsets)
718 );
719 assert_eq!(
720 3 * cell_height,
721 expected_min_decoded_row_count(770, cell_height, 1, 17846, 30000, &grid_cell_offsets)
722 );
723 assert_eq!(
724 1 * cell_height,
725 expected_min_decoded_row_count(462, cell_height, 2, 17846, 30000, &grid_cell_offsets)
726 );
727 assert_eq!(
728 2 * cell_height,
729 expected_min_decoded_row_count(462, cell_height, 2, 23000, 30000, &grid_cell_offsets)
730 );
731 assert_eq!(
732 1 * cell_height,
733 expected_min_decoded_row_count(308, cell_height, 3, 23000, 30000, &grid_cell_offsets)
734 );
735 assert_eq!(
736 2 * cell_height,
737 expected_min_decoded_row_count(308, cell_height, 3, 30000, 30000, &grid_cell_offsets)
738 );
739 }
740
741 #[test]
incremental_decode()742 fn incremental_decode() {
743 // Grid item offsets for sofa_grid1x5_420.avif:
744 // Each line is "$extent_offset + $extent_length".
745 let grid_cell_offsets: Vec<usize> = vec![
746 578 + 2680,
747 3258 + 7385,
748 10643 + 7203,
749 17846 + 4305,
750 22151 + 3258,
751 ];
752
753 let data = std::fs::read(get_test_file("sofa_grid1x5_420.avif")).expect("Unable to read file");
754 let len = data.len();
755 let available_size_rc = Rc::new(RefCell::new(0usize));
756 let mut decoder = decoder::Decoder::default();
757 decoder.settings.allow_incremental = true;
758 let io = Box::new(CustomIO {
759 available_size_rc: available_size_rc.clone(),
760 data,
761 });
762 decoder.set_io(io);
763 let step: usize = std::cmp::max(1, len / 10000) as usize;
764
765 // Parsing is not incremental.
766 let mut parse_result = decoder.parse();
767 while parse_result.is_err()
768 && matches!(parse_result.as_ref().err().unwrap(), AvifError::WaitingOnIo)
769 {
770 {
771 let mut available_size = available_size_rc.borrow_mut();
772 if *available_size >= len {
773 println!("parse returned waiting on io after full file.");
774 assert!(false);
775 }
776 *available_size = std::cmp::min(*available_size + step, len);
777 }
778 parse_result = decoder.parse();
779 }
780 assert!(parse_result.is_ok());
781 if !HAS_DECODER {
782 return;
783 }
784
785 // Decoding is incremental.
786 let mut previous_decoded_row_count = 0;
787 let mut decode_result = decoder.next_image();
788 while decode_result.is_err()
789 && matches!(
790 decode_result.as_ref().err().unwrap(),
791 AvifError::WaitingOnIo
792 )
793 {
794 {
795 let mut available_size = available_size_rc.borrow_mut();
796 if *available_size >= len {
797 println!("next_image returned waiting on io after full file.");
798 assert!(false);
799 }
800 let decoded_row_count = decoder.decoded_row_count();
801 assert!(decoded_row_count >= previous_decoded_row_count);
802 let expected_min_decoded_row_count = expected_min_decoded_row_count(
803 decoder.image().unwrap().height,
804 154,
805 1,
806 *available_size,
807 len,
808 &grid_cell_offsets,
809 );
810 assert!(decoded_row_count >= expected_min_decoded_row_count);
811 previous_decoded_row_count = decoded_row_count;
812 *available_size = std::cmp::min(*available_size + step, len);
813 }
814 decode_result = decoder.next_image();
815 }
816 assert!(decode_result.is_ok());
817 assert_eq!(decoder.decoded_row_count(), decoder.image().unwrap().height);
818
819 // TODO: check if incremental and non incremental produces same output.
820 }
821
822 #[test]
nth_image()823 fn nth_image() {
824 let mut decoder = get_decoder("colors-animated-8bpc.avif");
825 let res = decoder.parse();
826 assert!(res.is_ok());
827 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
828 assert_eq!(decoder.image_count(), 5);
829 if !HAS_DECODER {
830 return;
831 }
832 assert!(decoder.nth_image(3).is_ok());
833 assert!(decoder.next_image().is_ok());
834 assert!(decoder.next_image().is_err());
835 assert!(decoder.nth_image(1).is_ok());
836 assert!(decoder.nth_image(4).is_ok());
837 assert!(decoder.nth_image(50).is_err());
838 }
839
840 #[test]
color_and_alpha_dimensions_do_not_match()841 fn color_and_alpha_dimensions_do_not_match() {
842 let mut decoder = get_decoder("invalid_color10x10_alpha5x5.avif");
843 // Parsing should succeed.
844 let res = decoder.parse();
845 assert!(res.is_ok());
846 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
847 let image = decoder.image().expect("image was none");
848 assert_eq!(image.width, 10);
849 assert_eq!(image.height, 10);
850 if !HAS_DECODER {
851 return;
852 }
853 // Decoding should fail.
854 let res = decoder.next_image();
855 assert!(res.is_err());
856 }
857
858 #[test]
rgb_conversion_alpha_premultiply() -> AvifResult<()>859 fn rgb_conversion_alpha_premultiply() -> AvifResult<()> {
860 let mut decoder = get_decoder("alpha.avif");
861 let res = decoder.parse();
862 assert!(res.is_ok());
863 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
864 if !HAS_DECODER {
865 return Ok(());
866 }
867 let res = decoder.next_image();
868 assert!(res.is_ok());
869 let image = decoder.image().expect("image was none");
870 let mut rgb = rgb::Image::create_from_yuv(image);
871 rgb.premultiply_alpha = true;
872 rgb.allocate()?;
873 assert!(rgb.convert_from_yuv(image).is_ok());
874 Ok(())
875 }
876
877 #[test]
white_1x1() -> AvifResult<()>878 fn white_1x1() -> AvifResult<()> {
879 let mut decoder = get_decoder("white_1x1.avif");
880 assert_eq!(decoder.parse(), Ok(()));
881 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
882 if !HAS_DECODER {
883 return Ok(());
884 }
885 assert_eq!(decoder.next_image(), Ok(()));
886
887 let image = decoder.image().expect("image was none");
888 let mut rgb = rgb::Image::create_from_yuv(image);
889 rgb.allocate()?;
890 assert!(rgb.convert_from_yuv(image).is_ok());
891 assert_eq!(rgb.width * rgb.height, 1);
892 let format = rgb.format;
893 for i in [format.r_offset(), format.g_offset(), format.b_offset()] {
894 assert_eq!(rgb.row(0)?[i], 253); // Compressed with loss, not pure white.
895 }
896 if rgb.has_alpha() {
897 assert_eq!(rgb.row(0)?[rgb.format.alpha_offset()], 255);
898 }
899 Ok(())
900 }
901
902 #[test]
white_1x1_mdat_size0() -> AvifResult<()>903 fn white_1x1_mdat_size0() -> AvifResult<()> {
904 // Edit the file to simulate an 'mdat' box with size 0 (meaning it ends at EOF).
905 let mut file_bytes = std::fs::read(get_test_file("white_1x1.avif")).unwrap();
906 let mdat = [b'm', b'd', b'a', b't'];
907 let mdat_size_pos = file_bytes.windows(4).position(|w| w == mdat).unwrap() - 4;
908 file_bytes[mdat_size_pos + 3] = b'\0';
909
910 let mut decoder = decoder::Decoder::default();
911 decoder.set_io_vec(file_bytes);
912 assert_eq!(decoder.parse(), Ok(()));
913 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
914 Ok(())
915 }
916
917 #[test]
white_1x1_meta_size0() -> AvifResult<()>918 fn white_1x1_meta_size0() -> AvifResult<()> {
919 // Edit the file to simulate a 'meta' box with size 0 (invalid).
920 let mut file_bytes = std::fs::read(get_test_file("white_1x1.avif")).unwrap();
921 let meta = [b'm', b'e', b't', b'a'];
922 let meta_size_pos = file_bytes.windows(4).position(|w| w == meta).unwrap() - 4;
923 file_bytes[meta_size_pos + 3] = b'\0';
924
925 let mut decoder = decoder::Decoder::default();
926 decoder.set_io_vec(file_bytes);
927
928 // This should fail because the meta box contains the mdat box.
929 // However, the section 8.11.3.1 of ISO/IEC 14496-12 does not explicitly require the coded image
930 // item extents to be read from the MediaDataBox if the construction_method is 0.
931 // Maybe another section or specification enforces that.
932 assert_eq!(decoder.parse(), Ok(()));
933 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
934 if !HAS_DECODER {
935 return Ok(());
936 }
937 assert_eq!(decoder.next_image(), Ok(()));
938 Ok(())
939 }
940
941 #[test]
white_1x1_ftyp_size0() -> AvifResult<()>942 fn white_1x1_ftyp_size0() -> AvifResult<()> {
943 // Edit the file to simulate a 'ftyp' box with size 0 (invalid).
944 let mut file_bytes = std::fs::read(get_test_file("white_1x1.avif")).unwrap();
945 file_bytes[3] = b'\0';
946
947 let mut decoder = decoder::Decoder::default();
948 decoder.set_io_vec(file_bytes);
949 assert!(matches!(
950 decoder.parse(),
951 Err(AvifError::BmffParseFailed(_))
952 ));
953 Ok(())
954 }
955
956 #[test]
dimg_repetition()957 fn dimg_repetition() {
958 let mut decoder = get_decoder("sofa_grid1x5_420_dimg_repeat.avif");
959 assert_eq!(
960 decoder.parse(),
961 Err(AvifError::BmffParseFailed(
962 "multiple dimg references for item ID 1".into()
963 ))
964 );
965 }
966
967 #[test]
dimg_shared()968 fn dimg_shared() {
969 let mut decoder = get_decoder("color_grid_alpha_grid_tile_shared_in_dimg.avif");
970 assert_eq!(decoder.parse(), Err(AvifError::NotImplemented));
971 }
972
973 #[test]
dimg_ordering()974 fn dimg_ordering() {
975 if !HAS_DECODER {
976 return;
977 }
978 let mut decoder1 = get_decoder("sofa_grid1x5_420.avif");
979 let res = decoder1.parse();
980 assert!(res.is_ok());
981 let res = decoder1.next_image();
982 assert!(res.is_ok());
983 let mut decoder2 = get_decoder("sofa_grid1x5_420_random_dimg_order.avif");
984 let res = decoder2.parse();
985 assert!(res.is_ok());
986 let res = decoder2.next_image();
987 assert!(res.is_ok());
988 let image1 = decoder1.image().expect("image1 was none");
989 let image2 = decoder2.image().expect("image2 was none");
990 // Ensure that the pixels in image1 and image2 are not the same.
991 let row1 = image1.row(Plane::Y, 0).expect("row1 was none");
992 let row2 = image2.row(Plane::Y, 0).expect("row2 was none");
993 assert_ne!(row1, row2);
994 }
995
996 #[test]
heic_peek()997 fn heic_peek() {
998 let file_data = std::fs::read(get_test_file("blue.heic")).expect("could not read file");
999 assert_eq!(
1000 decoder::Decoder::peek_compatible_file_type(&file_data),
1001 cfg!(feature = "heic")
1002 );
1003 }
1004
1005 #[test]
heic_parsing()1006 fn heic_parsing() {
1007 let mut decoder = get_decoder("blue.heic");
1008 let res = decoder.parse();
1009 if cfg!(feature = "heic") {
1010 assert!(res.is_ok());
1011 let image = decoder.image().expect("image was none");
1012 assert_eq!(image.width, 320);
1013 assert_eq!(image.height, 240);
1014 assert_eq!(decoder.compression_format(), CompressionFormat::Heic);
1015 if cfg!(feature = "android_mediacodec") {
1016 // Decoding is available only via android_mediacodec.
1017 assert!(!matches!(
1018 decoder.next_image(),
1019 Err(AvifError::NoCodecAvailable)
1020 ));
1021 }
1022 } else {
1023 assert!(res.is_err());
1024 }
1025 }
1026
1027 #[test]
clap_irot_imir_non_essential()1028 fn clap_irot_imir_non_essential() {
1029 let mut decoder = get_decoder("clap_irot_imir_non_essential.avif");
1030 let res = decoder.parse();
1031 assert!(res.is_err());
1032 }
1033
1034 #[derive(Clone)]
1035 struct ExpectedOverlayImageInfo<'a> {
1036 filename: &'a str,
1037 width: u32,
1038 height: u32,
1039 expected_pixels: &'a [(usize, u32, [u8; 4])], // (x, y, [rgba]).
1040 }
1041
1042 const RED: [u8; 4] = [255, 0, 0, 255];
1043 const GREEN: [u8; 4] = [0, 255, 0, 255];
1044 const BLUE: [u8; 4] = [0, 0, 255, 255];
1045 const BLACK: [u8; 4] = [0, 0, 0, 255];
1046 const YELLOW: [u8; 4] = [255, 255, 0, 255];
1047
1048 const EXPECTED_OVERLAY_IMAGE_INFOS: [ExpectedOverlayImageInfo; 4] = [
1049 ExpectedOverlayImageInfo {
1050 // Three 80x60 sub-images with the following offsets:
1051 // horizontal_offsets: [0, 40, 80]
1052 // vertical_offsets: [0, 40, 80]
1053 filename: "overlay_exact_bounds.avif",
1054 width: 160,
1055 height: 140,
1056 expected_pixels: &[
1057 // Top left should be red.
1058 (0, 0, RED),
1059 (10, 10, RED),
1060 (20, 20, RED),
1061 // Green should be overlaid on top of the red block starting at (40, 40).
1062 (40, 40, GREEN),
1063 (50, 50, GREEN),
1064 (60, 60, GREEN),
1065 // Blue should be overlaid on top of the green block starting at (80, 80).
1066 (80, 80, BLUE),
1067 (90, 90, BLUE),
1068 (100, 100, BLUE),
1069 // Top right should be background color.
1070 (159, 0, BLACK),
1071 // Bottom left should be background color.
1072 (0, 139, BLACK),
1073 ],
1074 },
1075 ExpectedOverlayImageInfo {
1076 // Three 80x60 sub-images with the following offsets:
1077 // horizontal_offsets: [20, 60, 100]
1078 // vertical_offsets: [20, 60, 100]
1079 filename: "overlay_with_border.avif",
1080 width: 200,
1081 height: 180,
1082 expected_pixels: &[
1083 // Top left should be background color.
1084 (0, 0, BLACK),
1085 // Red should be overlaid starting at (20, 20).
1086 (20, 20, RED),
1087 (30, 30, RED),
1088 (40, 40, RED),
1089 // Green should be overlaid on top of the red block starting at (60, 60).
1090 (60, 60, GREEN),
1091 (70, 70, GREEN),
1092 (80, 80, GREEN),
1093 // Blue should be overlaid on top of the green block starting at (100, 100).
1094 (100, 100, BLUE),
1095 (110, 110, BLUE),
1096 (120, 120, BLUE),
1097 // Top right should be background color.
1098 (199, 0, BLACK),
1099 // Bottom left should be background color.
1100 (0, 179, BLACK),
1101 // Bottom right should be background color.
1102 (199, 179, BLACK),
1103 ],
1104 },
1105 ExpectedOverlayImageInfo {
1106 // Two 80x60 sub-images with the following offsets:
1107 // horizontal_offsets: [-40, 120]
1108 // vertical_offsets: [-40, 100]
1109 filename: "overlay_outside_bounds.avif",
1110 width: 160,
1111 height: 140,
1112 expected_pixels: &[
1113 // Red overlay is 40x20 in the top left.
1114 (0, 0, RED),
1115 (15, 15, RED),
1116 (39, 19, RED),
1117 (40, 20, BLACK),
1118 // Blue overlay is 40x40 in the bottom right.
1119 (119, 99, BLACK),
1120 (120, 100, BLUE),
1121 (140, 120, BLUE),
1122 (159, 139, BLUE),
1123 // Center of the image should be background color.
1124 (80, 70, BLACK),
1125 // Top right should be background color.
1126 (159, 0, BLACK),
1127 // Bottom left should be background color.
1128 (0, 139, BLACK),
1129 ],
1130 },
1131 ExpectedOverlayImageInfo {
1132 // Three 80x60 sub-images with the following offsets:
1133 // horizontal_offsets: [0, 40, 80]
1134 // vertical_offsets: [0, 40, 80]
1135 // canvas background color: yellow.
1136 filename: "overlay_yellow_bg.avif",
1137 width: 160,
1138 height: 140,
1139 expected_pixels: &[
1140 // Top left should be red.
1141 (0, 0, RED),
1142 (10, 10, RED),
1143 (20, 20, RED),
1144 // Green should be overlaid on top of the red block starting at (40, 40).
1145 (40, 40, GREEN),
1146 (50, 50, GREEN),
1147 (60, 60, GREEN),
1148 // Blue should be overlaid on top of the green block starting at (80, 80).
1149 (80, 80, BLUE),
1150 (90, 90, BLUE),
1151 (100, 100, BLUE),
1152 // Top right should be background color.
1153 (159, 0, YELLOW),
1154 // Bottom left should be background color.
1155 (0, 139, YELLOW),
1156 ],
1157 },
1158 ];
1159
1160 macro_rules! pixel_eq {
1161 ($a:expr, $b:expr) => {
1162 assert!((i32::from($a) - i32::from($b)).abs() <= 3);
1163 };
1164 }
1165
1166 #[test_case::test_matrix(0usize..4)]
overlay(index: usize)1167 fn overlay(index: usize) {
1168 let info = &EXPECTED_OVERLAY_IMAGE_INFOS[index];
1169 let mut decoder = get_decoder(info.filename);
1170 decoder.settings.strictness = decoder::Strictness::None;
1171 let res = decoder.parse();
1172 assert!(res.is_ok());
1173 assert_eq!(decoder.compression_format(), CompressionFormat::Avif);
1174 let image = decoder.image().expect("image was none");
1175 assert_eq!(image.width, info.width);
1176 assert_eq!(image.height, info.height);
1177 if !HAS_DECODER {
1178 return;
1179 }
1180 let res = decoder.next_image();
1181 assert!(res.is_ok());
1182 let image = decoder.image().expect("image was none");
1183 assert_eq!(image.width, info.width);
1184 assert_eq!(image.height, info.height);
1185 let mut rgb = rgb::Image::create_from_yuv(image);
1186 rgb.format = rgb::Format::Rgba;
1187 assert!(rgb.allocate().is_ok());
1188 assert!(rgb.convert_from_yuv(image).is_ok());
1189 for expected_pixel in info.expected_pixels {
1190 let column = expected_pixel.0;
1191 let row = expected_pixel.1;
1192 let pixels = rgb.row(row).expect("row was none");
1193 let r = pixels[column * 4];
1194 let g = pixels[(column * 4) + 1];
1195 let b = pixels[(column * 4) + 2];
1196 let a = pixels[(column * 4) + 3];
1197 pixel_eq!(r, expected_pixel.2[0]);
1198 pixel_eq!(g, expected_pixel.2[1]);
1199 pixel_eq!(b, expected_pixel.2[2]);
1200 pixel_eq!(a, expected_pixel.2[3]);
1201 }
1202 }
1203