11//! Decoding of AVIF images.
22use crate :: error:: {
3- DecodingError , ImageFormatHint , LimitError , LimitErrorKind , UnsupportedError ,
4- UnsupportedErrorKind ,
3+ DecodingError , LimitError , LimitErrorKind , UnsupportedError , UnsupportedErrorKind ,
54} ;
65use crate :: { ColorType , ImageDecoder , ImageError , ImageFormat , ImageResult } ;
76///
@@ -20,7 +19,7 @@ use crate::codecs::avif::ycgco::{
2019} ;
2120use crate :: codecs:: avif:: yuv:: * ;
2221use dav1d:: { PixelLayout , PlanarImageComponent } ;
23- use mp4parse:: { read_avif, ParseStrictness } ;
22+ use mp4parse:: { read_avif, AvifContext , ParseStrictness } ;
2423
2524fn error_map < E : Into < Box < dyn Error + Send + Sync > > > ( err : E ) -> ImageError {
2625 ImageError :: Decoding ( DecodingError :: new ( ImageFormat :: Avif . into ( ) , err) )
@@ -31,9 +30,13 @@ fn error_map<E: Into<Box<dyn Error + Send + Sync>>>(err: E) -> ImageError {
3130/// Reads one image into the chosen input.
3231pub struct AvifDecoder < R > {
3332 inner : PhantomData < R > ,
34- picture : dav1d:: Picture ,
35- alpha_picture : Option < dav1d:: Picture > ,
33+ width : u32 ,
34+ height : u32 ,
35+ bit_depth : u8 ,
36+ ctx : AvifContext ,
3637 icc_profile : Option < Vec < u8 > > ,
38+ exif_metadata : Option < Vec < u8 > > ,
39+ xmp_metadata : Option < Vec < u8 > > ,
3740}
3841
3942#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -77,46 +80,28 @@ impl<R: Read> AvifDecoder<R> {
7780 /// Create a new decoder that reads its input from `r`.
7881 pub fn new ( mut r : R ) -> ImageResult < Self > {
7982 let ctx = read_avif ( & mut r, ParseStrictness :: Normal ) . map_err ( error_map) ?;
80- let coded = ctx. primary_item_coded_data ( ) . unwrap_or_default ( ) ;
81-
82- let mut primary_decoder = dav1d:: Decoder :: new ( ) . map_err ( error_map) ?;
83- primary_decoder
84- . send_data ( coded. to_vec ( ) , None , None , None )
85- . map_err ( error_map) ?;
86- let picture = read_until_ready ( & mut primary_decoder) ?;
87- let alpha_item = ctx. alpha_item_coded_data ( ) . unwrap_or_default ( ) ;
88- let alpha_picture = if !alpha_item. is_empty ( ) {
89- let mut alpha_decoder = dav1d:: Decoder :: new ( ) . map_err ( error_map) ?;
90- alpha_decoder
91- . send_data ( alpha_item. to_vec ( ) , None , None , None )
92- . map_err ( error_map) ?;
93- Some ( read_until_ready ( & mut alpha_decoder) ?)
94- } else {
95- None
96- } ;
83+ let dimensions = ctx. spatial_extents ( ) . unwrap ( ) ;
84+ let av1_config = ctx. av1_config ( ) . unwrap ( ) ;
9785 let icc_profile = ctx
9886 . icc_colour_information ( )
9987 . map ( |x| x. ok ( ) . unwrap_or_default ( ) )
10088 . map ( |x| x. to_vec ( ) ) ;
89+ let exif_metadata = ctx
90+ . exif_metadata ( )
91+ . map ( |v| v. to_vec ( ) ) ;
92+ let xmp_metadata = ctx
93+ . xmp_metadata ( )
94+ . map ( |v| v. to_vec ( ) ) ;
10195
102- match picture. bit_depth ( ) {
103- 8 => ( ) ,
104- 10 | 12 => ( ) ,
105- _ => {
106- return ImageResult :: Err ( ImageError :: Decoding ( DecodingError :: new (
107- ImageFormatHint :: Exact ( ImageFormat :: Avif ) ,
108- format ! (
109- "Avif format does not support {} bit depth" ,
110- picture. bit_depth( )
111- ) ,
112- ) ) )
113- }
114- } ;
11596 Ok ( AvifDecoder {
11697 inner : PhantomData ,
117- picture,
118- alpha_picture,
98+ width : dimensions. image_width ,
99+ height : dimensions. image_height ,
100+ bit_depth : av1_config. bit_depth ,
101+ ctx,
119102 icc_profile,
103+ exif_metadata,
104+ xmp_metadata,
120105 } )
121106 }
122107}
@@ -328,11 +313,11 @@ fn get_matrix(
328313
329314impl < R : Read > ImageDecoder for AvifDecoder < R > {
330315 fn dimensions ( & self ) -> ( u32 , u32 ) {
331- ( self . picture . width ( ) , self . picture . height ( ) )
316+ ( self . width , self . height )
332317 }
333318
334319 fn color_type ( & self ) -> ColorType {
335- if self . picture . bit_depth ( ) == 8 {
320+ if self . bit_depth == 8 {
336321 ColorType :: Rgba8
337322 } else {
338323 ColorType :: Rgba16
@@ -343,14 +328,16 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
343328 Ok ( self . icc_profile . clone ( ) )
344329 }
345330
346- fn read_image ( self , buf : & mut [ u8 ] ) -> ImageResult < ( ) > {
347- assert_eq ! ( u64 :: try_from( buf. len( ) ) , Ok ( self . total_bytes( ) ) ) ;
331+ fn exif_metadata ( & mut self ) -> ImageResult < Option < Vec < u8 > > > {
332+ Ok ( self . exif_metadata . clone ( ) )
333+ }
348334
349- let bit_depth = self . picture . bit_depth ( ) ;
335+ fn xmp_metadata ( & mut self ) -> ImageResult < Option < Vec < u8 > > > {
336+ Ok ( self . xmp_metadata . clone ( ) )
337+ }
350338
351- // Normally this should never happen,
352- // if this happens then there is an incorrect implementation somewhere else
353- assert ! ( bit_depth == 8 || bit_depth == 10 || bit_depth == 12 ) ;
339+ fn read_image ( self , buf : & mut [ u8 ] ) -> ImageResult < ( ) > {
340+ assert_eq ! ( u64 :: try_from( buf. len( ) ) , Ok ( self . total_bytes( ) ) ) ;
354341
355342 let ( width, height) = self . dimensions ( ) ;
356343 // This is suspicious if this happens, better fail early
@@ -360,54 +347,75 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
360347 ) ) ) ;
361348 }
362349
363- let yuv_range = match self . picture . color_range ( ) {
350+ let coded = self . ctx . primary_item_coded_data ( ) . unwrap_or_default ( ) ;
351+
352+ let mut primary_decoder = dav1d:: Decoder :: new ( ) . map_err ( error_map) ?;
353+ primary_decoder
354+ . send_data ( coded. to_vec ( ) , None , None , None )
355+ . map_err ( error_map) ?;
356+ let picture = read_until_ready ( & mut primary_decoder) ?;
357+ let alpha_item = self . ctx . alpha_item_coded_data ( ) . unwrap_or_default ( ) ;
358+ let alpha_picture = if !alpha_item. is_empty ( ) {
359+ let mut alpha_decoder = dav1d:: Decoder :: new ( ) . map_err ( error_map) ?;
360+ alpha_decoder
361+ . send_data ( alpha_item. to_vec ( ) , None , None , None )
362+ . map_err ( error_map) ?;
363+ Some ( read_until_ready ( & mut alpha_decoder) ?)
364+ } else {
365+ None
366+ } ;
367+
368+ assert_eq ! ( width, picture. width( ) ) ;
369+ assert_eq ! ( height, picture. height( ) ) ;
370+ assert_eq ! ( self . bit_depth as usize , picture. bit_depth( ) ) ;
371+
372+ let yuv_range = match picture. color_range ( ) {
364373 dav1d:: pixel:: YUVRange :: Limited => YuvIntensityRange :: Tv ,
365374 dav1d:: pixel:: YUVRange :: Full => YuvIntensityRange :: Pc ,
366375 } ;
367376
368- let matrix_strategy = get_matrix ( self . picture . matrix_coefficients ( ) ) ?;
377+ let matrix_strategy = get_matrix ( picture. matrix_coefficients ( ) ) ?;
369378
370379 // Identity matrix should be possible only on 4:4:4
371380 if matrix_strategy == YuvMatrixStrategy :: Identity
372- && self . picture . pixel_layout ( ) != PixelLayout :: I444
381+ && picture. pixel_layout ( ) != PixelLayout :: I444
373382 {
374383 return Err ( ImageError :: Decoding ( DecodingError :: new (
375384 ImageFormat :: Avif . into ( ) ,
376- AvifDecoderError :: YuvLayoutOnIdentityMatrix ( self . picture . pixel_layout ( ) ) ,
385+ AvifDecoderError :: YuvLayoutOnIdentityMatrix ( picture. pixel_layout ( ) ) ,
377386 ) ) ) ;
378387 }
379388
380- if matrix_strategy == YuvMatrixStrategy :: CgCo
381- && self . picture . pixel_layout ( ) == PixelLayout :: I400
389+ if matrix_strategy == YuvMatrixStrategy :: CgCo && picture. pixel_layout ( ) == PixelLayout :: I400
382390 {
383391 return Err ( ImageError :: Decoding ( DecodingError :: new (
384392 ImageFormat :: Avif . into ( ) ,
385393 AvifDecoderError :: UnsupportedLayoutAndMatrix (
386- self . picture . pixel_layout ( ) ,
394+ picture. pixel_layout ( ) ,
387395 matrix_strategy,
388396 ) ,
389397 ) ) ) ;
390398 }
391399
392- if bit_depth == 8 {
393- let ref_y = self . picture . plane ( PlanarImageComponent :: Y ) ;
394- let ref_u = self . picture . plane ( PlanarImageComponent :: U ) ;
395- let ref_v = self . picture . plane ( PlanarImageComponent :: V ) ;
400+ if self . bit_depth == 8 {
401+ let ref_y = picture. plane ( PlanarImageComponent :: Y ) ;
402+ let ref_u = picture. plane ( PlanarImageComponent :: U ) ;
403+ let ref_v = picture. plane ( PlanarImageComponent :: V ) ;
396404
397405 let image = YuvPlanarImage {
398406 y_plane : ref_y. as_ref ( ) ,
399- y_stride : self . picture . stride ( PlanarImageComponent :: Y ) as usize ,
407+ y_stride : picture. stride ( PlanarImageComponent :: Y ) as usize ,
400408 u_plane : ref_u. as_ref ( ) ,
401- u_stride : self . picture . stride ( PlanarImageComponent :: U ) as usize ,
409+ u_stride : picture. stride ( PlanarImageComponent :: U ) as usize ,
402410 v_plane : ref_v. as_ref ( ) ,
403- v_stride : self . picture . stride ( PlanarImageComponent :: V ) as usize ,
411+ v_stride : picture. stride ( PlanarImageComponent :: V ) as usize ,
404412 width : width as usize ,
405413 height : height as usize ,
406414 } ;
407415
408416 match matrix_strategy {
409417 YuvMatrixStrategy :: KrKb ( standard) => {
410- let worker = match self . picture . pixel_layout ( ) {
418+ let worker = match picture. pixel_layout ( ) {
411419 PixelLayout :: I400 => yuv400_to_rgba8,
412420 PixelLayout :: I420 => yuv420_to_rgba8,
413421 PixelLayout :: I422 => yuv422_to_rgba8,
@@ -417,7 +425,7 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
417425 worker ( image, buf, yuv_range, standard) ?;
418426 }
419427 YuvMatrixStrategy :: CgCo => {
420- let worker = match self . picture . pixel_layout ( ) {
428+ let worker = match picture. pixel_layout ( ) {
421429 PixelLayout :: I400 => unreachable ! ( ) ,
422430 PixelLayout :: I420 => ycgco420_to_rgba8,
423431 PixelLayout :: I422 => ycgco422_to_rgba8,
@@ -427,7 +435,7 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
427435 worker ( image, buf, yuv_range) ?;
428436 }
429437 YuvMatrixStrategy :: Identity => {
430- let worker = match self . picture . pixel_layout ( ) {
438+ let worker = match picture. pixel_layout ( ) {
431439 PixelLayout :: I400 => unreachable ! ( ) ,
432440 PixelLayout :: I420 => unreachable ! ( ) ,
433441 PixelLayout :: I422 => unreachable ! ( ) ,
@@ -439,7 +447,7 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
439447 }
440448
441449 // Squashing alpha plane into a picture
442- if let Some ( picture) = self . alpha_picture {
450+ if let Some ( picture) = alpha_picture {
443451 if picture. pixel_layout ( ) != PixelLayout :: I400 {
444452 return Err ( ImageError :: Decoding ( DecodingError :: new (
445453 ImageFormat :: Avif . into ( ) ,
@@ -463,11 +471,23 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
463471 // // 8+ bit-depth case
464472 if let Ok ( buf) = bytemuck:: try_cast_slice_mut ( buf) {
465473 let target_slice: & mut [ u16 ] = buf;
466- self . process_16bit_picture ( target_slice, yuv_range, matrix_strategy) ?;
474+ self . process_16bit_picture (
475+ picture,
476+ alpha_picture,
477+ target_slice,
478+ yuv_range,
479+ matrix_strategy,
480+ ) ?;
467481 } else {
468482 // If buffer from Decoder is unaligned
469483 let mut aligned_store = vec ! [ 0u16 ; buf. len( ) / 2 ] ;
470- self . process_16bit_picture ( & mut aligned_store, yuv_range, matrix_strategy) ?;
484+ self . process_16bit_picture (
485+ picture,
486+ alpha_picture,
487+ & mut aligned_store,
488+ yuv_range,
489+ matrix_strategy,
490+ ) ?;
471491 let buf_chunks = buf. as_chunks_mut :: < 2 > ( ) . 0 . iter_mut ( ) ;
472492 for ( dst, src) in buf_chunks. zip ( aligned_store. iter ( ) ) {
473493 * dst = src. to_ne_bytes ( ) ;
@@ -486,14 +506,16 @@ impl<R: Read> ImageDecoder for AvifDecoder<R> {
486506impl < R : Read > AvifDecoder < R > {
487507 fn process_16bit_picture (
488508 & self ,
509+ picture : dav1d:: Picture ,
510+ alpha_picture : Option < dav1d:: Picture > ,
489511 target : & mut [ u16 ] ,
490512 yuv_range : YuvIntensityRange ,
491513 matrix_strategy : YuvMatrixStrategy ,
492514 ) -> ImageResult < ( ) > {
493- let y_dav1d_plane = self . picture . plane ( PlanarImageComponent :: Y ) ;
515+ let y_dav1d_plane = picture. plane ( PlanarImageComponent :: Y ) ;
494516
495- let ( width, height) = ( self . picture . width ( ) , self . picture . height ( ) ) ;
496- let bit_depth = self . picture . bit_depth ( ) ;
517+ let ( width, height) = ( picture. width ( ) , picture. height ( ) ) ;
518+ let bit_depth = picture. bit_depth ( ) ;
497519
498520 // dav1d may return not aligned and not correctly constrained data,
499521 // or at least I can't find guarantees on that
@@ -502,28 +524,28 @@ impl<R: Read> AvifDecoder<R> {
502524
503525 let y_plane_view = transmute_y_plane16 (
504526 & y_dav1d_plane,
505- self . picture . stride ( PlanarImageComponent :: Y ) as usize ,
527+ picture. stride ( PlanarImageComponent :: Y ) as usize ,
506528 width as usize ,
507529 height as usize ,
508530 ) ;
509531
510- let u_dav1d_plane = self . picture . plane ( PlanarImageComponent :: U ) ;
511- let v_dav1d_plane = self . picture . plane ( PlanarImageComponent :: V ) ;
532+ let u_dav1d_plane = picture. plane ( PlanarImageComponent :: U ) ;
533+ let v_dav1d_plane = picture. plane ( PlanarImageComponent :: V ) ;
512534 let mut u_plane_view = Plane16View :: default ( ) ;
513535 let mut v_plane_view = Plane16View :: default ( ) ;
514536
515- if self . picture . pixel_layout ( ) != PixelLayout :: I400 {
537+ if picture. pixel_layout ( ) != PixelLayout :: I400 {
516538 u_plane_view = transmute_chroma_plane16 (
517539 & u_dav1d_plane,
518- self . picture . pixel_layout ( ) ,
519- self . picture . stride ( PlanarImageComponent :: U ) as usize ,
540+ picture. pixel_layout ( ) ,
541+ picture. stride ( PlanarImageComponent :: U ) as usize ,
520542 width as usize ,
521543 height as usize ,
522544 ) ;
523545 v_plane_view = transmute_chroma_plane16 (
524546 & v_dav1d_plane,
525- self . picture . pixel_layout ( ) ,
526- self . picture . stride ( PlanarImageComponent :: V ) as usize ,
547+ picture. pixel_layout ( ) ,
548+ picture. stride ( PlanarImageComponent :: V ) as usize ,
527549 width as usize ,
528550 height as usize ,
529551 ) ;
@@ -542,7 +564,7 @@ impl<R: Read> AvifDecoder<R> {
542564
543565 match matrix_strategy {
544566 YuvMatrixStrategy :: KrKb ( standard) => {
545- let worker = match self . picture . pixel_layout ( ) {
567+ let worker = match picture. pixel_layout ( ) {
546568 PixelLayout :: I400 => {
547569 if bit_depth == 10 {
548570 yuv400_to_rgba10
@@ -575,7 +597,7 @@ impl<R: Read> AvifDecoder<R> {
575597 worker ( image, target, yuv_range, standard) ?;
576598 }
577599 YuvMatrixStrategy :: CgCo => {
578- let worker = match self . picture . pixel_layout ( ) {
600+ let worker = match picture. pixel_layout ( ) {
579601 PixelLayout :: I400 => unreachable ! ( ) ,
580602 PixelLayout :: I420 => {
581603 if bit_depth == 10 {
@@ -602,7 +624,7 @@ impl<R: Read> AvifDecoder<R> {
602624 worker ( image, target, yuv_range) ?;
603625 }
604626 YuvMatrixStrategy :: Identity => {
605- let worker = match self . picture . pixel_layout ( ) {
627+ let worker = match picture. pixel_layout ( ) {
606628 PixelLayout :: I400 => unreachable ! ( ) ,
607629 PixelLayout :: I420 => unreachable ! ( ) ,
608630 PixelLayout :: I422 => unreachable ! ( ) ,
@@ -619,7 +641,7 @@ impl<R: Read> AvifDecoder<R> {
619641 }
620642
621643 // Squashing alpha plane into a picture
622- if let Some ( picture) = & self . alpha_picture {
644+ if let Some ( picture) = & alpha_picture {
623645 if picture. pixel_layout ( ) != PixelLayout :: I400 {
624646 return Err ( ImageError :: Decoding ( DecodingError :: new (
625647 ImageFormat :: Avif . into ( ) ,
@@ -646,7 +668,7 @@ impl<R: Read> AvifDecoder<R> {
646668 }
647669
648670 // Expand current bit depth to target 16
649- let target_expand_bits = 16u32 - self . picture . bit_depth ( ) as u32 ;
671+ let target_expand_bits = 16u32 - picture. bit_depth ( ) as u32 ;
650672 for item in target. iter_mut ( ) {
651673 * item = ( * item) . rotate_left ( target_expand_bits) ;
652674 }
0 commit comments