2020-01-18 09:38:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/*
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2018 - 2024 ,  Andreas  Kling  < andreas @ ladybird . org > 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-13 16:09:41 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2022 ,  the  SerenityOS  developers . 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:38:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-22 01:24:48 -07:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
									
										
										
										
											2020-01-18 09:38:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-11 07:30:37 -05:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <AK/Vector.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-16 05:51:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGfx/ImageFormats/ExifOrientedBitmap.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-21 14:58:06 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGfx/ImageFormats/PNGLoader.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-22 22:45:22 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGfx/ImageFormats/TIFFLoader.h> 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								# include  <LibGfx/ImageFormats/TIFFMetadata.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-09 05:48:17 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGfx/ImmutableBitmap.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <LibGfx/Painter.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								# include  <png.h> 
 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 03:57:42 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-06 11:56:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								namespace  Gfx  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 03:57:42 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								struct  PNGLoadingContext  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ~ PNGLoadingContext ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        png_destroy_read_struct ( & png_ptr ,  & info_ptr ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    png_structp  png_ptr  {  nullptr  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    png_infop  info_ptr  {  nullptr  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ReadonlyBytes  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    IntSize  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u32  frame_count  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u32  loop_count  {  0  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Vector < ImageFrameDescriptor >  frame_descriptors ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    Optional < ByteBuffer >  icc_profile ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-22 22:45:22 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    OwnPtr < ExifMetadata >  exif_metadata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ErrorOr < size_t >  read_frames ( png_structp ,  png_infop ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-10-16 05:51:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    ErrorOr < void >  apply_exif_orientation ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    ErrorOr < void >  read_all_frames ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // NOTE: We need to setjmp() here because libpng uses longjmp() for error handling.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( auto  error_value  =  setjmp ( png_jmpbuf ( png_ptr ) ) ;  error_value )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  Error : : from_errno ( error_value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        png_read_update_info ( png_ptr ,  info_ptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        frame_count  =  TRY ( read_frames ( png_ptr ,  info_ptr ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( exif_metadata ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            TRY ( apply_exif_orientation ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 16:19:11 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < NonnullOwnPtr < ImageDecoderPlugin > >  PNGImageDecoderPlugin : : create ( ReadonlyBytes  bytes ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 16:40:40 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  decoder  =  adopt_own ( * new  PNGImageDecoderPlugin ( bytes ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    TRY ( decoder - > initialize ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  result  =  decoder - > m_context - > read_all_frames ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( result . is_error ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // NOTE: If we didn't fail in initialize(), that means we have size information.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //       We can create a single-frame bitmap with that size and return it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        //       This is weird, but kinda matches the behavior of other browsers.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  bitmap  =  TRY ( Bitmap : : create ( BitmapFormat : : BGRA8888 ,  AlphaType : : Premultiplied ,  decoder - > m_context - > size ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        decoder - > m_context - > frame_descriptors . append ( {  move ( bitmap ) ,  0  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        decoder - > m_context - > frame_count  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  decoder ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  decoder ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 16:40:40 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								PNGImageDecoderPlugin : : PNGImageDecoderPlugin ( ReadonlyBytes  data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    :  m_context ( adopt_own ( * new  PNGLoadingContext ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    m_context - > data  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								size_t  PNGImageDecoderPlugin : : first_animated_frame_index ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								IntSize  PNGImageDecoderPlugin : : size ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  m_context - > size ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-02 17:34:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								bool  PNGImageDecoderPlugin : : is_animated ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-14 17:55:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  m_context - > frame_count  >  1 ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-14 17:55:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								size_t  PNGImageDecoderPlugin : : loop_count ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 16:19:11 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  m_context - > loop_count ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 16:19:11 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								size_t  PNGImageDecoderPlugin : : frame_count ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 03:57:42 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  m_context - > frame_count ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-16 20:01:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 14:08:14 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < ImageFrameDescriptor >  PNGImageDecoderPlugin : : frame ( size_t  index ,  Optional < IntSize > ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-16 20:01:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( index  > =  m_context - > frame_descriptors . size ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  Error : : from_errno ( EINVAL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  m_context - > frame_descriptors [ index ] ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-16 20:01:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < Optional < ReadonlyBytes > >  PNGImageDecoderPlugin : : icc_data ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( m_context - > icc_profile . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  Optional < ReadonlyBytes > ( * m_context - > icc_profile ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  OptionalNone  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-08 11:51:18 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								static  void  log_png_error ( png_structp  png_ptr ,  char  const *  error_message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    dbgln ( " libpng error: {} " ,  error_message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    png_longjmp ( png_ptr ,  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								static  void  log_png_warning ( png_structp ,  char  const *  warning_message ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    dbgln ( " libpng warning: {} " ,  warning_message ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < void >  PNGImageDecoderPlugin : : initialize ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    m_context - > png_ptr  =  png_create_read_struct ( PNG_LIBPNG_VER_STRING ,  nullptr ,  nullptr ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! m_context - > png_ptr ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  Error : : from_string_view ( " Failed to allocate read struct " sv ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    m_context - > info_ptr  =  png_create_info_struct ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( ! m_context - > info_ptr )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  Error : : from_string_view ( " Failed to allocate info struct " sv ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( auto  error_value  =  setjmp ( png_jmpbuf ( m_context - > png_ptr ) ) ;  error_value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  Error : : from_errno ( error_value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 03:57:42 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    png_set_read_fn ( m_context - > png_ptr ,  & m_context - > data ,  [ ] ( png_structp  png_ptr ,  png_bytep  data ,  png_size_t  length )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        auto *  read_data  =  reinterpret_cast < ReadonlyBytes * > ( png_get_io_ptr ( png_ptr ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( read_data - > size ( )  <  length )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            png_error ( png_ptr ,  " Read error " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-11 09:32:17 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        memcpy ( data ,  read_data - > data ( ) ,  length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        * read_data  =  read_data - > slice ( length ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-11 09:32:17 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    png_set_error_fn ( m_context - > png_ptr ,  nullptr ,  log_png_error ,  log_png_warning ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-08 11:51:18 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    png_read_info ( m_context - > png_ptr ,  m_context - > info_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-05-21 10:30:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u32  width  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u32  height  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  bit_depth  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  color_type  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-04 19:08:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  interlace_type  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    png_get_IHDR ( m_context - > png_ptr ,  m_context - > info_ptr ,  & width ,  & height ,  & bit_depth ,  & color_type ,  & interlace_type ,  nullptr ,  nullptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    m_context - > size  =  {  static_cast < int > ( width ) ,  static_cast < int > ( height )  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( color_type  = =  PNG_COLOR_TYPE_PALETTE ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_palette_to_rgb ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( color_type  = =  PNG_COLOR_TYPE_GRAY  & &  bit_depth  <  8 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_expand_gray_1_2_4_to_8 ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( png_get_valid ( m_context - > png_ptr ,  m_context - > info_ptr ,  PNG_INFO_tRNS ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        png_set_tRNS_to_alpha ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( bit_depth  = =  16 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_strip_16 ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 19:04:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( color_type  = =  PNG_COLOR_TYPE_GRAY  | |  color_type  = =  PNG_COLOR_TYPE_GRAY_ALPHA ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_gray_to_rgb ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-04 19:08:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( interlace_type  ! =  PNG_INTERLACE_NONE ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_interlace_handling ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-04 19:08:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    png_set_filler ( m_context - > png_ptr ,  0xFF ,  PNG_FILLER_AFTER ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    png_set_bgr ( m_context - > png_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    char *  profile_name  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    int  compression_type  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u8 *  profile_data  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u32  profile_len  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( png_get_iCCP ( m_context - > png_ptr ,  m_context - > info_ptr ,  & profile_name ,  & compression_type ,  & profile_data ,  & profile_len ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        m_context - > icc_profile  =  TRY ( ByteBuffer : : copy ( profile_data ,  profile_len ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    u8 *  exif_data  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    u32  exif_length  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-18 08:54:05 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    int  const  num_exif_chunks  =  png_get_eXIf_1 ( m_context - > png_ptr ,  m_context - > info_ptr ,  & exif_length ,  & exif_data ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( num_exif_chunks  >  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        m_context - > exif_metadata  =  TRY ( TIFFImageDecoderPlugin : : read_exif_metadata ( {  exif_data ,  exif_length  } ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-13 13:17:43 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:58:08 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-15 21:48:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-10-16 05:51:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < void >  PNGLoadingContext : : apply_exif_orientation ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    auto  orientation  =  exif_metadata - > orientation ( ) . value_or ( TIFF : : Orientation : : Default ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( orientation  = =  TIFF : : Orientation : : Default ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    for  ( auto &  img_frame_descriptor  :  frame_descriptors )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto &  img  =  img_frame_descriptor . image ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  oriented_bmp  =  TRY ( ExifOrientedBitmap : : create ( orientation ,  img - > size ( ) ,  img - > format ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( int  y  =  0 ;  y  <  img - > size ( ) . height ( ) ;  + + y )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for  ( int  x  =  0 ;  x  <  img - > size ( ) . width ( ) ;  + + x )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                auto  pixel  =  img - > get_pixel ( x ,  y ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                oriented_bmp . set_pixel ( x ,  y ,  pixel . value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        img_frame_descriptor . image  =  oriented_bmp . bitmap ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    size  =  ExifOrientedBitmap : : oriented_size ( size ,  orientation ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								ErrorOr < size_t >  PNGLoadingContext : : read_frames ( png_structp  png_ptr ,  png_infop  info_ptr ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    if  ( png_get_acTL ( png_ptr ,  info_ptr ,  & frame_count ,  & loop_count ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // acTL chunk present: This is an APNG.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_set_acTL ( png_ptr ,  info_ptr ,  frame_count ,  loop_count ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // Conceptually, at the beginning of each play the output buffer must be completely initialized to a fully transparent black rectangle, with width and height dimensions from the `IHDR` chunk.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  output_buffer  =  TRY ( Bitmap : : create ( BitmapFormat : : BGRA8888 ,  AlphaType : : Unpremultiplied ,  size ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        auto  painter  =  Painter : : create ( output_buffer ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Vector < u8 * >  row_pointers ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        for  ( size_t  frame_index  =  0 ;  frame_index  <  frame_count ;  + + frame_index )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            png_read_frame_head ( png_ptr ,  info_ptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u32  width  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u32  height  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u32  x  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u32  y  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u16  delay_num  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u16  delay_den  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 15:49:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            u8  dispose_op  =  PNG_DISPOSE_OP_NONE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            u8  blend_op  =  PNG_BLEND_OP_SOURCE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  duration_ms  =  [ & ] ( )  - >  int  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( delay_num  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                u32  const  denominator  =  delay_den  ! =  0  ?  static_cast < u32 > ( delay_den )  :  100u ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                auto  unsigned_duration_ms  =  ( delay_num  *  1000 )  /  denominator ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  ( unsigned_duration_ms  >  INT_MAX ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    return  INT_MAX ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                return  static_cast < int > ( unsigned_duration_ms ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 15:49:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( png_get_valid ( png_ptr ,  info_ptr ,  PNG_INFO_fcTL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                png_get_next_frame_fcTL ( png_ptr ,  info_ptr ,  & width ,  & height ,  & x ,  & y ,  & delay_num ,  & delay_den ,  & dispose_op ,  & blend_op ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                width  =  png_get_image_width ( png_ptr ,  info_ptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                height  =  png_get_image_height ( png_ptr ,  info_ptr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  frame_rect  =  FloatRect  {  x ,  y ,  width ,  height  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-11 19:14:59 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            auto  decoded_frame_bitmap  =  TRY ( Bitmap : : create ( BitmapFormat : : BGRA8888 ,  AlphaType : : Unpremultiplied ,  IntSize  {  static_cast < int > ( width ) ,  static_cast < int > ( height )  } ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            row_pointers . resize ( height ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for  ( u32  i  =  0 ;  i  <  height ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                row_pointers [ i ]  =  decoded_frame_bitmap - > scanline_u8 ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            png_read_image ( png_ptr ,  row_pointers . data ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            RefPtr < Bitmap >  prev_output_buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( dispose_op  = =  PNG_DISPOSE_OP_PREVIOUS )  // Only actually clone if it's necessary
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                prev_output_buffer  =  TRY ( output_buffer - > clone ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            switch  ( blend_op )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PNG_BLEND_OP_SOURCE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // All color components of the frame, including alpha, overwrite the current contents of the frame's output buffer region.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                painter - > draw_bitmap ( frame_rect ,  Gfx : : ImmutableBitmap : : create ( * decoded_frame_bitmap ) ,  decoded_frame_bitmap - > rect ( ) ,  Gfx : : ScalingMode : : NearestNeighbor ,  { } ,  1.0f ,  Gfx : : CompositingAndBlendingOperator : : Copy ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PNG_BLEND_OP_OVER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // The frame should be composited onto the output buffer based on its alpha, using a simple OVER operation as described in the "Alpha Channel Processing" section of the PNG specification.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                painter - > draw_bitmap ( frame_rect ,  Gfx : : ImmutableBitmap : : create ( * decoded_frame_bitmap ) ,  decoded_frame_bitmap - > rect ( ) ,  ScalingMode : : NearestNeighbor ,  { } ,  1.0f ,  Gfx : : CompositingAndBlendingOperator : : SourceOver ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            frame_descriptors . append ( {  TRY ( output_buffer - > clone ( ) ) ,  duration_ms ( )  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            switch  ( dispose_op )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PNG_DISPOSE_OP_NONE : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // No disposal is done on this frame before rendering the next; the contents of the output buffer are left as is.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PNG_DISPOSE_OP_BACKGROUND : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // The frame's region of the output buffer is to be cleared to fully transparent black before rendering the next frame.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                painter - > clear_rect ( frame_rect ,  Gfx : : Color : : Transparent ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            case  PNG_DISPOSE_OP_PREVIOUS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // The frame's region of the output buffer is to be reverted to the previous contents before rendering the next frame.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-28 18:19:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                painter - > draw_bitmap ( frame_rect ,  Gfx : : ImmutableBitmap : : create ( * prev_output_buffer ) ,  IntRect  {  x ,  y ,  width ,  height  } ,  Gfx : : ScalingMode : : NearestNeighbor ,  { } ,  1.0f ,  Gfx : : CompositingAndBlendingOperator : : Copy ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                VERIFY_NOT_REACHED ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // This is a single-frame PNG.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-06-11 16:20:14 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        frame_count  =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        loop_count  =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-21 03:57:42 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 12:03:27 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        auto  decoded_frame_bitmap  =  TRY ( Bitmap : : create ( BitmapFormat : : BGRA8888 ,  AlphaType : : Unpremultiplied ,  size ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Vector < u8 * >  row_pointers ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        row_pointers . resize ( size . height ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  ( int  i  =  0 ;  i  <  size . height ( ) ;  + + i ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            row_pointers [ i ]  =  decoded_frame_bitmap - > scanline_u8 ( i ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 10:02:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        png_read_image ( png_ptr ,  row_pointers . data ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        frame_descriptors . append ( {  move ( decoded_frame_bitmap ) ,  0  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-07 10:02:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-18 21:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  this - > frame_count ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-15 21:48:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-14 13:26:37 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								PNGImageDecoderPlugin : : ~ PNGImageDecoderPlugin ( )  =  default ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-15 21:48:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-26 18:02:50 +00:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								bool  PNGImageDecoderPlugin : : sniff ( ReadonlyBytes  data ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-20 10:13:14 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:48:24 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    auto  constexpr  png_signature_size_in_bytes  =  8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( data . size ( )  <  png_signature_size_in_bytes ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 23:40:55 -06:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  false ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-04 10:48:24 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    return  png_sig_cmp ( data . data ( ) ,  0 ,  png_signature_size_in_bytes )  = =  0 ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-03 17:12:54 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-05-22 22:45:22 -04:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								Optional < Metadata  const & >  PNGImageDecoderPlugin : : metadata ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    if  ( m_context - > exif_metadata ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  * m_context - > exif_metadata ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  OptionalNone  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-02-06 11:56:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								}