summaryrefslogtreecommitdiff
path: root/core/fxcodec/lgif
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcodec/lgif')
-rw-r--r--core/fxcodec/lgif/cgifcontext.cpp471
-rw-r--r--core/fxcodec/lgif/cgifcontext.h13
-rw-r--r--core/fxcodec/lgif/fx_gif.cpp484
-rw-r--r--core/fxcodec/lgif/fx_gif.h11
4 files changed, 484 insertions, 495 deletions
diff --git a/core/fxcodec/lgif/cgifcontext.cpp b/core/fxcodec/lgif/cgifcontext.cpp
index 4dc663644c..1eb1b335aa 100644
--- a/core/fxcodec/lgif/cgifcontext.cpp
+++ b/core/fxcodec/lgif/cgifcontext.cpp
@@ -6,13 +6,21 @@
#include "core/fxcodec/lgif/cgifcontext.h"
+#include <algorithm>
#include <utility>
#include "core/fxcodec/codec/ccodec_gifmodule.h"
+#include "core/fxcodec/lbmp/fx_bmp.h"
#include "core/fxcodec/lgif/fx_gif.h"
#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
+namespace {
+
+const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2};
+
+} // namespace
+
CGifContext::CGifContext(CCodec_GifModule* gif_module,
CCodec_GifModule::Delegate* pDelegate)
: m_pModule(gif_module),
@@ -64,3 +72,466 @@ bool CGifContext::GetRecordPosition(uint32_t cur_pos,
cur_pos, FX_RECT(left, top, left + width, top + height), pal_num, pal_ptr,
delay_time, user_input, trans_index, disposal_method, interlace);
}
+
+GifDecodeStatus CGifContext::ReadHeader() {
+ uint32_t skip_size_org = skip_size;
+ GifHeader* gif_header_ptr = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&gif_header_ptr), 6))
+ return GifDecodeStatus::Unfinished;
+
+ if (strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||
+ gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') {
+ AddError("Not A Gif Image");
+ return GifDecodeStatus::Error;
+ }
+ GifLSD* gif_lsd_ptr = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&gif_lsd_ptr), 7)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ if (reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->global_pal) {
+ global_pal_exp =
+ reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
+ int32_t global_pal_size = (2 << global_pal_exp) * 3;
+ uint8_t* global_pal_ptr = nullptr;
+ if (!ReadData(&global_pal_ptr, global_pal_size)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;
+ global_color_resolution =
+ ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;
+ m_GlobalPalette.resize(global_pal_size / 3);
+ memcpy(m_GlobalPalette.data(), global_pal_ptr, global_pal_size);
+ }
+ width =
+ (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->width));
+ height =
+ (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->height));
+ bc_index = gif_lsd_ptr->bc_index;
+ pixel_aspect = gif_lsd_ptr->pixel_aspect;
+ return GifDecodeStatus::Success;
+}
+
+GifDecodeStatus CGifContext::GetFrame() {
+ GifDecodeStatus ret = GifDecodeStatus::Success;
+ while (true) {
+ switch (decode_status) {
+ case GIF_D_STATUS_TAIL:
+ return GifDecodeStatus::Success;
+ case GIF_D_STATUS_SIG: {
+ uint8_t* sig_ptr = nullptr;
+ if (!ReadData(&sig_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ switch (*sig_ptr) {
+ case GIF_SIG_EXTENSION:
+ SaveDecodingStatus(GIF_D_STATUS_EXT);
+ continue;
+ case GIF_SIG_IMAGE:
+ SaveDecodingStatus(GIF_D_STATUS_IMG_INFO);
+ continue;
+ case GIF_SIG_TRAILER:
+ SaveDecodingStatus(GIF_D_STATUS_TAIL);
+ return GifDecodeStatus::Success;
+ default:
+ if (avail_in) {
+ // The Gif File has non_standard Tag!
+ SaveDecodingStatus(GIF_D_STATUS_SIG);
+ continue;
+ }
+ // The Gif File Doesn't have Trailer Tag!
+ return GifDecodeStatus::Success;
+ }
+ }
+ case GIF_D_STATUS_EXT: {
+ uint8_t* ext_ptr = nullptr;
+ if (!ReadData(&ext_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ switch (*ext_ptr) {
+ case GIF_BLOCK_CE:
+ SaveDecodingStatus(GIF_D_STATUS_EXT_CE);
+ continue;
+ case GIF_BLOCK_GCE:
+ SaveDecodingStatus(GIF_D_STATUS_EXT_GCE);
+ continue;
+ case GIF_BLOCK_PTE:
+ SaveDecodingStatus(GIF_D_STATUS_EXT_PTE);
+ continue;
+ default: {
+ int32_t status = GIF_D_STATUS_EXT_UNE;
+ if (*ext_ptr == GIF_BLOCK_PTE) {
+ status = GIF_D_STATUS_EXT_PTE;
+ }
+ SaveDecodingStatus(status);
+ continue;
+ }
+ }
+ }
+ case GIF_D_STATUS_IMG_INFO: {
+ ret = DecodeImageInfo();
+ if (ret != GifDecodeStatus::Success)
+ return ret;
+
+ continue;
+ }
+ case GIF_D_STATUS_IMG_DATA: {
+ uint8_t* data_size_ptr = nullptr;
+ uint8_t* data_ptr = nullptr;
+ uint32_t skip_size_org = skip_size;
+ if (!ReadData(&data_size_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ if (!ReadData(&data_ptr, *data_size_ptr)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
+ skip_size_org = skip_size;
+ if (!ReadData(&data_size_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+ }
+ SaveDecodingStatus(GIF_D_STATUS_SIG);
+ continue;
+ }
+ default: {
+ ret = DecodeExtension();
+ if (ret != GifDecodeStatus::Success)
+ return ret;
+ break;
+ }
+ }
+ }
+ return GifDecodeStatus::Success;
+}
+
+GifDecodeStatus CGifContext::LoadFrame(int32_t frame_num) {
+ if (!pdfium::IndexInBounds(m_Images, frame_num))
+ return GifDecodeStatus::Error;
+
+ uint8_t* data_size_ptr = nullptr;
+ uint8_t* data_ptr = nullptr;
+ uint32_t skip_size_org = skip_size;
+ GifImage* gif_image_ptr = m_Images[frame_num].get();
+ uint32_t gif_img_row_bytes = gif_image_ptr->m_ImageInfo.width;
+ if (gif_img_row_bytes == 0) {
+ AddError("Error Invalid Number of Row Bytes");
+ return GifDecodeStatus::Error;
+ }
+ if (decode_status == GIF_D_STATUS_TAIL) {
+ gif_image_ptr->m_ImageRowBuf.resize(gif_img_row_bytes);
+ GifGCE* gif_img_gce_ptr = gif_image_ptr->m_ImageGCE.get();
+ int32_t loc_pal_num =
+ ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->local_pal
+ ? (2 << ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->pal_bits)
+ : 0;
+ avail_in = 0;
+ GifPalette* pLocalPalette = gif_image_ptr->m_LocalPalettes.empty()
+ ? nullptr
+ : gif_image_ptr->m_LocalPalettes.data();
+ if (!gif_img_gce_ptr) {
+ bool bRes = GetRecordPosition(
+ gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
+ gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
+ gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette, 0, 0,
+ -1, 0,
+ (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
+ if (!bRes) {
+ gif_image_ptr->m_ImageRowBuf.clear();
+ AddError("Error Read Record Position Data");
+ return GifDecodeStatus::Error;
+ }
+ } else {
+ bool bRes = GetRecordPosition(
+ gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
+ gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
+ gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette,
+ (int32_t)gif_image_ptr->m_ImageGCE->delay_time,
+ (bool)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->user_input,
+ ((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->transparency
+ ? (int32_t)gif_image_ptr->m_ImageGCE->trans_index
+ : -1,
+ (int32_t)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)
+ ->disposal_method,
+ (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
+ if (!bRes) {
+ gif_image_ptr->m_ImageRowBuf.clear();
+ AddError("Error Read Record Position Data");
+ return GifDecodeStatus::Error;
+ }
+ }
+ if (gif_image_ptr->image_code_exp > GIF_MAX_LZW_EXP) {
+ gif_image_ptr->m_ImageRowBuf.clear();
+ AddError("Error Invalid Code Size");
+ return GifDecodeStatus::Error;
+ }
+ if (!m_ImgDecoder.get())
+ m_ImgDecoder = pdfium::MakeUnique<CGifLZWDecoder>(m_szLastError);
+ m_ImgDecoder->InitTable(!gif_image_ptr->m_LocalPalettes.empty()
+ ? gif_image_ptr->local_pallette_exp
+ : global_pal_exp,
+ gif_image_ptr->image_code_exp);
+ img_row_offset = 0;
+ img_row_avail_size = 0;
+ img_pass_num = 0;
+ gif_image_ptr->image_row_num = 0;
+ SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
+ }
+ CGifLZWDecoder* img_decoder_ptr = m_ImgDecoder.get();
+ if (decode_status == GIF_D_STATUS_IMG_DATA) {
+ if (!ReadData(&data_size_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ if (!ReadData(&data_ptr, *data_size_ptr)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ img_decoder_ptr->Input(data_ptr, *data_size_ptr);
+ SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
+ img_row_offset += img_row_avail_size;
+ img_row_avail_size = gif_img_row_bytes - img_row_offset;
+ GifDecodeStatus ret = img_decoder_ptr->Decode(
+ gif_image_ptr->m_ImageRowBuf.data() + img_row_offset,
+ &img_row_avail_size);
+ if (ret == GifDecodeStatus::Error) {
+ DecodingFailureAtTailCleanup(gif_image_ptr);
+ return GifDecodeStatus::Error;
+ }
+ while (ret != GifDecodeStatus::Error) {
+ if (ret == GifDecodeStatus::Success) {
+ ReadScanline(gif_image_ptr->image_row_num,
+ gif_image_ptr->m_ImageRowBuf.data());
+ gif_image_ptr->m_ImageRowBuf.clear();
+ SaveDecodingStatus(GIF_D_STATUS_TAIL);
+ return GifDecodeStatus::Success;
+ }
+ if (ret == GifDecodeStatus::Unfinished) {
+ ASSERT(img_decoder_ptr->GetAvailInput() == 0);
+ skip_size_org = skip_size;
+ if (!ReadData(&data_size_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ if (!ReadData(&data_ptr, *data_size_ptr)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ img_decoder_ptr->Input(data_ptr, *data_size_ptr);
+ SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
+ img_row_offset += img_row_avail_size;
+ img_row_avail_size = gif_img_row_bytes - img_row_offset;
+ ret = img_decoder_ptr->Decode(
+ gif_image_ptr->m_ImageRowBuf.data() + img_row_offset,
+ &img_row_avail_size);
+ }
+ }
+ if (ret == GifDecodeStatus::InsufficientDestSize) {
+ if (((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace) {
+ ReadScanline(gif_image_ptr->image_row_num,
+ gif_image_ptr->m_ImageRowBuf.data());
+ gif_image_ptr->image_row_num += s_gif_interlace_step[img_pass_num];
+ if (gif_image_ptr->image_row_num >=
+ (int32_t)gif_image_ptr->m_ImageInfo.height) {
+ img_pass_num++;
+ if (img_pass_num == FX_ArraySize(s_gif_interlace_step)) {
+ DecodingFailureAtTailCleanup(gif_image_ptr);
+ return GifDecodeStatus::Error;
+ }
+ gif_image_ptr->image_row_num =
+ s_gif_interlace_step[img_pass_num] / 2;
+ }
+ } else {
+ ReadScanline(gif_image_ptr->image_row_num++,
+ gif_image_ptr->m_ImageRowBuf.data());
+ }
+ img_row_offset = 0;
+ img_row_avail_size = gif_img_row_bytes;
+ ret = img_decoder_ptr->Decode(
+ gif_image_ptr->m_ImageRowBuf.data() + img_row_offset,
+ &img_row_avail_size);
+ }
+ if (ret == GifDecodeStatus::Error) {
+ DecodingFailureAtTailCleanup(gif_image_ptr);
+ return GifDecodeStatus::Error;
+ }
+ }
+ }
+ SaveDecodingStatus(GIF_D_STATUS_TAIL);
+ }
+ AddError("Decode Image Data Error");
+ return GifDecodeStatus::Error;
+}
+
+void CGifContext::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
+ next_in = src_buf;
+ avail_in = src_size;
+ skip_size = 0;
+}
+
+uint32_t CGifContext::GetAvailInput(uint8_t** avail_buf_ptr) const {
+ if (avail_buf_ptr) {
+ *avail_buf_ptr = nullptr;
+ if (avail_in > 0)
+ *avail_buf_ptr = next_in;
+ }
+ return avail_in;
+}
+
+int32_t CGifContext::GetFrameNum() const {
+ return pdfium::CollectionSize<int32_t>(m_Images);
+}
+
+uint8_t* CGifContext::ReadData(uint8_t** des_buf_pp, uint32_t data_size) {
+ if (avail_in < skip_size + data_size)
+ return nullptr;
+
+ *des_buf_pp = next_in + skip_size;
+ skip_size += data_size;
+ return *des_buf_pp;
+}
+
+void CGifContext::SaveDecodingStatus(int32_t status) {
+ decode_status = status;
+ next_in += skip_size;
+ avail_in -= skip_size;
+ skip_size = 0;
+}
+
+GifDecodeStatus CGifContext::DecodeExtension() {
+ uint8_t* data_size_ptr = nullptr;
+ uint8_t* data_ptr = nullptr;
+ uint32_t skip_size_org = skip_size;
+ switch (decode_status) {
+ case GIF_D_STATUS_EXT_CE: {
+ if (!ReadData(&data_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ cmt_data.clear();
+ while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ uint8_t data_size = *data_size_ptr;
+ if (!ReadData(&data_ptr, *data_size_ptr) ||
+ !ReadData(&data_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ cmt_data += ByteString(data_ptr, data_size);
+ }
+ break;
+ }
+ case GIF_D_STATUS_EXT_PTE: {
+ GifPTE* gif_pte = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&gif_pte), 13))
+ return GifDecodeStatus::Unfinished;
+
+ m_GifGCE = nullptr;
+ if (!ReadData(&data_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ if (!ReadData(&data_ptr, *data_size_ptr) ||
+ !ReadData(&data_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ }
+ break;
+ }
+ case GIF_D_STATUS_EXT_GCE: {
+ GifGCE* gif_gce_ptr = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&gif_gce_ptr), 6))
+ return GifDecodeStatus::Unfinished;
+
+ if (!m_GifGCE.get())
+ m_GifGCE = pdfium::MakeUnique<GifGCE>();
+ m_GifGCE->block_size = gif_gce_ptr->block_size;
+ m_GifGCE->gce_flag = gif_gce_ptr->gce_flag;
+ m_GifGCE->delay_time = GetWord_LSBFirst(
+ reinterpret_cast<uint8_t*>(&gif_gce_ptr->delay_time));
+ m_GifGCE->trans_index = gif_gce_ptr->trans_index;
+ break;
+ }
+ default: {
+ if (decode_status == GIF_D_STATUS_EXT_PTE)
+ m_GifGCE = nullptr;
+ if (!ReadData(&data_size_ptr, 1))
+ return GifDecodeStatus::Unfinished;
+
+ while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
+ if (!ReadData(&data_ptr, *data_size_ptr) ||
+ !ReadData(&data_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ }
+ }
+ }
+ SaveDecodingStatus(GIF_D_STATUS_SIG);
+ return GifDecodeStatus::Success;
+}
+
+GifDecodeStatus CGifContext::DecodeImageInfo() {
+ if (width == 0 || height == 0) {
+ AddError("No Image Header Info");
+ return GifDecodeStatus::Error;
+ }
+ uint32_t skip_size_org = skip_size;
+ GifImageInfo* gif_img_info_ptr = nullptr;
+ if (!ReadData(reinterpret_cast<uint8_t**>(&gif_img_info_ptr), 9))
+ return GifDecodeStatus::Unfinished;
+
+ auto gif_image = pdfium::MakeUnique<GifImage>();
+ gif_image->m_ImageInfo.left =
+ GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->left));
+ gif_image->m_ImageInfo.top =
+ GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->top));
+ gif_image->m_ImageInfo.width =
+ GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->width));
+ gif_image->m_ImageInfo.height =
+ GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->height));
+ gif_image->m_ImageInfo.local_flag = gif_img_info_ptr->local_flag;
+ if (gif_image->m_ImageInfo.left + gif_image->m_ImageInfo.width > width ||
+ gif_image->m_ImageInfo.top + gif_image->m_ImageInfo.height > height) {
+ AddError("Image Data Out Of LSD, The File May Be Corrupt");
+ return GifDecodeStatus::Error;
+ }
+ GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
+ if (gif_img_info_lf_ptr->local_pal) {
+ gif_image->local_pallette_exp = gif_img_info_lf_ptr->pal_bits;
+ int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
+ uint8_t* loc_pal_ptr = nullptr;
+ if (!ReadData(&loc_pal_ptr, loc_pal_size)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ gif_image->m_LocalPalettes = std::vector<GifPalette>(loc_pal_size / 3);
+ std::copy(loc_pal_ptr, loc_pal_ptr + loc_pal_size,
+ reinterpret_cast<uint8_t*>(gif_image->m_LocalPalettes.data()));
+ }
+ uint8_t* code_size_ptr = nullptr;
+ if (!ReadData(&code_size_ptr, 1)) {
+ skip_size = skip_size_org;
+ return GifDecodeStatus::Unfinished;
+ }
+ gif_image->image_code_exp = *code_size_ptr;
+ RecordCurrentPosition(&gif_image->image_data_pos);
+ gif_image->image_data_pos += skip_size;
+ gif_image->m_ImageGCE = nullptr;
+ if (m_GifGCE.get()) {
+ gif_image->m_ImageGCE = std::move(m_GifGCE);
+ m_GifGCE = nullptr;
+ }
+ m_Images.push_back(std::move(gif_image));
+ SaveDecodingStatus(GIF_D_STATUS_IMG_DATA);
+ return GifDecodeStatus::Success;
+}
+
+void CGifContext::DecodingFailureAtTailCleanup(GifImage* gif_image_ptr) {
+ gif_image_ptr->m_ImageRowBuf.clear();
+ SaveDecodingStatus(GIF_D_STATUS_TAIL);
+ AddError("Decode Image Data Error");
+}
diff --git a/core/fxcodec/lgif/cgifcontext.h b/core/fxcodec/lgif/cgifcontext.h
index 71cf2bc75e..fdff235355 100644
--- a/core/fxcodec/lgif/cgifcontext.h
+++ b/core/fxcodec/lgif/cgifcontext.h
@@ -36,6 +36,12 @@ class CGifContext : public CCodec_GifModule::Context {
int32_t trans_index,
int32_t disposal_method,
bool interlace);
+ GifDecodeStatus ReadHeader();
+ GifDecodeStatus GetFrame();
+ GifDecodeStatus LoadFrame(int32_t frame_num);
+ void SetInputBuffer(uint8_t* src_buf, uint32_t src_size);
+ uint32_t GetAvailInput(uint8_t** avail_buf_ptr) const;
+ int32_t GetFrameNum() const;
UnownedPtr<CCodec_GifModule> m_pModule;
UnownedPtr<CCodec_GifModule::Delegate> m_pDelegate;
@@ -59,6 +65,13 @@ class CGifContext : public CCodec_GifModule::Context {
uint8_t global_color_resolution;
uint8_t img_pass_num;
char m_szLastError[GIF_MAX_ERROR_SIZE];
+
+ private:
+ uint8_t* ReadData(uint8_t** des_buf_pp, uint32_t data_size);
+ void SaveDecodingStatus(int32_t status);
+ GifDecodeStatus DecodeExtension();
+ GifDecodeStatus DecodeImageInfo();
+ void DecodingFailureAtTailCleanup(GifImage* gif_image_ptr);
};
#endif // CORE_FXCODEC_LGIF_CGIFCONTEXT_H_
diff --git a/core/fxcodec/lgif/fx_gif.cpp b/core/fxcodec/lgif/fx_gif.cpp
index ea78259420..6e1c26ed12 100644
--- a/core/fxcodec/lgif/fx_gif.cpp
+++ b/core/fxcodec/lgif/fx_gif.cpp
@@ -23,168 +23,6 @@ static_assert(sizeof(GifGCE) == 5, "GifGCE should have a size of 5");
static_assert(sizeof(GifHeader) == 6, "GifHeader should have a size of 6");
static_assert(sizeof(GifLSD) == 7, "GifLSD should have a size of 7");
-namespace {
-
-uint8_t* gif_read_data(CGifContext* context,
- uint8_t** des_buf_pp,
- uint32_t data_size) {
- if (!context || context->avail_in < context->skip_size + data_size)
- return nullptr;
-
- *des_buf_pp = context->next_in + context->skip_size;
- context->skip_size += data_size;
- return *des_buf_pp;
-}
-
-void gif_save_decoding_status(CGifContext* context, int32_t status) {
- context->decode_status = status;
- context->next_in += context->skip_size;
- context->avail_in -= context->skip_size;
- context->skip_size = 0;
-}
-
-GifDecodeStatus gif_decode_extension(CGifContext* context) {
- uint8_t* data_size_ptr = nullptr;
- uint8_t* data_ptr = nullptr;
- uint32_t skip_size_org = context->skip_size;
- switch (context->decode_status) {
- case GIF_D_STATUS_EXT_CE: {
- if (!gif_read_data(context, &data_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- context->cmt_data.clear();
- while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- uint8_t data_size = *data_size_ptr;
- if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
- !gif_read_data(context, &data_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- context->cmt_data += ByteString(data_ptr, data_size);
- }
- break;
- }
- case GIF_D_STATUS_EXT_PTE: {
- GifPTE* gif_pte = nullptr;
- if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_pte), 13))
- return GifDecodeStatus::Unfinished;
-
- context->m_GifGCE = nullptr;
- if (!gif_read_data(context, &data_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
- !gif_read_data(context, &data_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- }
- break;
- }
- case GIF_D_STATUS_EXT_GCE: {
- GifGCE* gif_gce_ptr = nullptr;
- if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_gce_ptr), 6))
- return GifDecodeStatus::Unfinished;
-
- if (!context->m_GifGCE.get())
- context->m_GifGCE = pdfium::MakeUnique<GifGCE>();
- context->m_GifGCE->block_size = gif_gce_ptr->block_size;
- context->m_GifGCE->gce_flag = gif_gce_ptr->gce_flag;
- context->m_GifGCE->delay_time = GetWord_LSBFirst(
- reinterpret_cast<uint8_t*>(&gif_gce_ptr->delay_time));
- context->m_GifGCE->trans_index = gif_gce_ptr->trans_index;
- break;
- }
- default: {
- if (context->decode_status == GIF_D_STATUS_EXT_PTE)
- context->m_GifGCE = nullptr;
- if (!gif_read_data(context, &data_size_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- if (!gif_read_data(context, &data_ptr, *data_size_ptr) ||
- !gif_read_data(context, &data_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- }
- }
- }
- gif_save_decoding_status(context, GIF_D_STATUS_SIG);
- return GifDecodeStatus::Success;
-}
-
-GifDecodeStatus gif_decode_image_info(CGifContext* context) {
- if (context->width == 0 || context->height == 0) {
- context->AddError("No Image Header Info");
- return GifDecodeStatus::Error;
- }
- uint32_t skip_size_org = context->skip_size;
- GifImageInfo* gif_img_info_ptr = nullptr;
- if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_img_info_ptr),
- 9))
- return GifDecodeStatus::Unfinished;
-
- auto gif_image = pdfium::MakeUnique<GifImage>();
- gif_image->m_ImageInfo.left =
- GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->left));
- gif_image->m_ImageInfo.top =
- GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->top));
- gif_image->m_ImageInfo.width =
- GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->width));
- gif_image->m_ImageInfo.height =
- GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_img_info_ptr->height));
- gif_image->m_ImageInfo.local_flag = gif_img_info_ptr->local_flag;
- if (gif_image->m_ImageInfo.left + gif_image->m_ImageInfo.width >
- context->width ||
- gif_image->m_ImageInfo.top + gif_image->m_ImageInfo.height >
- context->height) {
- context->AddError("Image Data Out Of LSD, The File May Be Corrupt");
- return GifDecodeStatus::Error;
- }
- GifLF* gif_img_info_lf_ptr = (GifLF*)&gif_img_info_ptr->local_flag;
- if (gif_img_info_lf_ptr->local_pal) {
- gif_image->local_pallette_exp = gif_img_info_lf_ptr->pal_bits;
- int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3;
- uint8_t* loc_pal_ptr = nullptr;
- if (!gif_read_data(context, &loc_pal_ptr, loc_pal_size)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- gif_image->m_LocalPalettes = std::vector<GifPalette>(loc_pal_size / 3);
- std::copy(loc_pal_ptr, loc_pal_ptr + loc_pal_size,
- reinterpret_cast<uint8_t*>(gif_image->m_LocalPalettes.data()));
- }
- uint8_t* code_size_ptr = nullptr;
- if (!gif_read_data(context, &code_size_ptr, 1)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- gif_image->image_code_exp = *code_size_ptr;
- context->RecordCurrentPosition(&gif_image->image_data_pos);
- gif_image->image_data_pos += context->skip_size;
- gif_image->m_ImageGCE = nullptr;
- if (context->m_GifGCE.get()) {
- gif_image->m_ImageGCE = std::move(context->m_GifGCE);
- context->m_GifGCE = nullptr;
- }
- context->m_Images.push_back(std::move(gif_image));
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
- return GifDecodeStatus::Success;
-}
-
-void gif_decoding_failure_at_tail_cleanup(CGifContext* context,
- GifImage* gif_image_ptr) {
- gif_image_ptr->m_ImageRowBuf.clear();
- gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
- context->AddError("Decode Image Data Error");
-}
-
-} // namespace
-
GifImage::GifImage() {}
GifImage::~GifImage() {}
@@ -369,325 +207,3 @@ GifDecodeStatus CGifLZWDecoder::Decode(uint8_t* des_buf, uint32_t* des_size) {
}
return GifDecodeStatus::Error;
}
-
-GifDecodeStatus gif_read_header(CGifContext* context) {
- if (!context)
- return GifDecodeStatus::Error;
-
- uint32_t skip_size_org = context->skip_size;
- GifHeader* gif_header_ptr = nullptr;
- if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_header_ptr), 6))
- return GifDecodeStatus::Unfinished;
-
- if (strncmp(gif_header_ptr->signature, GIF_SIGNATURE, 3) != 0 ||
- gif_header_ptr->version[0] != '8' || gif_header_ptr->version[2] != 'a') {
- context->AddError("Not A Gif Image");
- return GifDecodeStatus::Error;
- }
- GifLSD* gif_lsd_ptr = nullptr;
- if (!gif_read_data(context, reinterpret_cast<uint8_t**>(&gif_lsd_ptr), 7)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- if (reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->global_pal) {
- context->global_pal_exp =
- reinterpret_cast<GifGF*>(&gif_lsd_ptr->global_flag)->pal_bits;
- int32_t global_pal_size = (2 << context->global_pal_exp) * 3;
- uint8_t* global_pal_ptr = nullptr;
- if (!gif_read_data(context, &global_pal_ptr, global_pal_size)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- context->global_sort_flag = ((GifGF*)&gif_lsd_ptr->global_flag)->sort_flag;
- context->global_color_resolution =
- ((GifGF*)&gif_lsd_ptr->global_flag)->color_resolution;
- context->m_GlobalPalette.resize(global_pal_size / 3);
- memcpy(context->m_GlobalPalette.data(), global_pal_ptr, global_pal_size);
- }
- context->width =
- (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->width));
- context->height =
- (int)GetWord_LSBFirst(reinterpret_cast<uint8_t*>(&gif_lsd_ptr->height));
- context->bc_index = gif_lsd_ptr->bc_index;
- context->pixel_aspect = gif_lsd_ptr->pixel_aspect;
- return GifDecodeStatus::Success;
-}
-
-GifDecodeStatus gif_get_frame(CGifContext* context) {
- if (!context)
- return GifDecodeStatus::Error;
-
- GifDecodeStatus ret = GifDecodeStatus::Success;
- while (true) {
- switch (context->decode_status) {
- case GIF_D_STATUS_TAIL:
- return GifDecodeStatus::Success;
- case GIF_D_STATUS_SIG: {
- uint8_t* sig_ptr = nullptr;
- if (!gif_read_data(context, &sig_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- switch (*sig_ptr) {
- case GIF_SIG_EXTENSION:
- gif_save_decoding_status(context, GIF_D_STATUS_EXT);
- continue;
- case GIF_SIG_IMAGE:
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_INFO);
- continue;
- case GIF_SIG_TRAILER:
- gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
- return GifDecodeStatus::Success;
- default:
- if (context->avail_in) {
- // The Gif File has non_standard Tag!
- gif_save_decoding_status(context, GIF_D_STATUS_SIG);
- continue;
- }
- // The Gif File Doesn't have Trailer Tag!
- return GifDecodeStatus::Success;
- }
- }
- case GIF_D_STATUS_EXT: {
- uint8_t* ext_ptr = nullptr;
- if (!gif_read_data(context, &ext_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- switch (*ext_ptr) {
- case GIF_BLOCK_CE:
- gif_save_decoding_status(context, GIF_D_STATUS_EXT_CE);
- continue;
- case GIF_BLOCK_GCE:
- gif_save_decoding_status(context, GIF_D_STATUS_EXT_GCE);
- continue;
- case GIF_BLOCK_PTE:
- gif_save_decoding_status(context, GIF_D_STATUS_EXT_PTE);
- continue;
- default: {
- int32_t status = GIF_D_STATUS_EXT_UNE;
- if (*ext_ptr == GIF_BLOCK_PTE) {
- status = GIF_D_STATUS_EXT_PTE;
- }
- gif_save_decoding_status(context, status);
- continue;
- }
- }
- }
- case GIF_D_STATUS_IMG_INFO: {
- ret = gif_decode_image_info(context);
- if (ret != GifDecodeStatus::Success)
- return ret;
-
- continue;
- }
- case GIF_D_STATUS_IMG_DATA: {
- uint8_t* data_size_ptr = nullptr;
- uint8_t* data_ptr = nullptr;
- uint32_t skip_size_org = context->skip_size;
- if (!gif_read_data(context, &data_size_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- while (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
- skip_size_org = context->skip_size;
- if (!gif_read_data(context, &data_size_ptr, 1))
- return GifDecodeStatus::Unfinished;
- }
- gif_save_decoding_status(context, GIF_D_STATUS_SIG);
- continue;
- }
- default: {
- ret = gif_decode_extension(context);
- if (ret != GifDecodeStatus::Success)
- return ret;
- break;
- }
- }
- }
- return GifDecodeStatus::Success;
-}
-
-GifDecodeStatus gif_load_frame(CGifContext* context, int32_t frame_num) {
- if (!context || !pdfium::IndexInBounds(context->m_Images, frame_num))
- return GifDecodeStatus::Error;
-
- uint8_t* data_size_ptr = nullptr;
- uint8_t* data_ptr = nullptr;
- uint32_t skip_size_org = context->skip_size;
- GifImage* gif_image_ptr = context->m_Images[frame_num].get();
- uint32_t gif_img_row_bytes = gif_image_ptr->m_ImageInfo.width;
- if (gif_img_row_bytes == 0) {
- context->AddError("Error Invalid Number of Row Bytes");
- return GifDecodeStatus::Error;
- }
- if (context->decode_status == GIF_D_STATUS_TAIL) {
- gif_image_ptr->m_ImageRowBuf.resize(gif_img_row_bytes);
- GifGCE* gif_img_gce_ptr = gif_image_ptr->m_ImageGCE.get();
- int32_t loc_pal_num =
- ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->local_pal
- ? (2 << ((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->pal_bits)
- : 0;
- context->avail_in = 0;
- GifPalette* pLocalPalette = gif_image_ptr->m_LocalPalettes.empty()
- ? nullptr
- : gif_image_ptr->m_LocalPalettes.data();
- if (!gif_img_gce_ptr) {
- bool bRes = context->GetRecordPosition(
- gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
- gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
- gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette, 0, 0,
- -1, 0,
- (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
- if (!bRes) {
- gif_image_ptr->m_ImageRowBuf.clear();
- context->AddError("Error Read Record Position Data");
- return GifDecodeStatus::Error;
- }
- } else {
- bool bRes = context->GetRecordPosition(
- gif_image_ptr->image_data_pos, gif_image_ptr->m_ImageInfo.left,
- gif_image_ptr->m_ImageInfo.top, gif_image_ptr->m_ImageInfo.width,
- gif_image_ptr->m_ImageInfo.height, loc_pal_num, pLocalPalette,
- (int32_t)gif_image_ptr->m_ImageGCE->delay_time,
- (bool)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->user_input,
- ((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)->transparency
- ? (int32_t)gif_image_ptr->m_ImageGCE->trans_index
- : -1,
- (int32_t)((GifCEF*)&gif_image_ptr->m_ImageGCE->gce_flag)
- ->disposal_method,
- (bool)((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace);
- if (!bRes) {
- gif_image_ptr->m_ImageRowBuf.clear();
- context->AddError("Error Read Record Position Data");
- return GifDecodeStatus::Error;
- }
- }
- if (gif_image_ptr->image_code_exp > GIF_MAX_LZW_EXP) {
- gif_image_ptr->m_ImageRowBuf.clear();
- context->AddError("Error Invalid Code Size");
- return GifDecodeStatus::Error;
- }
- if (!context->m_ImgDecoder.get())
- context->m_ImgDecoder =
- pdfium::MakeUnique<CGifLZWDecoder>(context->m_szLastError);
- context->m_ImgDecoder->InitTable(!gif_image_ptr->m_LocalPalettes.empty()
- ? gif_image_ptr->local_pallette_exp
- : context->global_pal_exp,
- gif_image_ptr->image_code_exp);
- context->img_row_offset = 0;
- context->img_row_avail_size = 0;
- context->img_pass_num = 0;
- gif_image_ptr->image_row_num = 0;
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
- }
- CGifLZWDecoder* img_decoder_ptr = context->m_ImgDecoder.get();
- if (context->decode_status == GIF_D_STATUS_IMG_DATA) {
- if (!gif_read_data(context, &data_size_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- img_decoder_ptr->Input(data_ptr, *data_size_ptr);
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
- context->img_row_offset += context->img_row_avail_size;
- context->img_row_avail_size = gif_img_row_bytes - context->img_row_offset;
- GifDecodeStatus ret = img_decoder_ptr->Decode(
- gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
- &context->img_row_avail_size);
- if (ret == GifDecodeStatus::Error) {
- gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
- return GifDecodeStatus::Error;
- }
- while (ret != GifDecodeStatus::Error) {
- if (ret == GifDecodeStatus::Success) {
- context->ReadScanline(gif_image_ptr->image_row_num,
- gif_image_ptr->m_ImageRowBuf.data());
- gif_image_ptr->m_ImageRowBuf.clear();
- gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
- return GifDecodeStatus::Success;
- }
- if (ret == GifDecodeStatus::Unfinished) {
- ASSERT(img_decoder_ptr->GetAvailInput() == 0);
- skip_size_org = context->skip_size;
- if (!gif_read_data(context, &data_size_ptr, 1))
- return GifDecodeStatus::Unfinished;
-
- if (*data_size_ptr != GIF_BLOCK_TERMINAL) {
- if (!gif_read_data(context, &data_ptr, *data_size_ptr)) {
- context->skip_size = skip_size_org;
- return GifDecodeStatus::Unfinished;
- }
- img_decoder_ptr->Input(data_ptr, *data_size_ptr);
- gif_save_decoding_status(context, GIF_D_STATUS_IMG_DATA);
- context->img_row_offset += context->img_row_avail_size;
- context->img_row_avail_size =
- gif_img_row_bytes - context->img_row_offset;
- ret = img_decoder_ptr->Decode(
- gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
- &context->img_row_avail_size);
- }
- }
- if (ret == GifDecodeStatus::InsufficientDestSize) {
- if (((GifLF*)&gif_image_ptr->m_ImageInfo.local_flag)->interlace) {
- context->ReadScanline(gif_image_ptr->image_row_num,
- gif_image_ptr->m_ImageRowBuf.data());
- gif_image_ptr->image_row_num +=
- s_gif_interlace_step[context->img_pass_num];
- if (gif_image_ptr->image_row_num >=
- (int32_t)gif_image_ptr->m_ImageInfo.height) {
- context->img_pass_num++;
- if (context->img_pass_num == FX_ArraySize(s_gif_interlace_step)) {
- gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
- return GifDecodeStatus::Error;
- }
- gif_image_ptr->image_row_num =
- s_gif_interlace_step[context->img_pass_num] / 2;
- }
- } else {
- context->ReadScanline(gif_image_ptr->image_row_num++,
- gif_image_ptr->m_ImageRowBuf.data());
- }
- context->img_row_offset = 0;
- context->img_row_avail_size = gif_img_row_bytes;
- ret = img_decoder_ptr->Decode(
- gif_image_ptr->m_ImageRowBuf.data() + context->img_row_offset,
- &context->img_row_avail_size);
- }
- if (ret == GifDecodeStatus::Error) {
- gif_decoding_failure_at_tail_cleanup(context, gif_image_ptr);
- return GifDecodeStatus::Error;
- }
- }
- }
- gif_save_decoding_status(context, GIF_D_STATUS_TAIL);
- }
- context->AddError("Decode Image Data Error");
- return GifDecodeStatus::Error;
-}
-
-void gif_input_buffer(CGifContext* context,
- uint8_t* src_buf,
- uint32_t src_size) {
- context->next_in = src_buf;
- context->avail_in = src_size;
- context->skip_size = 0;
-}
-
-uint32_t gif_get_avail_input(CGifContext* context, uint8_t** avail_buf_ptr) {
- if (avail_buf_ptr) {
- *avail_buf_ptr = nullptr;
- if (context->avail_in > 0)
- *avail_buf_ptr = context->next_in;
- }
- return context->avail_in;
-}
-
-int32_t gif_get_frame_num(CGifContext* context) {
- return pdfium::CollectionSize<int32_t>(context->m_Images);
-}
diff --git a/core/fxcodec/lgif/fx_gif.h b/core/fxcodec/lgif/fx_gif.h
index bddb22b30c..c3ddf36e3b 100644
--- a/core/fxcodec/lgif/fx_gif.h
+++ b/core/fxcodec/lgif/fx_gif.h
@@ -164,15 +164,4 @@ class CGifLZWDecoder {
char* err_msg_ptr;
};
-static const int32_t s_gif_interlace_step[4] = {8, 8, 4, 2};
-
-GifDecodeStatus gif_read_header(CGifContext* gif_ptr);
-GifDecodeStatus gif_get_frame(CGifContext* gif_ptr);
-int32_t gif_get_frame_num(CGifContext* gif_ptr);
-GifDecodeStatus gif_load_frame(CGifContext* gif_ptr, int32_t frame_num);
-void gif_input_buffer(CGifContext* gif_ptr,
- uint8_t* src_buf,
- uint32_t src_size);
-uint32_t gif_get_avail_input(CGifContext* gif_ptr, uint8_t** avail_buf_ptr);
-
#endif // CORE_FXCODEC_LGIF_FX_GIF_H_