From fdc00a7042d912aafaabddae4d9c84199921ef23 Mon Sep 17 00:00:00 2001 From: Bo Xu Date: Tue, 28 Oct 2014 23:03:33 -0700 Subject: Merge XFA to PDFium master at 4dc95e7 on 10/28/2014 --- core/src/fxcodec/lgif/fx_gif.cpp | 1368 ++++++++++++++++++++++++++++++++++++++ core/src/fxcodec/lgif/fx_gif.h | 307 +++++++++ 2 files changed, 1675 insertions(+) create mode 100644 core/src/fxcodec/lgif/fx_gif.cpp create mode 100644 core/src/fxcodec/lgif/fx_gif.h (limited to 'core/src/fxcodec/lgif') diff --git a/core/src/fxcodec/lgif/fx_gif.cpp b/core/src/fxcodec/lgif/fx_gif.cpp new file mode 100644 index 0000000000..8f5794e786 --- /dev/null +++ b/core/src/fxcodec/lgif/fx_gif.cpp @@ -0,0 +1,1368 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "fx_gif.h" +void CGifLZWDecoder::Input(FX_LPBYTE src_buf, FX_DWORD src_size) +{ + next_in = src_buf; + avail_in = src_size; +} +FX_DWORD CGifLZWDecoder::GetAvailInput() +{ + return avail_in; +} +void CGifLZWDecoder::InitTable(FX_BYTE code_len) +{ + code_size = code_len; + code_clear = 1 << code_size; + code_end = code_clear + 1; + bits_left = 0; + code_store = 0; + next_in = NULL; + avail_in = 0; + stack_size = 0; + code_first = 0; + ClearTable(); +} +void CGifLZWDecoder::ClearTable() +{ + code_size_cur = code_size + 1; + code_next = code_end + 1; + code_old = (FX_WORD) - 1; + FXSYS_memset32(code_table, 0, sizeof(tag_Table)*GIF_MAX_LZW_CODE); + FXSYS_memset32(stack, 0, GIF_MAX_LZW_CODE); + for (FX_WORD i = 0; i < code_clear; i++) { + code_table[i].suffix = (FX_BYTE)i; + } +} +void CGifLZWDecoder::DecodeString(FX_WORD code) +{ + stack_size = 0; + while (TRUE) { + ASSERT(code <= code_next); + if(code < code_clear || code > code_next) { + break; + } + stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = code_table[code].suffix; + code = code_table[code].prefix; + } + stack[GIF_MAX_LZW_CODE - 1 - stack_size++] = (FX_BYTE)code; + code_first = (FX_BYTE)code; +} +void CGifLZWDecoder::AddCode(FX_WORD prefix_code, FX_BYTE append_char) +{ + if(code_next == GIF_MAX_LZW_CODE) { + return; + } + code_table[code_next].prefix = prefix_code; + code_table[code_next].suffix = append_char; + if(++code_next < GIF_MAX_LZW_CODE) { + if(code_next >> code_size_cur) { + code_size_cur++; + } + } +} +FX_INT32 CGifLZWDecoder::Decode(FX_LPBYTE des_buf, FX_DWORD& des_size) +{ + if(des_size == 0) { + return 3; + } + FX_DWORD i = 0; + if(stack_size != 0) { + if(des_size < stack_size) { + FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size); + stack_size -= (FX_WORD)des_size; + return 3; + } + FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size); + des_buf += stack_size; + i += stack_size; + stack_size = 0; + } + FX_WORD code = 0; + while(i <= des_size && (avail_in > 0 || bits_left >= code_size_cur)) { + if(code_size_cur > 12) { + if(err_msg_ptr) { + FXSYS_strncpy(err_msg_ptr, "Code Length Out Of Range", GIF_MAX_ERROR_SIZE - 1); + } + return 0; + } + if (avail_in > 0) { + code_store |= (*next_in++) << bits_left; + avail_in--; + bits_left += 8; + } + while (bits_left >= code_size_cur) { + code = (FX_WORD)code_store & ((1 << code_size_cur) - 1); + code_store >>= code_size_cur; + bits_left -= code_size_cur; + if(code == code_clear) { + ClearTable(); + continue; + } else if (code == code_end) { + des_size = i; + return 1; + } else { + if(code_old != (FX_WORD) - 1) { + if(code_next < GIF_MAX_LZW_CODE) { + if(code == code_next) { + AddCode(code_old, code_first); + DecodeString(code); + } else if(code > code_next) { + if(err_msg_ptr) { + FXSYS_strncpy(err_msg_ptr, "Decode Error, Out Of Range", GIF_MAX_ERROR_SIZE - 1); + } + return 0; + } else { + DecodeString(code); + FX_BYTE append_char = stack[GIF_MAX_LZW_CODE - stack_size]; + AddCode(code_old, append_char); + } + } + } else { + DecodeString(code); + } + code_old = code; + if(i + stack_size > des_size) { + FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size - i); + stack_size -= (FX_WORD)(des_size - i); + return 3; + } + FXSYS_memcpy32(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], stack_size); + des_buf += stack_size; + i += stack_size; + stack_size = 0; + } + } + } + if(avail_in == 0) { + des_size = i; + return 2; + } + return 0; +} +static FX_BOOL _gif_grow_buf(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD size) +{ + if (dst_len < size) { + FX_DWORD len_org = dst_len; + while (dst_buf && dst_len < size) { + dst_len <<= 1; + dst_buf = FX_Realloc(FX_BYTE, dst_buf, dst_len); + } + if (dst_buf == NULL) { + dst_len = size; + dst_buf = FX_Realloc(FX_BYTE, dst_buf, dst_len); + if (dst_buf == NULL) { + return FALSE; + } + } + FXSYS_memset32(dst_buf + len_org, 0, dst_len - len_org); + return dst_buf != NULL; + } + return TRUE; +} +static inline void _gif_cut_index(FX_BYTE& val, FX_DWORD index, FX_BYTE index_bit, FX_BYTE index_bit_use, FX_BYTE bit_use) +{ + FX_DWORD cut = ((1 << (index_bit - index_bit_use)) - 1) << index_bit_use; + val |= ((index & cut) >> index_bit_use) << bit_use; +} +static inline FX_BYTE _gif_cut_buf(FX_LPCBYTE buf, FX_DWORD& offset, FX_BYTE bit_cut, FX_BYTE& bit_offset, FX_DWORD& bit_num) +{ + if (bit_cut != 8) { + FX_WORD index = 0; + index |= ((1 << bit_cut) - 1) << (7 - bit_offset); + FX_BYTE ret = ((index & buf[offset]) >> (7 - bit_offset)); + bit_offset += bit_cut; + if (bit_offset >= 8) { + if (bit_offset > 8) { + ret |= ((index & (buf[offset + 1] << 8)) >> 8); + } + bit_offset -= 8; + offset ++; + } + bit_num += bit_cut; + return ret; + } + bit_num += bit_cut; + return buf[offset++]; +} +CGifLZWEncoder::CGifLZWEncoder() +{ + FXSYS_memset32(this, 0, sizeof(CGifLZWEncoder)); +} +CGifLZWEncoder::~CGifLZWEncoder() +{ +} +void CGifLZWEncoder::ClearTable() +{ + index_bit_cur = code_size + 1; + index_num = code_end + 1; + table_cur = code_end + 1; + for (FX_WORD i = 0; i < GIF_MAX_LZW_CODE; i++) { + code_table[i].prefix = 0; + code_table[i].suffix = 0; + } +} +void CGifLZWEncoder::Start( FX_BYTE code_len, FX_LPCBYTE src_buf, FX_LPBYTE& dst_buf, FX_DWORD& offset) +{ + code_size = code_len + 1; + src_bit_cut = code_size; + if (code_len == 0) { + src_bit_cut = 1; + code_size = 2; + } + code_clear = 1 << code_size; + code_end = code_clear + 1; + dst_buf[offset++] = code_size; + bit_offset = 0; + ClearTable(); + src_offset = 0; + src_bit_offset = 0; + src_bit_num = 0; + code_table[index_num].prefix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); + code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); +} +void CGifLZWEncoder::WriteBlock(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset) +{ + if (!_gif_grow_buf(dst_buf, dst_len, offset + GIF_DATA_BLOCK + 1)) { + longjmp(jmp, 1); + } + dst_buf[offset++] = index_buf_len; + FXSYS_memcpy32(&dst_buf[offset], index_buf, index_buf_len); + offset += index_buf_len; + FXSYS_memset32(index_buf, 0, GIF_DATA_BLOCK); + index_buf_len = 0; +} +void CGifLZWEncoder::EncodeString( FX_DWORD index, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset ) +{ + FX_BYTE index_bit_use; + index_bit_use = 0; + if (index_buf_len == GIF_DATA_BLOCK) { + WriteBlock(dst_buf, dst_len, offset); + } + _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset); + if (index_bit_cur <= (8 - bit_offset)) { + bit_offset += index_bit_cur; + } else if (index_bit_cur <= (16 - bit_offset)) { + index_bit_use += (8 - bit_offset); + bit_offset = 0; + index_buf_len++; + if (index_buf_len == GIF_DATA_BLOCK) { + WriteBlock(dst_buf, dst_len, offset); + } + _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset); + bit_offset = index_bit_cur - index_bit_use; + } else { + index_bit_use += (8 - bit_offset); + bit_offset = 0; + index_buf_len++; + if (index_buf_len == GIF_DATA_BLOCK) { + WriteBlock(dst_buf, dst_len, offset); + } + _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset); + index_bit_use += 8; + bit_offset = 0; + index_buf_len++; + if (index_buf_len == GIF_DATA_BLOCK) { + WriteBlock(dst_buf, dst_len, offset); + } + _gif_cut_index(index_buf[index_buf_len], index, index_bit_cur, index_bit_use, bit_offset); + bit_offset = index_bit_cur - index_bit_use; + } + if (bit_offset == 8) { + bit_offset = 0; + index_buf_len++; + if (index_buf_len == GIF_DATA_BLOCK) { + WriteBlock(dst_buf, dst_len, offset); + } + } + if (index == code_end) { + index_buf_len++; + WriteBlock(dst_buf, dst_len, offset); + } + if (index_num++ >> index_bit_cur) { + index_bit_cur++; + } +} +FX_BOOL CGifLZWEncoder::Encode( FX_LPCBYTE src_buf, FX_DWORD src_len, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset ) +{ + FX_BYTE suffix; + if (setjmp(jmp)) { + return FALSE; + } + while(src_bit_num < src_len) { + if (!LookUpInTable(src_buf, src_offset, src_bit_offset)) { + EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset); + if (index_num == GIF_MAX_LZW_CODE) { + suffix = code_table[index_num - 1].suffix; + EncodeString(code_clear, dst_buf, dst_len, offset); + ClearTable(); + code_table[index_num].prefix = suffix; + code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); + } else { + code_table[index_num].prefix = code_table[index_num - 1].suffix; + code_table[index_num].suffix = _gif_cut_buf(src_buf, src_offset, src_bit_cut, src_bit_offset, src_bit_num); + } + } + } + src_offset = 0; + src_bit_offset = 0; + src_bit_num = 0; + return TRUE; +} +FX_BOOL CGifLZWEncoder::LookUpInTable( FX_LPCBYTE buf, FX_DWORD& offset, FX_BYTE& bit_offset ) +{ + for (FX_WORD i = table_cur; i < index_num; i++) { + if (code_table[i].prefix == code_table[index_num].prefix && + code_table[i].suffix == code_table[index_num].suffix) { + code_table[index_num].prefix = i; + code_table[index_num].suffix = _gif_cut_buf(buf, offset, src_bit_cut, bit_offset, src_bit_num); + table_cur = i; + return TRUE; + } + } + table_cur = code_end + 1; + return FALSE; +} +void CGifLZWEncoder::Finish(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset) +{ + EncodeString(code_table[index_num].prefix, dst_buf, dst_len, offset); + EncodeString(code_end, dst_buf, dst_len, offset); + bit_offset = 0; + ClearTable(); +} +gif_decompress_struct_p _gif_create_decompress() +{ + gif_decompress_struct_p gif_ptr = (gif_decompress_struct*)FX_Alloc(FX_BYTE, sizeof(gif_decompress_struct)); + if(gif_ptr == NULL) { + return NULL; + } + FXSYS_memset32(gif_ptr, 0, sizeof(gif_decompress_struct)); + gif_ptr->decode_status = GIF_D_STATUS_SIG; + gif_ptr->img_ptr_arr_ptr = FX_NEW CFX_ArrayTemplate; + if(gif_ptr->img_ptr_arr_ptr == NULL) { + FX_Free(gif_ptr); + return NULL; + } +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + gif_ptr->cmt_data_ptr = FX_NEW CFX_ByteString; + if(gif_ptr->cmt_data_ptr == NULL) { + delete gif_ptr->img_ptr_arr_ptr; + FX_Free(gif_ptr); + return NULL; + } +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + gif_ptr->pt_ptr_arr_ptr = FX_NEW CFX_ArrayTemplate; + if(gif_ptr->pt_ptr_arr_ptr == NULL) { + delete(gif_ptr->cmt_data_ptr); + delete gif_ptr->img_ptr_arr_ptr; + FX_Free(gif_ptr); + return NULL; + } +#endif + return gif_ptr; +} +void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr) +{ + if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) { + return; + } + gif_decompress_struct_p gif_ptr = *gif_ptr_ptr; + *gif_ptr_ptr = NULL; + if(gif_ptr->global_pal_ptr != NULL) { + FX_Free(gif_ptr->global_pal_ptr); + } + if(gif_ptr->img_decoder_ptr != NULL) { + delete gif_ptr->img_decoder_ptr; + } + if(gif_ptr->img_ptr_arr_ptr != NULL) { + FX_INT32 size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize(); + for (FX_INT32 i = 0; i < size_img_arr; i++) { + GifImage* p = gif_ptr->img_ptr_arr_ptr->GetAt(i); + if(p->image_info_ptr != NULL) { + FX_Free(p->image_info_ptr); + } + if(p->image_gce_ptr != NULL) { + FX_Free(p->image_gce_ptr); + } + if(p->image_row_buf != NULL) { + FX_Free(p->image_row_buf); + } + if(p->local_pal_ptr != NULL && p->local_pal_ptr != gif_ptr->global_pal_ptr) { + FX_Free(p->local_pal_ptr); + } + FX_Free(p); + } + gif_ptr->img_ptr_arr_ptr->RemoveAll(); + delete gif_ptr->img_ptr_arr_ptr; + } +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + if(gif_ptr->app_data != NULL) { + FX_Free(gif_ptr->app_data); + } +#endif +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + if(gif_ptr->cmt_data_ptr != NULL) { + delete gif_ptr->cmt_data_ptr; + } +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + if(gif_ptr->gce_ptr != NULL) { + FX_Free(gif_ptr->gce_ptr); + } +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + if(gif_ptr->pt_ptr_arr_ptr != NULL) { + FX_INT32 size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize(); + for (FX_INT32 i = 0; i < size_pt_arr; i++) { + GifPlainText* p = gif_ptr->pt_ptr_arr_ptr->GetAt(i); + if(p->gce_ptr != NULL) { + FX_Free(p->gce_ptr); + } + if(p->pte_ptr != NULL) { + FX_Free(p->pte_ptr); + } + if(p->string_ptr != NULL) { + delete p->string_ptr; + } + } + gif_ptr->pt_ptr_arr_ptr->RemoveAll(); + delete gif_ptr->pt_ptr_arr_ptr; + } +#endif + FX_Free(gif_ptr); +} +gif_compress_struct_p _gif_create_compress() +{ + gif_compress_struct_p gif_ptr = (gif_compress_struct*)FX_Alloc(FX_BYTE, sizeof(gif_compress_struct)); + if (gif_ptr == NULL) { + return NULL; + } + FXSYS_memset32(gif_ptr, 0, sizeof(gif_compress_struct)); + gif_ptr->img_encoder_ptr = FX_NEW CGifLZWEncoder; + if (gif_ptr->img_encoder_ptr == NULL) { + FX_Free(gif_ptr); + return NULL; + } + gif_ptr->header_ptr = (GifHeader*)FX_Alloc(FX_BYTE, sizeof(GifHeader)); + if (gif_ptr->header_ptr == NULL) { + delete(gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } + FXSYS_memcpy32(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3); + FXSYS_memcpy32(gif_ptr->header_ptr->version, "89a", 3); + gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(FX_BYTE, sizeof(GifLSD)); + if (gif_ptr->lsd_ptr == NULL) { + FX_Free(gif_ptr->header_ptr); + delete(gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } + FXSYS_memset32(gif_ptr->lsd_ptr, 0, sizeof(GifLSD)); + gif_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(FX_BYTE, sizeof(GifImageInfo)); + if (gif_ptr->image_info_ptr == NULL) { + FX_Free(gif_ptr->lsd_ptr); + FX_Free(gif_ptr->header_ptr); + delete(gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } + FXSYS_memset32(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo)); +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + FXSYS_memcpy32(gif_ptr->app_identify, "netscape", 8); + FXSYS_memcpy32(gif_ptr->app_authentication, "2.0", 3); +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(FX_BYTE, sizeof(GifGCE)); + if (gif_ptr->gce_ptr == NULL) { + FX_Free(gif_ptr->image_info_ptr); + FX_Free(gif_ptr->lsd_ptr); + FX_Free(gif_ptr->header_ptr); + delete(gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + gif_ptr->pte_ptr = (GifPTE*)FX_Alloc(FX_BYTE, sizeof(GifPTE)); + if (gif_ptr->pte_ptr == NULL) { + FX_Free(gif_ptr->gce_ptr); + FX_Free(gif_ptr->image_info_ptr); + FX_Free(gif_ptr->lsd_ptr); + FX_Free(gif_ptr->header_ptr); + delete(gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } + FXSYS_memset32(gif_ptr->pte_ptr, 0, sizeof(GifPTE)); + gif_ptr->pte_ptr->block_size = 12; +#endif + return gif_ptr; +} +void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr) +{ + if(gif_ptr_ptr == NULL || *gif_ptr_ptr == NULL) { + return; + } + gif_compress_struct_p gif_ptr = *gif_ptr_ptr; + *gif_ptr_ptr = NULL; + if(gif_ptr->header_ptr != NULL) { + FX_Free(gif_ptr->header_ptr); + } + if(gif_ptr->lsd_ptr != NULL) { + FX_Free(gif_ptr->lsd_ptr); + } + if(gif_ptr->global_pal != NULL) { + FX_Free(gif_ptr->global_pal); + } + if(gif_ptr->image_info_ptr != NULL) { + FX_Free(gif_ptr->image_info_ptr); + } + if(gif_ptr->local_pal != NULL) { + FX_Free(gif_ptr->local_pal); + } + if(gif_ptr->img_encoder_ptr != NULL) { + delete gif_ptr->img_encoder_ptr; + } +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + if(gif_ptr->app_data != NULL) { + FX_Free(gif_ptr->app_data); + } +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + if(gif_ptr->gce_ptr != NULL) { + FX_Free(gif_ptr->gce_ptr); + } +#endif +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + if(gif_ptr->cmt_data_ptr != NULL) { + FX_Free(gif_ptr->cmt_data_ptr); + } +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + if(gif_ptr->pte_ptr != NULL) { + FX_Free(gif_ptr->pte_ptr); + } +#endif + FX_Free(gif_ptr); +} +void _gif_error(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg) +{ + if(gif_ptr != NULL && gif_ptr->_gif_error_fn != NULL) { + gif_ptr->_gif_error_fn(gif_ptr, err_msg); + } +} +void _gif_warn(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg) {} +FX_INT32 _gif_read_header(gif_decompress_struct_p gif_ptr) +{ + if(gif_ptr == NULL) { + return 0; + } + FX_DWORD skip_size_org = gif_ptr->skip_size; + ASSERT(sizeof(GifHeader) == 6); + GifHeader* gif_header_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_header_ptr, 6) == NULL) { + return 2; + } + if(FXSYS_strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 || + gif_header_ptr->version[0] != '8' || + gif_header_ptr->version[2] != 'a') { + _gif_error(gif_ptr, "Not A Gif Image"); + return 0; + } + ASSERT(sizeof(GifLSD) == 7); + GifLSD* gif_lsd_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_lsd_ptr, 7) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + if(((GifGF*)&gif_lsd_ptr->global_flag)->global_pal) { + gif_ptr->global_pal_num = 2 << ((GifGF*)&gif_lsd_ptr->global_flag)->pal_bits; + ASSERT(sizeof(GifPalette) == 3); + FX_INT32 global_pal_size = gif_ptr->global_pal_num * 3; + FX_LPBYTE global_pal_ptr = NULL; + if (_gif_read_data(gif_ptr, &global_pal_ptr, global_pal_size) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + gif_ptr->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag; + gif_ptr->global_color_resolution = ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution; + if(gif_ptr->global_pal_ptr != NULL) { + FX_Free(gif_ptr->global_pal_ptr); + } + gif_ptr->global_pal_ptr = NULL; + gif_ptr->global_pal_ptr = (GifPalette*)FX_Alloc(FX_BYTE, global_pal_size); + GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr); + FXSYS_memcpy32(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size); + } + gif_ptr->width = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->width); + gif_ptr->height = (int)_GetWord_LSBFirst((FX_LPBYTE)&gif_lsd_ptr->height); + gif_ptr->bc_index = gif_lsd_ptr->bc_index; + gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect; + return 1; +} +FX_INT32 _gif_get_frame(gif_decompress_struct_p gif_ptr) +{ + if(gif_ptr == NULL) { + return 0; + } + FX_INT32 ret = 1; + while (TRUE) { + switch(gif_ptr->decode_status) { + case GIF_D_STATUS_TAIL: + return 1; + case GIF_D_STATUS_SIG: { + FX_LPBYTE sig_ptr = NULL; + if(_gif_read_data(gif_ptr, &sig_ptr, 1) == NULL) { + return 2; + } + switch(*sig_ptr) { + case GIF_SIG_EXTENSION: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT); + continue; + case GIF_SIG_IMAGE: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_INFO); + continue; + case GIF_SIG_TRAILER: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); + return 1; + default: + if (gif_ptr->avail_in) { + _gif_warn(gif_ptr, "The Gif File has non_standard Tag!"); + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); + continue; + } + _gif_warn(gif_ptr, "The Gif File Doesn't have Trailer Tag!"); + return 1; + } + } + case GIF_D_STATUS_EXT: { + FX_LPBYTE ext_ptr = NULL; + if(_gif_read_data(gif_ptr, &ext_ptr, 1) == NULL) { + return 2; + } + switch(*ext_ptr) { +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + case GIF_BLOCK_AE: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_AE); + continue; +#endif +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + case GIF_BLOCK_CE: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_CE); + continue; +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + case GIF_BLOCK_GCE: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_GCE); + continue; +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + case GIF_BLOCK_PTE: + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_EXT_PTE); + continue; +#endif + default: { + FX_INT32 status = GIF_D_STATUS_EXT_UNE; +#ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + if(*ext_ptr == GIF_BLOCK_PTE) { + status = GIF_D_STATUS_EXT_PTE; + } +#endif + _gif_save_decoding_status(gif_ptr, status); + continue; + } + } + } + case GIF_D_STATUS_IMG_INFO: { + ret = _gif_decode_image_info(gif_ptr); + if(ret != 1) { + return ret; + } + continue; + } + case GIF_D_STATUS_IMG_DATA: { + FX_LPBYTE data_size_ptr = NULL; + FX_LPBYTE data_ptr = NULL; + FX_DWORD skip_size_org = gif_ptr->skip_size; + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + return 2; + } + while(*data_size_ptr != GIF_BLOCK_TERMINAL) { + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); + skip_size_org = gif_ptr->skip_size; + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + return 2; + } + } + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); + continue; + } + default: { + ret = _gif_decode_extension(gif_ptr); + if(ret != 1) { + return ret; + } + continue; + } + } + } + return 1; +} +void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, GifGCE** gce_ptr_ptr) +{ + *gce_ptr_ptr = NULL; +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + if(gif_ptr->gce_ptr != NULL && gce_ptr_ptr != NULL) { + *gce_ptr_ptr = gif_ptr->gce_ptr; + gif_ptr->gce_ptr = NULL; + } +#endif +} +FX_INT32 _gif_decode_extension(gif_decompress_struct_p gif_ptr) +{ + FX_LPBYTE data_size_ptr = NULL; + FX_LPBYTE data_ptr = NULL; + FX_DWORD skip_size_org = gif_ptr->skip_size; + switch(gif_ptr->decode_status) { +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + case GIF_D_STATUS_EXT_AE: { + ASSERT(sizeof(GifAE) == 12); + GifAE* gif_ae_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_ae_ptr, 12) == NULL) { + return 2; + } + CFX_ByteString gif_ae_data_str; + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + while(*data_size_ptr != GIF_BLOCK_TERMINAL) { + FX_BYTE data_size = *data_size_ptr; + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL || + _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + gif_ae_data_str += CFX_ByteString((FX_LPCBYTE)data_ptr, data_size); + } + FXSYS_memcpy32(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8); + FXSYS_memcpy32(gif_ptr->app_authentication, gif_ae_ptr->app_authentication, 3); + gif_ptr->app_data_size = gif_ae_data_str.GetLength(); + if(gif_ptr->app_data != NULL) { + FX_Free(gif_ptr->app_data); + gif_ptr->app_data = NULL; + } + gif_ptr->app_data = FX_Alloc(FX_BYTE, gif_ptr->app_data_size); + GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr); + FXSYS_memcpy32(gif_ptr->app_data, FX_LPCBYTE(gif_ae_data_str), gif_ptr->app_data_size); + } + break; +#endif +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + case GIF_D_STATUS_EXT_CE: { + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + gif_ptr->cmt_data_ptr->Empty(); + while(*data_size_ptr != GIF_BLOCK_TERMINAL) { + FX_BYTE data_size = *data_size_ptr; + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL || + _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + *(gif_ptr->cmt_data_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size); + } + } + break; +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + case GIF_D_STATUS_EXT_PTE: { + ASSERT(sizeof(GifPTE) == 13); + GifPTE* gif_pte_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_pte_ptr, 13) == NULL) { + return 2; + } + GifPlainText* gif_pt_ptr = FX_Alloc(GifPlainText, 1); + GIF_PTR_NOT_NULL(gif_pt_ptr, gif_ptr); + FXSYS_memset32(gif_pt_ptr, 0, sizeof(GifPlainText)); + _gif_takeover_gce_ptr(gif_ptr, &gif_pt_ptr->gce_ptr); + gif_pt_ptr->pte_ptr = (GifPTE*)FX_Alloc(FX_BYTE, sizeof(GifPTE)); + GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr); + gif_pt_ptr->string_ptr = FX_NEW CFX_ByteString; + GIF_PTR_NOT_NULL(gif_pt_ptr->string_ptr, gif_ptr); + gif_pt_ptr->pte_ptr->block_size = gif_pte_ptr->block_size; + gif_pt_ptr->pte_ptr->grid_left = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_left); + gif_pt_ptr->pte_ptr->grid_top = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_top); + gif_pt_ptr->pte_ptr->grid_width = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_width); + gif_pt_ptr->pte_ptr->grid_height = _GetWord_LSBFirst((FX_LPBYTE)&gif_pte_ptr->grid_height); + gif_pt_ptr->pte_ptr->char_width = gif_pte_ptr->char_width; + gif_pt_ptr->pte_ptr->char_height = gif_pte_ptr->char_height; + gif_pt_ptr->pte_ptr->fc_index = gif_pte_ptr->fc_index; + gif_pt_ptr->pte_ptr->bc_index = gif_pte_ptr->bc_index; + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + if(gif_pt_ptr != NULL) { + if(gif_pt_ptr->gce_ptr != NULL) { + FX_Free(gif_pt_ptr->gce_ptr); + } + if(gif_pt_ptr->pte_ptr != NULL) { + FX_Free(gif_pt_ptr->pte_ptr); + } + if(gif_pt_ptr->string_ptr != NULL) { + delete gif_pt_ptr->string_ptr; + } + FX_Free(gif_pt_ptr); + } + return 2; + } + while(*data_size_ptr != GIF_BLOCK_TERMINAL) { + FX_BYTE data_size = *data_size_ptr; + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL || + _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + if(gif_pt_ptr != NULL) { + if(gif_pt_ptr->gce_ptr != NULL) { + FX_Free(gif_pt_ptr->gce_ptr); + } + if(gif_pt_ptr->pte_ptr != NULL) { + FX_Free(gif_pt_ptr->pte_ptr); + } + if(gif_pt_ptr->string_ptr != NULL) { + delete gif_pt_ptr->string_ptr; + } + FX_Free(gif_pt_ptr); + } + return 2; + } + *(gif_pt_ptr->string_ptr) += CFX_ByteString((FX_LPCSTR)data_ptr, data_size); + } + gif_ptr->pt_ptr_arr_ptr->Add(gif_pt_ptr); + } + break; +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + case GIF_D_STATUS_EXT_GCE: { + ASSERT(sizeof(GifGCE) == 5); + GifGCE* gif_gce_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_gce_ptr, 6) == NULL) { + return 2; + } + if(gif_ptr->gce_ptr == NULL) { + gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(FX_BYTE, sizeof(GifGCE)); + GIF_PTR_NOT_NULL(gif_ptr->gce_ptr, gif_ptr); + } + gif_ptr->gce_ptr->block_size = gif_gce_ptr->block_size; + gif_ptr->gce_ptr->gce_flag = gif_gce_ptr->gce_flag; + gif_ptr->gce_ptr->delay_time = _GetWord_LSBFirst((FX_LPBYTE)&gif_gce_ptr->delay_time); + gif_ptr->gce_ptr->trans_index = gif_gce_ptr->trans_index; + } + break; +#endif + default: { +#ifndef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + if(gif_ptr->decode_status == GIF_D_STATUS_EXT_PTE) { +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + if(gif_ptr->gce_ptr != NULL) { + FX_Free(gif_ptr->gce_ptr); + gif_ptr->gce_ptr = NULL; + } +#endif + } +#endif + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + return 2; + } + while(*data_size_ptr != GIF_BLOCK_TERMINAL) { + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL || + _gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL ) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + } + } + } + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_SIG); + return 1; +} +FX_INT32 _gif_decode_image_info(gif_decompress_struct_p gif_ptr) +{ + if(gif_ptr->width == 0 || gif_ptr->height == 0) { + _gif_error(gif_ptr, "No Image Header Info"); + return 0; + } + FX_DWORD skip_size_org = gif_ptr->skip_size; + ASSERT(sizeof(GifImageInfo) == 9); + GifImageInfo* gif_img_info_ptr = NULL; + if(_gif_read_data(gif_ptr, (FX_LPBYTE*)&gif_img_info_ptr, 9) == NULL) { + return 2; + } + GifImage* gif_image_ptr = (GifImage*)FX_Alloc(FX_BYTE, sizeof(GifImage)); + GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr); + FXSYS_memset32(gif_image_ptr, 0, sizeof(GifImage)); + gif_image_ptr->image_info_ptr = (GifImageInfo*)FX_Alloc(FX_BYTE, sizeof(GifImageInfo)); + GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr); + gif_image_ptr->image_info_ptr->left = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->left); + gif_image_ptr->image_info_ptr->top = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->top); + gif_image_ptr->image_info_ptr->width = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->width); + gif_image_ptr->image_info_ptr->height = _GetWord_LSBFirst((FX_LPBYTE)&gif_img_info_ptr->height); + gif_image_ptr->image_info_ptr->local_flag = gif_img_info_ptr->local_flag; + if(gif_image_ptr->image_info_ptr->left + gif_image_ptr->image_info_ptr->width > gif_ptr->width || + gif_image_ptr->image_info_ptr->top + gif_image_ptr->image_info_ptr->height > gif_ptr->height) { + if(gif_image_ptr->image_info_ptr != NULL) { + FX_Free(gif_image_ptr->image_info_ptr); + } + if(gif_image_ptr->image_row_buf != NULL) { + FX_Free(gif_image_ptr->image_row_buf); + } + FX_Free(gif_image_ptr); + _gif_error(gif_ptr, "Image Data Out Of LSD, The File May Be Corrupt"); + return 0; + } + GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag; + if(gif_img_info_lf_ptr->local_pal) { + ASSERT(sizeof(GifPalette) == 3); + FX_INT32 loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3; + FX_LPBYTE loc_pal_ptr = NULL; + if(_gif_read_data(gif_ptr, &loc_pal_ptr, loc_pal_size) == NULL) { + gif_ptr->skip_size = skip_size_org; + if(gif_image_ptr->image_info_ptr != NULL) { + FX_Free(gif_image_ptr->image_info_ptr); + } + if(gif_image_ptr->image_row_buf != NULL) { + FX_Free(gif_image_ptr->image_row_buf); + } + FX_Free(gif_image_ptr); + return 2; + } + gif_image_ptr->local_pal_ptr = (GifPalette*)gif_ptr->_gif_ask_buf_for_pal_fn(gif_ptr, loc_pal_size); + if(gif_image_ptr->local_pal_ptr != NULL) { + FXSYS_memcpy32((FX_LPBYTE)gif_image_ptr->local_pal_ptr, loc_pal_ptr, loc_pal_size); + } + } + FX_LPBYTE code_size_ptr = NULL; + if(_gif_read_data(gif_ptr, &code_size_ptr, 1) == NULL) { + gif_ptr->skip_size = skip_size_org; + if(gif_image_ptr->image_info_ptr != NULL) { + FX_Free(gif_image_ptr->image_info_ptr); + } + if(gif_image_ptr->local_pal_ptr != NULL) { + FX_Free(gif_image_ptr->local_pal_ptr); + } + if(gif_image_ptr->image_row_buf != NULL) { + FX_Free(gif_image_ptr->image_row_buf); + } + FX_Free(gif_image_ptr); + return 2; + } + gif_image_ptr->image_code_size = *code_size_ptr; + gif_ptr->_gif_record_current_position_fn(gif_ptr, &gif_image_ptr->image_data_pos); + gif_image_ptr->image_data_pos += gif_ptr->skip_size; + _gif_takeover_gce_ptr(gif_ptr, &gif_image_ptr->image_gce_ptr); + gif_ptr->img_ptr_arr_ptr->Add(gif_image_ptr); + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); + return 1; +} +FX_INT32 _gif_load_frame(gif_decompress_struct_p gif_ptr, FX_INT32 frame_num) +{ + if(gif_ptr == NULL || + frame_num < 0 || + frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize() + ) { + return 0; + } + FX_LPBYTE data_size_ptr = NULL; + FX_LPBYTE data_ptr = NULL; + FX_DWORD skip_size_org = gif_ptr->skip_size; + GifImage* gif_image_ptr = gif_ptr->img_ptr_arr_ptr->GetAt(frame_num); + FX_DWORD gif_img_row_bytes = gif_image_ptr->image_info_ptr->width; + if(gif_ptr->decode_status == GIF_D_STATUS_TAIL) { + if(gif_image_ptr->image_row_buf) { + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + } + gif_image_ptr->image_row_buf = FX_Alloc(FX_BYTE, gif_img_row_bytes); + GIF_PTR_NOT_NULL(gif_image_ptr->image_row_buf, gif_ptr); + GifGCE* gif_img_gce_ptr = gif_image_ptr->image_gce_ptr; + FX_INT32 loc_pal_num = ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->local_pal ? + (2 << ((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->pal_bits) : 0; + gif_ptr->avail_in = 0; + if(gif_img_gce_ptr == NULL) { + FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos, + gif_image_ptr->image_info_ptr->left, + gif_image_ptr->image_info_ptr->top, + gif_image_ptr->image_info_ptr->width, + gif_image_ptr->image_info_ptr->height, + loc_pal_num, gif_image_ptr->local_pal_ptr, + 0, 0, -1, 0, + (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace + ); + if(!bRes) { + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + _gif_error(gif_ptr, "Error Read Record Position Data"); + return 0; + } + } else { + FX_BOOL bRes = gif_ptr->_gif_get_record_position_fn(gif_ptr, gif_image_ptr->image_data_pos, + gif_image_ptr->image_info_ptr->left, + gif_image_ptr->image_info_ptr->top, + gif_image_ptr->image_info_ptr->width, + gif_image_ptr->image_info_ptr->height, + loc_pal_num, gif_image_ptr->local_pal_ptr, + (FX_INT32)gif_image_ptr->image_gce_ptr->delay_time, + (FX_BOOL)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->user_input, + ((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->transparency ? + (FX_INT32)gif_image_ptr->image_gce_ptr->trans_index : -1, + (FX_INT32)((GifCEF*)&gif_image_ptr->image_gce_ptr->gce_flag)->disposal_method, + (FX_BOOL)((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace + ); + if(!bRes) { + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + _gif_error(gif_ptr, "Error Read Record Position Data"); + return 0; + } + } + if(gif_ptr->img_decoder_ptr == NULL) { + gif_ptr->img_decoder_ptr = FX_NEW CGifLZWDecoder(gif_ptr->err_ptr); + GIF_PTR_NOT_NULL(gif_ptr->img_decoder_ptr, gif_ptr); + } + gif_ptr->img_decoder_ptr->InitTable(gif_image_ptr->image_code_size); + gif_ptr->img_row_offset = 0; + gif_ptr->img_row_avail_size = 0; + gif_ptr->img_pass_num = 0; + gif_image_ptr->image_row_num = 0; + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); + } + CGifLZWDecoder* img_decoder_ptr = gif_ptr->img_decoder_ptr; + if(gif_ptr->decode_status == GIF_D_STATUS_IMG_DATA) { + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + return 2; + } + if(*data_size_ptr != GIF_BLOCK_TERMINAL) { + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + img_decoder_ptr->Input(data_ptr, *data_size_ptr); + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); + gif_ptr->img_row_offset += gif_ptr->img_row_avail_size; + gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset; + FX_INT32 ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size); + if(ret == 0) { + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); + _gif_error(gif_ptr, "Decode Image Data Error"); + return 0; + } + while (ret != 0) { + if(ret == 1) { + gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf); + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); + return 1; + } + if(ret == 2) { + ASSERT(img_decoder_ptr->GetAvailInput() == 0); + skip_size_org = gif_ptr->skip_size; + if(_gif_read_data(gif_ptr, &data_size_ptr, 1) == NULL) { + return 2; + } + if (*data_size_ptr != GIF_BLOCK_TERMINAL) { + if(_gif_read_data(gif_ptr, &data_ptr, *data_size_ptr) == NULL) { + gif_ptr->skip_size = skip_size_org; + return 2; + } + img_decoder_ptr->Input(data_ptr, *data_size_ptr); + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_IMG_DATA); + gif_ptr->img_row_offset += gif_ptr->img_row_avail_size; + gif_ptr->img_row_avail_size = gif_img_row_bytes - gif_ptr->img_row_offset; + ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size); + } + } + if(ret == 3) { + if(((GifLF*)&gif_image_ptr->image_info_ptr->local_flag)->interlace) { + gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num, gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_num += s_gif_interlace_step[gif_ptr->img_pass_num]; + if(gif_image_ptr->image_row_num >= (FX_INT32)gif_image_ptr->image_info_ptr->height) { + gif_ptr->img_pass_num++; + gif_image_ptr->image_row_num = s_gif_interlace_step[gif_ptr->img_pass_num] / 2; + } + } else { + gif_ptr->_gif_get_row_fn(gif_ptr, gif_image_ptr->image_row_num++, gif_image_ptr->image_row_buf); + } + gif_ptr->img_row_offset = 0; + gif_ptr->img_row_avail_size = gif_img_row_bytes; + ret = img_decoder_ptr->Decode(gif_image_ptr->image_row_buf + gif_ptr->img_row_offset, gif_ptr->img_row_avail_size); + } + if(ret == 0) { + FX_Free(gif_image_ptr->image_row_buf); + gif_image_ptr->image_row_buf = NULL; + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); + _gif_error(gif_ptr, "Decode Image Data Error"); + return 0; + } + } + } + _gif_save_decoding_status(gif_ptr, GIF_D_STATUS_TAIL); + } + _gif_error(gif_ptr, "Decode Image Data Error"); + return 0; +} +void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, FX_INT32 status) +{ + gif_ptr->decode_status = status; + gif_ptr->next_in += gif_ptr->skip_size; + gif_ptr->avail_in -= gif_ptr->skip_size; + gif_ptr->skip_size = 0; +} +FX_LPBYTE _gif_read_data(gif_decompress_struct_p gif_ptr, FX_LPBYTE* des_buf_pp, FX_DWORD data_size) +{ + if(gif_ptr == NULL || + gif_ptr->avail_in < gif_ptr->skip_size + data_size) { + return NULL; + } + *des_buf_pp = gif_ptr->next_in + gif_ptr->skip_size; + gif_ptr->skip_size += data_size; + return *des_buf_pp; +} +void _gif_input_buffer(gif_decompress_struct_p gif_ptr, FX_LPBYTE src_buf, FX_DWORD src_size) +{ + gif_ptr->next_in = src_buf; + gif_ptr->avail_in = src_size; + gif_ptr->skip_size = 0; +} +FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, FX_LPBYTE* avial_buf_ptr) +{ + if(avial_buf_ptr != NULL) { + *avial_buf_ptr = NULL; + if(gif_ptr->avail_in > 0) { + *avial_buf_ptr = gif_ptr->next_in; + } + } + return gif_ptr->avail_in; +} +FX_INT32 _gif_get_frame_num(gif_decompress_struct_p gif_ptr) +{ + return gif_ptr->img_ptr_arr_ptr->GetSize(); +} +static FX_BOOL _gif_write_header( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len ) +{ + if (gif_ptr->cur_offset) { + return TRUE; + } + dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF); + dst_buf = FX_AllocNL(FX_BYTE, dst_len); + if (dst_buf == NULL) { + return FALSE; + } + FXSYS_memset32(dst_buf, 0, dst_len); + FXSYS_memcpy32(dst_buf, gif_ptr->header_ptr, sizeof(GifHeader)); + gif_ptr->cur_offset += sizeof(GifHeader); + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->width); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->lsd_ptr->height); + gif_ptr->cur_offset += 2; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->global_flag; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->bc_index; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->lsd_ptr->pixel_aspect; + if (gif_ptr->global_pal) { + FX_WORD size = sizeof(GifPalette) * gif_ptr->gpal_num; + if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + size)) { + return FALSE; + } + FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size); + gif_ptr->cur_offset += size; + } + return TRUE; +} +void interlace_buf(FX_LPCBYTE buf, FX_DWORD pitch, FX_DWORD height) +{ + CFX_ArrayTemplate pass[4]; + int i, j; + FX_DWORD row; + row = 0; + FX_LPBYTE temp; + while (row < height) { + if (row % 8 == 0) { + j = 0; + } else if (row % 4 == 0) { + j = 1; + } else if (row % 2 == 0) { + j = 2; + } else { + j = 3; + } + temp = FX_Alloc(FX_BYTE, pitch); + if (temp == NULL) { + return; + } + FXSYS_memcpy32(temp, &buf[pitch * row], pitch); + pass[j].Add(temp); + row ++; + } + for (i = 0, row = 0; i < 4; i++) { + for (j = 0; j < pass[i].GetSize(); j++, row++) { + FXSYS_memcpy32((FX_LPBYTE)&buf[pitch * row], pass[i].GetAt(j), pitch); + FX_Free(pass[i].GetAt(j)); + } + } +} +static void _gif_write_block_data(FX_LPCBYTE src_buf, FX_DWORD src_len, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& dst_offset) +{ + FX_DWORD src_offset = 0; + while (src_len > GIF_DATA_BLOCK) { + dst_buf[dst_offset++] = GIF_DATA_BLOCK; + FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], GIF_DATA_BLOCK); + dst_offset += GIF_DATA_BLOCK; + src_offset += GIF_DATA_BLOCK; + src_len -= GIF_DATA_BLOCK; + } + dst_buf[dst_offset++] = (FX_BYTE)src_len; + FXSYS_memcpy32(&dst_buf[dst_offset], &src_buf[src_offset], src_len); + dst_offset += src_len; +} +static FX_BOOL _gif_write_data( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len ) +{ + if (!_gif_grow_buf(dst_buf, dst_len, gif_ptr->cur_offset + GIF_DATA_BLOCK)) { + return FALSE; + } +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0) { + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; + dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_GCE; + gif_ptr->gce_ptr->block_size = 4; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->block_size; + gif_ptr->gce_ptr->gce_flag = 0; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->gce_flag; + gif_ptr->gce_ptr->delay_time = 10; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->gce_ptr->delay_time); + gif_ptr->cur_offset += 2; + gif_ptr->gce_ptr->trans_index = 0; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->gce_ptr->trans_index; + dst_buf[gif_ptr->cur_offset++] = 0; + } +#endif + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_IMAGE; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->left); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->top); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->width); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->image_info_ptr->height); + gif_ptr->cur_offset += 2; + GifLF& lf = (GifLF&)gif_ptr->image_info_ptr->local_flag; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->image_info_ptr->local_flag; + if (gif_ptr->local_pal) { + FX_DWORD pal_size = sizeof(GifPalette) * gif_ptr->lpal_num; + if (!_gif_grow_buf(dst_buf, dst_len, pal_size + gif_ptr->cur_offset)) { + return FALSE; + } + FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->local_pal, pal_size); + gif_ptr->cur_offset += pal_size; + } + if (lf.interlace) { + interlace_buf(gif_ptr->src_buf, gif_ptr->src_pitch, gif_ptr->image_info_ptr->height); + } + FX_BYTE code_bit = lf.pal_bits; + if (lf.local_pal == 0) { + GifGF& gf = (GifGF&)gif_ptr->lsd_ptr->global_flag; + code_bit = gf.pal_bits; + } + gif_ptr->img_encoder_ptr->Start(code_bit, gif_ptr->src_buf, dst_buf, gif_ptr->cur_offset); + FX_DWORD i; + for (i = 0; i < gif_ptr->src_row; i++) { + if (!gif_ptr->img_encoder_ptr->Encode(&gif_ptr->src_buf[i * gif_ptr->src_pitch], gif_ptr->src_width * (code_bit + 1), + dst_buf, dst_len, gif_ptr->cur_offset)) { + return FALSE; + } + } + gif_ptr->img_encoder_ptr->Finish(dst_buf, dst_len, gif_ptr->cur_offset); + dst_buf[gif_ptr->cur_offset++] = 0; +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->cmt_data_ptr) { + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; + dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_CE; + _gif_write_block_data(gif_ptr->cmt_data_ptr, gif_ptr->cmt_data_len, dst_buf, dst_len, gif_ptr->cur_offset); + dst_buf[gif_ptr->cur_offset++] = 0; + } +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->pte_data_ptr) { + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; + dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_PTE; + dst_buf[gif_ptr->cur_offset++] = gif_ptr->pte_ptr->block_size; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_left); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_top); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_width); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->grid_height); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_width); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->char_height); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->fc_index); + gif_ptr->cur_offset += 2; + _SetWord_LSBFirst(dst_buf + gif_ptr->cur_offset, gif_ptr->pte_ptr->bc_index); + gif_ptr->cur_offset += 2; + _gif_write_block_data(gif_ptr->pte_data_ptr, gif_ptr->pte_data_len, dst_buf, dst_len, gif_ptr->cur_offset); + gif_ptr->cur_offset += gif_ptr->pte_data_len; + dst_buf[gif_ptr->cur_offset++] = 0; + } +#endif +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + if (FXSYS_memcmp32(gif_ptr->header_ptr->version, "89a", 3) == 0 && gif_ptr->app_data) { + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_EXTENSION; + dst_buf[gif_ptr->cur_offset++] = GIF_BLOCK_AE; + dst_buf[gif_ptr->cur_offset++] = 11; + FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8); + gif_ptr->cur_offset += 8; + FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8); + gif_ptr->cur_offset += 3; + FXSYS_memcpy32(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_data, gif_ptr->app_data_size); + gif_ptr->cur_offset += gif_ptr->app_data_size; + dst_buf[gif_ptr->cur_offset++] = 0; + } +#endif + dst_buf[gif_ptr->cur_offset++] = GIF_SIG_TRAILER; + return TRUE; +} +FX_BOOL _gif_encode( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len ) +{ + if (!_gif_write_header(gif_ptr, dst_buf, dst_len)) { + return FALSE; + } + FX_DWORD cur_offset = gif_ptr->cur_offset; + FX_BOOL res = TRUE; + if (gif_ptr->frames) { + gif_ptr->cur_offset--; + } + if (!_gif_write_data(gif_ptr, dst_buf, dst_len)) { + gif_ptr->cur_offset = cur_offset; + res = FALSE; + } + dst_len = gif_ptr->cur_offset; + dst_buf[dst_len - 1] = GIF_SIG_TRAILER; + if (res) { + gif_ptr->frames++; + } + return res; +} diff --git a/core/src/fxcodec/lgif/fx_gif.h b/core/src/fxcodec/lgif/fx_gif.h new file mode 100644 index 0000000000..b499a542b6 --- /dev/null +++ b/core/src/fxcodec/lgif/fx_gif.h @@ -0,0 +1,307 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef _FX_BASIC_H_ +#include "../../../include/fxcrt/fx_basic.h" +#endif +extern FX_WORD _GetWord_LSBFirst(FX_LPBYTE p); +extern void _SetWord_LSBFirst(FX_LPBYTE p, FX_WORD v); +extern void _BpcConvert(FX_LPCBYTE src_buf, FX_DWORD src_len, FX_INT32 src_bpc, FX_INT32 dst_bpc, + FX_LPBYTE& dst_buf, FX_DWORD& dst_len); +#define GIF_SUPPORT_COMMENT_EXTENSION +#define GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION +#define GIF_SUPPORT_PLAIN_TEXT_EXTENSION +#define GIF_SIGNATURE "GIF" +#define GIF_SIG_EXTENSION 0x21 +#define GIF_SIG_IMAGE 0x2C +#define GIF_SIG_TRAILER 0x3B +#define GIF_BLOCK_GCE 0xF9 +#define GIF_BLOCK_PTE 0x01 +#define GIF_BLOCK_CE 0xFE +#define GIF_BLOCK_AE 0xFF +#define GIF_BLOCK_TERMINAL 0x00 +#define GIF_MAX_LZW_CODE 4096 +#define GIF_DATA_BLOCK 255 +#define GIF_MAX_ERROR_SIZE 256 +#define GIF_D_STATUS_SIG 0x01 +#define GIF_D_STATUS_TAIL 0x02 +#define GIF_D_STATUS_EXT 0x03 +#define GIF_D_STATUS_EXT_AE 0x04 +#define GIF_D_STATUS_EXT_CE 0x05 +#define GIF_D_STATUS_EXT_GCE 0x06 +#define GIF_D_STATUS_EXT_PTE 0x07 +#define GIF_D_STATUS_EXT_UNE 0x08 +#define GIF_D_STATUS_IMG_INFO 0x09 +#define GIF_D_STATUS_IMG_DATA 0x0A +#pragma pack(1) +typedef struct tagGifGF { + FX_BYTE pal_bits : 3; + FX_BYTE sort_flag : 1; + FX_BYTE color_resolution : 3; + FX_BYTE global_pal : 1; +} GifGF; +typedef struct tagGifLF { + FX_BYTE pal_bits : 3; + FX_BYTE reserved : 2; + FX_BYTE sort_flag : 1; + FX_BYTE interlace : 1; + FX_BYTE local_pal : 1; +} GifLF; +typedef struct tagGifHeader { + char signature[3]; + char version[3]; +} GifHeader; +typedef struct tagGifLSD { + FX_WORD width; + FX_WORD height; + FX_BYTE global_flag; + FX_BYTE bc_index; + FX_BYTE pixel_aspect; +} GifLSD; +typedef struct tagGifImageInfo { + FX_WORD left; + FX_WORD top; + FX_WORD width; + FX_WORD height; + + FX_BYTE local_flag; +} GifImageInfo; +typedef struct tagGifCEF { + FX_BYTE transparency : 1; + FX_BYTE user_input : 1; + FX_BYTE disposal_method : 3; + FX_BYTE reserved : 3; +} GifCEF; +typedef struct tagGifGCE { + FX_BYTE block_size; + FX_BYTE gce_flag; + FX_WORD delay_time; + FX_BYTE trans_index; +} GifGCE; +typedef struct tagGifPTE { + FX_BYTE block_size; + FX_WORD grid_left; + FX_WORD grid_top; + FX_WORD grid_width; + FX_WORD grid_height; + + FX_BYTE char_width; + FX_BYTE char_height; + + FX_BYTE fc_index; + FX_BYTE bc_index; +} GifPTE; +typedef struct tagGifAE { + FX_BYTE block_size; + FX_BYTE app_identify[8]; + FX_BYTE app_authentication[3]; +} GifAE; +typedef struct tagGifPalette { + FX_BYTE r, g, b; +} GifPalette; +#pragma pack() +typedef struct tagGifImage { + GifGCE* image_gce_ptr; + GifPalette* local_pal_ptr; + GifImageInfo* image_info_ptr; + FX_BYTE image_code_size; + FX_DWORD image_data_pos; + FX_LPBYTE image_row_buf; + FX_INT32 image_row_num; +} GifImage; +typedef struct tagGifPlainText { + GifGCE* gce_ptr; + GifPTE* pte_ptr; + CFX_ByteString* string_ptr; +} GifPlainText; +class CGifLZWDecoder : public CFX_Object +{ +public: + struct tag_Table { + FX_WORD prefix; + FX_BYTE suffix; + }; + CGifLZWDecoder(FX_LPSTR error_ptr = NULL) + { + err_msg_ptr = error_ptr; + } + void InitTable(FX_BYTE code_len); + + FX_INT32 Decode(FX_LPBYTE des_buf, FX_DWORD& des_size); + + void Input(FX_LPBYTE src_buf, FX_DWORD src_size); + FX_DWORD GetAvailInput(); + +private: + void ClearTable(); + void AddCode(FX_WORD prefix_code, FX_BYTE append_char); + void DecodeString(FX_WORD code); + FX_BYTE code_size; + FX_BYTE code_size_cur; + FX_WORD code_clear; + FX_WORD code_end; + FX_WORD code_next; + FX_BYTE code_first; + FX_BYTE stack[GIF_MAX_LZW_CODE]; + FX_WORD stack_size; + tag_Table code_table[GIF_MAX_LZW_CODE]; + FX_WORD code_old; + + FX_LPBYTE next_in; + FX_DWORD avail_in; + + FX_BYTE bits_left; + FX_DWORD code_store; + + FX_LPSTR err_msg_ptr; +}; +class CGifLZWEncoder : public CFX_Object +{ +public: + struct tag_Table { + FX_WORD prefix; + FX_BYTE suffix; + }; + CGifLZWEncoder(); + ~CGifLZWEncoder(); + void Start(FX_BYTE code_len, FX_LPCBYTE src_buf, FX_LPBYTE& dst_buf, FX_DWORD& offset); + FX_BOOL Encode(FX_LPCBYTE src_buf, FX_DWORD src_len, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); + void Finish(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); +private: + void ClearTable(); + FX_BOOL LookUpInTable(FX_LPCBYTE buf, FX_DWORD& offset, FX_BYTE& bit_offset); + void EncodeString(FX_DWORD index, FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); + void WriteBlock(FX_LPBYTE& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); + jmp_buf jmp; + FX_DWORD src_offset; + FX_BYTE src_bit_offset; + FX_BYTE src_bit_cut; + FX_DWORD src_bit_num; + FX_BYTE code_size; + FX_WORD code_clear; + FX_WORD code_end; + FX_WORD index_num; + FX_BYTE bit_offset; + FX_BYTE index_bit_cur; + FX_BYTE index_buf[GIF_DATA_BLOCK]; + FX_BYTE index_buf_len; + tag_Table code_table[GIF_MAX_LZW_CODE]; + FX_WORD table_cur; +}; +typedef struct tag_gif_decompress_struct gif_decompress_struct; +typedef gif_decompress_struct *gif_decompress_struct_p; +typedef gif_decompress_struct_p *gif_decompress_struct_pp; +static FX_INT32 s_gif_interlace_step[4] = {8, 8, 4, 2}; +struct tag_gif_decompress_struct { + jmp_buf jmpbuf; + FX_LPSTR err_ptr; + void (*_gif_error_fn)(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg); + void* context_ptr; + int width; + int height; + GifPalette* global_pal_ptr; + FX_INT32 global_pal_num; + FX_BYTE global_sort_flag; + FX_BYTE global_color_resolution; + + FX_BYTE bc_index; + FX_BYTE pixel_aspect; + CGifLZWDecoder* img_decoder_ptr; + FX_DWORD img_row_offset; + FX_DWORD img_row_avail_size; + FX_BYTE img_pass_num; + CFX_ArrayTemplate* img_ptr_arr_ptr; + FX_LPBYTE (*_gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr, FX_INT32 pal_size); + FX_LPBYTE next_in; + FX_DWORD avail_in; + FX_INT32 decode_status; + FX_DWORD skip_size; + void (*_gif_record_current_position_fn)(gif_decompress_struct_p gif_ptr, FX_DWORD* cur_pos_ptr); + void (*_gif_get_row_fn)(gif_decompress_struct_p gif_ptr, FX_INT32 row_num, FX_LPBYTE row_buf); + FX_BOOL (*_gif_get_record_position_fn)(gif_decompress_struct_p gif_ptr, FX_DWORD cur_pos, + FX_INT32 left, FX_INT32 top, FX_INT32 width, FX_INT32 height, + FX_INT32 pal_num, void* pal_ptr, + FX_INT32 delay_time, FX_BOOL user_input, + FX_INT32 trans_index, FX_INT32 disposal_method, FX_BOOL interlace); +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + FX_BYTE app_identify[8]; + FX_BYTE app_authentication[3]; + FX_DWORD app_data_size; + FX_LPBYTE app_data; +#endif +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + CFX_ByteString* cmt_data_ptr; +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + GifGCE* gce_ptr; +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + CFX_ArrayTemplate* pt_ptr_arr_ptr; +#endif +}; +typedef struct tag_gif_compress_struct gif_compress_struct; +typedef gif_compress_struct *gif_compress_struct_p; +typedef gif_compress_struct_p *gif_compress_struct_pp; +struct tag_gif_compress_struct { + FX_LPCBYTE src_buf; + FX_DWORD src_pitch; + FX_DWORD src_width; + FX_DWORD src_row; + FX_DWORD cur_offset; + FX_DWORD frames; + GifHeader* header_ptr; + GifLSD* lsd_ptr; + GifPalette* global_pal; + FX_WORD gpal_num; + GifPalette* local_pal; + FX_WORD lpal_num; + GifImageInfo* image_info_ptr; + CGifLZWEncoder* img_encoder_ptr; +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + FX_BYTE app_identify[8]; + FX_BYTE app_authentication[3]; + FX_DWORD app_data_size; + FX_LPBYTE app_data; +#endif + +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + FX_LPBYTE cmt_data_ptr; + FX_DWORD cmt_data_len; +#endif + +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + GifGCE* gce_ptr; +#endif + +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + GifPTE* pte_ptr; + FX_LPCBYTE pte_data_ptr; + FX_DWORD pte_data_len; +#endif +}; +void _gif_error(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg); +void _gif_warn(gif_decompress_struct_p gif_ptr, FX_LPCSTR err_msg); +gif_decompress_struct_p _gif_create_decompress(); +void _gif_destroy_decompress(gif_decompress_struct_pp gif_ptr_ptr); +gif_compress_struct_p _gif_create_compress(); +void _gif_destroy_compress(gif_compress_struct_pp gif_ptr_ptr); +FX_INT32 _gif_read_header(gif_decompress_struct_p gif_ptr); +FX_INT32 _gif_get_frame(gif_decompress_struct_p gif_ptr); +FX_INT32 _gif_get_frame_num(gif_decompress_struct_p gif_ptr); +FX_INT32 _gif_decode_extension(gif_decompress_struct_p gif_ptr); +FX_INT32 _gif_decode_image_info(gif_decompress_struct_p gif_ptr); +void _gif_takeover_gce_ptr(gif_decompress_struct_p gif_ptr, GifGCE** gce_ptr_ptr); +FX_INT32 _gif_load_frame(gif_decompress_struct_p gif_ptr, FX_INT32 frame_num); +FX_LPBYTE _gif_read_data(gif_decompress_struct_p gif_ptr, FX_LPBYTE* des_buf_pp, FX_DWORD data_size); +void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, FX_INT32 status); +void _gif_input_buffer(gif_decompress_struct_p gif_ptr, FX_LPBYTE src_buf, FX_DWORD src_size); +FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, FX_LPBYTE* avial_buf_ptr); +void interlace_buf(FX_LPCBYTE buf, FX_DWORD width, FX_DWORD height); +FX_BOOL _gif_encode( gif_compress_struct_p gif_ptr, FX_LPBYTE& dst_buf, FX_DWORD& dst_len ); +#define GIF_PTR_NOT_NULL(ptr,gif_ptr) if(ptr == NULL){ \ + _gif_error(gif_ptr,"Out Of Memory");\ + return 0; \ + } -- cgit v1.2.3