1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include <setjmp.h> 8 9 #include "core/include/fxcrt/fx_basic.h" 10 11 extern FX_WORD _GetWord_LSBFirst(uint8_t* p); 12 extern void _SetWord_LSBFirst(uint8_t* p, FX_WORD v); 13 extern void _BpcConvert(const uint8_t* src_buf, 14 FX_DWORD src_len, 15 int32_t src_bpc, 16 int32_t dst_bpc, 17 uint8_t*& dst_buf, 18 FX_DWORD& dst_len); 19 #define GIF_SUPPORT_COMMENT_EXTENSION 20 #define GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION 21 #define GIF_SUPPORT_PLAIN_TEXT_EXTENSION 22 #define GIF_SIGNATURE "GIF" 23 #define GIF_SIG_EXTENSION 0x21 24 #define GIF_SIG_IMAGE 0x2C 25 #define GIF_SIG_TRAILER 0x3B 26 #define GIF_BLOCK_GCE 0xF9 27 #define GIF_BLOCK_PTE 0x01 28 #define GIF_BLOCK_CE 0xFE 29 #define GIF_BLOCK_AE 0xFF 30 #define GIF_BLOCK_TERMINAL 0x00 31 #define GIF_MAX_LZW_CODE 4096 32 #define GIF_DATA_BLOCK 255 33 #define GIF_MAX_ERROR_SIZE 256 34 #define GIF_D_STATUS_SIG 0x01 35 #define GIF_D_STATUS_TAIL 0x02 36 #define GIF_D_STATUS_EXT 0x03 37 #define GIF_D_STATUS_EXT_AE 0x04 38 #define GIF_D_STATUS_EXT_CE 0x05 39 #define GIF_D_STATUS_EXT_GCE 0x06 40 #define GIF_D_STATUS_EXT_PTE 0x07 41 #define GIF_D_STATUS_EXT_UNE 0x08 42 #define GIF_D_STATUS_IMG_INFO 0x09 43 #define GIF_D_STATUS_IMG_DATA 0x0A 44 #pragma pack(1) 45 typedef struct tagGifGF { 46 uint8_t pal_bits : 3; 47 uint8_t sort_flag : 1; 48 uint8_t color_resolution : 3; 49 uint8_t global_pal : 1; 50 } GifGF; 51 typedef struct tagGifLF { 52 uint8_t pal_bits : 3; 53 uint8_t reserved : 2; 54 uint8_t sort_flag : 1; 55 uint8_t interlace : 1; 56 uint8_t local_pal : 1; 57 } GifLF; 58 typedef struct tagGifHeader { 59 char signature[3]; 60 char version[3]; 61 } GifHeader; 62 typedef struct tagGifLSD { 63 FX_WORD width; 64 FX_WORD height; 65 uint8_t global_flag; 66 uint8_t bc_index; 67 uint8_t pixel_aspect; 68 } GifLSD; 69 typedef struct tagGifImageInfo { 70 FX_WORD left; 71 FX_WORD top; 72 FX_WORD width; 73 FX_WORD height; 74 75 uint8_t local_flag; 76 } GifImageInfo; 77 typedef struct tagGifCEF { 78 uint8_t transparency : 1; 79 uint8_t user_input : 1; 80 uint8_t disposal_method : 3; 81 uint8_t reserved : 3; 82 } GifCEF; 83 typedef struct tagGifGCE { 84 uint8_t block_size; 85 uint8_t gce_flag; 86 FX_WORD delay_time; 87 uint8_t trans_index; 88 } GifGCE; 89 typedef struct tagGifPTE { 90 uint8_t block_size; 91 FX_WORD grid_left; 92 FX_WORD grid_top; 93 FX_WORD grid_width; 94 FX_WORD grid_height; 95 96 uint8_t char_width; 97 uint8_t char_height; 98 99 uint8_t fc_index; 100 uint8_t bc_index; 101 } GifPTE; 102 typedef struct tagGifAE { 103 uint8_t block_size; 104 uint8_t app_identify[8]; 105 uint8_t app_authentication[3]; 106 } GifAE; 107 typedef struct tagGifPalette { uint8_t r, g, b; } GifPalette; 108 #pragma pack() 109 typedef struct tagGifImage { 110 GifGCE* image_gce_ptr; 111 GifPalette* local_pal_ptr; 112 GifImageInfo* image_info_ptr; 113 uint8_t image_code_size; 114 FX_DWORD image_data_pos; 115 uint8_t* image_row_buf; 116 int32_t image_row_num; 117 } GifImage; 118 typedef struct tagGifPlainText { 119 GifGCE* gce_ptr; 120 GifPTE* pte_ptr; 121 CFX_ByteString* string_ptr; 122 } GifPlainText; 123 class CGifLZWDecoder { 124 public: 125 struct tag_Table { 126 FX_WORD prefix; 127 uint8_t suffix; 128 }; 129 CGifLZWDecoder(FX_CHAR* error_ptr = NULL) { err_msg_ptr = error_ptr; } 130 void InitTable(uint8_t code_len); 131 132 int32_t Decode(uint8_t* des_buf, FX_DWORD& des_size); 133 134 void Input(uint8_t* src_buf, FX_DWORD src_size); 135 FX_DWORD GetAvailInput(); 136 137 private: 138 void ClearTable(); 139 void AddCode(FX_WORD prefix_code, uint8_t append_char); 140 void DecodeString(FX_WORD code); 141 uint8_t code_size; 142 uint8_t code_size_cur; 143 FX_WORD code_clear; 144 FX_WORD code_end; 145 FX_WORD code_next; 146 uint8_t code_first; 147 uint8_t stack[GIF_MAX_LZW_CODE]; 148 FX_WORD stack_size; 149 tag_Table code_table[GIF_MAX_LZW_CODE]; 150 FX_WORD code_old; 151 152 uint8_t* next_in; 153 FX_DWORD avail_in; 154 155 uint8_t bits_left; 156 FX_DWORD code_store; 157 158 FX_CHAR* err_msg_ptr; 159 }; 160 class CGifLZWEncoder { 161 public: 162 struct tag_Table { 163 FX_WORD prefix; 164 uint8_t suffix; 165 }; 166 CGifLZWEncoder(); 167 ~CGifLZWEncoder(); 168 void Start(uint8_t code_len, 169 const uint8_t* src_buf, 170 uint8_t*& dst_buf, 171 FX_DWORD& offset); 172 FX_BOOL Encode(const uint8_t* src_buf, 173 FX_DWORD src_len, 174 uint8_t*& dst_buf, 175 FX_DWORD& dst_len, 176 FX_DWORD& offset); 177 void Finish(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); 178 179 private: 180 void ClearTable(); 181 FX_BOOL LookUpInTable(const uint8_t* buf, 182 FX_DWORD& offset, 183 uint8_t& bit_offset); 184 void EncodeString(FX_DWORD index, 185 uint8_t*& dst_buf, 186 FX_DWORD& dst_len, 187 FX_DWORD& offset); 188 void WriteBlock(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); 189 jmp_buf jmp; 190 FX_DWORD src_offset; 191 uint8_t src_bit_offset; 192 uint8_t src_bit_cut; 193 FX_DWORD src_bit_num; 194 uint8_t code_size; 195 FX_WORD code_clear; 196 FX_WORD code_end; 197 FX_WORD index_num; 198 uint8_t bit_offset; 199 uint8_t index_bit_cur; 200 uint8_t index_buf[GIF_DATA_BLOCK]; 201 uint8_t index_buf_len; 202 tag_Table code_table[GIF_MAX_LZW_CODE]; 203 FX_WORD table_cur; 204 }; 205 typedef struct tag_gif_decompress_struct gif_decompress_struct; 206 typedef gif_decompress_struct* gif_decompress_struct_p; 207 typedef gif_decompress_struct_p* gif_decompress_struct_pp; 208 static int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; 209 struct tag_gif_decompress_struct { 210 jmp_buf jmpbuf; 211 FX_CHAR* err_ptr; 212 void (*_gif_error_fn)(gif_decompress_struct_p gif_ptr, 213 const FX_CHAR* err_msg); 214 void* context_ptr; 215 int width; 216 int height; 217 GifPalette* global_pal_ptr; 218 int32_t global_pal_num; 219 uint8_t global_sort_flag; 220 uint8_t global_color_resolution; 221 222 uint8_t bc_index; 223 uint8_t pixel_aspect; 224 CGifLZWDecoder* img_decoder_ptr; 225 FX_DWORD img_row_offset; 226 FX_DWORD img_row_avail_size; 227 uint8_t img_pass_num; 228 CFX_ArrayTemplate<GifImage*>* img_ptr_arr_ptr; 229 uint8_t* (*_gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr, 230 int32_t pal_size); 231 uint8_t* next_in; 232 FX_DWORD avail_in; 233 int32_t decode_status; 234 FX_DWORD skip_size; 235 void (*_gif_record_current_position_fn)(gif_decompress_struct_p gif_ptr, 236 FX_DWORD* cur_pos_ptr); 237 void (*_gif_get_row_fn)(gif_decompress_struct_p gif_ptr, 238 int32_t row_num, 239 uint8_t* row_buf); 240 FX_BOOL (*_gif_get_record_position_fn)(gif_decompress_struct_p gif_ptr, FX_DWORD cur_pos, 241 int32_t left, int32_t top, int32_t width, int32_t height, 242 int32_t pal_num, void* pal_ptr, 243 int32_t delay_time, FX_BOOL user_input, 244 int32_t trans_index, int32_t disposal_method, FX_BOOL interlace); 245 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION 246 uint8_t app_identify[8]; 247 uint8_t app_authentication[3]; 248 FX_DWORD app_data_size; 249 uint8_t* app_data; 250 #endif 251 #ifdef GIF_SUPPORT_COMMENT_EXTENSION 252 CFX_ByteString* cmt_data_ptr; 253 #endif 254 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION 255 GifGCE* gce_ptr; 256 #endif 257 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION 258 CFX_ArrayTemplate<GifPlainText*>* pt_ptr_arr_ptr; 259 #endif 260 }; 261 typedef struct tag_gif_compress_struct gif_compress_struct; 262 typedef gif_compress_struct* gif_compress_struct_p; 263 typedef gif_compress_struct_p* gif_compress_struct_pp; 264 struct tag_gif_compress_struct { 265 const uint8_t* src_buf; 266 FX_DWORD src_pitch; 267 FX_DWORD src_width; 268 FX_DWORD src_row; 269 FX_DWORD cur_offset; 270 FX_DWORD frames; 271 GifHeader* header_ptr; 272 GifLSD* lsd_ptr; 273 GifPalette* global_pal; 274 FX_WORD gpal_num; 275 GifPalette* local_pal; 276 FX_WORD lpal_num; 277 GifImageInfo* image_info_ptr; 278 CGifLZWEncoder* img_encoder_ptr; 279 #ifdef GIF_SUPPORT_APPLICATION_EXTENSION 280 uint8_t app_identify[8]; 281 uint8_t app_authentication[3]; 282 FX_DWORD app_data_size; 283 uint8_t* app_data; 284 #endif 285 286 #ifdef GIF_SUPPORT_COMMENT_EXTENSION 287 uint8_t* cmt_data_ptr; 288 FX_DWORD cmt_data_len; 289 #endif 290 291 #ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION 292 GifGCE* gce_ptr; 293 #endif 294 295 #ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION 296 GifPTE* pte_ptr; 297 const uint8_t* pte_data_ptr; 298 FX_DWORD pte_data_len; 299 #endif 300 }; 301 void _gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); 302 void _gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); 303 gif_decompress_struct_p _gif_create_decompress(); 304 void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr); 305 gif_compress_struct_p _gif_create_compress(); 306 void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr); 307 int32_t _gif_read_header(gif_decompress_struct_p gif_ptr); 308 int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr); 309 int32_t _gif_get_frame_num(gif_decompress_struct_p gif_ptr); 310 int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr); 311 int32_t _gif_decode_image_info(gif_decompress_struct_p gif_ptr); 312 void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, 313 GifGCE** gce_ptr_ptr); 314 int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num); 315 uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr, 316 uint8_t** des_buf_pp, 317 FX_DWORD data_size); 318 void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status); 319 void _gif_input_buffer(gif_decompress_struct_p gif_ptr, 320 uint8_t* src_buf, 321 FX_DWORD src_size); 322 FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, 323 uint8_t** avial_buf_ptr); 324 void interlace_buf(const uint8_t* buf, FX_DWORD width, FX_DWORD height); 325 FX_BOOL _gif_encode(gif_compress_struct_p gif_ptr, 326 uint8_t*& dst_buf, 327 FX_DWORD& dst_len); 328 #define GIF_PTR_NOT_NULL(ptr, gif_ptr) \ 329 if (ptr == NULL) { \ 330 _gif_error(gif_ptr, "Out Of Memory"); \ 331 return 0; \ 332 } 333