diff options
author | Bo Xu <bo_xu@foxitsoftware.com> | 2014-10-28 23:03:33 -0700 |
---|---|---|
committer | Bo Xu <bo_xu@foxitsoftware.com> | 2014-11-03 11:10:11 -0800 |
commit | fdc00a7042d912aafaabddae4d9c84199921ef23 (patch) | |
tree | 32ab8ac91cc68d2cd15b9168782a71b3f3f5e7b9 /core/src/fxcodec/lgif | |
parent | e9b38fa38de2c95d8260be31c57d9272c4d127ed (diff) | |
download | pdfium-fdc00a7042d912aafaabddae4d9c84199921ef23.tar.xz |
Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
Diffstat (limited to 'core/src/fxcodec/lgif')
-rw-r--r-- | core/src/fxcodec/lgif/fx_gif.cpp | 1368 | ||||
-rw-r--r-- | core/src/fxcodec/lgif/fx_gif.h | 307 |
2 files changed, 1675 insertions, 0 deletions
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<GifImage*>;
+ 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<GifPlainText*>;
+ 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<FX_LPBYTE> 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<GifImage*>* 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<GifPlainText*>* 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; \
+ }
|