2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  ( c )  2023 ,  Nico  Weber  < thakis @ chromium . org > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  SPDX - License - Identifier :  BSD - 2 - Clause 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-31 10:38:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <AK/BitStream.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# include  <AK/Debug.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <AK/Endian.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <AK/Format.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-03-31 10:38:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <AK/MemoryStream.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <AK/Vector.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-03-21 14:58:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# include  <LibGfx/ImageFormats/WebPLoader.h> 
  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 22:50:54 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// Overview: https://developers.google.com/speed/webp/docs/compression
  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// Container: https://developers.google.com/speed/webp/docs/riff_container
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Lossless format: https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Lossy format: https://datatracker.ietf.org/doc/html/rfc6386
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  Gfx  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  FourCC  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    constexpr  FourCC ( char  const *  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cc [ 0 ]  =  name [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cc [ 1 ]  =  name [ 1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cc [ 2 ]  =  name [ 2 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cc [ 3 ]  =  name [ 3 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator = = ( FourCC  const & )  const  =  default ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator ! = ( FourCC  const & )  const  =  default ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  cc [ 4 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  WebPFileHeader  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FourCC  riff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LittleEndian < u32 >  file_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FourCC  webp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static_assert ( AssertSize < WebPFileHeader ,  12 > ( ) ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  ChunkHeader  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FourCC  chunk_type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LittleEndian < u32 >  chunk_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static_assert ( AssertSize < ChunkHeader ,  8 > ( ) ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  Chunk  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FourCC  type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ReadonlyBytes  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  VP8Header  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  version ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  show_frame ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  size_of_first_partition ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  width ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  horizontal_scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  height ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  vertical_scale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  VP8LHeader  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  width ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  height ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_alpha_used ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  VP8XHeader  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_icc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_alpha ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_exif ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_xmp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_animation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  width ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  height ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-26 09:13:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								struct  ANIMChunk  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  background_color ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  loop_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  WebPLoadingContext  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    enum  State  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        NotDecoded  =  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Error , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        HeaderDecoded , 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:05:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        FirstChunkRead , 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        FirstChunkDecoded , 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        ChunksDecoded , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        BitmapDecoded , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    State  state  {  State : : NotDecoded  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ReadonlyBytes  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ReadonlyBytes  chunks_cursor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < IntSize >  size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    RefPtr < Gfx : : Bitmap >  bitmap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // Either 'VP8 ' (simple lossy file), 'VP8L' (simple lossless file), or 'VP8X' (extended file).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  first_chunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    union  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        VP8Header  vp8_header ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        VP8LHeader  vp8l_header ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        VP8XHeader  vp8x_header ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If first_chunk is not a VP8X chunk, then only image_data_chunk is set and all the other Chunks are not set.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "For a still image, the image data consists of a single frame, which is made up of:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //     An optional alpha subchunk.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //     A bitstream subchunk."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  alpha_chunk ;       // 'ALPH'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  image_data_chunk ;  // Either 'VP8 ' or 'VP8L'.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  animation_header_chunk ;  // 'ANIM'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Vector < Chunk >  animation_frame_chunks ;    // 'ANMF'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  iccp_chunk ;  // 'ICCP'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  exif_chunk ;  // 'EXIF'
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional < Chunk >  xmp_chunk ;   // 'XMP '
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    template < size_t  N > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    [[nodiscard]]  class  Error  error ( char  const  ( & string_literal ) [ N ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        state  =  WebPLoadingContext : : State : : Error ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Error : : from_string_literal ( string_literal ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  ErrorOr < void >  decode_webp_header ( WebPLoadingContext &  context )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . state  > =  WebPLoadingContext : : HeaderDecoded ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . data . size ( )  <  sizeof ( WebPFileHeader ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " Missing WebP header " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto &  header  =  * bit_cast < WebPFileHeader  const * > ( context . data . data ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( header . riff  ! =  FourCC ( " RIFF " )  | |  header . webp  ! =  FourCC ( " WEBP " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " Invalid WebP header " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "File Size: [...] The size of the file in bytes starting at offset 8. The maximum value of this field is 2^32 minus 10 bytes."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  const  maximum_webp_file_size  =  0xffff'ffff  -  9 ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( header . file_size  >  maximum_webp_file_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebP header file size over maximum " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "The file size in the header is the total size of the chunks that follow plus 4 bytes for the 'WEBP' FourCC.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  The file SHOULD NOT contain any data after the data specified by File Size.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Readers MAY parse such files, ignoring the trailing data."
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . data . size ( )  -  8  <  header . file_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebP data too small for size in header " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    if  ( context . data . size ( )  -  8  >  header . file_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dbgln_if ( WEBP_DEBUG ,  " WebP has {} bytes of data, but header needs only {}. Trimming. " ,  context . data . size ( ) ,  header . file_size  +  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . data  =  context . data . trim ( header . file_size  +  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . state  =  WebPLoadingContext : : HeaderDecoded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:04:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#riff_file_format
  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  ErrorOr < Chunk >  decode_webp_chunk_header ( WebPLoadingContext &  context ,  ReadonlyBytes  chunks )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( chunks . size ( )  <  sizeof ( ChunkHeader ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " Not enough data for WebP chunk header " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  const &  header  =  * bit_cast < ChunkHeader  const * > ( chunks . data ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dbgln_if ( WEBP_DEBUG ,  " chunk {} size {} " ,  header . chunk_type ,  header . chunk_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( chunks . size ( )  <  sizeof ( ChunkHeader )  +  header . chunk_size ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " Not enough data for WebP chunk " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  Chunk  {  header . chunk_type ,  {  chunks . data ( )  +  sizeof ( ChunkHeader ) ,  header . chunk_size  }  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:04:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#riff_file_format
  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								static  ErrorOr < Chunk >  decode_webp_advance_chunk ( WebPLoadingContext &  context ,  ReadonlyBytes &  chunks )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  chunk  =  TRY ( decode_webp_chunk_header ( context ,  chunks ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:04:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "Chunk Size: 32 bits (uint32)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      The size of the chunk in bytes, not including this field, the chunk identifier or padding.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Chunk Payload: Chunk Size bytes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      The data payload. If Chunk Size is odd, a single padding byte -- that MUST be 0 to conform with RIFF -- is added."
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    chunks  =  chunks . slice ( sizeof ( ChunkHeader )  +  chunk . data . size ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:04:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( chunk . data . size ( )  %  2  ! =  0 )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( chunks . is_empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  context . error ( " Missing data for padding byte " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( * chunks . data ( )  ! =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  context . error ( " Padding byte is not 0 " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 14:04:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        chunks  =  chunks . slice ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    return  chunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#simple_file_format_lossy
  
						 
					
						
							
								
									
										
										
										
											2023-02-24 22:32:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://datatracker.ietf.org/doc/html/rfc6386#section-19 "Annex A: Bitstream Syntax"
  
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < VP8Header >  decode_webp_chunk_VP8_header ( WebPLoadingContext &  context ,  Chunk  const &  vp8_chunk )  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-24 22:32:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    VERIFY ( vp8_chunk . type  = =  FourCC ( " VP8  " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( vp8_chunk . data . size ( )  <  10 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: 'VP8 ' chunk too small " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Eventually, this should probably call into LibVideo/VP8,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // and image decoders should move into LibImageDecoders which depends on both LibGfx and LibVideo.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // (LibVideo depends on LibGfx, so LibGfx can't depend on LibVideo itself.)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://datatracker.ietf.org/doc/html/rfc6386#section-4 "Overview of Compressed Data Format"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "The decoder is simply presented with a sequence of compressed frames [...]
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  The first frame presented to the decompressor is [...] a key frame.  [...]
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  [E]very compressed frame has three or more pieces. It begins with an uncompressed data chunk comprising 10 bytes in the case of key frames
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  const *  data  =  vp8_chunk . data . data ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://datatracker.ietf.org/doc/html/rfc6386#section-9.1 "Uncompressed Data Chunk"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  frame_tag  =  data [ 0 ]  |  ( data [ 1 ]  < <  8 )  |  ( data [ 2 ]  < <  16 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_key_frame  =  ( frame_tag  &  1 )  = =  0 ;  // https://www.rfc-editor.org/errata/eid5534
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  version  =  ( frame_tag  &  0xe )  > >  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  show_frame  =  ( frame_tag  &  0x10 )  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  size_of_first_partition  =  frame_tag  > >  5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! is_key_frame ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: 'VP8 ' chunk not a key frame " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: !show_frame does not make sense in a webp file either, probably?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  start_code  =  data [ 3 ]  |  ( data [ 4 ]  < <  8 )  |  ( data [ 5 ]  < <  16 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( start_code  ! =  0x2a019d )  // https://www.rfc-editor.org/errata/eid7370
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: 'VP8 ' chunk invalid start_code " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "The scaling specifications for each dimension are encoded as follows.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   0     | No upscaling (the most common case).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   1     | Upscale by 5/4.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   2     | Upscale by 5/3.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //   3     | Upscale by 2."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // This is a display-time operation and doesn't affect decoding.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  width_and_horizontal_scale  =  data [ 6 ]  |  ( data [ 7 ]  < <  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  width  =  width_and_horizontal_scale  &  0x3fff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  horizontal_scale  =  width_and_horizontal_scale  > >  14 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  heigth_and_vertical_scale  =  data [ 8 ]  |  ( data [ 9 ]  < <  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  height  =  heigth_and_vertical_scale  &  0x3fff ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  vertical_scale  =  heigth_and_vertical_scale  > >  14 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dbgln_if ( WEBP_DEBUG ,  " version {}, show_frame {}, size_of_first_partition {}, width {}, horizontal_scale {}, height {}, vertical_scale {} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        version ,  show_frame ,  size_of_first_partition ,  width ,  horizontal_scale ,  height ,  vertical_scale ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  VP8Header  {  version ,  show_frame ,  size_of_first_partition ,  width ,  horizontal_scale ,  height ,  vertical_scale  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#simple_file_format_lossless
  
						 
					
						
							
								
									
										
										
										
											2023-02-24 23:15:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#7_overall_structure_of_the_format
  
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < VP8LHeader >  decode_webp_chunk_VP8L_header ( WebPLoadingContext &  context ,  Chunk  const &  vp8l_chunk )  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-24 23:15:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    VERIFY ( vp8l_chunk . type  = =  FourCC ( " VP8L " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developers.google.com/speed/webp/docs/webp_lossless_bitstream_specification#3_riff_header
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( vp8l_chunk . data . size ( )  <  5 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: VP8L chunk too small " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-03-31 10:38:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    FixedMemoryStream  memory_stream  {  vp8l_chunk . data . trim ( 5 )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    LittleEndianInputBitStream  bit_stream  {  MaybeOwned < Stream > ( memory_stream )  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  signature  =  TRY ( bit_stream . read_bits ( 8 ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 23:15:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( signature  ! =  0x2f ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: VP8L chunk invalid signature " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 14 bits width-1, 14 bits height-1, 1 bit alpha hint, 3 bit version_number.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-03-31 10:38:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    u16  width  =  TRY ( bit_stream . read_bits ( 14 ) )  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  height  =  TRY ( bit_stream . read_bits ( 14 ) )  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_alpha_used  =  TRY ( bit_stream . read_bits ( 1 ) )  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  version_number  =  TRY ( bit_stream . read_bits ( 3 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY ( bit_stream . is_eof ( ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 23:15:22 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dbgln_if ( WEBP_DEBUG ,  " width {}, height {}, is_alpha_used {}, version_number {} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        width ,  height ,  is_alpha_used ,  version_number ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "The version_number is a 3 bit code that must be set to 0. Any other value should be treated as an error. [AMENDED]"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( version_number  ! =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: VP8L chunk invalid version_number " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  VP8LHeader  {  width ,  height ,  is_alpha_used  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < VP8XHeader >  decode_webp_chunk_VP8X ( WebPLoadingContext &  context ,  Chunk  const &  vp8x_chunk )  
						 
					
						
							
								
									
										
										
										
											2023-02-24 21:47:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY ( vp8x_chunk . type  = =  FourCC ( " VP8X " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The VP8X chunk is documented at "Extended WebP file header:" at the end of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( vp8x_chunk . data . size ( )  <  10 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: VP8X chunk too small " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  const *  data  =  vp8x_chunk . data . data ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1 byte flags
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "Reserved (Rsv): 2 bits   MUST be 0. Readers MUST ignore this field.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  ICC profile (I): 1 bit   Set if the file contains an ICC profile.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Alpha (L): 1 bit         Set if any of the frames of the image contain transparency information ("alpha").
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Exif metadata (E): 1 bit Set if the file contains Exif metadata.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  XMP metadata (X): 1 bit  Set if the file contains XMP metadata.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Animation (A): 1 bit     Set if this is an animated image. Data in 'ANIM' and 'ANMF' chunks should be used to control the animation.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  Reserved (R): 1 bit      MUST be 0. Readers MUST ignore this field."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  flags  =  data [ 0 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_icc  =  flags  &  0x20 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_alpha  =  flags  &  0x10 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_exif  =  flags  &  0x8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_xmp  =  flags  &  0x4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_animation  =  flags  &  0x2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 3 bytes reserved
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 3 bytes width minus one
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 21:47:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    u32  width  =  ( data [ 4 ]  |  ( data [ 5 ]  < <  8 )  |  ( data [ 6 ]  < <  16 ) )  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // 3 bytes height minus one
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 21:47:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    u32  height  =  ( data [ 7 ]  |  ( data [ 8 ]  < <  8 )  |  ( data [ 9 ]  < <  16 ) )  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dbgln_if ( WEBP_DEBUG ,  " flags 0x{:x} --{}{}{}{}{}{}, width {}, height {} " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_icc  ?  "  icc "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_alpha  ?  "  alpha "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_exif  ?  "  exif "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_xmp  ?  "  xmp "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_animation  ?  "  anim "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ( flags  &  0x3e )  = =  0  ?  "  none "  :  " " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        width ,  height ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  VP8XHeader  {  has_icc ,  has_alpha ,  has_exif ,  has_xmp ,  has_animation ,  width ,  height  } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 21:47:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-26 09:13:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#animation
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  ErrorOr < ANIMChunk >  decode_webp_chunk_ANIM ( WebPLoadingContext &  context ,  Chunk  const &  anim_chunk )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY ( anim_chunk . type  = =  FourCC ( " ANIM " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( anim_chunk . data . size ( )  <  6 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: ANIM chunk too small " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u8  const *  data  =  anim_chunk . data . data ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u32  background_color  =  ( u32 ) data [ 0 ]  |  ( ( u32 ) data [ 1 ]  < <  8 )  |  ( ( u32 ) data [ 2 ]  < <  16 )  |  ( ( u32 ) data [ 3 ]  < <  24 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    u16  loop_count  =  data [ 4 ]  |  ( data [ 5 ]  < <  8 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ANIMChunk  {  background_color ,  loop_count  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								// https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
  
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < void >  decode_webp_extended ( WebPLoadingContext &  context ,  ReadonlyBytes  chunks )  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:22:01 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    VERIFY ( context . first_chunk - > type  = =  FourCC ( " VP8X " ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    // FIXME: This isn't quite to spec, which says
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "All chunks SHOULD be placed in the same order as listed above.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //  If a chunk appears in the wrong place, the file is invalid, but readers MAY parse the file, ignoring the chunks that are out of order."
 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    auto  store  =  [ ] ( auto &  field ,  Chunk  const &  chunk )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! field . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            field  =  chunk ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    while  ( ! chunks . is_empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        auto  chunk  =  TRY ( decode_webp_advance_chunk ( context ,  chunks ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( chunk . type  = =  FourCC ( " ICCP " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            store ( context . iccp_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " ALPH " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            store ( context . alpha_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " ANIM " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            store ( context . animation_header_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " ANMF " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            TRY ( context . animation_frame_chunks . try_append ( chunk ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " EXIF " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            store ( context . exif_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " XMP  " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            store ( context . xmp_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  if  ( chunk . type  = =  FourCC ( " VP8  " )  | |  chunk . type  = =  FourCC ( " VP8L " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            store ( context . image_data_chunk ,  chunk ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:22:01 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    // Validate chunks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developers.google.com/speed/webp/docs/riff_container#animation
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "ANIM Chunk: [...] This chunk MUST appear if the Animation flag in the VP8X chunk is set. If the Animation flag is not set and this chunk is present, it MUST be ignored."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . vp8x_header . has_animation  & &  ! context . animation_header_chunk . has_value ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: Header claims animation, but no ANIM chunk " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! context . vp8x_header . has_animation  & &  context . animation_header_chunk . has_value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dbgln_if ( WEBP_DEBUG ,  " WebPImageDecoderPlugin: Header claims no animation, but ANIM chunk present. Ignoring ANIM chunk. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . animation_header_chunk . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "ANMF Chunk: [...] If the Animation flag is not set, then this chunk SHOULD NOT be present."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! context . vp8x_header . has_animation  & &  context . animation_header_chunk . has_value ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dbgln_if ( WEBP_DEBUG ,  " WebPImageDecoderPlugin: Header claims no animation, but ANMF chunks present. Ignoring ANMF chunks. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . animation_frame_chunks . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developers.google.com/speed/webp/docs/riff_container#alpha
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "A frame containing a 'VP8L' chunk SHOULD NOT contain this chunk."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Also check in ANMF chunks.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . alpha_chunk . has_value ( )  & &  context . image_data_chunk . has_value ( )  & &  context . image_data_chunk - > type  = =  FourCC ( " VP8L " ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dbgln_if ( WEBP_DEBUG ,  " WebPImageDecoderPlugin: VP8L frames should not have ALPH chunks. Ignoring ALPH chunk. " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . alpha_chunk . clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // https://developers.google.com/speed/webp/docs/riff_container#color_profile
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // "This chunk MUST appear before the image data."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: Doesn't check animated files.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . iccp_chunk . has_value ( )  & &  context . image_data_chunk . has_value ( )  & &  context . iccp_chunk - > data . data ( )  >  context . image_data_chunk - > data . data ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: ICCP chunk is after image data " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    context . state  =  WebPLoadingContext : : State : : ChunksDecoded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:05:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < void >  read_webp_first_chunk ( WebPLoadingContext &  context )  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:05:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . state  > =  WebPLoadingContext : : State : : FirstChunkRead ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . state  <  WebPLoadingContext : : HeaderDecoded ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( decode_webp_header ( context ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    context . chunks_cursor  =  context . data . slice ( sizeof ( WebPFileHeader ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  first_chunk  =  TRY ( decode_webp_advance_chunk ( context ,  context . chunks_cursor ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( first_chunk . type  ! =  FourCC ( " VP8  " )  & &  first_chunk . type  ! =  FourCC ( " VP8L " )  & &  first_chunk . type  ! =  FourCC ( " VP8X " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  context . error ( " WebPImageDecoderPlugin: Invalid first chunk type " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . first_chunk  =  first_chunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:05:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    context . state  =  WebPLoadingContext : : State : : FirstChunkRead ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( first_chunk . type  = =  FourCC ( " VP8  " )  | |  first_chunk . type  = =  FourCC ( " VP8L " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . image_data_chunk  =  first_chunk ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								static  ErrorOr < void >  decode_webp_first_chunk ( WebPLoadingContext &  context )  
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . state  > =  WebPLoadingContext : : State : : FirstChunkDecoded ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:05:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . state  <  WebPLoadingContext : : FirstChunkRead ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( read_webp_first_chunk ( context ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . first_chunk - > type  = =  FourCC ( " VP8  " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        context . vp8_header  =  TRY ( decode_webp_chunk_VP8_header ( context ,  context . first_chunk . value ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . size  =  IntSize  {  context . vp8_header . width ,  context . vp8_header . height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . state  =  WebPLoadingContext : : State : : FirstChunkDecoded ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . first_chunk - > type  = =  FourCC ( " VP8L " ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        context . vp8l_header  =  TRY ( decode_webp_chunk_VP8L_header ( context ,  context . first_chunk . value ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . size  =  IntSize  {  context . vp8l_header . width ,  context . vp8l_header . height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . state  =  WebPLoadingContext : : State : : FirstChunkDecoded ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    VERIFY ( context . first_chunk - > type  = =  FourCC ( " VP8X " ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    context . vp8x_header  =  TRY ( decode_webp_chunk_VP8X ( context ,  context . first_chunk . value ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . size  =  IntSize  {  context . vp8x_header . width ,  context . vp8x_header . height  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . state  =  WebPLoadingContext : : State : : FirstChunkDecoded ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								static  ErrorOr < void >  decode_webp_chunks ( WebPLoadingContext &  context )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context . state  > =  WebPLoadingContext : : State : : ChunksDecoded ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . state  <  WebPLoadingContext : : FirstChunkDecoded ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( decode_webp_first_chunk ( context ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( context . first_chunk - > type  = =  FourCC ( " VP8X " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  decode_webp_extended ( context ,  context . chunks_cursor ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    context . state  =  WebPLoadingContext : : State : : ChunksDecoded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								WebPImageDecoderPlugin : : WebPImageDecoderPlugin ( ReadonlyBytes  data ,  OwnPtr < WebPLoadingContext >  context )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  m_context ( move ( context ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    m_context - > data  =  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								WebPImageDecoderPlugin : : ~ WebPImageDecoderPlugin ( )  =  default ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								IntSize  WebPImageDecoderPlugin : : size ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_context - > state  = =  WebPLoadingContext : : State : : Error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 20:08:00 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( m_context - > state  <  WebPLoadingContext : : State : : FirstChunkDecoded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( decode_webp_first_chunk ( * m_context ) . is_error ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  { } ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  m_context - > size . value ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								void  WebPImageDecoderPlugin : : set_volatile ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_context - > bitmap ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        m_context - > bitmap - > set_volatile ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  WebPImageDecoderPlugin : : set_nonvolatile ( bool &  was_purged )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! m_context - > bitmap ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  m_context - > bitmap - > set_nonvolatile ( was_purged ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  WebPImageDecoderPlugin : : initialize ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ! decode_webp_header ( * m_context ) . is_error ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-26 18:02:50 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								bool  WebPImageDecoderPlugin : : sniff ( ReadonlyBytes  data )  
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    WebPLoadingContext  context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . data  =  data ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-26 17:52:56 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  ! decode_webp_header ( context ) . is_error ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ErrorOr < NonnullOwnPtr < ImageDecoderPlugin > >  WebPImageDecoderPlugin : : create ( ReadonlyBytes  data )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  context  =  TRY ( try_make < WebPLoadingContext > ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  adopt_nonnull_own_or_enomem ( new  ( nothrow )  WebPImageDecoderPlugin ( data ,  move ( context ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								bool  WebPImageDecoderPlugin : : is_animated ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-25 22:15:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( m_context - > state  = =  WebPLoadingContext : : State : : Error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_context - > state  <  WebPLoadingContext : : State : : FirstChunkDecoded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( decode_webp_first_chunk ( * m_context ) . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  m_context - > first_chunk - > type  = =  FourCC ( " VP8X " )  & &  m_context - > vp8x_header . has_animation ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								size_t  WebPImageDecoderPlugin : : loop_count ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-26 09:13:27 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! is_animated ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_context - > state  <  WebPLoadingContext : : State : : ChunksDecoded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( decode_webp_chunks ( * m_context ) . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    auto  anim_or_error  =  decode_webp_chunk_ANIM ( * m_context ,  m_context - > animation_header_chunk . value ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( decode_webp_chunks ( * m_context ) . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  anim_or_error . value ( ) . loop_count ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								size_t  WebPImageDecoderPlugin : : frame_count ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
									
										
										
										
											2023-02-25 22:15:34 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( ! is_animated ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( m_context - > state  <  WebPLoadingContext : : State : : ChunksDecoded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( decode_webp_chunks ( * m_context ) . is_error ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  m_context - > animation_frame_chunks . size ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ErrorOr < ImageFrameDescriptor >  WebPImageDecoderPlugin : : frame ( size_t  index )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( index  > =  frame_count ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  Error : : from_string_literal ( " WebPImageDecoderPlugin: Invalid frame index " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  Error : : from_string_literal ( " WebPImageDecoderPlugin: decoding not yet implemented " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ErrorOr < Optional < ReadonlyBytes > >  WebPImageDecoderPlugin : : icc_data ( )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								{  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    TRY ( decode_webp_chunks ( * m_context ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-24 16:16:50 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // FIXME: "If this chunk is not present, sRGB SHOULD be assumed."
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-25 16:14:05 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  m_context - > iccp_chunk . map ( [ ] ( auto  iccp_chunk )  {  return  iccp_chunk . data ;  } ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-23 22:37:08 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  AK : : Formatter < Gfx : : FourCC >  :  StandardFormatter  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ErrorOr < void >  format ( FormatBuilder &  builder ,  Gfx : : FourCC  const &  four_cc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( ' \' ' ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( four_cc . cc [ 0 ] ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( four_cc . cc [ 1 ] ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( four_cc . cc [ 2 ] ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( four_cc . cc [ 3 ] ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        TRY ( builder . put_padding ( ' \' ' ,  1 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;