From 94293688e82ee6a979478fa983e217549c44e3c2 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 27 Jan 2016 18:27:56 -0800 Subject: XFA: Fix DOS newlines, final round. TBR=tsepez@chromium.org Review URL: https://codereview.chromium.org/1641963002 . --- core/src/fxcodec/codec/fx_codec_bmp.cpp | 254 +- core/src/fxcodec/codec/fx_codec_gif.cpp | 378 +-- core/src/fxcodec/codec/fx_codec_png.cpp | 512 +-- core/src/fxcodec/codec/fx_codec_progress.cpp | 4708 +++++++++++++------------- core/src/fxcodec/codec/fx_codec_progress.h | 446 +-- core/src/fxcodec/codec/fx_codec_tiff.cpp | 1088 +++--- core/src/fxcodec/lbmp/fx_bmp.cpp | 1950 +++++------ core/src/fxcodec/lbmp/fx_bmp.h | 310 +- core/src/fxcodec/lgif/fx_gif.cpp | 2852 ++++++++-------- core/src/fxcodec/lgif/fx_gif.h | 664 ++-- 10 files changed, 6581 insertions(+), 6581 deletions(-) (limited to 'core/src/fxcodec') diff --git a/core/src/fxcodec/codec/fx_codec_bmp.cpp b/core/src/fxcodec/codec/fx_codec_bmp.cpp index 08b2f480df..2396f36c1a 100644 --- a/core/src/fxcodec/codec/fx_codec_bmp.cpp +++ b/core/src/fxcodec/codec/fx_codec_bmp.cpp @@ -1,127 +1,127 @@ -// 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 "core/include/fxcodec/fx_codec.h" -#include "core/include/fxge/fx_dib.h" -#include "codec_int.h" -#include "core/src/fxcodec/lbmp/fx_bmp.h" -struct FXBMP_Context { - bmp_decompress_struct_p bmp_ptr; - void* parent_ptr; - void* child_ptr; - - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; -extern "C" { -static void* _bmp_alloc_func(unsigned int size) { - return FX_Alloc(char, size); -} -static void _bmp_free_func(void* p) { - if (p != NULL) { - FX_Free(p); - } -} -}; -static void _bmp_error_data(bmp_decompress_struct_p bmp_ptr, - const FX_CHAR* err_msg) { - FXSYS_strncpy((char*)bmp_ptr->err_ptr, err_msg, BMP_MAX_ERROR_SIZE - 1); - longjmp(bmp_ptr->jmpbuf, 1); -} -static void _bmp_read_scanline(bmp_decompress_struct_p bmp_ptr, - int32_t row_num, - uint8_t* row_buf) { - FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; - CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; - pModule->ReadScanlineCallback(p->child_ptr, row_num, row_buf); -} -static FX_BOOL _bmp_get_data_position(bmp_decompress_struct_p bmp_ptr, - FX_DWORD rcd_pos) { - FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; - CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; - return pModule->InputImagePositionBufCallback(p->child_ptr, rcd_pos); -} -void* CCodec_BmpModule::Start(void* pModule) { - FXBMP_Context* p = (FXBMP_Context*)FX_Alloc(uint8_t, sizeof(FXBMP_Context)); - if (p == NULL) { - return NULL; - } - FXSYS_memset(p, 0, sizeof(FXBMP_Context)); - if (p == NULL) { - return NULL; - } - p->m_AllocFunc = _bmp_alloc_func; - p->m_FreeFunc = _bmp_free_func; - p->bmp_ptr = NULL; - p->parent_ptr = (void*)this; - p->child_ptr = pModule; - p->bmp_ptr = _bmp_create_decompress(); - if (p->bmp_ptr == NULL) { - FX_Free(p); - return NULL; - } - p->bmp_ptr->context_ptr = (void*)p; - p->bmp_ptr->err_ptr = m_szLastError; - p->bmp_ptr->_bmp_error_fn = _bmp_error_data; - p->bmp_ptr->_bmp_get_row_fn = _bmp_read_scanline; - p->bmp_ptr->_bmp_get_data_position_fn = _bmp_get_data_position; - return p; -} -void CCodec_BmpModule::Finish(void* pContext) { - FXBMP_Context* p = (FXBMP_Context*)pContext; - if (p != NULL) { - _bmp_destroy_decompress(&p->bmp_ptr); - p->m_FreeFunc(p); - } -} -int32_t CCodec_BmpModule::ReadHeader(void* pContext, - int32_t* width, - int32_t* height, - FX_BOOL* tb_flag, - int32_t* components, - int32_t* pal_num, - FX_DWORD** pal_pp, - CFX_DIBAttribute* pAttribute) { - FXBMP_Context* p = (FXBMP_Context*)pContext; - if (setjmp(p->bmp_ptr->jmpbuf)) { - return 0; - } - int32_t ret = _bmp_read_header(p->bmp_ptr); - if (ret != 1) { - return ret; - } - *width = p->bmp_ptr->width; - *height = p->bmp_ptr->height; - *tb_flag = p->bmp_ptr->imgTB_flag; - *components = p->bmp_ptr->components; - *pal_num = p->bmp_ptr->pal_num; - *pal_pp = p->bmp_ptr->pal_ptr; - if (pAttribute) { - pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; - pAttribute->m_nXDPI = p->bmp_ptr->dpi_x; - pAttribute->m_nYDPI = p->bmp_ptr->dpi_y; - pAttribute->m_nBmpCompressType = p->bmp_ptr->compress_flag; - } - return 1; -} -int32_t CCodec_BmpModule::LoadImage(void* pContext) { - FXBMP_Context* p = (FXBMP_Context*)pContext; - if (setjmp(p->bmp_ptr->jmpbuf)) { - return 0; - } - return _bmp_decode_image(p->bmp_ptr); -} -FX_DWORD CCodec_BmpModule::GetAvailInput(void* pContext, - uint8_t** avial_buf_ptr) { - FXBMP_Context* p = (FXBMP_Context*)pContext; - return _bmp_get_avail_input(p->bmp_ptr, avial_buf_ptr); -} -void CCodec_BmpModule::Input(void* pContext, - const uint8_t* src_buf, - FX_DWORD src_size) { - FXBMP_Context* p = (FXBMP_Context*)pContext; - _bmp_input_buffer(p->bmp_ptr, (uint8_t*)src_buf, src_size); -} +// 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 "core/include/fxcodec/fx_codec.h" +#include "core/include/fxge/fx_dib.h" +#include "codec_int.h" +#include "core/src/fxcodec/lbmp/fx_bmp.h" +struct FXBMP_Context { + bmp_decompress_struct_p bmp_ptr; + void* parent_ptr; + void* child_ptr; + + void* (*m_AllocFunc)(unsigned int); + void (*m_FreeFunc)(void*); +}; +extern "C" { +static void* _bmp_alloc_func(unsigned int size) { + return FX_Alloc(char, size); +} +static void _bmp_free_func(void* p) { + if (p != NULL) { + FX_Free(p); + } +} +}; +static void _bmp_error_data(bmp_decompress_struct_p bmp_ptr, + const FX_CHAR* err_msg) { + FXSYS_strncpy((char*)bmp_ptr->err_ptr, err_msg, BMP_MAX_ERROR_SIZE - 1); + longjmp(bmp_ptr->jmpbuf, 1); +} +static void _bmp_read_scanline(bmp_decompress_struct_p bmp_ptr, + int32_t row_num, + uint8_t* row_buf) { + FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; + CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; + pModule->ReadScanlineCallback(p->child_ptr, row_num, row_buf); +} +static FX_BOOL _bmp_get_data_position(bmp_decompress_struct_p bmp_ptr, + FX_DWORD rcd_pos) { + FXBMP_Context* p = (FXBMP_Context*)bmp_ptr->context_ptr; + CCodec_BmpModule* pModule = (CCodec_BmpModule*)p->parent_ptr; + return pModule->InputImagePositionBufCallback(p->child_ptr, rcd_pos); +} +void* CCodec_BmpModule::Start(void* pModule) { + FXBMP_Context* p = (FXBMP_Context*)FX_Alloc(uint8_t, sizeof(FXBMP_Context)); + if (p == NULL) { + return NULL; + } + FXSYS_memset(p, 0, sizeof(FXBMP_Context)); + if (p == NULL) { + return NULL; + } + p->m_AllocFunc = _bmp_alloc_func; + p->m_FreeFunc = _bmp_free_func; + p->bmp_ptr = NULL; + p->parent_ptr = (void*)this; + p->child_ptr = pModule; + p->bmp_ptr = _bmp_create_decompress(); + if (p->bmp_ptr == NULL) { + FX_Free(p); + return NULL; + } + p->bmp_ptr->context_ptr = (void*)p; + p->bmp_ptr->err_ptr = m_szLastError; + p->bmp_ptr->_bmp_error_fn = _bmp_error_data; + p->bmp_ptr->_bmp_get_row_fn = _bmp_read_scanline; + p->bmp_ptr->_bmp_get_data_position_fn = _bmp_get_data_position; + return p; +} +void CCodec_BmpModule::Finish(void* pContext) { + FXBMP_Context* p = (FXBMP_Context*)pContext; + if (p != NULL) { + _bmp_destroy_decompress(&p->bmp_ptr); + p->m_FreeFunc(p); + } +} +int32_t CCodec_BmpModule::ReadHeader(void* pContext, + int32_t* width, + int32_t* height, + FX_BOOL* tb_flag, + int32_t* components, + int32_t* pal_num, + FX_DWORD** pal_pp, + CFX_DIBAttribute* pAttribute) { + FXBMP_Context* p = (FXBMP_Context*)pContext; + if (setjmp(p->bmp_ptr->jmpbuf)) { + return 0; + } + int32_t ret = _bmp_read_header(p->bmp_ptr); + if (ret != 1) { + return ret; + } + *width = p->bmp_ptr->width; + *height = p->bmp_ptr->height; + *tb_flag = p->bmp_ptr->imgTB_flag; + *components = p->bmp_ptr->components; + *pal_num = p->bmp_ptr->pal_num; + *pal_pp = p->bmp_ptr->pal_ptr; + if (pAttribute) { + pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; + pAttribute->m_nXDPI = p->bmp_ptr->dpi_x; + pAttribute->m_nYDPI = p->bmp_ptr->dpi_y; + pAttribute->m_nBmpCompressType = p->bmp_ptr->compress_flag; + } + return 1; +} +int32_t CCodec_BmpModule::LoadImage(void* pContext) { + FXBMP_Context* p = (FXBMP_Context*)pContext; + if (setjmp(p->bmp_ptr->jmpbuf)) { + return 0; + } + return _bmp_decode_image(p->bmp_ptr); +} +FX_DWORD CCodec_BmpModule::GetAvailInput(void* pContext, + uint8_t** avial_buf_ptr) { + FXBMP_Context* p = (FXBMP_Context*)pContext; + return _bmp_get_avail_input(p->bmp_ptr, avial_buf_ptr); +} +void CCodec_BmpModule::Input(void* pContext, + const uint8_t* src_buf, + FX_DWORD src_size) { + FXBMP_Context* p = (FXBMP_Context*)pContext; + _bmp_input_buffer(p->bmp_ptr, (uint8_t*)src_buf, src_size); +} diff --git a/core/src/fxcodec/codec/fx_codec_gif.cpp b/core/src/fxcodec/codec/fx_codec_gif.cpp index 45aeb09c41..d61ccc6f70 100644 --- a/core/src/fxcodec/codec/fx_codec_gif.cpp +++ b/core/src/fxcodec/codec/fx_codec_gif.cpp @@ -1,189 +1,189 @@ -// 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 "core/include/fxcodec/fx_codec.h" -#include "core/include/fxge/fx_dib.h" -#include "codec_int.h" -#include "core/src/fxcodec/lgif/fx_gif.h" -struct FXGIF_Context { - gif_decompress_struct_p gif_ptr; - void* parent_ptr; - void* child_ptr; - - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; -extern "C" { -static void* _gif_alloc_func(unsigned int size) { - return FX_Alloc(char, size); -} -static void _gif_free_func(void* p) { - if (p != NULL) { - FX_Free(p); - } -} -}; -static void _gif_error_data(gif_decompress_struct_p gif_ptr, - const FX_CHAR* err_msg) { - FXSYS_strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1); - longjmp(gif_ptr->jmpbuf, 1); -} -static uint8_t* _gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr, - int32_t pal_size) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - return pModule->AskLocalPaletteBufCallback( - p->child_ptr, _gif_get_frame_num(gif_ptr), pal_size); -} -static void _gif_record_current_position(gif_decompress_struct_p gif_ptr, - FX_DWORD* cur_pos_ptr) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - pModule->RecordCurrentPositionCallback(p->child_ptr, *cur_pos_ptr); -} -static void _gif_read_scanline(gif_decompress_struct_p gif_ptr, - int32_t row_num, - uint8_t* row_buf) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - pModule->ReadScanlineCallback(p->child_ptr, row_num, row_buf); -} -static FX_BOOL _gif_get_record_position(gif_decompress_struct_p gif_ptr, - FX_DWORD cur_pos, - int32_t left, - int32_t top, - int32_t width, - int32_t height, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - FX_BOOL user_input, - int32_t trans_index, - int32_t disposal_method, - FX_BOOL interlace) { - FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; - CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; - return pModule->InputRecordPositionBufCallback( - p->child_ptr, cur_pos, FX_RECT(left, top, left + width, top + height), - pal_num, pal_ptr, delay_time, user_input, trans_index, disposal_method, - interlace); -} -void* CCodec_GifModule::Start(void* pModule) { - FXGIF_Context* p = (FXGIF_Context*)FX_Alloc(uint8_t, sizeof(FXGIF_Context)); - if (p == NULL) { - return NULL; - } - FXSYS_memset(p, 0, sizeof(FXGIF_Context)); - p->m_AllocFunc = _gif_alloc_func; - p->m_FreeFunc = _gif_free_func; - p->gif_ptr = NULL; - p->parent_ptr = (void*)this; - p->child_ptr = pModule; - p->gif_ptr = _gif_create_decompress(); - if (p->gif_ptr == NULL) { - FX_Free(p); - return NULL; - } - p->gif_ptr->context_ptr = (void*)p; - p->gif_ptr->err_ptr = m_szLastError; - p->gif_ptr->_gif_error_fn = _gif_error_data; - p->gif_ptr->_gif_ask_buf_for_pal_fn = _gif_ask_buf_for_pal; - p->gif_ptr->_gif_record_current_position_fn = _gif_record_current_position; - p->gif_ptr->_gif_get_row_fn = _gif_read_scanline; - p->gif_ptr->_gif_get_record_position_fn = _gif_get_record_position; - return p; -} -void CCodec_GifModule::Finish(void* pContext) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - if (p != NULL) { - _gif_destroy_decompress(&p->gif_ptr); - p->m_FreeFunc(p); - } -} -int32_t CCodec_GifModule::ReadHeader(void* pContext, - int* width, - int* height, - int* pal_num, - void** pal_pp, - int* bg_index, - CFX_DIBAttribute* pAttribute) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - if (setjmp(p->gif_ptr->jmpbuf)) { - return 0; - } - int32_t ret = _gif_read_header(p->gif_ptr); - if (ret != 1) { - return ret; - } - if (pAttribute) { - } - *width = p->gif_ptr->width; - *height = p->gif_ptr->height; - *pal_num = p->gif_ptr->global_pal_num; - *pal_pp = p->gif_ptr->global_pal_ptr; - *bg_index = p->gif_ptr->bc_index; - return 1; -} -int32_t CCodec_GifModule::LoadFrameInfo(void* pContext, int* frame_num) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - if (setjmp(p->gif_ptr->jmpbuf)) { - return 0; - } - int32_t ret = _gif_get_frame(p->gif_ptr); - if (ret != 1) { - return ret; - } - *frame_num = _gif_get_frame_num(p->gif_ptr); - return 1; -} -int32_t CCodec_GifModule::LoadFrame(void* pContext, - int frame_num, - CFX_DIBAttribute* pAttribute) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - if (setjmp(p->gif_ptr->jmpbuf)) { - return 0; - } - int32_t ret = _gif_load_frame(p->gif_ptr, frame_num); - if (ret == 1) { - if (pAttribute) { - pAttribute->m_nGifLeft = - p->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->left; - pAttribute->m_nGifTop = - p->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->top; - pAttribute->m_fAspectRatio = p->gif_ptr->pixel_aspect; - if (p->gif_ptr->cmt_data_ptr) { - const uint8_t* buf = - (const uint8_t*)p->gif_ptr->cmt_data_ptr->GetBuffer(0); - FX_DWORD len = p->gif_ptr->cmt_data_ptr->GetLength(); - if (len > 21) { - uint8_t size = *buf++; - if (size) { - pAttribute->m_strAuthor = CFX_ByteString(buf, size); - } else { - pAttribute->m_strAuthor.Empty(); - } - buf += size; - size = *buf++; - if (size == 20) { - FXSYS_memcpy(pAttribute->m_strTime, buf, size); - } - } - } - } - } - return ret; -} -FX_DWORD CCodec_GifModule::GetAvailInput(void* pContext, - uint8_t** avial_buf_ptr) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - return _gif_get_avail_input(p->gif_ptr, avial_buf_ptr); -} -void CCodec_GifModule::Input(void* pContext, - const uint8_t* src_buf, - FX_DWORD src_size) { - FXGIF_Context* p = (FXGIF_Context*)pContext; - _gif_input_buffer(p->gif_ptr, (uint8_t*)src_buf, src_size); -} +// 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 "core/include/fxcodec/fx_codec.h" +#include "core/include/fxge/fx_dib.h" +#include "codec_int.h" +#include "core/src/fxcodec/lgif/fx_gif.h" +struct FXGIF_Context { + gif_decompress_struct_p gif_ptr; + void* parent_ptr; + void* child_ptr; + + void* (*m_AllocFunc)(unsigned int); + void (*m_FreeFunc)(void*); +}; +extern "C" { +static void* _gif_alloc_func(unsigned int size) { + return FX_Alloc(char, size); +} +static void _gif_free_func(void* p) { + if (p != NULL) { + FX_Free(p); + } +} +}; +static void _gif_error_data(gif_decompress_struct_p gif_ptr, + const FX_CHAR* err_msg) { + FXSYS_strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1); + longjmp(gif_ptr->jmpbuf, 1); +} +static uint8_t* _gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr, + int32_t pal_size) { + FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; + CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; + return pModule->AskLocalPaletteBufCallback( + p->child_ptr, _gif_get_frame_num(gif_ptr), pal_size); +} +static void _gif_record_current_position(gif_decompress_struct_p gif_ptr, + FX_DWORD* cur_pos_ptr) { + FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; + CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; + pModule->RecordCurrentPositionCallback(p->child_ptr, *cur_pos_ptr); +} +static void _gif_read_scanline(gif_decompress_struct_p gif_ptr, + int32_t row_num, + uint8_t* row_buf) { + FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; + CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; + pModule->ReadScanlineCallback(p->child_ptr, row_num, row_buf); +} +static FX_BOOL _gif_get_record_position(gif_decompress_struct_p gif_ptr, + FX_DWORD cur_pos, + int32_t left, + int32_t top, + int32_t width, + int32_t height, + int32_t pal_num, + void* pal_ptr, + int32_t delay_time, + FX_BOOL user_input, + int32_t trans_index, + int32_t disposal_method, + FX_BOOL interlace) { + FXGIF_Context* p = (FXGIF_Context*)gif_ptr->context_ptr; + CCodec_GifModule* pModule = (CCodec_GifModule*)p->parent_ptr; + return pModule->InputRecordPositionBufCallback( + p->child_ptr, cur_pos, FX_RECT(left, top, left + width, top + height), + pal_num, pal_ptr, delay_time, user_input, trans_index, disposal_method, + interlace); +} +void* CCodec_GifModule::Start(void* pModule) { + FXGIF_Context* p = (FXGIF_Context*)FX_Alloc(uint8_t, sizeof(FXGIF_Context)); + if (p == NULL) { + return NULL; + } + FXSYS_memset(p, 0, sizeof(FXGIF_Context)); + p->m_AllocFunc = _gif_alloc_func; + p->m_FreeFunc = _gif_free_func; + p->gif_ptr = NULL; + p->parent_ptr = (void*)this; + p->child_ptr = pModule; + p->gif_ptr = _gif_create_decompress(); + if (p->gif_ptr == NULL) { + FX_Free(p); + return NULL; + } + p->gif_ptr->context_ptr = (void*)p; + p->gif_ptr->err_ptr = m_szLastError; + p->gif_ptr->_gif_error_fn = _gif_error_data; + p->gif_ptr->_gif_ask_buf_for_pal_fn = _gif_ask_buf_for_pal; + p->gif_ptr->_gif_record_current_position_fn = _gif_record_current_position; + p->gif_ptr->_gif_get_row_fn = _gif_read_scanline; + p->gif_ptr->_gif_get_record_position_fn = _gif_get_record_position; + return p; +} +void CCodec_GifModule::Finish(void* pContext) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + if (p != NULL) { + _gif_destroy_decompress(&p->gif_ptr); + p->m_FreeFunc(p); + } +} +int32_t CCodec_GifModule::ReadHeader(void* pContext, + int* width, + int* height, + int* pal_num, + void** pal_pp, + int* bg_index, + CFX_DIBAttribute* pAttribute) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + if (setjmp(p->gif_ptr->jmpbuf)) { + return 0; + } + int32_t ret = _gif_read_header(p->gif_ptr); + if (ret != 1) { + return ret; + } + if (pAttribute) { + } + *width = p->gif_ptr->width; + *height = p->gif_ptr->height; + *pal_num = p->gif_ptr->global_pal_num; + *pal_pp = p->gif_ptr->global_pal_ptr; + *bg_index = p->gif_ptr->bc_index; + return 1; +} +int32_t CCodec_GifModule::LoadFrameInfo(void* pContext, int* frame_num) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + if (setjmp(p->gif_ptr->jmpbuf)) { + return 0; + } + int32_t ret = _gif_get_frame(p->gif_ptr); + if (ret != 1) { + return ret; + } + *frame_num = _gif_get_frame_num(p->gif_ptr); + return 1; +} +int32_t CCodec_GifModule::LoadFrame(void* pContext, + int frame_num, + CFX_DIBAttribute* pAttribute) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + if (setjmp(p->gif_ptr->jmpbuf)) { + return 0; + } + int32_t ret = _gif_load_frame(p->gif_ptr, frame_num); + if (ret == 1) { + if (pAttribute) { + pAttribute->m_nGifLeft = + p->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->left; + pAttribute->m_nGifTop = + p->gif_ptr->img_ptr_arr_ptr->GetAt(frame_num)->image_info_ptr->top; + pAttribute->m_fAspectRatio = p->gif_ptr->pixel_aspect; + if (p->gif_ptr->cmt_data_ptr) { + const uint8_t* buf = + (const uint8_t*)p->gif_ptr->cmt_data_ptr->GetBuffer(0); + FX_DWORD len = p->gif_ptr->cmt_data_ptr->GetLength(); + if (len > 21) { + uint8_t size = *buf++; + if (size) { + pAttribute->m_strAuthor = CFX_ByteString(buf, size); + } else { + pAttribute->m_strAuthor.Empty(); + } + buf += size; + size = *buf++; + if (size == 20) { + FXSYS_memcpy(pAttribute->m_strTime, buf, size); + } + } + } + } + } + return ret; +} +FX_DWORD CCodec_GifModule::GetAvailInput(void* pContext, + uint8_t** avial_buf_ptr) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + return _gif_get_avail_input(p->gif_ptr, avial_buf_ptr); +} +void CCodec_GifModule::Input(void* pContext, + const uint8_t* src_buf, + FX_DWORD src_size) { + FXGIF_Context* p = (FXGIF_Context*)pContext; + _gif_input_buffer(p->gif_ptr, (uint8_t*)src_buf, src_size); +} diff --git a/core/src/fxcodec/codec/fx_codec_png.cpp b/core/src/fxcodec/codec/fx_codec_png.cpp index 9e08473339..32b0d3d48f 100644 --- a/core/src/fxcodec/codec/fx_codec_png.cpp +++ b/core/src/fxcodec/codec/fx_codec_png.cpp @@ -1,256 +1,256 @@ -// 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 - -#include "core/include/fxcodec/fx_codec.h" -#include "core/include/fxge/fx_dib.h" -#include "codec_int.h" - -extern "C" { -#undef FAR -#include "third_party/libpng16/png.h" -} - -static void _png_error_data(png_structp png_ptr, png_const_charp error_msg) { - if (png_get_error_ptr(png_ptr)) { - FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg, - PNG_ERROR_SIZE - 1); - } - longjmp(png_jmpbuf(png_ptr), 1); -} -static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg) {} -static void _png_load_bmp_attribute(png_structp png_ptr, - png_infop info_ptr, - CFX_DIBAttribute* pAttribute) { - if (pAttribute) { -#if defined(PNG_pHYs_SUPPORTED) - pAttribute->m_nXDPI = png_get_x_pixels_per_meter(png_ptr, info_ptr); - pAttribute->m_nYDPI = png_get_y_pixels_per_meter(png_ptr, info_ptr); - png_uint_32 res_x, res_y; - int unit_type; - png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type); - switch (unit_type) { - case PNG_RESOLUTION_METER: - pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; - break; - default: - pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_NONE; - } -#endif -#if defined(PNG_iCCP_SUPPORTED) - png_charp icc_name; - png_bytep icc_profile; - png_uint_32 icc_proflen; - int compress_type; - png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile, - &icc_proflen); -#endif - int bTime = 0; -#if defined(PNG_tIME_SUPPORTED) - png_timep t = NULL; - png_get_tIME(png_ptr, info_ptr, &t); - if (t) { - FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); - FXSYS_snprintf((FX_CHAR*)pAttribute->m_strTime, - sizeof(pAttribute->m_strTime), "%4d:%2d:%2d %2d:%2d:%2d", - t->year, t->month, t->day, t->hour, t->minute, t->second); - pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0; - bTime = 1; - } -#endif -#if defined(PNG_TEXT_SUPPORTED) - int i; - FX_STRSIZE len; - const FX_CHAR* buf; - int num_text; - png_textp text = NULL; - png_get_text(png_ptr, info_ptr, &text, &num_text); - for (i = 0; i < num_text; i++) { - len = FXSYS_strlen(text[i].key); - buf = "Time"; - if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { - if (!bTime) { - FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); - FXSYS_memcpy( - pAttribute->m_strTime, text[i].text, - std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length)); - } - } else { - buf = "Author"; - if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { - pAttribute->m_strAuthor.Empty(); - pAttribute->m_strAuthor.Load((uint8_t*)text[i].text, - (FX_STRSIZE)text[i].text_length); - } - } - } -#endif - } -} -struct FXPNG_Context { - png_structp png_ptr; - png_infop info_ptr; - void* parent_ptr; - void* child_ptr; - - void* (*m_AllocFunc)(unsigned int); - void (*m_FreeFunc)(void*); -}; -extern "C" { -static void* _png_alloc_func(unsigned int size) { - return FX_Alloc(char, size); -} -static void _png_free_func(void* p) { - if (p != NULL) { - FX_Free(p); - } -} -}; -static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { - FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); - if (p == NULL) { - return; - } - CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; - if (pModule == NULL) { - return; - } - png_uint_32 width = 0, height = 0; - int bpc = 0, color_type = 0, color_type1 = 0, pass = 0; - double gamma = 1.0; - png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, NULL, - NULL, NULL); - color_type1 = color_type; - if (bpc > 8) { - png_set_strip_16(png_ptr); - } else if (bpc < 8) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } - bpc = 8; - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - pass = png_set_interlace_handling(png_ptr); - if (!pModule->ReadHeaderCallback(p->child_ptr, width, height, bpc, pass, - &color_type, &gamma)) { - png_error(p->png_ptr, "Read Header Callback Error"); - } - int intent; - if (png_get_sRGB(png_ptr, info_ptr, &intent)) { - png_set_gamma(png_ptr, gamma, 0.45455); - } else { - double image_gamma; - if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) { - png_set_gamma(png_ptr, gamma, image_gamma); - } else { - png_set_gamma(png_ptr, gamma, 0.45455); - } - } - switch (color_type) { - case PNG_COLOR_TYPE_GRAY: - case PNG_COLOR_TYPE_GRAY_ALPHA: { - if (color_type1 & PNG_COLOR_MASK_COLOR) { - png_set_rgb_to_gray(png_ptr, 1, 0.299, 0.587); - } - } break; - case PNG_COLOR_TYPE_PALETTE: - if (color_type1 != PNG_COLOR_TYPE_PALETTE) { - png_error(p->png_ptr, "Not Support Output Palette Now"); - } - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - if (!(color_type1 & PNG_COLOR_MASK_COLOR)) { - png_set_gray_to_rgb(png_ptr); - } - png_set_bgr(png_ptr); - break; - } - if (!(color_type & PNG_COLOR_MASK_ALPHA)) { - png_set_strip_alpha(png_ptr); - } - if (color_type & PNG_COLOR_MASK_ALPHA && - !(color_type1 & PNG_COLOR_MASK_ALPHA)) { - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); - } - png_read_update_info(png_ptr, info_ptr); -} -static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {} -static void _png_get_row_func(png_structp png_ptr, - png_bytep new_row, - png_uint_32 row_num, - int pass) { - FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); - if (p == NULL) { - return; - } - CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; - uint8_t* src_buf = NULL; - if (!pModule->AskScanlineBufCallback(p->child_ptr, row_num, src_buf)) { - png_error(png_ptr, "Ask Scanline buffer Callback Error"); - } - if (src_buf != NULL) { - png_progressive_combine_row(png_ptr, src_buf, new_row); - } - pModule->FillScanlineBufCompletedCallback(p->child_ptr, pass, row_num); -} -void* CCodec_PngModule::Start(void* pModule) { - FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context)); - if (p == NULL) { - return NULL; - } - p->m_AllocFunc = _png_alloc_func; - p->m_FreeFunc = _png_free_func; - p->png_ptr = NULL; - p->info_ptr = NULL; - p->parent_ptr = (void*)this; - p->child_ptr = pModule; - p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (p->png_ptr == NULL) { - FX_Free(p); - return NULL; - } - p->info_ptr = png_create_info_struct(p->png_ptr); - if (p->info_ptr == NULL) { - png_destroy_read_struct(&(p->png_ptr), (png_infopp)NULL, (png_infopp)NULL); - FX_Free(p); - return NULL; - } - if (setjmp(png_jmpbuf(p->png_ptr))) { - if (p != NULL) { - png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); - FX_Free(p); - } - return NULL; - } - png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func, - _png_get_row_func, _png_get_end_func); - png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, - (png_error_ptr)_png_warning_data); - return p; -} -void CCodec_PngModule::Finish(void* pContext) { - FXPNG_Context* p = (FXPNG_Context*)pContext; - if (p != NULL) { - png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); - p->m_FreeFunc(p); - } -} -FX_BOOL CCodec_PngModule::Input(void* pContext, - const uint8_t* src_buf, - FX_DWORD src_size, - CFX_DIBAttribute* pAttribute) { - FXPNG_Context* p = (FXPNG_Context*)pContext; - if (setjmp(png_jmpbuf(p->png_ptr))) { - if (pAttribute && - 0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) { - _png_load_bmp_attribute(p->png_ptr, p->info_ptr, pAttribute); - } - return FALSE; - } - png_process_data(p->png_ptr, p->info_ptr, (uint8_t*)src_buf, src_size); - return TRUE; -} +// 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 + +#include "core/include/fxcodec/fx_codec.h" +#include "core/include/fxge/fx_dib.h" +#include "codec_int.h" + +extern "C" { +#undef FAR +#include "third_party/libpng16/png.h" +} + +static void _png_error_data(png_structp png_ptr, png_const_charp error_msg) { + if (png_get_error_ptr(png_ptr)) { + FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg, + PNG_ERROR_SIZE - 1); + } + longjmp(png_jmpbuf(png_ptr), 1); +} +static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg) {} +static void _png_load_bmp_attribute(png_structp png_ptr, + png_infop info_ptr, + CFX_DIBAttribute* pAttribute) { + if (pAttribute) { +#if defined(PNG_pHYs_SUPPORTED) + pAttribute->m_nXDPI = png_get_x_pixels_per_meter(png_ptr, info_ptr); + pAttribute->m_nYDPI = png_get_y_pixels_per_meter(png_ptr, info_ptr); + png_uint_32 res_x, res_y; + int unit_type; + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type); + switch (unit_type) { + case PNG_RESOLUTION_METER: + pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; + break; + default: + pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_NONE; + } +#endif +#if defined(PNG_iCCP_SUPPORTED) + png_charp icc_name; + png_bytep icc_profile; + png_uint_32 icc_proflen; + int compress_type; + png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile, + &icc_proflen); +#endif + int bTime = 0; +#if defined(PNG_tIME_SUPPORTED) + png_timep t = NULL; + png_get_tIME(png_ptr, info_ptr, &t); + if (t) { + FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); + FXSYS_snprintf((FX_CHAR*)pAttribute->m_strTime, + sizeof(pAttribute->m_strTime), "%4d:%2d:%2d %2d:%2d:%2d", + t->year, t->month, t->day, t->hour, t->minute, t->second); + pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0; + bTime = 1; + } +#endif +#if defined(PNG_TEXT_SUPPORTED) + int i; + FX_STRSIZE len; + const FX_CHAR* buf; + int num_text; + png_textp text = NULL; + png_get_text(png_ptr, info_ptr, &text, &num_text); + for (i = 0; i < num_text; i++) { + len = FXSYS_strlen(text[i].key); + buf = "Time"; + if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { + if (!bTime) { + FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); + FXSYS_memcpy( + pAttribute->m_strTime, text[i].text, + std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length)); + } + } else { + buf = "Author"; + if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { + pAttribute->m_strAuthor.Empty(); + pAttribute->m_strAuthor.Load((uint8_t*)text[i].text, + (FX_STRSIZE)text[i].text_length); + } + } + } +#endif + } +} +struct FXPNG_Context { + png_structp png_ptr; + png_infop info_ptr; + void* parent_ptr; + void* child_ptr; + + void* (*m_AllocFunc)(unsigned int); + void (*m_FreeFunc)(void*); +}; +extern "C" { +static void* _png_alloc_func(unsigned int size) { + return FX_Alloc(char, size); +} +static void _png_free_func(void* p) { + if (p != NULL) { + FX_Free(p); + } +} +}; +static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { + FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); + if (p == NULL) { + return; + } + CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; + if (pModule == NULL) { + return; + } + png_uint_32 width = 0, height = 0; + int bpc = 0, color_type = 0, color_type1 = 0, pass = 0; + double gamma = 1.0; + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, NULL, + NULL, NULL); + color_type1 = color_type; + if (bpc > 8) { + png_set_strip_16(png_ptr); + } else if (bpc < 8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + } + bpc = 8; + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_palette_to_rgb(png_ptr); + } + pass = png_set_interlace_handling(png_ptr); + if (!pModule->ReadHeaderCallback(p->child_ptr, width, height, bpc, pass, + &color_type, &gamma)) { + png_error(p->png_ptr, "Read Header Callback Error"); + } + int intent; + if (png_get_sRGB(png_ptr, info_ptr, &intent)) { + png_set_gamma(png_ptr, gamma, 0.45455); + } else { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) { + png_set_gamma(png_ptr, gamma, image_gamma); + } else { + png_set_gamma(png_ptr, gamma, 0.45455); + } + } + switch (color_type) { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_GRAY_ALPHA: { + if (color_type1 & PNG_COLOR_MASK_COLOR) { + png_set_rgb_to_gray(png_ptr, 1, 0.299, 0.587); + } + } break; + case PNG_COLOR_TYPE_PALETTE: + if (color_type1 != PNG_COLOR_TYPE_PALETTE) { + png_error(p->png_ptr, "Not Support Output Palette Now"); + } + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + if (!(color_type1 & PNG_COLOR_MASK_COLOR)) { + png_set_gray_to_rgb(png_ptr); + } + png_set_bgr(png_ptr); + break; + } + if (!(color_type & PNG_COLOR_MASK_ALPHA)) { + png_set_strip_alpha(png_ptr); + } + if (color_type & PNG_COLOR_MASK_ALPHA && + !(color_type1 & PNG_COLOR_MASK_ALPHA)) { + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + } + png_read_update_info(png_ptr, info_ptr); +} +static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {} +static void _png_get_row_func(png_structp png_ptr, + png_bytep new_row, + png_uint_32 row_num, + int pass) { + FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); + if (p == NULL) { + return; + } + CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; + uint8_t* src_buf = NULL; + if (!pModule->AskScanlineBufCallback(p->child_ptr, row_num, src_buf)) { + png_error(png_ptr, "Ask Scanline buffer Callback Error"); + } + if (src_buf != NULL) { + png_progressive_combine_row(png_ptr, src_buf, new_row); + } + pModule->FillScanlineBufCompletedCallback(p->child_ptr, pass, row_num); +} +void* CCodec_PngModule::Start(void* pModule) { + FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context)); + if (p == NULL) { + return NULL; + } + p->m_AllocFunc = _png_alloc_func; + p->m_FreeFunc = _png_free_func; + p->png_ptr = NULL; + p->info_ptr = NULL; + p->parent_ptr = (void*)this; + p->child_ptr = pModule; + p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (p->png_ptr == NULL) { + FX_Free(p); + return NULL; + } + p->info_ptr = png_create_info_struct(p->png_ptr); + if (p->info_ptr == NULL) { + png_destroy_read_struct(&(p->png_ptr), (png_infopp)NULL, (png_infopp)NULL); + FX_Free(p); + return NULL; + } + if (setjmp(png_jmpbuf(p->png_ptr))) { + if (p != NULL) { + png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); + FX_Free(p); + } + return NULL; + } + png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func, + _png_get_row_func, _png_get_end_func); + png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, + (png_error_ptr)_png_warning_data); + return p; +} +void CCodec_PngModule::Finish(void* pContext) { + FXPNG_Context* p = (FXPNG_Context*)pContext; + if (p != NULL) { + png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); + p->m_FreeFunc(p); + } +} +FX_BOOL CCodec_PngModule::Input(void* pContext, + const uint8_t* src_buf, + FX_DWORD src_size, + CFX_DIBAttribute* pAttribute) { + FXPNG_Context* p = (FXPNG_Context*)pContext; + if (setjmp(png_jmpbuf(p->png_ptr))) { + if (pAttribute && + 0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) { + _png_load_bmp_attribute(p->png_ptr, p->info_ptr, pAttribute); + } + return FALSE; + } + png_process_data(p->png_ptr, p->info_ptr, (uint8_t*)src_buf, src_size); + return TRUE; +} diff --git a/core/src/fxcodec/codec/fx_codec_progress.cpp b/core/src/fxcodec/codec/fx_codec_progress.cpp index 383e3ed93d..5dbc19b4b6 100644 --- a/core/src/fxcodec/codec/fx_codec_progress.cpp +++ b/core/src/fxcodec/codec/fx_codec_progress.cpp @@ -1,2354 +1,2354 @@ -// 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 "core/include/fxge/fx_dib.h" -#include "core/include/fxcodec/fx_codec.h" -#include "fx_codec_progress.h" -void CFXCODEC_WeightTable::Calc(int dest_len, - int dest_min, - int dest_max, - int src_len, - int src_min, - int src_max, - FX_BOOL bInterpol) { - if (m_pWeightTables) { - FX_Free(m_pWeightTables); - } - double scale, base; - scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); - if (dest_len < 0) { - base = (FX_FLOAT)(src_len); - } else { - base = 0.0f; - } - m_ItemSize = - (int)(sizeof(int) * 2 + - sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + 1)); - m_DestMin = dest_min; - m_pWeightTables = FX_Alloc(uint8_t, (dest_max - dest_min) * m_ItemSize + 4); - if (m_pWeightTables == NULL) { - return; - } - if (FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { - for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { - PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); - double src_pos = dest_pixel * scale + scale / 2 + base; - if (bInterpol) { - pixel_weights.m_SrcStart = - (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); - pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); - if (pixel_weights.m_SrcStart < src_min) { - pixel_weights.m_SrcStart = src_min; - } - if (pixel_weights.m_SrcEnd >= src_max) { - pixel_weights.m_SrcEnd = src_max - 1; - } - if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { - pixel_weights.m_Weights[0] = 65536; - } else { - pixel_weights.m_Weights[1] = FXSYS_round( - (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * - 65536); - pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; - } - } else { - pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = - (int)FXSYS_floor((FX_FLOAT)src_pos); - pixel_weights.m_Weights[0] = 65536; - } - } - return; - } - for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { - PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); - double src_start = dest_pixel * scale + base; - double src_end = src_start + scale; - int start_i, end_i; - if (src_start < src_end) { - start_i = (int)FXSYS_floor((FX_FLOAT)src_start); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); - } else { - start_i = (int)FXSYS_floor((FX_FLOAT)src_end); - end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); - } - if (start_i < src_min) { - start_i = src_min; - } - if (end_i >= src_max) { - end_i = src_max - 1; - } - if (start_i > end_i) { - pixel_weights.m_SrcStart = start_i; - pixel_weights.m_SrcEnd = start_i; - continue; - } - pixel_weights.m_SrcStart = start_i; - pixel_weights.m_SrcEnd = end_i; - for (int j = start_i; j <= end_i; j++) { - double dest_start = FXSYS_Div((FX_FLOAT)(j)-base, scale); - double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); - if (dest_start > dest_end) { - double temp = dest_start; - dest_start = dest_end; - dest_end = temp; - } - double area_start = dest_start > (FX_FLOAT)(dest_pixel) - ? dest_start - : (FX_FLOAT)(dest_pixel); - double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) - ? (FX_FLOAT)(dest_pixel + 1) - : dest_end; - double weight = area_start >= area_end ? 0.0f : area_end - area_start; - if (weight == 0 && j == end_i) { - pixel_weights.m_SrcEnd--; - break; - } - pixel_weights.m_Weights[j - start_i] = - FXSYS_round((FX_FLOAT)(weight * 65536)); - } - } -} -void CFXCODEC_HorzTable::Calc(int dest_len, int src_len, FX_BOOL bInterpol) { - if (m_pWeightTables) { - FX_Free(m_pWeightTables); - } - double scale = (double)dest_len / (double)src_len; - m_ItemSize = sizeof(int) * 4; - int size = dest_len * m_ItemSize + 4; - m_pWeightTables = FX_Alloc(uint8_t, size); - if (m_pWeightTables == NULL) { - return; - } - FXSYS_memset(m_pWeightTables, 0, size); - if (scale > 1) { - int pre_des_col = 0; - for (int src_col = 0; src_col < src_len; src_col++) { - double des_col_f = src_col * scale; - int des_col = FXSYS_round((FX_FLOAT)des_col_f); - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize); - pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - if (src_col == src_len - 1 && des_col < dest_len - 1) { - for (int des_col_index = pre_des_col + 1; des_col_index < dest_len; - des_col_index++) { - pWeight = - (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize); - pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - } - return; - } - int des_col_len = des_col - pre_des_col; - for (int des_col_index = pre_des_col + 1; des_col_index < des_col; - des_col_index++) { - pWeight = (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize); - pWeight->m_SrcStart = src_col - 1; - pWeight->m_SrcEnd = src_col; - pWeight->m_Weights[0] = - bInterpol ? FXSYS_round((FX_FLOAT)( - ((FX_FLOAT)des_col - (FX_FLOAT)des_col_index) / - (FX_FLOAT)des_col_len * 65536)) - : 65536; - pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; - } - pre_des_col = des_col; - } - return; - } - for (int des_col = 0; des_col < dest_len; des_col++) { - double src_col_f = des_col / scale; - int src_col = FXSYS_round((FX_FLOAT)src_col_f); - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize); - pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - } -} -void CFXCODEC_VertTable::Calc(int dest_len, int src_len) { - if (m_pWeightTables) { - FX_Free(m_pWeightTables); - } - double scale = (double)dest_len / (double)src_len; - m_ItemSize = sizeof(int) * 4; - int size = dest_len * m_ItemSize + 4; - m_pWeightTables = FX_Alloc(uint8_t, size); - if (m_pWeightTables == NULL) { - return; - } - FXSYS_memset(m_pWeightTables, 0, size); - if (scale > 1) { - double step = 0.0; - int src_row = 0; - while (step < (double)dest_len) { - int start_step = (int)step; - step = scale * (++src_row); - int end_step = (int)step; - if (end_step >= dest_len) { - end_step = dest_len; - for (int des_row = start_step; des_row < end_step; des_row++) { - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); - pWeight->m_SrcStart = start_step; - pWeight->m_SrcEnd = start_step; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - } - return; - } - int length = end_step - start_step; - { - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + start_step * m_ItemSize); - pWeight->m_SrcStart = start_step; - pWeight->m_SrcEnd = start_step; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - } - for (int des_row = start_step + 1; des_row < end_step; des_row++) { - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); - pWeight->m_SrcStart = start_step; - pWeight->m_SrcEnd = end_step; - pWeight->m_Weights[0] = FXSYS_round((FX_FLOAT)(end_step - des_row) / - (FX_FLOAT)length * 65536); - pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; - } - } - } else { - for (int des_row = 0; des_row < dest_len; des_row++) { - PixelWeight* pWeight = - (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); - pWeight->m_SrcStart = des_row; - pWeight->m_SrcEnd = des_row; - pWeight->m_Weights[0] = 65536; - pWeight->m_Weights[1] = 0; - } - } -} -CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( - CCodec_ModuleMgr* pCodecMgr) { - m_pFile = NULL; - m_pJpegContext = NULL; - m_pPngContext = NULL; - m_pGifContext = NULL; - m_pBmpContext = NULL; - m_pTiffContext = NULL; - m_pCodecMgr = NULL; - m_pSrcBuf = NULL; - m_pDecodeBuf = NULL; - m_pDeviceBitmap = NULL; - m_pSrcPalette = NULL; - m_pCodecMgr = pCodecMgr; - m_offSet = 0; - m_SrcSize = 0; - m_ScanlineSize = 0; - m_SrcWidth = m_SrcHeight = 0; - m_SrcComponents = 0; - m_SrcBPC = 0; - m_SrcPassNumber = 0; - m_clipBox = FX_RECT(0, 0, 0, 0); - m_imagType = FXCODEC_IMAGE_UNKNOWN; - m_status = FXCODEC_STATUS_DECODE_FINISH; - m_TransMethod = -1; - m_SrcRow = 0; - m_SrcFormat = FXCodec_Invalid; - m_bInterpol = TRUE; - m_FrameNumber = 0; - m_FrameCur = 0; - m_SrcPaletteNumber = 0; - m_GifPltNumber = 0; - m_GifBgIndex = 0; - m_pGifPalette = NULL; - m_GifTransIndex = -1; - m_GifFrameRect = FX_RECT(0, 0, 0, 0); - m_BmpIsTopBottom = FALSE; -} -CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { - m_pFile = NULL; - if (m_pJpegContext != NULL) { - m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext); - } - if (m_pPngContext != NULL) { - m_pCodecMgr->GetPngModule()->Finish(m_pPngContext); - } - if (m_pGifContext != NULL) { - m_pCodecMgr->GetGifModule()->Finish(m_pGifContext); - } - if (m_pBmpContext != NULL) { - m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext); - } - if (m_pTiffContext != NULL) { - m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext); - } - if (m_pSrcBuf != NULL) { - FX_Free(m_pSrcBuf); - } - if (m_pDecodeBuf != NULL) { - FX_Free(m_pDecodeBuf); - } - if (m_pSrcPalette != NULL) { - FX_Free(m_pSrcPalette); - } -} -FX_BOOL CCodec_ProgressiveDecoder::JpegReadMoreData( - ICodec_JpegModule* pJpegModule, - FXCODEC_STATUS& err_status) { - FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); - if (dwSize <= m_offSet) { - return FALSE; - } - dwSize = dwSize - m_offSet; - FX_DWORD dwAvail = pJpegModule->GetAvailInput(m_pJpegContext, NULL); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - } else { - FX_DWORD dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += dwSize; - pJpegModule->Input(m_pJpegContext, m_pSrcBuf, dwSize + dwAvail); - return TRUE; -} -FX_BOOL CCodec_ProgressiveDecoder::PngReadHeaderFunc(void* pModule, - int width, - int height, - int bpc, - int pass, - int* color_type, - double* gamma) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - if (pCodec->m_pDeviceBitmap == NULL) { - pCodec->m_SrcWidth = width; - pCodec->m_SrcHeight = height; - pCodec->m_SrcBPC = bpc; - pCodec->m_SrcPassNumber = pass; - pCodec->m_SrcComponents = - *color_type == 0 ? 1 : *color_type == 2 - ? 3 - : *color_type == 3 - ? 4 - : *color_type == 4 - ? 2 - : *color_type == 6 ? 4 : 0; - pCodec->m_clipBox = FX_RECT(0, 0, width, height); - return FALSE; - } - FXDIB_Format format = pCodec->m_pDeviceBitmap->GetFormat(); - switch (format) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - ASSERT(FALSE); - return FALSE; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: - *color_type = 0; - break; - case FXDIB_Rgb: - *color_type = 2; - break; - case FXDIB_Rgb32: - case FXDIB_Argb: - *color_type = 6; - break; - default: - ASSERT(FALSE); - return FALSE; - } - *gamma = FXCODEC_PNG_GAMMA; - return TRUE; -} -FX_BOOL CCodec_ProgressiveDecoder::PngAskScanlineBufFunc(void* pModule, - int line, - uint8_t*& src_buf) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; - ASSERT(pDIBitmap != NULL); - if (pDIBitmap == NULL) { - return FALSE; - } - if (line >= pCodec->m_clipBox.top && line < pCodec->m_clipBox.bottom) { - double scale_y = - (double)pCodec->m_sizeY / (double)pCodec->m_clipBox.Height(); - int32_t row = - (int32_t)((line - pCodec->m_clipBox.top) * scale_y) + pCodec->m_startY; - uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row); - uint8_t* des_scan = pCodec->m_pDecodeBuf; - src_buf = pCodec->m_pDecodeBuf; - int32_t src_Bpp = pDIBitmap->GetBPP() >> 3; - int32_t des_Bpp = (pCodec->m_SrcFormat & 0xff) >> 3; - int32_t src_left = pCodec->m_startX; - int32_t des_left = pCodec->m_clipBox.left; - src_scan += src_left * src_Bpp; - des_scan += des_left * des_Bpp; - for (int32_t src_col = 0; src_col < pCodec->m_sizeX; src_col++) { - PixelWeight* pPixelWeights = - pCodec->m_WeightHorzOO.GetPixelWeight(src_col); - if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) { - continue; - } - switch (pDIBitmap->GetFormat()) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - ASSERT(FALSE); - return FALSE; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDIBitmap->GetPalette() != NULL) { - return FALSE; - } - FX_DWORD des_g = 0; - des_g += pPixelWeights->m_Weights[0] * src_scan[src_col]; - des_scan[pPixelWeights->m_SrcStart] = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - const uint8_t* p = src_scan + src_col * src_Bpp; - des_b += pPixelWeights->m_Weights[0] * (*p++); - des_g += pPixelWeights->m_Weights[0] * (*p++); - des_r += pPixelWeights->m_Weights[0] * (*p); - uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; - *pDes++ = (uint8_t)((des_b) >> 16); - *pDes++ = (uint8_t)((des_g) >> 16); - *pDes = (uint8_t)((des_r) >> 16); - } break; - case FXDIB_Argb: { - FX_DWORD des_r = 0, des_g = 0, des_b = 0; - const uint8_t* p = src_scan + src_col * src_Bpp; - des_b += pPixelWeights->m_Weights[0] * (*p++); - des_g += pPixelWeights->m_Weights[0] * (*p++); - des_r += pPixelWeights->m_Weights[0] * (*p++); - uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; - *pDes++ = (uint8_t)((des_b) >> 16); - *pDes++ = (uint8_t)((des_g) >> 16); - *pDes++ = (uint8_t)((des_r) >> 16); - *pDes = *p; - } break; - default: - return FALSE; - } - } - } - return TRUE; -} -void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( - CFX_DIBitmap* pDeviceBitmap, - int32_t des_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - uint8_t* des_scan = (uint8_t*)pDeviceBitmap->GetScanline(des_line); - int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; - int32_t des_Bpp = pDeviceBitmap->GetBPP() >> 3; - int32_t src_left = m_clipBox.left; - int32_t des_left = m_startX; - src_scan += src_left * src_Bpp; - des_scan += des_left * des_Bpp; - for (int32_t des_col = 0; des_col < m_sizeX; des_col++) { - PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(des_col); - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - ASSERT(FALSE); - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette() != NULL) { - return; - } - FX_DWORD des_g = 0; - des_g += - pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; - des_g += - pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; - *des_scan++ = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - des_b += pPixelWeights->m_Weights[0] * (*p++); - des_g += pPixelWeights->m_Weights[0] * (*p++); - des_r += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - des_b += pPixelWeights->m_Weights[1] * (*p++); - des_g += pPixelWeights->m_Weights[1] * (*p++); - des_r += pPixelWeights->m_Weights[1] * (*p); - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - des_scan += des_Bpp - 3; - } break; - case FXDIB_Argb: { - FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - des_b += pPixelWeights->m_Weights[0] * (*p++); - des_g += pPixelWeights->m_Weights[0] * (*p++); - des_r += pPixelWeights->m_Weights[0] * (*p++); - des_a += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - des_b += pPixelWeights->m_Weights[1] * (*p++); - des_g += pPixelWeights->m_Weights[1] * (*p++); - des_r += pPixelWeights->m_Weights[1] * (*p++); - des_a += pPixelWeights->m_Weights[1] * (*p); - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - *des_scan++ = (uint8_t)((des_a) >> 16); - } break; - default: - return; - } - } -} -void CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc(void* pModule, - int pass, - int line) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; - ASSERT(pDIBitmap != NULL); - int src_top = pCodec->m_clipBox.top; - int src_bottom = pCodec->m_clipBox.bottom; - int des_top = pCodec->m_startY; - int src_hei = pCodec->m_clipBox.Height(); - int des_hei = pCodec->m_sizeY; - if (line >= src_top && line < src_bottom) { - double scale_y = (double)des_hei / (double)src_hei; - int src_row = line - src_top; - int des_row = (int)(src_row * scale_y) + des_top; - if (des_row >= des_top + des_hei) { - return; - } - pCodec->PngOneOneMapResampleHorz(pDIBitmap, des_row, pCodec->m_pDecodeBuf, - pCodec->m_SrcFormat); - if (pCodec->m_SrcPassNumber == 1 && scale_y > 1.0) { - pCodec->ResampleVert(pDIBitmap, scale_y, des_row); - return; - } - if (pass == 6 && scale_y > 1.0) { - pCodec->ResampleVert(pDIBitmap, scale_y, des_row); - } - } -} -FX_BOOL CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, - FXCODEC_STATUS& err_status) { - FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); - if (dwSize <= m_offSet) { - return FALSE; - } - dwSize = dwSize - m_offSet; - FX_DWORD dwAvail = pGifModule->GetAvailInput(m_pGifContext, NULL); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - } else { - FX_DWORD dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += dwSize; - pGifModule->Input(m_pGifContext, m_pSrcBuf, dwSize + dwAvail); - return TRUE; -} -void CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback( - void* pModule, - FX_DWORD& cur_pos) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - FX_DWORD remain_size = - pCodec->m_pCodecMgr->GetGifModule()->GetAvailInput(pCodec->m_pGifContext); - cur_pos = pCodec->m_offSet - remain_size; -} -uint8_t* CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback( - void* pModule, - int32_t frame_num, - int32_t pal_size) { - return FX_Alloc(uint8_t, pal_size); -} -FX_BOOL CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback( - void* pModule, - FX_DWORD rcd_pos, - const FX_RECT& img_rc, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - FX_BOOL user_input, - int32_t trans_index, - int32_t disposal_method, - FX_BOOL interlace) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - pCodec->m_offSet = rcd_pos; - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!pCodec->GifReadMoreData(pCodec->m_pCodecMgr->GetGifModule(), - error_status)) { - return FALSE; - } - uint8_t* pPalette = NULL; - if (pal_num != 0 && pal_ptr) { - pPalette = (uint8_t*)pal_ptr; - } else { - pal_num = pCodec->m_GifPltNumber; - pPalette = pCodec->m_pGifPalette; - } - if (pCodec->m_pSrcPalette == NULL) { - pCodec->m_pSrcPalette = FX_Alloc(FX_ARGB, pal_num); - } else if (pal_num > pCodec->m_SrcPaletteNumber) { - pCodec->m_pSrcPalette = FX_Realloc(FX_ARGB, pCodec->m_pSrcPalette, pal_num); - } - if (pCodec->m_pSrcPalette == NULL) { - return FALSE; - } - pCodec->m_SrcPaletteNumber = pal_num; - for (int i = 0; i < pal_num; i++) { - FX_DWORD j = i * 3; - pCodec->m_pSrcPalette[i] = - ArgbEncode(0xff, pPalette[j], pPalette[j + 1], pPalette[j + 2]); - } - pCodec->m_GifTransIndex = trans_index; - pCodec->m_GifFrameRect = img_rc; - pCodec->m_SrcPassNumber = interlace ? 4 : 1; - int32_t pal_index = pCodec->m_GifBgIndex; - CFX_DIBitmap* pDevice = pCodec->m_pDeviceBitmap; - if (trans_index >= pal_num) { - trans_index = -1; - } - if (trans_index != -1) { - pCodec->m_pSrcPalette[trans_index] &= 0x00ffffff; - if (pDevice->HasAlpha()) { - pal_index = trans_index; - } - } - int startX = pCodec->m_startX; - int startY = pCodec->m_startY; - int sizeX = pCodec->m_sizeX; - int sizeY = pCodec->m_sizeY; - int Bpp = pDevice->GetBPP() / 8; - FX_ARGB argb = pCodec->m_pSrcPalette[pal_index]; - for (int row = 0; row < sizeY; row++) { - uint8_t* pScanline = - (uint8_t*)pDevice->GetScanline(row + startY) + startX * Bpp; - switch (pCodec->m_TransMethod) { - case 3: { - uint8_t gray = - FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); - FXSYS_memset(pScanline, gray, sizeX); - break; - } - case 8: { - for (int col = 0; col < sizeX; col++) { - *pScanline++ = FXARGB_B(argb); - *pScanline++ = FXARGB_G(argb); - *pScanline++ = FXARGB_R(argb); - pScanline += Bpp - 3; - } - break; - } - case 12: { - for (int col = 0; col < sizeX; col++) { - FXARGB_SETDIB(pScanline, argb); - pScanline += 4; - } - break; - } - } - } - return TRUE; -} -void CCodec_ProgressiveDecoder::GifReadScanlineCallback(void* pModule, - int32_t row_num, - uint8_t* row_buf) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; - ASSERT(pDIBitmap != NULL); - int32_t img_width = pCodec->m_GifFrameRect.Width(); - if (!pDIBitmap->HasAlpha()) { - uint8_t* byte_ptr = row_buf; - for (int i = 0; i < img_width; i++) { - if (*byte_ptr == pCodec->m_GifTransIndex) { - *byte_ptr = pCodec->m_GifBgIndex; - } - byte_ptr++; - } - } - int32_t pal_index = pCodec->m_GifBgIndex; - if (pCodec->m_GifTransIndex != -1 && pCodec->m_pDeviceBitmap->HasAlpha()) { - pal_index = pCodec->m_GifTransIndex; - } - FXSYS_memset(pCodec->m_pDecodeBuf, pal_index, pCodec->m_SrcWidth); - FX_BOOL bLastPass = (row_num % 2) == 1; - int32_t line = row_num + pCodec->m_GifFrameRect.top; - int32_t left = pCodec->m_GifFrameRect.left; - FXSYS_memcpy(pCodec->m_pDecodeBuf + left, row_buf, img_width); - int src_top = pCodec->m_clipBox.top; - int src_bottom = pCodec->m_clipBox.bottom; - int des_top = pCodec->m_startY; - int src_hei = pCodec->m_clipBox.Height(); - int des_hei = pCodec->m_sizeY; - if (line >= src_top && line < src_bottom) { - double scale_y = (double)des_hei / (double)src_hei; - int src_row = line - src_top; - int des_row = (int)(src_row * scale_y) + des_top; - if (des_row >= des_top + des_hei) { - return; - } - pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, - pCodec->m_SrcFormat); - if (scale_y > 1.0 && - (!pCodec->m_bInterpol || pCodec->m_SrcPassNumber == 1)) { - pCodec->ResampleVert(pDIBitmap, scale_y, des_row); - return; - } - if (scale_y > 1.0) { - int des_bottom = des_top + pCodec->m_sizeY; - int des_Bpp = pDIBitmap->GetBPP() >> 3; - FX_DWORD des_ScanOffet = pCodec->m_startX * des_Bpp; - if (des_row + (int)scale_y >= des_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDIBitmap->GetScanline(des_row) + des_ScanOffet; - int cur_row = des_row; - while (++cur_row < des_bottom) { - uint8_t* scan_des = - (uint8_t*)pDIBitmap->GetScanline(cur_row) + des_ScanOffet; - FX_DWORD size = pCodec->m_sizeX * des_Bpp; - FXSYS_memcpy(scan_des, scan_src, size); - } - } - if (bLastPass) { - pCodec->GifDoubleLineResampleVert(pDIBitmap, scale_y, des_row); - } - } - } -} -void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( - CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row) { - int des_Bpp = pDeviceBitmap->GetBPP() >> 3; - FX_DWORD des_ScanOffet = m_startX * des_Bpp; - int des_top = m_startY; - int des_row_1 = des_row - int(2 * scale_y); - if (des_row_1 < des_top) { - des_row_1 = des_top; - } - for (; des_row_1 < des_row; des_row_1++) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + - des_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet; - for (int des_col = 0; des_col < m_sizeX; des_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette() != NULL) { - return; - } - int des_g = 0; - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += des_Bpp - 3; - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += des_Bpp - 3; - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - scan_des += des_Bpp - 3; - } break; - case FXDIB_Argb: { - FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - des_a += pWeight->m_Weights[0] * (*scan_src1++); - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - des_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - *scan_des++ = (uint8_t)((des_a) >> 16); - } break; - default: - return; - } - } - } - int des_bottom = des_top + m_sizeY - 1; - if (des_row + (int)(2 * scale_y) >= des_bottom && - des_row + (int)scale_y < des_bottom) { - GifDoubleLineResampleVert(pDeviceBitmap, scale_y, des_row + (int)scale_y); - } -} -FX_BOOL CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, - FXCODEC_STATUS& err_status) { - FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); - if (dwSize <= m_offSet) { - return FALSE; - } - dwSize = dwSize - m_offSet; - FX_DWORD dwAvail = pBmpModule->GetAvailInput(m_pBmpContext, NULL); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - } else { - FX_DWORD dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += dwSize; - pBmpModule->Input(m_pBmpContext, m_pSrcBuf, dwSize + dwAvail); - return TRUE; -} -FX_BOOL CCodec_ProgressiveDecoder::BmpInputImagePositionBufCallback( - void* pModule, - FX_DWORD rcd_pos) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - pCodec->m_offSet = rcd_pos; - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!pCodec->BmpReadMoreData(pCodec->m_pCodecMgr->GetBmpModule(), - error_status)) { - return FALSE; - } - return TRUE; -} -void CCodec_ProgressiveDecoder::BmpReadScanlineCallback(void* pModule, - int32_t row_num, - uint8_t* row_buf) { - CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; - CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; - ASSERT(pDIBitmap != NULL); - FXSYS_memcpy(pCodec->m_pDecodeBuf, row_buf, pCodec->m_ScanlineSize); - int src_top = pCodec->m_clipBox.top; - int src_bottom = pCodec->m_clipBox.bottom; - int des_top = pCodec->m_startY; - int src_hei = pCodec->m_clipBox.Height(); - int des_hei = pCodec->m_sizeY; - if (row_num >= src_top && row_num < src_bottom) { - double scale_y = (double)des_hei / (double)src_hei; - int src_row = row_num - src_top; - int des_row = (int)(src_row * scale_y) + des_top; - if (des_row >= des_top + des_hei) { - return; - } - pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, - pCodec->m_SrcFormat); - if (scale_y > 1.0) { - if (pCodec->m_BmpIsTopBottom || !pCodec->m_bInterpol) { - pCodec->ResampleVert(pDIBitmap, scale_y, des_row); - return; - } else { - pCodec->ResampleVertBT(pDIBitmap, scale_y, des_row); - } - } - } -} -void CCodec_ProgressiveDecoder::ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row) { - int des_Bpp = pDeviceBitmap->GetBPP() >> 3; - FX_DWORD des_ScanOffet = m_startX * des_Bpp; - int des_top = m_startY; - int des_bottom = m_startY + m_sizeY; - int des_row_1 = des_row + int(scale_y); - if (des_row_1 >= des_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - while (++des_row < des_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - FX_DWORD size = m_sizeX * des_Bpp; - FXSYS_memcpy(scan_des, scan_src, size); - } - return; - } - for (; des_row_1 > des_row; des_row_1--) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + - des_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet; - for (int des_col = 0; des_col < m_sizeX; des_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette() != NULL) { - return; - } - int des_g = 0; - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += des_Bpp - 3; - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += des_Bpp - 3; - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - scan_des += des_Bpp - 3; - } break; - case FXDIB_Argb: { - FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - des_a += pWeight->m_Weights[0] * (*scan_src1++); - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - des_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - *scan_des++ = (uint8_t)((des_a) >> 16); - } break; - default: - return; - } - } - } -} -FX_BOOL CCodec_ProgressiveDecoder::DetectImageType( - FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute) { - m_offSet = 0; - FX_DWORD size = (FX_DWORD)m_pFile->GetSize(); - if (size > FXCODEC_BLOCK_SIZE) { - size = FXCODEC_BLOCK_SIZE; - } - if (m_pSrcBuf != NULL) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = NULL; - } - m_pSrcBuf = FX_Alloc(uint8_t, size); - if (m_pSrcBuf == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FXSYS_memset(m_pSrcBuf, 0, size); - m_SrcSize = size; - switch (imageType) { - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (pBmpModule == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - pBmpModule->InputImagePositionBufCallback = - BmpInputImagePositionBufCallback; - pBmpModule->ReadScanlineCallback = BmpReadScanlineCallback; - m_pBmpContext = pBmpModule->Start((void*)this); - if (m_pBmpContext == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += size; - pBmpModule->Input(m_pBmpContext, m_pSrcBuf, size); - FX_DWORD* pPalette = NULL; - int32_t readResult = pBmpModule->ReadHeader( - m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, - &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_status = error_status; - return FALSE; - } - readResult = pBmpModule->ReadHeader( - m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, - &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); - } - if (readResult == 1) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - if (m_pSrcPalette != NULL) { - FX_Free(m_pSrcPalette); - m_pSrcPalette = NULL; - } - if (m_SrcPaletteNumber) { - m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber); - if (m_pSrcPalette == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FXSYS_memcpy(m_pSrcPalette, pPalette, - m_SrcPaletteNumber * sizeof(FX_DWORD)); - } - return TRUE; - } - if (m_pBmpContext != NULL) { - pBmpModule->Finish(m_pBmpContext); - m_pBmpContext = NULL; - } - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } break; - case FXCODEC_IMAGE_JPG: { - ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - if (pJpegModule == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - m_pJpegContext = pJpegModule->Start(); - if (m_pJpegContext == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += size; - pJpegModule->Input(m_pJpegContext, m_pSrcBuf, size); - int32_t readResult = - pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_status = error_status; - return FALSE; - } - readResult = - pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); - } - if (!readResult) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return TRUE; - } - if (m_pJpegContext != NULL) { - pJpegModule->Finish(m_pJpegContext); - m_pJpegContext = NULL; - } - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } break; - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (pPngModule == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - pPngModule->ReadHeaderCallback = - CCodec_ProgressiveDecoder::PngReadHeaderFunc; - pPngModule->AskScanlineBufCallback = - CCodec_ProgressiveDecoder::PngAskScanlineBufFunc; - pPngModule->FillScanlineBufCompletedCallback = - CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc; - m_pPngContext = pPngModule->Start((void*)this); - if (m_pPngContext == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += size; - bResult = pPngModule->Input(m_pPngContext, m_pSrcBuf, size, pAttribute); - while (bResult) { - FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet; - FX_DWORD input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - if (m_pPngContext != NULL) { - pPngModule->Finish(m_pPngContext); - } - m_pPngContext = NULL; - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } - if (m_pSrcBuf != NULL && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - if (m_pSrcBuf == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FXSYS_memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, pAttribute); - } - ASSERT(!bResult); - if (m_pPngContext != NULL) { - pPngModule->Finish(m_pPngContext); - m_pPngContext = NULL; - } - if (m_SrcPassNumber == 0) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } - } break; - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (pGifModule == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - pGifModule->RecordCurrentPositionCallback = - CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback; - pGifModule->AskLocalPaletteBufCallback = - CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback; - pGifModule->InputRecordPositionBufCallback = - CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback; - pGifModule->ReadScanlineCallback = - CCodec_ProgressiveDecoder::GifReadScanlineCallback; - m_pGifContext = pGifModule->Start((void*)this); - if (m_pGifContext == NULL) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return FALSE; - } - FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return FALSE; - } - m_offSet += size; - pGifModule->Input(m_pGifContext, m_pSrcBuf, size); - m_SrcComponents = 1; - int32_t readResult = pGifModule->ReadHeader( - m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, - (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!GifReadMoreData(pGifModule, error_status)) { - m_status = error_status; - return FALSE; - } - readResult = pGifModule->ReadHeader( - m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, - (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); - } - if (readResult == 1) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return TRUE; - } - if (m_pGifContext != NULL) { - pGifModule->Finish(m_pGifContext); - m_pGifContext = NULL; - } - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } break; - case FXCODEC_IMAGE_TIF: { - ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (pTiffModule == NULL) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } - m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); - if (m_pTiffContext == NULL) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } - int32_t frames = 0; - pTiffModule->GetFrames(m_pTiffContext, frames); - FX_DWORD bpc; - FX_BOOL ret = pTiffModule->LoadFrameInfo( - m_pTiffContext, 0, (FX_DWORD&)m_SrcWidth, (FX_DWORD&)m_SrcHeight, - (FX_DWORD&)m_SrcComponents, bpc, pAttribute); - m_SrcComponents = 4; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - if (!ret) { - pTiffModule->DestroyDecoder(m_pTiffContext); - (m_pTiffContext = NULL); - (m_status = FXCODEC_STATUS_ERR_FORMAT); - return FALSE; - } - } break; - default: - m_status = FXCODEC_STATUS_ERR_FORMAT; - return FALSE; - } - return TRUE; -} -FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( - IFX_FileRead* pFile, - FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute) { - switch (m_status) { - case FXCODEC_STATUS_FRAME_READY: - case FXCODEC_STATUS_FRAME_TOBECONTINUE: - case FXCODEC_STATUS_DECODE_READY: - case FXCODEC_STATUS_DECODE_TOBECONTINUE: - return FXCODEC_STATUS_ERROR; - default:; - } - if (pFile == NULL) { - m_status = FXCODEC_STATUS_ERR_PARAMS; - m_pFile = NULL; - return m_status; - } - m_pFile = pFile; - m_offSet = 0; - m_SrcWidth = m_SrcHeight = 0; - m_SrcComponents = m_SrcBPC = 0; - m_clipBox = FX_RECT(0, 0, 0, 0); - m_startX = m_startY = 0; - m_sizeX = m_sizeY = 0; - m_SrcPassNumber = 0; - if (imageType != FXCODEC_IMAGE_UNKNOWN && - DetectImageType(imageType, pAttribute)) { - m_imagType = imageType; - m_status = FXCODEC_STATUS_FRAME_READY; - return m_status; - } - for (int type = FXCODEC_IMAGE_BMP; type < FXCODEC_IMAGE_MAX; type++) { - if (DetectImageType((FXCODEC_IMAGE_TYPE)type, pAttribute)) { - m_imagType = (FXCODEC_IMAGE_TYPE)type; - m_status = FXCODEC_STATUS_FRAME_READY; - return m_status; - } - } - m_status = FXCODEC_STATUS_ERR_FORMAT; - m_pFile = NULL; - return m_status; -} -void CCodec_ProgressiveDecoder::SetClipBox(FX_RECT* clip) { - if (m_status != FXCODEC_STATUS_FRAME_READY) { - return; - } - if (clip->IsEmpty()) { - m_clipBox = FX_RECT(0, 0, 0, 0); - return; - } - if (clip->left < 0) { - clip->left = 0; - } - if (clip->right > m_SrcWidth) { - clip->right = m_SrcWidth; - } - if (clip->top < 0) { - clip->top = 0; - } - if (clip->bottom > m_SrcHeight) { - clip->bottom = m_SrcHeight; - } - if (clip->IsEmpty()) { - m_clipBox = FX_RECT(0, 0, 0, 0); - return; - } - m_clipBox = *clip; -} -void CCodec_ProgressiveDecoder::GetDownScale(int& down_scale) { - down_scale = 1; - int ratio_w = m_clipBox.Width() / m_sizeX; - int ratio_h = m_clipBox.Height() / m_sizeY; - int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w; - if (ratio >= 8) { - down_scale = 8; - } else if (ratio >= 4) { - down_scale = 4; - } else if (ratio >= 2) { - down_scale = 2; - } - m_clipBox.left /= down_scale; - m_clipBox.right /= down_scale; - m_clipBox.top /= down_scale; - m_clipBox.bottom /= down_scale; - if (m_clipBox.right == m_clipBox.left) { - m_clipBox.right = m_clipBox.left + 1; - } - if (m_clipBox.bottom == m_clipBox.top) { - m_clipBox.bottom = m_clipBox.top + 1; - } -} -void CCodec_ProgressiveDecoder::GetTransMethod(FXDIB_Format des_format, - FXCodec_Format src_format) { - switch (des_format) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: { - switch (src_format) { - case FXCodec_1bppGray: - m_TransMethod = 0; - break; - default: - m_TransMethod = -1; - } - } break; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - switch (src_format) { - case FXCodec_1bppGray: - m_TransMethod = 1; - break; - case FXCodec_8bppGray: - m_TransMethod = 2; - break; - case FXCodec_1bppRgb: - case FXCodec_8bppRgb: - m_TransMethod = 3; - break; - case FXCodec_Rgb: - case FXCodec_Rgb32: - case FXCodec_Argb: - m_TransMethod = 4; - break; - case FXCodec_Cmyk: - m_TransMethod = 5; - break; - default: - m_TransMethod = -1; - } - } break; - case FXDIB_Rgb: { - switch (src_format) { - case FXCodec_1bppGray: - m_TransMethod = 6; - break; - case FXCodec_8bppGray: - m_TransMethod = 7; - break; - case FXCodec_1bppRgb: - case FXCodec_8bppRgb: - m_TransMethod = 8; - break; - case FXCodec_Rgb: - case FXCodec_Rgb32: - case FXCodec_Argb: - m_TransMethod = 9; - break; - case FXCodec_Cmyk: - m_TransMethod = 10; - break; - default: - m_TransMethod = -1; - } - } break; - case FXDIB_Rgb32: - case FXDIB_Argb: { - switch (src_format) { - case FXCodec_1bppGray: - m_TransMethod = 6; - break; - case FXCodec_8bppGray: - m_TransMethod = 7; - break; - case FXCodec_1bppRgb: - case FXCodec_8bppRgb: - if (des_format == FXDIB_Argb) { - m_TransMethod = 12; - } else { - m_TransMethod = 8; - } - break; - case FXCodec_Rgb: - case FXCodec_Rgb32: - m_TransMethod = 9; - break; - case FXCodec_Cmyk: - m_TransMethod = 10; - break; - case FXCodec_Argb: - m_TransMethod = 11; - break; - default: - m_TransMethod = -1; - } - } break; - default: - m_TransMethod = -1; - } -} -void _RGB2BGR(uint8_t* buffer, int width = 1) { - if (buffer && width > 0) { - uint8_t temp; - int i = 0; - int j = 0; - for (; i < width; i++, j += 3) { - temp = buffer[j]; - buffer[j] = buffer[j + 2]; - buffer[j + 2] = temp; - } - } -} -void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, - int des_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - int src_left = m_clipBox.left; - int des_left = m_startX; - uint8_t* des_scan = - pDeviceBitmap->GetBuffer() + des_line * pDeviceBitmap->GetPitch(); - int src_bpp = src_format & 0xff; - int des_bpp = pDeviceBitmap->GetBPP(); - int src_Bpp = src_bpp >> 3; - int des_Bpp = des_bpp >> 3; - src_scan += src_left * src_Bpp; - des_scan += des_left * des_Bpp; - for (int des_col = 0; des_col < m_sizeX; des_col++) { - PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(des_col); - switch (m_TransMethod) { - case -1: - return; - case 0: - return; - case 1: - return; - case 2: { - FX_DWORD des_g = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - des_g += pixel_weight * src_scan[j]; - } - *des_scan++ = (uint8_t)(des_g >> 16); - } break; - case 3: { - int des_r = 0, des_g = 0, des_b = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - unsigned long argb = m_pSrcPalette[src_scan[j]]; - des_r += pixel_weight * (uint8_t)(argb >> 16); - des_g += pixel_weight * (uint8_t)(argb >> 8); - des_b += pixel_weight * (uint8_t)argb; - } - *des_scan++ = - (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); - } break; - case 4: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - const uint8_t* src_pixel = src_scan + j * src_Bpp; - des_b += pixel_weight * (*src_pixel++); - des_g += pixel_weight * (*src_pixel++); - des_r += pixel_weight * (*src_pixel); - } - *des_scan++ = - (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); - } break; - case 5: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - const uint8_t* src_pixel = src_scan + j * src_Bpp; - uint8_t src_b = 0, src_g = 0, src_r = 0; - AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], - 255 - src_pixel[2], 255 - src_pixel[3], src_r, - src_g, src_b); - des_b += pixel_weight * src_b; - des_g += pixel_weight * src_g; - des_r += pixel_weight * src_r; - } - *des_scan++ = - (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); - } break; - case 6: - return; - case 7: { - FX_DWORD des_g = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - des_g += pixel_weight * src_scan[j]; - } - FXSYS_memset(des_scan, (uint8_t)(des_g >> 16), 3); - des_scan += des_Bpp; - } break; - case 8: { - int des_r = 0, des_g = 0, des_b = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - unsigned long argb = m_pSrcPalette[src_scan[j]]; - des_r += pixel_weight * (uint8_t)(argb >> 16); - des_g += pixel_weight * (uint8_t)(argb >> 8); - des_b += pixel_weight * (uint8_t)argb; - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - des_scan += des_Bpp - 3; - } break; - case 12: { - if (m_pBmpContext) { - int des_r = 0, des_g = 0, des_b = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - unsigned long argb = m_pSrcPalette[src_scan[j]]; - des_r += pixel_weight * (uint8_t)(argb >> 16); - des_g += pixel_weight * (uint8_t)(argb >> 8); - des_b += pixel_weight * (uint8_t)argb; - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - *des_scan++ = 0xFF; - } else { - int des_a = 0, des_r = 0, des_g = 0, des_b = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - unsigned long argb = m_pSrcPalette[src_scan[j]]; - des_a += pixel_weight * (uint8_t)(argb >> 24); - des_r += pixel_weight * (uint8_t)(argb >> 16); - des_g += pixel_weight * (uint8_t)(argb >> 8); - des_b += pixel_weight * (uint8_t)argb; - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - *des_scan++ = (uint8_t)((des_a) >> 16); - } - } break; - case 9: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - const uint8_t* src_pixel = src_scan + j * src_Bpp; - des_b += pixel_weight * (*src_pixel++); - des_g += pixel_weight * (*src_pixel++); - des_r += pixel_weight * (*src_pixel); - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - des_scan += des_Bpp - 3; - } break; - case 10: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - const uint8_t* src_pixel = src_scan + j * src_Bpp; - uint8_t src_b = 0, src_g = 0, src_r = 0; - AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], - 255 - src_pixel[2], 255 - src_pixel[3], src_r, - src_g, src_b); - des_b += pixel_weight * src_b; - des_g += pixel_weight * src_g; - des_r += pixel_weight * src_r; - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - des_scan += des_Bpp - 3; - } break; - case 11: { - FX_DWORD des_alpha = 0, des_r = 0, des_g = 0, des_b = 0; - for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; - j++) { - int pixel_weight = - pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; - const uint8_t* src_pixel = src_scan + j * src_Bpp; - pixel_weight = pixel_weight * src_pixel[3] / 255; - des_b += pixel_weight * (*src_pixel++); - des_g += pixel_weight * (*src_pixel++); - des_r += pixel_weight * (*src_pixel); - des_alpha += pixel_weight; - } - *des_scan++ = (uint8_t)((des_b) >> 16); - *des_scan++ = (uint8_t)((des_g) >> 16); - *des_scan++ = (uint8_t)((des_r) >> 16); - *des_scan++ = (uint8_t)((des_alpha * 255) >> 16); - } break; - default: - return; - } - } -} -void CCodec_ProgressiveDecoder::ResampleVert(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row) { - int des_Bpp = pDeviceBitmap->GetBPP() >> 3; - FX_DWORD des_ScanOffet = m_startX * des_Bpp; - if (m_bInterpol) { - int des_top = m_startY; - int des_row_1 = des_row - int(scale_y); - if (des_row_1 < des_top) { - int des_bottom = des_top + m_sizeY; - if (des_row + (int)scale_y >= des_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - while (++des_row < des_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - FX_DWORD size = m_sizeX * des_Bpp; - FXSYS_memcpy(scan_des, scan_src, size); - } - } - return; - } - for (; des_row_1 < des_row; des_row_1++) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + - des_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + - des_ScanOffet; - for (int des_col = 0; des_col < m_sizeX; des_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette() != NULL) { - return; - } - int des_g = 0; - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(des_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - FX_DWORD des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += des_Bpp - 3; - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += des_Bpp - 3; - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - scan_des += des_Bpp - 3; - } break; - case FXDIB_Argb: { - FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; - des_b += pWeight->m_Weights[0] * (*scan_src1++); - des_g += pWeight->m_Weights[0] * (*scan_src1++); - des_r += pWeight->m_Weights[0] * (*scan_src1++); - des_a += pWeight->m_Weights[0] * (*scan_src1++); - des_b += pWeight->m_Weights[1] * (*scan_src2++); - des_g += pWeight->m_Weights[1] * (*scan_src2++); - des_r += pWeight->m_Weights[1] * (*scan_src2++); - des_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((des_b) >> 16); - *scan_des++ = (uint8_t)((des_g) >> 16); - *scan_des++ = (uint8_t)((des_r) >> 16); - *scan_des++ = (uint8_t)((des_a) >> 16); - } break; - default: - return; - } - } - } - int des_bottom = des_top + m_sizeY; - if (des_row + (int)scale_y >= des_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - while (++des_row < des_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - FX_DWORD size = m_sizeX * des_Bpp; - FXSYS_memcpy(scan_des, scan_src, size); - } - } - return; - } - int multiple = (int)FXSYS_ceil((FX_FLOAT)scale_y - 1); - if (multiple > 0) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; - for (int i = 1; i <= multiple; i++) { - if (des_row + i >= m_startY + m_sizeY) { - return; - } - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet; - FX_DWORD size = m_sizeX * des_Bpp; - FXSYS_memcpy(scan_des, scan_src, size); - } - } -} -void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, - int32_t src_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - int src_top = m_clipBox.top; - int des_top = m_startY; - int src_hei = m_clipBox.Height(); - int des_hei = m_sizeY; - if (src_line >= src_top) { - double scale_y = (double)des_hei / (double)src_hei; - int src_row = src_line - src_top; - int des_row = (int)(src_row * scale_y) + des_top; - if (des_row >= des_top + des_hei) { - return; - } - ReSampleScanline(pDeviceBitmap, des_row, m_pDecodeBuf, src_format); - if (scale_y > 1.0) { - ResampleVert(pDeviceBitmap, scale_y, des_row); - } - } -} -FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames, - IFX_Pause* pPause) { - if (!(m_status == FXCODEC_STATUS_FRAME_READY || - m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { - return FXCODEC_STATUS_ERROR; - } - switch (m_imagType) { - case FXCODEC_IMAGE_BMP: - case FXCODEC_IMAGE_JPG: - case FXCODEC_IMAGE_PNG: - case FXCODEC_IMAGE_TIF: - frames = m_FrameNumber = 1; - return m_status = FXCODEC_STATUS_DECODE_READY; - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - while (TRUE) { - int32_t readResult = - pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; - if (!GifReadMoreData(pGifModule, error_status)) { - return error_status; - } - if (pPause && pPause->NeedToPauseNow()) { - return m_status = FXCODEC_STATUS_FRAME_TOBECONTINUE; - } - readResult = pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); - } - if (readResult == 1) { - frames = m_FrameNumber; - return m_status = FXCODEC_STATUS_DECODE_READY; - } - if (m_pGifContext != NULL) { - pGifModule->Finish(m_pGifContext); - m_pGifContext = NULL; - } - return m_status = FXCODEC_STATUS_ERROR; - } - } break; - default:; - } - return FXCODEC_STATUS_ERROR; -} -FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(CFX_DIBitmap* pDIBitmap, - int start_x, - int start_y, - int size_x, - int size_y, - int32_t frames, - FX_BOOL bInterpol) { - if (m_status != FXCODEC_STATUS_DECODE_READY) { - return FXCODEC_STATUS_ERROR; - } - if (pDIBitmap == NULL || pDIBitmap->GetBPP() < 8 || frames < 0 || - frames >= m_FrameNumber) { - return FXCODEC_STATUS_ERR_PARAMS; - } - m_pDeviceBitmap = pDIBitmap; - if (m_clipBox.IsEmpty()) { - return FXCODEC_STATUS_ERR_PARAMS; - } - if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535) { - return FXCODEC_STATUS_ERR_PARAMS; - } - FX_RECT device_rc = - FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y); - int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth(); - int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight(); - device_rc.Intersect( - FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight())); - if (device_rc.IsEmpty()) { - return FXCODEC_STATUS_ERR_PARAMS; - } - m_startX = device_rc.left; - m_startY = device_rc.top; - m_sizeX = device_rc.Width(); - m_sizeY = device_rc.Height(); - m_bInterpol = bInterpol; - m_FrameCur = 0; - if (start_x < 0 || out_range_x > 0) { - FX_FLOAT scaleX = (FX_FLOAT)m_clipBox.Width() / (FX_FLOAT)size_x; - if (start_x < 0) { - m_clipBox.left -= (int32_t)FXSYS_ceil((FX_FLOAT)start_x * scaleX); - } - if (out_range_x > 0) { - m_clipBox.right -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_x * scaleX); - } - } - if (start_y < 0 || out_range_y > 0) { - FX_FLOAT scaleY = (FX_FLOAT)m_clipBox.Height() / (FX_FLOAT)size_y; - if (start_y < 0) { - m_clipBox.top -= (int32_t)FXSYS_ceil((FX_FLOAT)start_y * scaleY); - } - if (out_range_y > 0) { - m_clipBox.bottom -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_y * scaleY); - } - } - if (m_clipBox.IsEmpty()) { - return FXCODEC_STATUS_ERR_PARAMS; - } - switch (m_imagType) { - case FXCODEC_IMAGE_JPG: { - ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - int down_scale = 1; - GetDownScale(down_scale); - FX_BOOL bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); - while (!bStart) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = error_status; - } - bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); - } - int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; - scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; - if (m_pDecodeBuf != NULL) { - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = NULL; - } - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - if (m_pDecodeBuf == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppGray; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Cmyk; - break; - } - GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } break; - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (pPngModule == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - if (m_pPngContext != NULL) { - pPngModule->Finish(m_pPngContext); - m_pPngContext = NULL; - } - m_pPngContext = pPngModule->Start((void*)this); - if (m_pPngContext == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - m_offSet = 0; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppMask: - case FXDIB_8bppRgb: - m_SrcComponents = 1; - m_SrcFormat = FXCodec_8bppGray; - break; - case FXDIB_Rgb: - m_SrcComponents = 3; - m_SrcFormat = FXCodec_Rgb; - break; - case FXDIB_Rgb32: - case FXDIB_Argb: - m_SrcComponents = 4; - m_SrcFormat = FXCodec_Argb; - break; - default: { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_PARAMS; - } - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - if (m_pDecodeBuf != NULL) { - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = NULL; - } - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - if (m_pDecodeBuf == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } break; - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (pGifModule == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - m_SrcFormat = FXCodec_8bppRgb; - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth + 3) / 4 * 4; - if (m_pDecodeBuf != NULL) { - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = NULL; - } - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - if (m_pDecodeBuf == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - FXSYS_memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_FrameCur = frames; - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } break; - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (pBmpModule == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppRgb; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Rgb32; - break; - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - if (m_pDecodeBuf != NULL) { - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = NULL; - } - m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); - if (m_pDecodeBuf == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - FXSYS_memset(m_pDecodeBuf, 0, m_ScanlineSize); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width(), m_bInterpol); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } break; - case FXCODEC_IMAGE_TIF: - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - default: - break; - } - return FXCODEC_STATUS_ERROR; -} -FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode(IFX_Pause* pPause) { - if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) { - return FXCODEC_STATUS_ERROR; - } - switch (m_imagType) { - case FXCODEC_IMAGE_JPG: { - ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - while (TRUE) { - FX_BOOL readRes = - pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); - while (!readRes) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = error_status; - } - readRes = pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); - } - if (m_SrcFormat == FXCodec_Rgb) { - int src_Bpp = (m_SrcFormat & 0xff) >> 3; - _RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); - } - if (m_SrcRow >= m_clipBox.bottom) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } - Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); - m_SrcRow++; - if (pPause && pPause->NeedToPauseNow()) { - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } - } - } break; - case FXCODEC_IMAGE_PNG: { - ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - while (TRUE) { - FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet; - FX_DWORD input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - if (m_pPngContext != NULL) { - pPngModule->Finish(m_pPngContext); - } - m_pPngContext = NULL; - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } - if (m_pSrcBuf != NULL && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - if (m_pSrcBuf == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - FXSYS_memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_READ; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, nullptr); - if (!bResult) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERROR; - } - if (pPause && pPause->NeedToPauseNow()) { - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } - } - } break; - case FXCODEC_IMAGE_GIF: { - ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - while (TRUE) { - int32_t readRes = - pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!GifReadMoreData(pGifModule, error_status)) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = error_status; - } - if (pPause && pPause->NeedToPauseNow()) { - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } - readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); - } - if (readRes == 1) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERROR; - } - } break; - case FXCODEC_IMAGE_BMP: { - ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - while (TRUE) { - int32_t readRes = pBmpModule->LoadImage(m_pBmpContext); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = error_status; - } - if (pPause && pPause->NeedToPauseNow()) { - return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - } - readRes = pBmpModule->LoadImage(m_pBmpContext); - } - if (readRes == 1) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERROR; - } - } break; - case FXCODEC_IMAGE_TIF: { - ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - FX_BOOL ret = FALSE; - if (m_pDeviceBitmap->GetBPP() == 32 && - m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && - m_pDeviceBitmap->GetHeight() == m_SrcHeight && - m_SrcHeight == m_sizeY && m_startX == 0 && m_startY == 0 && - m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) { - ret = pTiffModule->Decode(m_pTiffContext, m_pDeviceBitmap); - m_pDeviceBitmap = NULL; - m_pFile = NULL; - if (!ret) { - return m_status = FXCODEC_STATUS_ERROR; - } - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } else { - CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; - pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); - if (pDIBitmap->GetBuffer() == NULL) { - delete pDIBitmap; - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - ret = pTiffModule->Decode(m_pTiffContext, pDIBitmap); - if (!ret) { - delete pDIBitmap; - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERROR; - } - CFX_DIBitmap* pClipBitmap = - (m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) - ? pDIBitmap - : pDIBitmap->Clone(&m_clipBox); - if (pDIBitmap != pClipBitmap) { - delete pDIBitmap; - } - if (pClipBitmap == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - CFX_DIBitmap* pFormatBitmap = NULL; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_8bppRgb); - break; - case FXDIB_8bppMask: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_8bppMask); - break; - case FXDIB_Rgb: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_Rgb); - break; - case FXDIB_Rgb32: - pFormatBitmap = new CFX_DIBitmap; - pFormatBitmap->Create(pClipBitmap->GetWidth(), - pClipBitmap->GetHeight(), FXDIB_Rgb32); - break; - case FXDIB_Argb: - pFormatBitmap = pClipBitmap; - break; - default:; - } - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - case FXDIB_8bppMask: { - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *des_line++ = FXRGB2GRAY(r, g, b); - src_line += 4; - } - } - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - int32_t desBpp = - (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *des_line++ = b; - *des_line++ = g; - *des_line++ = r; - des_line += desBpp - 3; - src_line += 4; - } - } - } break; - default:; - } - if (pClipBitmap != pFormatBitmap) { - delete pClipBitmap; - } - if (pFormatBitmap == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - CFX_DIBitmap* pStrechBitmap = pFormatBitmap->StretchTo( - m_sizeX, m_sizeY, m_bInterpol ? FXDIB_INTERPOL : FXDIB_DOWNSAMPLE); - delete pFormatBitmap; - pFormatBitmap = NULL; - if (pStrechBitmap == NULL) { - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_ERR_MEMORY; - } - m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, - pStrechBitmap, 0, 0); - delete pStrechBitmap; - pStrechBitmap = NULL; - m_pDeviceBitmap = NULL; - m_pFile = NULL; - return m_status = FXCODEC_STATUS_DECODE_FINISH; - } - } break; - default: - break; - } - return FXCODEC_STATUS_ERROR; -} -ICodec_ProgressiveDecoder* CCodec_ModuleMgr::CreateProgressiveDecoder() { - return new CCodec_ProgressiveDecoder(this); -} +// 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 "core/include/fxge/fx_dib.h" +#include "core/include/fxcodec/fx_codec.h" +#include "fx_codec_progress.h" +void CFXCODEC_WeightTable::Calc(int dest_len, + int dest_min, + int dest_max, + int src_len, + int src_min, + int src_max, + FX_BOOL bInterpol) { + if (m_pWeightTables) { + FX_Free(m_pWeightTables); + } + double scale, base; + scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); + if (dest_len < 0) { + base = (FX_FLOAT)(src_len); + } else { + base = 0.0f; + } + m_ItemSize = + (int)(sizeof(int) * 2 + + sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + 1)); + m_DestMin = dest_min; + m_pWeightTables = FX_Alloc(uint8_t, (dest_max - dest_min) * m_ItemSize + 4); + if (m_pWeightTables == NULL) { + return; + } + if (FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { + for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { + PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); + double src_pos = dest_pixel * scale + scale / 2 + base; + if (bInterpol) { + pixel_weights.m_SrcStart = + (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); + pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); + if (pixel_weights.m_SrcStart < src_min) { + pixel_weights.m_SrcStart = src_min; + } + if (pixel_weights.m_SrcEnd >= src_max) { + pixel_weights.m_SrcEnd = src_max - 1; + } + if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { + pixel_weights.m_Weights[0] = 65536; + } else { + pixel_weights.m_Weights[1] = FXSYS_round( + (FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * + 65536); + pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; + } + } else { + pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = + (int)FXSYS_floor((FX_FLOAT)src_pos); + pixel_weights.m_Weights[0] = 65536; + } + } + return; + } + for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) { + PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); + double src_start = dest_pixel * scale + base; + double src_end = src_start + scale; + int start_i, end_i; + if (src_start < src_end) { + start_i = (int)FXSYS_floor((FX_FLOAT)src_start); + end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); + } else { + start_i = (int)FXSYS_floor((FX_FLOAT)src_end); + end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); + } + if (start_i < src_min) { + start_i = src_min; + } + if (end_i >= src_max) { + end_i = src_max - 1; + } + if (start_i > end_i) { + pixel_weights.m_SrcStart = start_i; + pixel_weights.m_SrcEnd = start_i; + continue; + } + pixel_weights.m_SrcStart = start_i; + pixel_weights.m_SrcEnd = end_i; + for (int j = start_i; j <= end_i; j++) { + double dest_start = FXSYS_Div((FX_FLOAT)(j)-base, scale); + double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); + if (dest_start > dest_end) { + double temp = dest_start; + dest_start = dest_end; + dest_end = temp; + } + double area_start = dest_start > (FX_FLOAT)(dest_pixel) + ? dest_start + : (FX_FLOAT)(dest_pixel); + double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) + ? (FX_FLOAT)(dest_pixel + 1) + : dest_end; + double weight = area_start >= area_end ? 0.0f : area_end - area_start; + if (weight == 0 && j == end_i) { + pixel_weights.m_SrcEnd--; + break; + } + pixel_weights.m_Weights[j - start_i] = + FXSYS_round((FX_FLOAT)(weight * 65536)); + } + } +} +void CFXCODEC_HorzTable::Calc(int dest_len, int src_len, FX_BOOL bInterpol) { + if (m_pWeightTables) { + FX_Free(m_pWeightTables); + } + double scale = (double)dest_len / (double)src_len; + m_ItemSize = sizeof(int) * 4; + int size = dest_len * m_ItemSize + 4; + m_pWeightTables = FX_Alloc(uint8_t, size); + if (m_pWeightTables == NULL) { + return; + } + FXSYS_memset(m_pWeightTables, 0, size); + if (scale > 1) { + int pre_des_col = 0; + for (int src_col = 0; src_col < src_len; src_col++) { + double des_col_f = src_col * scale; + int des_col = FXSYS_round((FX_FLOAT)des_col_f); + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize); + pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + if (src_col == src_len - 1 && des_col < dest_len - 1) { + for (int des_col_index = pre_des_col + 1; des_col_index < dest_len; + des_col_index++) { + pWeight = + (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize); + pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + } + return; + } + int des_col_len = des_col - pre_des_col; + for (int des_col_index = pre_des_col + 1; des_col_index < des_col; + des_col_index++) { + pWeight = (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize); + pWeight->m_SrcStart = src_col - 1; + pWeight->m_SrcEnd = src_col; + pWeight->m_Weights[0] = + bInterpol ? FXSYS_round((FX_FLOAT)( + ((FX_FLOAT)des_col - (FX_FLOAT)des_col_index) / + (FX_FLOAT)des_col_len * 65536)) + : 65536; + pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; + } + pre_des_col = des_col; + } + return; + } + for (int des_col = 0; des_col < dest_len; des_col++) { + double src_col_f = des_col / scale; + int src_col = FXSYS_round((FX_FLOAT)src_col_f); + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize); + pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + } +} +void CFXCODEC_VertTable::Calc(int dest_len, int src_len) { + if (m_pWeightTables) { + FX_Free(m_pWeightTables); + } + double scale = (double)dest_len / (double)src_len; + m_ItemSize = sizeof(int) * 4; + int size = dest_len * m_ItemSize + 4; + m_pWeightTables = FX_Alloc(uint8_t, size); + if (m_pWeightTables == NULL) { + return; + } + FXSYS_memset(m_pWeightTables, 0, size); + if (scale > 1) { + double step = 0.0; + int src_row = 0; + while (step < (double)dest_len) { + int start_step = (int)step; + step = scale * (++src_row); + int end_step = (int)step; + if (end_step >= dest_len) { + end_step = dest_len; + for (int des_row = start_step; des_row < end_step; des_row++) { + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); + pWeight->m_SrcStart = start_step; + pWeight->m_SrcEnd = start_step; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + } + return; + } + int length = end_step - start_step; + { + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + start_step * m_ItemSize); + pWeight->m_SrcStart = start_step; + pWeight->m_SrcEnd = start_step; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + } + for (int des_row = start_step + 1; des_row < end_step; des_row++) { + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); + pWeight->m_SrcStart = start_step; + pWeight->m_SrcEnd = end_step; + pWeight->m_Weights[0] = FXSYS_round((FX_FLOAT)(end_step - des_row) / + (FX_FLOAT)length * 65536); + pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; + } + } + } else { + for (int des_row = 0; des_row < dest_len; des_row++) { + PixelWeight* pWeight = + (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize); + pWeight->m_SrcStart = des_row; + pWeight->m_SrcEnd = des_row; + pWeight->m_Weights[0] = 65536; + pWeight->m_Weights[1] = 0; + } + } +} +CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( + CCodec_ModuleMgr* pCodecMgr) { + m_pFile = NULL; + m_pJpegContext = NULL; + m_pPngContext = NULL; + m_pGifContext = NULL; + m_pBmpContext = NULL; + m_pTiffContext = NULL; + m_pCodecMgr = NULL; + m_pSrcBuf = NULL; + m_pDecodeBuf = NULL; + m_pDeviceBitmap = NULL; + m_pSrcPalette = NULL; + m_pCodecMgr = pCodecMgr; + m_offSet = 0; + m_SrcSize = 0; + m_ScanlineSize = 0; + m_SrcWidth = m_SrcHeight = 0; + m_SrcComponents = 0; + m_SrcBPC = 0; + m_SrcPassNumber = 0; + m_clipBox = FX_RECT(0, 0, 0, 0); + m_imagType = FXCODEC_IMAGE_UNKNOWN; + m_status = FXCODEC_STATUS_DECODE_FINISH; + m_TransMethod = -1; + m_SrcRow = 0; + m_SrcFormat = FXCodec_Invalid; + m_bInterpol = TRUE; + m_FrameNumber = 0; + m_FrameCur = 0; + m_SrcPaletteNumber = 0; + m_GifPltNumber = 0; + m_GifBgIndex = 0; + m_pGifPalette = NULL; + m_GifTransIndex = -1; + m_GifFrameRect = FX_RECT(0, 0, 0, 0); + m_BmpIsTopBottom = FALSE; +} +CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { + m_pFile = NULL; + if (m_pJpegContext != NULL) { + m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext); + } + if (m_pPngContext != NULL) { + m_pCodecMgr->GetPngModule()->Finish(m_pPngContext); + } + if (m_pGifContext != NULL) { + m_pCodecMgr->GetGifModule()->Finish(m_pGifContext); + } + if (m_pBmpContext != NULL) { + m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext); + } + if (m_pTiffContext != NULL) { + m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext); + } + if (m_pSrcBuf != NULL) { + FX_Free(m_pSrcBuf); + } + if (m_pDecodeBuf != NULL) { + FX_Free(m_pDecodeBuf); + } + if (m_pSrcPalette != NULL) { + FX_Free(m_pSrcPalette); + } +} +FX_BOOL CCodec_ProgressiveDecoder::JpegReadMoreData( + ICodec_JpegModule* pJpegModule, + FXCODEC_STATUS& err_status) { + FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); + if (dwSize <= m_offSet) { + return FALSE; + } + dwSize = dwSize - m_offSet; + FX_DWORD dwAvail = pJpegModule->GetAvailInput(m_pJpegContext, NULL); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + } else { + FX_DWORD dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += dwSize; + pJpegModule->Input(m_pJpegContext, m_pSrcBuf, dwSize + dwAvail); + return TRUE; +} +FX_BOOL CCodec_ProgressiveDecoder::PngReadHeaderFunc(void* pModule, + int width, + int height, + int bpc, + int pass, + int* color_type, + double* gamma) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + if (pCodec->m_pDeviceBitmap == NULL) { + pCodec->m_SrcWidth = width; + pCodec->m_SrcHeight = height; + pCodec->m_SrcBPC = bpc; + pCodec->m_SrcPassNumber = pass; + pCodec->m_SrcComponents = + *color_type == 0 ? 1 : *color_type == 2 + ? 3 + : *color_type == 3 + ? 4 + : *color_type == 4 + ? 2 + : *color_type == 6 ? 4 : 0; + pCodec->m_clipBox = FX_RECT(0, 0, width, height); + return FALSE; + } + FXDIB_Format format = pCodec->m_pDeviceBitmap->GetFormat(); + switch (format) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + ASSERT(FALSE); + return FALSE; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: + *color_type = 0; + break; + case FXDIB_Rgb: + *color_type = 2; + break; + case FXDIB_Rgb32: + case FXDIB_Argb: + *color_type = 6; + break; + default: + ASSERT(FALSE); + return FALSE; + } + *gamma = FXCODEC_PNG_GAMMA; + return TRUE; +} +FX_BOOL CCodec_ProgressiveDecoder::PngAskScanlineBufFunc(void* pModule, + int line, + uint8_t*& src_buf) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; + ASSERT(pDIBitmap != NULL); + if (pDIBitmap == NULL) { + return FALSE; + } + if (line >= pCodec->m_clipBox.top && line < pCodec->m_clipBox.bottom) { + double scale_y = + (double)pCodec->m_sizeY / (double)pCodec->m_clipBox.Height(); + int32_t row = + (int32_t)((line - pCodec->m_clipBox.top) * scale_y) + pCodec->m_startY; + uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row); + uint8_t* des_scan = pCodec->m_pDecodeBuf; + src_buf = pCodec->m_pDecodeBuf; + int32_t src_Bpp = pDIBitmap->GetBPP() >> 3; + int32_t des_Bpp = (pCodec->m_SrcFormat & 0xff) >> 3; + int32_t src_left = pCodec->m_startX; + int32_t des_left = pCodec->m_clipBox.left; + src_scan += src_left * src_Bpp; + des_scan += des_left * des_Bpp; + for (int32_t src_col = 0; src_col < pCodec->m_sizeX; src_col++) { + PixelWeight* pPixelWeights = + pCodec->m_WeightHorzOO.GetPixelWeight(src_col); + if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) { + continue; + } + switch (pDIBitmap->GetFormat()) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + ASSERT(FALSE); + return FALSE; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDIBitmap->GetPalette() != NULL) { + return FALSE; + } + FX_DWORD des_g = 0; + des_g += pPixelWeights->m_Weights[0] * src_scan[src_col]; + des_scan[pPixelWeights->m_SrcStart] = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + const uint8_t* p = src_scan + src_col * src_Bpp; + des_b += pPixelWeights->m_Weights[0] * (*p++); + des_g += pPixelWeights->m_Weights[0] * (*p++); + des_r += pPixelWeights->m_Weights[0] * (*p); + uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; + *pDes++ = (uint8_t)((des_b) >> 16); + *pDes++ = (uint8_t)((des_g) >> 16); + *pDes = (uint8_t)((des_r) >> 16); + } break; + case FXDIB_Argb: { + FX_DWORD des_r = 0, des_g = 0, des_b = 0; + const uint8_t* p = src_scan + src_col * src_Bpp; + des_b += pPixelWeights->m_Weights[0] * (*p++); + des_g += pPixelWeights->m_Weights[0] * (*p++); + des_r += pPixelWeights->m_Weights[0] * (*p++); + uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; + *pDes++ = (uint8_t)((des_b) >> 16); + *pDes++ = (uint8_t)((des_g) >> 16); + *pDes++ = (uint8_t)((des_r) >> 16); + *pDes = *p; + } break; + default: + return FALSE; + } + } + } + return TRUE; +} +void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( + CFX_DIBitmap* pDeviceBitmap, + int32_t des_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + uint8_t* des_scan = (uint8_t*)pDeviceBitmap->GetScanline(des_line); + int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; + int32_t des_Bpp = pDeviceBitmap->GetBPP() >> 3; + int32_t src_left = m_clipBox.left; + int32_t des_left = m_startX; + src_scan += src_left * src_Bpp; + des_scan += des_left * des_Bpp; + for (int32_t des_col = 0; des_col < m_sizeX; des_col++) { + PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(des_col); + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + ASSERT(FALSE); + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette() != NULL) { + return; + } + FX_DWORD des_g = 0; + des_g += + pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; + des_g += + pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; + *des_scan++ = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + des_b += pPixelWeights->m_Weights[0] * (*p++); + des_g += pPixelWeights->m_Weights[0] * (*p++); + des_r += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + des_b += pPixelWeights->m_Weights[1] * (*p++); + des_g += pPixelWeights->m_Weights[1] * (*p++); + des_r += pPixelWeights->m_Weights[1] * (*p); + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + des_scan += des_Bpp - 3; + } break; + case FXDIB_Argb: { + FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + des_b += pPixelWeights->m_Weights[0] * (*p++); + des_g += pPixelWeights->m_Weights[0] * (*p++); + des_r += pPixelWeights->m_Weights[0] * (*p++); + des_a += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + des_b += pPixelWeights->m_Weights[1] * (*p++); + des_g += pPixelWeights->m_Weights[1] * (*p++); + des_r += pPixelWeights->m_Weights[1] * (*p++); + des_a += pPixelWeights->m_Weights[1] * (*p); + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + *des_scan++ = (uint8_t)((des_a) >> 16); + } break; + default: + return; + } + } +} +void CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc(void* pModule, + int pass, + int line) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; + ASSERT(pDIBitmap != NULL); + int src_top = pCodec->m_clipBox.top; + int src_bottom = pCodec->m_clipBox.bottom; + int des_top = pCodec->m_startY; + int src_hei = pCodec->m_clipBox.Height(); + int des_hei = pCodec->m_sizeY; + if (line >= src_top && line < src_bottom) { + double scale_y = (double)des_hei / (double)src_hei; + int src_row = line - src_top; + int des_row = (int)(src_row * scale_y) + des_top; + if (des_row >= des_top + des_hei) { + return; + } + pCodec->PngOneOneMapResampleHorz(pDIBitmap, des_row, pCodec->m_pDecodeBuf, + pCodec->m_SrcFormat); + if (pCodec->m_SrcPassNumber == 1 && scale_y > 1.0) { + pCodec->ResampleVert(pDIBitmap, scale_y, des_row); + return; + } + if (pass == 6 && scale_y > 1.0) { + pCodec->ResampleVert(pDIBitmap, scale_y, des_row); + } + } +} +FX_BOOL CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, + FXCODEC_STATUS& err_status) { + FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); + if (dwSize <= m_offSet) { + return FALSE; + } + dwSize = dwSize - m_offSet; + FX_DWORD dwAvail = pGifModule->GetAvailInput(m_pGifContext, NULL); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + } else { + FX_DWORD dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += dwSize; + pGifModule->Input(m_pGifContext, m_pSrcBuf, dwSize + dwAvail); + return TRUE; +} +void CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback( + void* pModule, + FX_DWORD& cur_pos) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + FX_DWORD remain_size = + pCodec->m_pCodecMgr->GetGifModule()->GetAvailInput(pCodec->m_pGifContext); + cur_pos = pCodec->m_offSet - remain_size; +} +uint8_t* CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback( + void* pModule, + int32_t frame_num, + int32_t pal_size) { + return FX_Alloc(uint8_t, pal_size); +} +FX_BOOL CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback( + void* pModule, + FX_DWORD rcd_pos, + const FX_RECT& img_rc, + int32_t pal_num, + void* pal_ptr, + int32_t delay_time, + FX_BOOL user_input, + int32_t trans_index, + int32_t disposal_method, + FX_BOOL interlace) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + pCodec->m_offSet = rcd_pos; + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!pCodec->GifReadMoreData(pCodec->m_pCodecMgr->GetGifModule(), + error_status)) { + return FALSE; + } + uint8_t* pPalette = NULL; + if (pal_num != 0 && pal_ptr) { + pPalette = (uint8_t*)pal_ptr; + } else { + pal_num = pCodec->m_GifPltNumber; + pPalette = pCodec->m_pGifPalette; + } + if (pCodec->m_pSrcPalette == NULL) { + pCodec->m_pSrcPalette = FX_Alloc(FX_ARGB, pal_num); + } else if (pal_num > pCodec->m_SrcPaletteNumber) { + pCodec->m_pSrcPalette = FX_Realloc(FX_ARGB, pCodec->m_pSrcPalette, pal_num); + } + if (pCodec->m_pSrcPalette == NULL) { + return FALSE; + } + pCodec->m_SrcPaletteNumber = pal_num; + for (int i = 0; i < pal_num; i++) { + FX_DWORD j = i * 3; + pCodec->m_pSrcPalette[i] = + ArgbEncode(0xff, pPalette[j], pPalette[j + 1], pPalette[j + 2]); + } + pCodec->m_GifTransIndex = trans_index; + pCodec->m_GifFrameRect = img_rc; + pCodec->m_SrcPassNumber = interlace ? 4 : 1; + int32_t pal_index = pCodec->m_GifBgIndex; + CFX_DIBitmap* pDevice = pCodec->m_pDeviceBitmap; + if (trans_index >= pal_num) { + trans_index = -1; + } + if (trans_index != -1) { + pCodec->m_pSrcPalette[trans_index] &= 0x00ffffff; + if (pDevice->HasAlpha()) { + pal_index = trans_index; + } + } + int startX = pCodec->m_startX; + int startY = pCodec->m_startY; + int sizeX = pCodec->m_sizeX; + int sizeY = pCodec->m_sizeY; + int Bpp = pDevice->GetBPP() / 8; + FX_ARGB argb = pCodec->m_pSrcPalette[pal_index]; + for (int row = 0; row < sizeY; row++) { + uint8_t* pScanline = + (uint8_t*)pDevice->GetScanline(row + startY) + startX * Bpp; + switch (pCodec->m_TransMethod) { + case 3: { + uint8_t gray = + FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); + FXSYS_memset(pScanline, gray, sizeX); + break; + } + case 8: { + for (int col = 0; col < sizeX; col++) { + *pScanline++ = FXARGB_B(argb); + *pScanline++ = FXARGB_G(argb); + *pScanline++ = FXARGB_R(argb); + pScanline += Bpp - 3; + } + break; + } + case 12: { + for (int col = 0; col < sizeX; col++) { + FXARGB_SETDIB(pScanline, argb); + pScanline += 4; + } + break; + } + } + } + return TRUE; +} +void CCodec_ProgressiveDecoder::GifReadScanlineCallback(void* pModule, + int32_t row_num, + uint8_t* row_buf) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; + ASSERT(pDIBitmap != NULL); + int32_t img_width = pCodec->m_GifFrameRect.Width(); + if (!pDIBitmap->HasAlpha()) { + uint8_t* byte_ptr = row_buf; + for (int i = 0; i < img_width; i++) { + if (*byte_ptr == pCodec->m_GifTransIndex) { + *byte_ptr = pCodec->m_GifBgIndex; + } + byte_ptr++; + } + } + int32_t pal_index = pCodec->m_GifBgIndex; + if (pCodec->m_GifTransIndex != -1 && pCodec->m_pDeviceBitmap->HasAlpha()) { + pal_index = pCodec->m_GifTransIndex; + } + FXSYS_memset(pCodec->m_pDecodeBuf, pal_index, pCodec->m_SrcWidth); + FX_BOOL bLastPass = (row_num % 2) == 1; + int32_t line = row_num + pCodec->m_GifFrameRect.top; + int32_t left = pCodec->m_GifFrameRect.left; + FXSYS_memcpy(pCodec->m_pDecodeBuf + left, row_buf, img_width); + int src_top = pCodec->m_clipBox.top; + int src_bottom = pCodec->m_clipBox.bottom; + int des_top = pCodec->m_startY; + int src_hei = pCodec->m_clipBox.Height(); + int des_hei = pCodec->m_sizeY; + if (line >= src_top && line < src_bottom) { + double scale_y = (double)des_hei / (double)src_hei; + int src_row = line - src_top; + int des_row = (int)(src_row * scale_y) + des_top; + if (des_row >= des_top + des_hei) { + return; + } + pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, + pCodec->m_SrcFormat); + if (scale_y > 1.0 && + (!pCodec->m_bInterpol || pCodec->m_SrcPassNumber == 1)) { + pCodec->ResampleVert(pDIBitmap, scale_y, des_row); + return; + } + if (scale_y > 1.0) { + int des_bottom = des_top + pCodec->m_sizeY; + int des_Bpp = pDIBitmap->GetBPP() >> 3; + FX_DWORD des_ScanOffet = pCodec->m_startX * des_Bpp; + if (des_row + (int)scale_y >= des_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDIBitmap->GetScanline(des_row) + des_ScanOffet; + int cur_row = des_row; + while (++cur_row < des_bottom) { + uint8_t* scan_des = + (uint8_t*)pDIBitmap->GetScanline(cur_row) + des_ScanOffet; + FX_DWORD size = pCodec->m_sizeX * des_Bpp; + FXSYS_memcpy(scan_des, scan_src, size); + } + } + if (bLastPass) { + pCodec->GifDoubleLineResampleVert(pDIBitmap, scale_y, des_row); + } + } + } +} +void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( + CFX_DIBitmap* pDeviceBitmap, + double scale_y, + int des_row) { + int des_Bpp = pDeviceBitmap->GetBPP() >> 3; + FX_DWORD des_ScanOffet = m_startX * des_Bpp; + int des_top = m_startY; + int des_row_1 = des_row - int(2 * scale_y); + if (des_row_1 < des_top) { + des_row_1 = des_top; + } + for (; des_row_1 < des_row; des_row_1++) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + + des_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet; + for (int des_col = 0; des_col < m_sizeX; des_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette() != NULL) { + return; + } + int des_g = 0; + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += des_Bpp - 3; + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += des_Bpp - 3; + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + scan_des += des_Bpp - 3; + } break; + case FXDIB_Argb: { + FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + des_a += pWeight->m_Weights[0] * (*scan_src1++); + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + des_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + *scan_des++ = (uint8_t)((des_a) >> 16); + } break; + default: + return; + } + } + } + int des_bottom = des_top + m_sizeY - 1; + if (des_row + (int)(2 * scale_y) >= des_bottom && + des_row + (int)scale_y < des_bottom) { + GifDoubleLineResampleVert(pDeviceBitmap, scale_y, des_row + (int)scale_y); + } +} +FX_BOOL CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, + FXCODEC_STATUS& err_status) { + FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize(); + if (dwSize <= m_offSet) { + return FALSE; + } + dwSize = dwSize - m_offSet; + FX_DWORD dwAvail = pBmpModule->GetAvailInput(m_pBmpContext, NULL); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + } else { + FX_DWORD dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + FXSYS_memcpy(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += dwSize; + pBmpModule->Input(m_pBmpContext, m_pSrcBuf, dwSize + dwAvail); + return TRUE; +} +FX_BOOL CCodec_ProgressiveDecoder::BmpInputImagePositionBufCallback( + void* pModule, + FX_DWORD rcd_pos) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + pCodec->m_offSet = rcd_pos; + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!pCodec->BmpReadMoreData(pCodec->m_pCodecMgr->GetBmpModule(), + error_status)) { + return FALSE; + } + return TRUE; +} +void CCodec_ProgressiveDecoder::BmpReadScanlineCallback(void* pModule, + int32_t row_num, + uint8_t* row_buf) { + CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule; + CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap; + ASSERT(pDIBitmap != NULL); + FXSYS_memcpy(pCodec->m_pDecodeBuf, row_buf, pCodec->m_ScanlineSize); + int src_top = pCodec->m_clipBox.top; + int src_bottom = pCodec->m_clipBox.bottom; + int des_top = pCodec->m_startY; + int src_hei = pCodec->m_clipBox.Height(); + int des_hei = pCodec->m_sizeY; + if (row_num >= src_top && row_num < src_bottom) { + double scale_y = (double)des_hei / (double)src_hei; + int src_row = row_num - src_top; + int des_row = (int)(src_row * scale_y) + des_top; + if (des_row >= des_top + des_hei) { + return; + } + pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, + pCodec->m_SrcFormat); + if (scale_y > 1.0) { + if (pCodec->m_BmpIsTopBottom || !pCodec->m_bInterpol) { + pCodec->ResampleVert(pDIBitmap, scale_y, des_row); + return; + } else { + pCodec->ResampleVertBT(pDIBitmap, scale_y, des_row); + } + } + } +} +void CCodec_ProgressiveDecoder::ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, + double scale_y, + int des_row) { + int des_Bpp = pDeviceBitmap->GetBPP() >> 3; + FX_DWORD des_ScanOffet = m_startX * des_Bpp; + int des_top = m_startY; + int des_bottom = m_startY + m_sizeY; + int des_row_1 = des_row + int(scale_y); + if (des_row_1 >= des_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + while (++des_row < des_bottom) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + FX_DWORD size = m_sizeX * des_Bpp; + FXSYS_memcpy(scan_des, scan_src, size); + } + return; + } + for (; des_row_1 > des_row; des_row_1--) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + + des_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet; + for (int des_col = 0; des_col < m_sizeX; des_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette() != NULL) { + return; + } + int des_g = 0; + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += des_Bpp - 3; + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += des_Bpp - 3; + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + scan_des += des_Bpp - 3; + } break; + case FXDIB_Argb: { + FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + des_a += pWeight->m_Weights[0] * (*scan_src1++); + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + des_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + *scan_des++ = (uint8_t)((des_a) >> 16); + } break; + default: + return; + } + } + } +} +FX_BOOL CCodec_ProgressiveDecoder::DetectImageType( + FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute) { + m_offSet = 0; + FX_DWORD size = (FX_DWORD)m_pFile->GetSize(); + if (size > FXCODEC_BLOCK_SIZE) { + size = FXCODEC_BLOCK_SIZE; + } + if (m_pSrcBuf != NULL) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = NULL; + } + m_pSrcBuf = FX_Alloc(uint8_t, size); + if (m_pSrcBuf == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FXSYS_memset(m_pSrcBuf, 0, size); + m_SrcSize = size; + switch (imageType) { + case FXCODEC_IMAGE_BMP: { + ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (pBmpModule == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + pBmpModule->InputImagePositionBufCallback = + BmpInputImagePositionBufCallback; + pBmpModule->ReadScanlineCallback = BmpReadScanlineCallback; + m_pBmpContext = pBmpModule->Start((void*)this); + if (m_pBmpContext == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += size; + pBmpModule->Input(m_pBmpContext, m_pSrcBuf, size); + FX_DWORD* pPalette = NULL; + int32_t readResult = pBmpModule->ReadHeader( + m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, + &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!BmpReadMoreData(pBmpModule, error_status)) { + m_status = error_status; + return FALSE; + } + readResult = pBmpModule->ReadHeader( + m_pBmpContext, &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom, + &m_SrcComponents, &m_SrcPaletteNumber, &pPalette, pAttribute); + } + if (readResult == 1) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + if (m_pSrcPalette != NULL) { + FX_Free(m_pSrcPalette); + m_pSrcPalette = NULL; + } + if (m_SrcPaletteNumber) { + m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber); + if (m_pSrcPalette == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FXSYS_memcpy(m_pSrcPalette, pPalette, + m_SrcPaletteNumber * sizeof(FX_DWORD)); + } + return TRUE; + } + if (m_pBmpContext != NULL) { + pBmpModule->Finish(m_pBmpContext); + m_pBmpContext = NULL; + } + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } break; + case FXCODEC_IMAGE_JPG: { + ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + if (pJpegModule == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + m_pJpegContext = pJpegModule->Start(); + if (m_pJpegContext == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += size; + pJpegModule->Input(m_pJpegContext, m_pSrcBuf, size); + int32_t readResult = + pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_status = error_status; + return FALSE; + } + readResult = + pJpegModule->ReadHeader(m_pJpegContext, &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + } + if (!readResult) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return TRUE; + } + if (m_pJpegContext != NULL) { + pJpegModule->Finish(m_pJpegContext); + m_pJpegContext = NULL; + } + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } break; + case FXCODEC_IMAGE_PNG: { + ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (pPngModule == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + pPngModule->ReadHeaderCallback = + CCodec_ProgressiveDecoder::PngReadHeaderFunc; + pPngModule->AskScanlineBufCallback = + CCodec_ProgressiveDecoder::PngAskScanlineBufFunc; + pPngModule->FillScanlineBufCompletedCallback = + CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc; + m_pPngContext = pPngModule->Start((void*)this); + if (m_pPngContext == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += size; + bResult = pPngModule->Input(m_pPngContext, m_pSrcBuf, size, pAttribute); + while (bResult) { + FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet; + FX_DWORD input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + if (m_pPngContext != NULL) { + pPngModule->Finish(m_pPngContext); + } + m_pPngContext = NULL; + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } + if (m_pSrcBuf != NULL && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + if (m_pSrcBuf == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FXSYS_memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += input_size; + bResult = + pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, pAttribute); + } + ASSERT(!bResult); + if (m_pPngContext != NULL) { + pPngModule->Finish(m_pPngContext); + m_pPngContext = NULL; + } + if (m_SrcPassNumber == 0) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } + } break; + case FXCODEC_IMAGE_GIF: { + ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (pGifModule == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + pGifModule->RecordCurrentPositionCallback = + CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback; + pGifModule->AskLocalPaletteBufCallback = + CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback; + pGifModule->InputRecordPositionBufCallback = + CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback; + pGifModule->ReadScanlineCallback = + CCodec_ProgressiveDecoder::GifReadScanlineCallback; + m_pGifContext = pGifModule->Start((void*)this); + if (m_pGifContext == NULL) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return FALSE; + } + FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return FALSE; + } + m_offSet += size; + pGifModule->Input(m_pGifContext, m_pSrcBuf, size); + m_SrcComponents = 1; + int32_t readResult = pGifModule->ReadHeader( + m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, + (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!GifReadMoreData(pGifModule, error_status)) { + m_status = error_status; + return FALSE; + } + readResult = pGifModule->ReadHeader( + m_pGifContext, &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, + (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); + } + if (readResult == 1) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return TRUE; + } + if (m_pGifContext != NULL) { + pGifModule->Finish(m_pGifContext); + m_pGifContext = NULL; + } + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } break; + case FXCODEC_IMAGE_TIF: { + ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (pTiffModule == NULL) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } + m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); + if (m_pTiffContext == NULL) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } + int32_t frames = 0; + pTiffModule->GetFrames(m_pTiffContext, frames); + FX_DWORD bpc; + FX_BOOL ret = pTiffModule->LoadFrameInfo( + m_pTiffContext, 0, (FX_DWORD&)m_SrcWidth, (FX_DWORD&)m_SrcHeight, + (FX_DWORD&)m_SrcComponents, bpc, pAttribute); + m_SrcComponents = 4; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + if (!ret) { + pTiffModule->DestroyDecoder(m_pTiffContext); + (m_pTiffContext = NULL); + (m_status = FXCODEC_STATUS_ERR_FORMAT); + return FALSE; + } + } break; + default: + m_status = FXCODEC_STATUS_ERR_FORMAT; + return FALSE; + } + return TRUE; +} +FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( + IFX_FileRead* pFile, + FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute) { + switch (m_status) { + case FXCODEC_STATUS_FRAME_READY: + case FXCODEC_STATUS_FRAME_TOBECONTINUE: + case FXCODEC_STATUS_DECODE_READY: + case FXCODEC_STATUS_DECODE_TOBECONTINUE: + return FXCODEC_STATUS_ERROR; + default:; + } + if (pFile == NULL) { + m_status = FXCODEC_STATUS_ERR_PARAMS; + m_pFile = NULL; + return m_status; + } + m_pFile = pFile; + m_offSet = 0; + m_SrcWidth = m_SrcHeight = 0; + m_SrcComponents = m_SrcBPC = 0; + m_clipBox = FX_RECT(0, 0, 0, 0); + m_startX = m_startY = 0; + m_sizeX = m_sizeY = 0; + m_SrcPassNumber = 0; + if (imageType != FXCODEC_IMAGE_UNKNOWN && + DetectImageType(imageType, pAttribute)) { + m_imagType = imageType; + m_status = FXCODEC_STATUS_FRAME_READY; + return m_status; + } + for (int type = FXCODEC_IMAGE_BMP; type < FXCODEC_IMAGE_MAX; type++) { + if (DetectImageType((FXCODEC_IMAGE_TYPE)type, pAttribute)) { + m_imagType = (FXCODEC_IMAGE_TYPE)type; + m_status = FXCODEC_STATUS_FRAME_READY; + return m_status; + } + } + m_status = FXCODEC_STATUS_ERR_FORMAT; + m_pFile = NULL; + return m_status; +} +void CCodec_ProgressiveDecoder::SetClipBox(FX_RECT* clip) { + if (m_status != FXCODEC_STATUS_FRAME_READY) { + return; + } + if (clip->IsEmpty()) { + m_clipBox = FX_RECT(0, 0, 0, 0); + return; + } + if (clip->left < 0) { + clip->left = 0; + } + if (clip->right > m_SrcWidth) { + clip->right = m_SrcWidth; + } + if (clip->top < 0) { + clip->top = 0; + } + if (clip->bottom > m_SrcHeight) { + clip->bottom = m_SrcHeight; + } + if (clip->IsEmpty()) { + m_clipBox = FX_RECT(0, 0, 0, 0); + return; + } + m_clipBox = *clip; +} +void CCodec_ProgressiveDecoder::GetDownScale(int& down_scale) { + down_scale = 1; + int ratio_w = m_clipBox.Width() / m_sizeX; + int ratio_h = m_clipBox.Height() / m_sizeY; + int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w; + if (ratio >= 8) { + down_scale = 8; + } else if (ratio >= 4) { + down_scale = 4; + } else if (ratio >= 2) { + down_scale = 2; + } + m_clipBox.left /= down_scale; + m_clipBox.right /= down_scale; + m_clipBox.top /= down_scale; + m_clipBox.bottom /= down_scale; + if (m_clipBox.right == m_clipBox.left) { + m_clipBox.right = m_clipBox.left + 1; + } + if (m_clipBox.bottom == m_clipBox.top) { + m_clipBox.bottom = m_clipBox.top + 1; + } +} +void CCodec_ProgressiveDecoder::GetTransMethod(FXDIB_Format des_format, + FXCodec_Format src_format) { + switch (des_format) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: { + switch (src_format) { + case FXCodec_1bppGray: + m_TransMethod = 0; + break; + default: + m_TransMethod = -1; + } + } break; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + switch (src_format) { + case FXCodec_1bppGray: + m_TransMethod = 1; + break; + case FXCodec_8bppGray: + m_TransMethod = 2; + break; + case FXCodec_1bppRgb: + case FXCodec_8bppRgb: + m_TransMethod = 3; + break; + case FXCodec_Rgb: + case FXCodec_Rgb32: + case FXCodec_Argb: + m_TransMethod = 4; + break; + case FXCodec_Cmyk: + m_TransMethod = 5; + break; + default: + m_TransMethod = -1; + } + } break; + case FXDIB_Rgb: { + switch (src_format) { + case FXCodec_1bppGray: + m_TransMethod = 6; + break; + case FXCodec_8bppGray: + m_TransMethod = 7; + break; + case FXCodec_1bppRgb: + case FXCodec_8bppRgb: + m_TransMethod = 8; + break; + case FXCodec_Rgb: + case FXCodec_Rgb32: + case FXCodec_Argb: + m_TransMethod = 9; + break; + case FXCodec_Cmyk: + m_TransMethod = 10; + break; + default: + m_TransMethod = -1; + } + } break; + case FXDIB_Rgb32: + case FXDIB_Argb: { + switch (src_format) { + case FXCodec_1bppGray: + m_TransMethod = 6; + break; + case FXCodec_8bppGray: + m_TransMethod = 7; + break; + case FXCodec_1bppRgb: + case FXCodec_8bppRgb: + if (des_format == FXDIB_Argb) { + m_TransMethod = 12; + } else { + m_TransMethod = 8; + } + break; + case FXCodec_Rgb: + case FXCodec_Rgb32: + m_TransMethod = 9; + break; + case FXCodec_Cmyk: + m_TransMethod = 10; + break; + case FXCodec_Argb: + m_TransMethod = 11; + break; + default: + m_TransMethod = -1; + } + } break; + default: + m_TransMethod = -1; + } +} +void _RGB2BGR(uint8_t* buffer, int width = 1) { + if (buffer && width > 0) { + uint8_t temp; + int i = 0; + int j = 0; + for (; i < width; i++, j += 3) { + temp = buffer[j]; + buffer[j] = buffer[j + 2]; + buffer[j + 2] = temp; + } + } +} +void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, + int des_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + int src_left = m_clipBox.left; + int des_left = m_startX; + uint8_t* des_scan = + pDeviceBitmap->GetBuffer() + des_line * pDeviceBitmap->GetPitch(); + int src_bpp = src_format & 0xff; + int des_bpp = pDeviceBitmap->GetBPP(); + int src_Bpp = src_bpp >> 3; + int des_Bpp = des_bpp >> 3; + src_scan += src_left * src_Bpp; + des_scan += des_left * des_Bpp; + for (int des_col = 0; des_col < m_sizeX; des_col++) { + PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(des_col); + switch (m_TransMethod) { + case -1: + return; + case 0: + return; + case 1: + return; + case 2: { + FX_DWORD des_g = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + des_g += pixel_weight * src_scan[j]; + } + *des_scan++ = (uint8_t)(des_g >> 16); + } break; + case 3: { + int des_r = 0, des_g = 0, des_b = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + unsigned long argb = m_pSrcPalette[src_scan[j]]; + des_r += pixel_weight * (uint8_t)(argb >> 16); + des_g += pixel_weight * (uint8_t)(argb >> 8); + des_b += pixel_weight * (uint8_t)argb; + } + *des_scan++ = + (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); + } break; + case 4: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + const uint8_t* src_pixel = src_scan + j * src_Bpp; + des_b += pixel_weight * (*src_pixel++); + des_g += pixel_weight * (*src_pixel++); + des_r += pixel_weight * (*src_pixel); + } + *des_scan++ = + (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); + } break; + case 5: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + const uint8_t* src_pixel = src_scan + j * src_Bpp; + uint8_t src_b = 0, src_g = 0, src_r = 0; + AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], + 255 - src_pixel[2], 255 - src_pixel[3], src_r, + src_g, src_b); + des_b += pixel_weight * src_b; + des_g += pixel_weight * src_g; + des_r += pixel_weight * src_r; + } + *des_scan++ = + (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); + } break; + case 6: + return; + case 7: { + FX_DWORD des_g = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + des_g += pixel_weight * src_scan[j]; + } + FXSYS_memset(des_scan, (uint8_t)(des_g >> 16), 3); + des_scan += des_Bpp; + } break; + case 8: { + int des_r = 0, des_g = 0, des_b = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + unsigned long argb = m_pSrcPalette[src_scan[j]]; + des_r += pixel_weight * (uint8_t)(argb >> 16); + des_g += pixel_weight * (uint8_t)(argb >> 8); + des_b += pixel_weight * (uint8_t)argb; + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + des_scan += des_Bpp - 3; + } break; + case 12: { + if (m_pBmpContext) { + int des_r = 0, des_g = 0, des_b = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + unsigned long argb = m_pSrcPalette[src_scan[j]]; + des_r += pixel_weight * (uint8_t)(argb >> 16); + des_g += pixel_weight * (uint8_t)(argb >> 8); + des_b += pixel_weight * (uint8_t)argb; + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + *des_scan++ = 0xFF; + } else { + int des_a = 0, des_r = 0, des_g = 0, des_b = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + unsigned long argb = m_pSrcPalette[src_scan[j]]; + des_a += pixel_weight * (uint8_t)(argb >> 24); + des_r += pixel_weight * (uint8_t)(argb >> 16); + des_g += pixel_weight * (uint8_t)(argb >> 8); + des_b += pixel_weight * (uint8_t)argb; + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + *des_scan++ = (uint8_t)((des_a) >> 16); + } + } break; + case 9: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + const uint8_t* src_pixel = src_scan + j * src_Bpp; + des_b += pixel_weight * (*src_pixel++); + des_g += pixel_weight * (*src_pixel++); + des_r += pixel_weight * (*src_pixel); + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + des_scan += des_Bpp - 3; + } break; + case 10: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + const uint8_t* src_pixel = src_scan + j * src_Bpp; + uint8_t src_b = 0, src_g = 0, src_r = 0; + AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1], + 255 - src_pixel[2], 255 - src_pixel[3], src_r, + src_g, src_b); + des_b += pixel_weight * src_b; + des_g += pixel_weight * src_g; + des_r += pixel_weight * src_r; + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + des_scan += des_Bpp - 3; + } break; + case 11: { + FX_DWORD des_alpha = 0, des_r = 0, des_g = 0, des_b = 0; + for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd; + j++) { + int pixel_weight = + pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart]; + const uint8_t* src_pixel = src_scan + j * src_Bpp; + pixel_weight = pixel_weight * src_pixel[3] / 255; + des_b += pixel_weight * (*src_pixel++); + des_g += pixel_weight * (*src_pixel++); + des_r += pixel_weight * (*src_pixel); + des_alpha += pixel_weight; + } + *des_scan++ = (uint8_t)((des_b) >> 16); + *des_scan++ = (uint8_t)((des_g) >> 16); + *des_scan++ = (uint8_t)((des_r) >> 16); + *des_scan++ = (uint8_t)((des_alpha * 255) >> 16); + } break; + default: + return; + } + } +} +void CCodec_ProgressiveDecoder::ResampleVert(CFX_DIBitmap* pDeviceBitmap, + double scale_y, + int des_row) { + int des_Bpp = pDeviceBitmap->GetBPP() >> 3; + FX_DWORD des_ScanOffet = m_startX * des_Bpp; + if (m_bInterpol) { + int des_top = m_startY; + int des_row_1 = des_row - int(scale_y); + if (des_row_1 < des_top) { + int des_bottom = des_top + m_sizeY; + if (des_row + (int)scale_y >= des_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + while (++des_row < des_bottom) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + FX_DWORD size = m_sizeX * des_Bpp; + FXSYS_memcpy(scan_des, scan_src, size); + } + } + return; + } + for (; des_row_1 < des_row; des_row_1++) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + + des_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + + des_ScanOffet; + for (int des_col = 0; des_col < m_sizeX; des_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette() != NULL) { + return; + } + int des_g = 0; + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(des_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + FX_DWORD des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += des_Bpp - 3; + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += des_Bpp - 3; + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + scan_des += des_Bpp - 3; + } break; + case FXDIB_Argb: { + FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0; + des_b += pWeight->m_Weights[0] * (*scan_src1++); + des_g += pWeight->m_Weights[0] * (*scan_src1++); + des_r += pWeight->m_Weights[0] * (*scan_src1++); + des_a += pWeight->m_Weights[0] * (*scan_src1++); + des_b += pWeight->m_Weights[1] * (*scan_src2++); + des_g += pWeight->m_Weights[1] * (*scan_src2++); + des_r += pWeight->m_Weights[1] * (*scan_src2++); + des_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((des_b) >> 16); + *scan_des++ = (uint8_t)((des_g) >> 16); + *scan_des++ = (uint8_t)((des_r) >> 16); + *scan_des++ = (uint8_t)((des_a) >> 16); + } break; + default: + return; + } + } + } + int des_bottom = des_top + m_sizeY; + if (des_row + (int)scale_y >= des_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + while (++des_row < des_bottom) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + FX_DWORD size = m_sizeX * des_Bpp; + FXSYS_memcpy(scan_des, scan_src, size); + } + } + return; + } + int multiple = (int)FXSYS_ceil((FX_FLOAT)scale_y - 1); + if (multiple > 0) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; + for (int i = 1; i <= multiple; i++) { + if (des_row + i >= m_startY + m_sizeY) { + return; + } + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet; + FX_DWORD size = m_sizeX * des_Bpp; + FXSYS_memcpy(scan_des, scan_src, size); + } + } +} +void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, + int32_t src_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + int src_top = m_clipBox.top; + int des_top = m_startY; + int src_hei = m_clipBox.Height(); + int des_hei = m_sizeY; + if (src_line >= src_top) { + double scale_y = (double)des_hei / (double)src_hei; + int src_row = src_line - src_top; + int des_row = (int)(src_row * scale_y) + des_top; + if (des_row >= des_top + des_hei) { + return; + } + ReSampleScanline(pDeviceBitmap, des_row, m_pDecodeBuf, src_format); + if (scale_y > 1.0) { + ResampleVert(pDeviceBitmap, scale_y, des_row); + } + } +} +FXCODEC_STATUS CCodec_ProgressiveDecoder::GetFrames(int32_t& frames, + IFX_Pause* pPause) { + if (!(m_status == FXCODEC_STATUS_FRAME_READY || + m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { + return FXCODEC_STATUS_ERROR; + } + switch (m_imagType) { + case FXCODEC_IMAGE_BMP: + case FXCODEC_IMAGE_JPG: + case FXCODEC_IMAGE_PNG: + case FXCODEC_IMAGE_TIF: + frames = m_FrameNumber = 1; + return m_status = FXCODEC_STATUS_DECODE_READY; + case FXCODEC_IMAGE_GIF: { + ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + while (TRUE) { + int32_t readResult = + pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; + if (!GifReadMoreData(pGifModule, error_status)) { + return error_status; + } + if (pPause && pPause->NeedToPauseNow()) { + return m_status = FXCODEC_STATUS_FRAME_TOBECONTINUE; + } + readResult = pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber); + } + if (readResult == 1) { + frames = m_FrameNumber; + return m_status = FXCODEC_STATUS_DECODE_READY; + } + if (m_pGifContext != NULL) { + pGifModule->Finish(m_pGifContext); + m_pGifContext = NULL; + } + return m_status = FXCODEC_STATUS_ERROR; + } + } break; + default:; + } + return FXCODEC_STATUS_ERROR; +} +FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(CFX_DIBitmap* pDIBitmap, + int start_x, + int start_y, + int size_x, + int size_y, + int32_t frames, + FX_BOOL bInterpol) { + if (m_status != FXCODEC_STATUS_DECODE_READY) { + return FXCODEC_STATUS_ERROR; + } + if (pDIBitmap == NULL || pDIBitmap->GetBPP() < 8 || frames < 0 || + frames >= m_FrameNumber) { + return FXCODEC_STATUS_ERR_PARAMS; + } + m_pDeviceBitmap = pDIBitmap; + if (m_clipBox.IsEmpty()) { + return FXCODEC_STATUS_ERR_PARAMS; + } + if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535) { + return FXCODEC_STATUS_ERR_PARAMS; + } + FX_RECT device_rc = + FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y); + int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth(); + int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight(); + device_rc.Intersect( + FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight())); + if (device_rc.IsEmpty()) { + return FXCODEC_STATUS_ERR_PARAMS; + } + m_startX = device_rc.left; + m_startY = device_rc.top; + m_sizeX = device_rc.Width(); + m_sizeY = device_rc.Height(); + m_bInterpol = bInterpol; + m_FrameCur = 0; + if (start_x < 0 || out_range_x > 0) { + FX_FLOAT scaleX = (FX_FLOAT)m_clipBox.Width() / (FX_FLOAT)size_x; + if (start_x < 0) { + m_clipBox.left -= (int32_t)FXSYS_ceil((FX_FLOAT)start_x * scaleX); + } + if (out_range_x > 0) { + m_clipBox.right -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_x * scaleX); + } + } + if (start_y < 0 || out_range_y > 0) { + FX_FLOAT scaleY = (FX_FLOAT)m_clipBox.Height() / (FX_FLOAT)size_y; + if (start_y < 0) { + m_clipBox.top -= (int32_t)FXSYS_ceil((FX_FLOAT)start_y * scaleY); + } + if (out_range_y > 0) { + m_clipBox.bottom -= (int32_t)FXSYS_floor((FX_FLOAT)out_range_y * scaleY); + } + } + if (m_clipBox.IsEmpty()) { + return FXCODEC_STATUS_ERR_PARAMS; + } + switch (m_imagType) { + case FXCODEC_IMAGE_JPG: { + ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + int down_scale = 1; + GetDownScale(down_scale); + FX_BOOL bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); + while (!bStart) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = error_status; + } + bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); + } + int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; + scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; + if (m_pDecodeBuf != NULL) { + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = NULL; + } + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + if (m_pDecodeBuf == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + FXSYS_memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width(), m_bInterpol); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppGray; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Cmyk; + break; + } + GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } break; + case FXCODEC_IMAGE_PNG: { + ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (pPngModule == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + if (m_pPngContext != NULL) { + pPngModule->Finish(m_pPngContext); + m_pPngContext = NULL; + } + m_pPngContext = pPngModule->Start((void*)this); + if (m_pPngContext == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + m_offSet = 0; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppMask: + case FXDIB_8bppRgb: + m_SrcComponents = 1; + m_SrcFormat = FXCodec_8bppGray; + break; + case FXDIB_Rgb: + m_SrcComponents = 3; + m_SrcFormat = FXCodec_Rgb; + break; + case FXDIB_Rgb32: + case FXDIB_Argb: + m_SrcComponents = 4; + m_SrcFormat = FXCodec_Argb; + break; + default: { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_PARAMS; + } + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + if (m_pDecodeBuf != NULL) { + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = NULL; + } + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + if (m_pDecodeBuf == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + FXSYS_memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width(), m_bInterpol); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } break; + case FXCODEC_IMAGE_GIF: { + ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (pGifModule == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + m_SrcFormat = FXCodec_8bppRgb; + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth + 3) / 4 * 4; + if (m_pDecodeBuf != NULL) { + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = NULL; + } + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + if (m_pDecodeBuf == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + FXSYS_memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width(), m_bInterpol); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_FrameCur = frames; + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } break; + case FXCODEC_IMAGE_BMP: { + ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (pBmpModule == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppRgb; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Rgb32; + break; + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + if (m_pDecodeBuf != NULL) { + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = NULL; + } + m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); + if (m_pDecodeBuf == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + FXSYS_memset(m_pDecodeBuf, 0, m_ScanlineSize); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width(), m_bInterpol); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } break; + case FXCODEC_IMAGE_TIF: + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + default: + break; + } + return FXCODEC_STATUS_ERROR; +} +FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode(IFX_Pause* pPause) { + if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) { + return FXCODEC_STATUS_ERROR; + } + switch (m_imagType) { + case FXCODEC_IMAGE_JPG: { + ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + while (TRUE) { + FX_BOOL readRes = + pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); + while (!readRes) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = error_status; + } + readRes = pJpegModule->ReadScanline(m_pJpegContext, m_pDecodeBuf); + } + if (m_SrcFormat == FXCodec_Rgb) { + int src_Bpp = (m_SrcFormat & 0xff) >> 3; + _RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); + } + if (m_SrcRow >= m_clipBox.bottom) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } + Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); + m_SrcRow++; + if (pPause && pPause->NeedToPauseNow()) { + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } + } + } break; + case FXCODEC_IMAGE_PNG: { + ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + while (TRUE) { + FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet; + FX_DWORD input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + if (m_pPngContext != NULL) { + pPngModule->Finish(m_pPngContext); + } + m_pPngContext = NULL; + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } + if (m_pSrcBuf != NULL && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + if (m_pSrcBuf == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + FXSYS_memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_READ; + } + m_offSet += input_size; + bResult = + pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, nullptr); + if (!bResult) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERROR; + } + if (pPause && pPause->NeedToPauseNow()) { + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } + } + } break; + case FXCODEC_IMAGE_GIF: { + ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + while (TRUE) { + int32_t readRes = + pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); + while (readRes == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = error_status; + } + if (pPause && pPause->NeedToPauseNow()) { + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } + readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur, nullptr); + } + if (readRes == 1) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERROR; + } + } break; + case FXCODEC_IMAGE_BMP: { + ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + while (TRUE) { + int32_t readRes = pBmpModule->LoadImage(m_pBmpContext); + while (readRes == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!BmpReadMoreData(pBmpModule, error_status)) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = error_status; + } + if (pPause && pPause->NeedToPauseNow()) { + return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + } + readRes = pBmpModule->LoadImage(m_pBmpContext); + } + if (readRes == 1) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERROR; + } + } break; + case FXCODEC_IMAGE_TIF: { + ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + FX_BOOL ret = FALSE; + if (m_pDeviceBitmap->GetBPP() == 32 && + m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && + m_pDeviceBitmap->GetHeight() == m_SrcHeight && + m_SrcHeight == m_sizeY && m_startX == 0 && m_startY == 0 && + m_clipBox.left == 0 && m_clipBox.top == 0 && + m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) { + ret = pTiffModule->Decode(m_pTiffContext, m_pDeviceBitmap); + m_pDeviceBitmap = NULL; + m_pFile = NULL; + if (!ret) { + return m_status = FXCODEC_STATUS_ERROR; + } + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } else { + CFX_DIBitmap* pDIBitmap = new CFX_DIBitmap; + pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); + if (pDIBitmap->GetBuffer() == NULL) { + delete pDIBitmap; + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + ret = pTiffModule->Decode(m_pTiffContext, pDIBitmap); + if (!ret) { + delete pDIBitmap; + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERROR; + } + CFX_DIBitmap* pClipBitmap = + (m_clipBox.left == 0 && m_clipBox.top == 0 && + m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) + ? pDIBitmap + : pDIBitmap->Clone(&m_clipBox); + if (pDIBitmap != pClipBitmap) { + delete pDIBitmap; + } + if (pClipBitmap == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + CFX_DIBitmap* pFormatBitmap = NULL; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + pFormatBitmap = new CFX_DIBitmap; + pFormatBitmap->Create(pClipBitmap->GetWidth(), + pClipBitmap->GetHeight(), FXDIB_8bppRgb); + break; + case FXDIB_8bppMask: + pFormatBitmap = new CFX_DIBitmap; + pFormatBitmap->Create(pClipBitmap->GetWidth(), + pClipBitmap->GetHeight(), FXDIB_8bppMask); + break; + case FXDIB_Rgb: + pFormatBitmap = new CFX_DIBitmap; + pFormatBitmap->Create(pClipBitmap->GetWidth(), + pClipBitmap->GetHeight(), FXDIB_Rgb); + break; + case FXDIB_Rgb32: + pFormatBitmap = new CFX_DIBitmap; + pFormatBitmap->Create(pClipBitmap->GetWidth(), + pClipBitmap->GetHeight(), FXDIB_Rgb32); + break; + case FXDIB_Argb: + pFormatBitmap = pClipBitmap; + break; + default:; + } + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + case FXDIB_8bppMask: { + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *des_line++ = FXRGB2GRAY(r, g, b); + src_line += 4; + } + } + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + int32_t desBpp = + (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *des_line++ = b; + *des_line++ = g; + *des_line++ = r; + des_line += desBpp - 3; + src_line += 4; + } + } + } break; + default:; + } + if (pClipBitmap != pFormatBitmap) { + delete pClipBitmap; + } + if (pFormatBitmap == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + CFX_DIBitmap* pStrechBitmap = pFormatBitmap->StretchTo( + m_sizeX, m_sizeY, m_bInterpol ? FXDIB_INTERPOL : FXDIB_DOWNSAMPLE); + delete pFormatBitmap; + pFormatBitmap = NULL; + if (pStrechBitmap == NULL) { + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_ERR_MEMORY; + } + m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, + pStrechBitmap, 0, 0); + delete pStrechBitmap; + pStrechBitmap = NULL; + m_pDeviceBitmap = NULL; + m_pFile = NULL; + return m_status = FXCODEC_STATUS_DECODE_FINISH; + } + } break; + default: + break; + } + return FXCODEC_STATUS_ERROR; +} +ICodec_ProgressiveDecoder* CCodec_ModuleMgr::CreateProgressiveDecoder() { + return new CCodec_ProgressiveDecoder(this); +} diff --git a/core/src/fxcodec/codec/fx_codec_progress.h b/core/src/fxcodec/codec/fx_codec_progress.h index cee8b39c50..2da92c9b01 100644 --- a/core/src/fxcodec/codec/fx_codec_progress.h +++ b/core/src/fxcodec/codec/fx_codec_progress.h @@ -1,223 +1,223 @@ -// 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_CODEC_PROGRESS_H_ -#define _FX_CODEC_PROGRESS_H_ -#define FXCODEC_BLOCK_SIZE 4096 -#define FXCODEC_PNG_GAMMA 2.2 -#if _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ -#undef FXCODEC_PNG_GAMMA -#define FXCODEC_PNG_GAMMA 1.7 -#endif -struct PixelWeight { - int m_SrcStart; - int m_SrcEnd; - int m_Weights[1]; -}; -class CFXCODEC_WeightTable { - public: - CFXCODEC_WeightTable() { m_pWeightTables = NULL; } - ~CFXCODEC_WeightTable() { - if (m_pWeightTables != NULL) { - FX_Free(m_pWeightTables); - } - } - - void Calc(int dest_len, - int dest_min, - int dest_max, - int src_len, - int src_min, - int src_max, - FX_BOOL bInterpol); - PixelWeight* GetPixelWeight(int pixel) { - return (PixelWeight*)(m_pWeightTables + (pixel - m_DestMin) * m_ItemSize); - } - - int m_DestMin, m_ItemSize; - uint8_t* m_pWeightTables; -}; -class CFXCODEC_HorzTable { - public: - CFXCODEC_HorzTable() { m_pWeightTables = NULL; } - ~CFXCODEC_HorzTable() { - if (m_pWeightTables != NULL) { - FX_Free(m_pWeightTables); - } - } - - void Calc(int dest_len, int src_len, FX_BOOL bInterpol); - PixelWeight* GetPixelWeight(int pixel) { - return (PixelWeight*)(m_pWeightTables + pixel * m_ItemSize); - } - - int m_ItemSize; - uint8_t* m_pWeightTables; -}; -class CFXCODEC_VertTable { - public: - CFXCODEC_VertTable() { m_pWeightTables = NULL; } - ~CFXCODEC_VertTable() { - if (m_pWeightTables != NULL) { - FX_Free(m_pWeightTables); - } - } - void Calc(int dest_len, int src_len); - PixelWeight* GetPixelWeight(int pixel) { - return (PixelWeight*)(m_pWeightTables + pixel * m_ItemSize); - } - int m_ItemSize; - uint8_t* m_pWeightTables; -}; -enum FXCodec_Format { - FXCodec_Invalid = 0, - FXCodec_1bppGray = 0x101, - FXCodec_1bppRgb = 0x001, - FXCodec_8bppGray = 0x108, - FXCodec_8bppRgb = 0x008, - FXCodec_Rgb = 0x018, - FXCodec_Rgb32 = 0x020, - FXCodec_Argb = 0x220, - FXCodec_Cmyk = 0x120 -}; -class CCodec_ProgressiveDecoder : public ICodec_ProgressiveDecoder { - public: - CCodec_ProgressiveDecoder(CCodec_ModuleMgr* pCodecMgr); - ~CCodec_ProgressiveDecoder() override; - - FXCODEC_STATUS LoadImageInfo(IFX_FileRead* pFile, - FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute) override; - - FXCODEC_IMAGE_TYPE GetType() const override { return m_imagType; } - int32_t GetWidth() const override { return m_SrcWidth; } - int32_t GetHeight() const override { return m_SrcHeight; } - int32_t GetNumComponents() const override { return m_SrcComponents; } - int32_t GetBPC() const override { return m_SrcBPC; } - void SetClipBox(FX_RECT* clip) override; - - FXCODEC_STATUS GetFrames(int32_t& frames, IFX_Pause* pPause) override; - FXCODEC_STATUS StartDecode(CFX_DIBitmap* pDIBitmap, - int start_x, - int start_y, - int size_x, - int size_y, - int32_t frames, - FX_BOOL bInterpol) override; - - FXCODEC_STATUS ContinueDecode(IFX_Pause* pPause) override; - - protected: - static FX_BOOL PngReadHeaderFunc(void* pModule, - int width, - int height, - int bpc, - int pass, - int* color_type, - double* gamma); - static FX_BOOL PngAskScanlineBufFunc(void* pModule, - int line, - uint8_t*& src_buf); - static void PngFillScanlineBufCompletedFunc(void* pModule, - int pass, - int line); - static void GifRecordCurrentPositionCallback(void* pModule, - FX_DWORD& cur_pos); - static uint8_t* GifAskLocalPaletteBufCallback(void* pModule, - int32_t frame_num, - int32_t pal_size); - static FX_BOOL GifInputRecordPositionBufCallback(void* pModule, - FX_DWORD rcd_pos, - const FX_RECT& img_rc, - int32_t pal_num, - void* pal_ptr, - int32_t delay_time, - FX_BOOL user_input, - int32_t trans_index, - int32_t disposal_method, - FX_BOOL interlace); - static void GifReadScanlineCallback(void* pModule, - int32_t row_num, - uint8_t* row_buf); - static FX_BOOL BmpInputImagePositionBufCallback(void* pModule, - FX_DWORD rcd_pos); - static void BmpReadScanlineCallback(void* pModule, - int32_t row_num, - uint8_t* row_buf); - - FX_BOOL DetectImageType(FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute); - void GetDownScale(int& down_scale); - void GetTransMethod(FXDIB_Format des_format, FXCodec_Format src_format); - void ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, - int32_t des_line, - uint8_t* src_scan, - FXCodec_Format src_format); - void Resample(CFX_DIBitmap* pDeviceBitmap, - int32_t src_line, - uint8_t* src_scan, - FXCodec_Format src_format); - void ResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); - FX_BOOL JpegReadMoreData(ICodec_JpegModule* pJpegModule, - FXCODEC_STATUS& err_status); - void PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, - int32_t des_line, - uint8_t* src_scan, - FXCodec_Format src_format); - FX_BOOL GifReadMoreData(ICodec_GifModule* pGifModule, - FXCODEC_STATUS& err_status); - void GifDoubleLineResampleVert(CFX_DIBitmap* pDeviceBitmap, - double scale_y, - int des_row); - FX_BOOL BmpReadMoreData(ICodec_BmpModule* pBmpModule, - FXCODEC_STATUS& err_status); - void ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); - - public: - IFX_FileRead* m_pFile; - CCodec_ModuleMgr* m_pCodecMgr; - void* m_pJpegContext; - void* m_pPngContext; - void* m_pGifContext; - void* m_pBmpContext; - void* m_pTiffContext; - FXCODEC_IMAGE_TYPE m_imagType; - FX_DWORD m_offSet; - uint8_t* m_pSrcBuf; - FX_DWORD m_SrcSize; - uint8_t* m_pDecodeBuf; - int m_ScanlineSize; - CFX_DIBitmap* m_pDeviceBitmap; - FX_BOOL m_bInterpol; - CFXCODEC_WeightTable m_WeightHorz; - CFXCODEC_VertTable m_WeightVert; - CFXCODEC_HorzTable m_WeightHorzOO; - int m_SrcWidth; - int m_SrcHeight; - int m_SrcComponents; - int m_SrcBPC; - FX_RECT m_clipBox; - int m_startX; - int m_startY; - int m_sizeX; - int m_sizeY; - int m_TransMethod; - FX_ARGB* m_pSrcPalette; - int m_SrcPaletteNumber; - int m_SrcRow; - FXCodec_Format m_SrcFormat; - int m_SrcPassNumber; - int m_FrameNumber; - int m_FrameCur; - int m_GifBgIndex; - uint8_t* m_pGifPalette; - int32_t m_GifPltNumber; - int m_GifTransIndex; - FX_RECT m_GifFrameRect; - FX_BOOL m_BmpIsTopBottom; - FXCODEC_STATUS m_status; -}; -#endif +// 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_CODEC_PROGRESS_H_ +#define _FX_CODEC_PROGRESS_H_ +#define FXCODEC_BLOCK_SIZE 4096 +#define FXCODEC_PNG_GAMMA 2.2 +#if _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ +#undef FXCODEC_PNG_GAMMA +#define FXCODEC_PNG_GAMMA 1.7 +#endif +struct PixelWeight { + int m_SrcStart; + int m_SrcEnd; + int m_Weights[1]; +}; +class CFXCODEC_WeightTable { + public: + CFXCODEC_WeightTable() { m_pWeightTables = NULL; } + ~CFXCODEC_WeightTable() { + if (m_pWeightTables != NULL) { + FX_Free(m_pWeightTables); + } + } + + void Calc(int dest_len, + int dest_min, + int dest_max, + int src_len, + int src_min, + int src_max, + FX_BOOL bInterpol); + PixelWeight* GetPixelWeight(int pixel) { + return (PixelWeight*)(m_pWeightTables + (pixel - m_DestMin) * m_ItemSize); + } + + int m_DestMin, m_ItemSize; + uint8_t* m_pWeightTables; +}; +class CFXCODEC_HorzTable { + public: + CFXCODEC_HorzTable() { m_pWeightTables = NULL; } + ~CFXCODEC_HorzTable() { + if (m_pWeightTables != NULL) { + FX_Free(m_pWeightTables); + } + } + + void Calc(int dest_len, int src_len, FX_BOOL bInterpol); + PixelWeight* GetPixelWeight(int pixel) { + return (PixelWeight*)(m_pWeightTables + pixel * m_ItemSize); + } + + int m_ItemSize; + uint8_t* m_pWeightTables; +}; +class CFXCODEC_VertTable { + public: + CFXCODEC_VertTable() { m_pWeightTables = NULL; } + ~CFXCODEC_VertTable() { + if (m_pWeightTables != NULL) { + FX_Free(m_pWeightTables); + } + } + void Calc(int dest_len, int src_len); + PixelWeight* GetPixelWeight(int pixel) { + return (PixelWeight*)(m_pWeightTables + pixel * m_ItemSize); + } + int m_ItemSize; + uint8_t* m_pWeightTables; +}; +enum FXCodec_Format { + FXCodec_Invalid = 0, + FXCodec_1bppGray = 0x101, + FXCodec_1bppRgb = 0x001, + FXCodec_8bppGray = 0x108, + FXCodec_8bppRgb = 0x008, + FXCodec_Rgb = 0x018, + FXCodec_Rgb32 = 0x020, + FXCodec_Argb = 0x220, + FXCodec_Cmyk = 0x120 +}; +class CCodec_ProgressiveDecoder : public ICodec_ProgressiveDecoder { + public: + CCodec_ProgressiveDecoder(CCodec_ModuleMgr* pCodecMgr); + ~CCodec_ProgressiveDecoder() override; + + FXCODEC_STATUS LoadImageInfo(IFX_FileRead* pFile, + FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute) override; + + FXCODEC_IMAGE_TYPE GetType() const override { return m_imagType; } + int32_t GetWidth() const override { return m_SrcWidth; } + int32_t GetHeight() const override { return m_SrcHeight; } + int32_t GetNumComponents() const override { return m_SrcComponents; } + int32_t GetBPC() const override { return m_SrcBPC; } + void SetClipBox(FX_RECT* clip) override; + + FXCODEC_STATUS GetFrames(int32_t& frames, IFX_Pause* pPause) override; + FXCODEC_STATUS StartDecode(CFX_DIBitmap* pDIBitmap, + int start_x, + int start_y, + int size_x, + int size_y, + int32_t frames, + FX_BOOL bInterpol) override; + + FXCODEC_STATUS ContinueDecode(IFX_Pause* pPause) override; + + protected: + static FX_BOOL PngReadHeaderFunc(void* pModule, + int width, + int height, + int bpc, + int pass, + int* color_type, + double* gamma); + static FX_BOOL PngAskScanlineBufFunc(void* pModule, + int line, + uint8_t*& src_buf); + static void PngFillScanlineBufCompletedFunc(void* pModule, + int pass, + int line); + static void GifRecordCurrentPositionCallback(void* pModule, + FX_DWORD& cur_pos); + static uint8_t* GifAskLocalPaletteBufCallback(void* pModule, + int32_t frame_num, + int32_t pal_size); + static FX_BOOL GifInputRecordPositionBufCallback(void* pModule, + FX_DWORD rcd_pos, + const FX_RECT& img_rc, + int32_t pal_num, + void* pal_ptr, + int32_t delay_time, + FX_BOOL user_input, + int32_t trans_index, + int32_t disposal_method, + FX_BOOL interlace); + static void GifReadScanlineCallback(void* pModule, + int32_t row_num, + uint8_t* row_buf); + static FX_BOOL BmpInputImagePositionBufCallback(void* pModule, + FX_DWORD rcd_pos); + static void BmpReadScanlineCallback(void* pModule, + int32_t row_num, + uint8_t* row_buf); + + FX_BOOL DetectImageType(FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute); + void GetDownScale(int& down_scale); + void GetTransMethod(FXDIB_Format des_format, FXCodec_Format src_format); + void ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, + int32_t des_line, + uint8_t* src_scan, + FXCodec_Format src_format); + void Resample(CFX_DIBitmap* pDeviceBitmap, + int32_t src_line, + uint8_t* src_scan, + FXCodec_Format src_format); + void ResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); + FX_BOOL JpegReadMoreData(ICodec_JpegModule* pJpegModule, + FXCODEC_STATUS& err_status); + void PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, + int32_t des_line, + uint8_t* src_scan, + FXCodec_Format src_format); + FX_BOOL GifReadMoreData(ICodec_GifModule* pGifModule, + FXCODEC_STATUS& err_status); + void GifDoubleLineResampleVert(CFX_DIBitmap* pDeviceBitmap, + double scale_y, + int des_row); + FX_BOOL BmpReadMoreData(ICodec_BmpModule* pBmpModule, + FXCODEC_STATUS& err_status); + void ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row); + + public: + IFX_FileRead* m_pFile; + CCodec_ModuleMgr* m_pCodecMgr; + void* m_pJpegContext; + void* m_pPngContext; + void* m_pGifContext; + void* m_pBmpContext; + void* m_pTiffContext; + FXCODEC_IMAGE_TYPE m_imagType; + FX_DWORD m_offSet; + uint8_t* m_pSrcBuf; + FX_DWORD m_SrcSize; + uint8_t* m_pDecodeBuf; + int m_ScanlineSize; + CFX_DIBitmap* m_pDeviceBitmap; + FX_BOOL m_bInterpol; + CFXCODEC_WeightTable m_WeightHorz; + CFXCODEC_VertTable m_WeightVert; + CFXCODEC_HorzTable m_WeightHorzOO; + int m_SrcWidth; + int m_SrcHeight; + int m_SrcComponents; + int m_SrcBPC; + FX_RECT m_clipBox; + int m_startX; + int m_startY; + int m_sizeX; + int m_sizeY; + int m_TransMethod; + FX_ARGB* m_pSrcPalette; + int m_SrcPaletteNumber; + int m_SrcRow; + FXCodec_Format m_SrcFormat; + int m_SrcPassNumber; + int m_FrameNumber; + int m_FrameCur; + int m_GifBgIndex; + uint8_t* m_pGifPalette; + int32_t m_GifPltNumber; + int m_GifTransIndex; + FX_RECT m_GifFrameRect; + FX_BOOL m_BmpIsTopBottom; + FXCODEC_STATUS m_status; +}; +#endif diff --git a/core/src/fxcodec/codec/fx_codec_tiff.cpp b/core/src/fxcodec/codec/fx_codec_tiff.cpp index d158c0009a..cfdc5feb97 100644 --- a/core/src/fxcodec/codec/fx_codec_tiff.cpp +++ b/core/src/fxcodec/codec/fx_codec_tiff.cpp @@ -1,544 +1,544 @@ -// 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 "core/include/fxcodec/fx_codec.h" -#include "core/include/fxge/fx_dib.h" -#include "codec_int.h" - -extern "C" { -#include "third_party/libtiff/tiffiop.h" -} - -void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, - unsigned int dwProfileSize, - int nComponents, - int intent, - FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT); -void IccLib_TranslateImage(void* pTransform, - unsigned char* pDest, - const unsigned char* pSrc, - int pixels); -void IccLib_DestroyTransform(void* pTransform); -class CCodec_TiffContext { - public: - CCodec_TiffContext(); - ~CCodec_TiffContext(); - - FX_BOOL InitDecoder(IFX_FileRead* file_ptr); - void GetFrames(int32_t& frames); - FX_BOOL LoadFrameInfo(int32_t frame, - FX_DWORD& width, - FX_DWORD& height, - FX_DWORD& comps, - FX_DWORD& bpc, - CFX_DIBAttribute* pAttribute); - FX_BOOL Decode(CFX_DIBitmap* pDIBitmap); - - union { - IFX_FileRead* in; - IFX_FileStream* out; - } io; - - FX_DWORD offset; - - TIFF* tif_ctx; - void* icc_ctx; - int32_t frame_num; - int32_t frame_cur; - FX_BOOL isDecoder; - - private: - FX_BOOL isSupport(CFX_DIBitmap* pDIBitmap); - void SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps); - FX_BOOL Decode1bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp); - FX_BOOL Decode8bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp); - FX_BOOL Decode24bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp); -}; -CCodec_TiffContext::CCodec_TiffContext() { - offset = 0; - frame_num = 0; - frame_cur = 0; - io.in = NULL; - tif_ctx = NULL; - icc_ctx = NULL; - isDecoder = TRUE; -} -CCodec_TiffContext::~CCodec_TiffContext() { - if (icc_ctx) { - IccLib_DestroyTransform(icc_ctx); - icc_ctx = NULL; - } - if (tif_ctx) { - TIFFClose(tif_ctx); - } -} -static tsize_t _tiff_read(thandle_t context, tdata_t buf, tsize_t length) { - CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; - FX_BOOL ret = FALSE; - if (pTiffContext->isDecoder) { - ret = pTiffContext->io.in->ReadBlock(buf, pTiffContext->offset, length); - } else { - ret = pTiffContext->io.out->ReadBlock(buf, pTiffContext->offset, length); - } - if (!ret) { - return 0; - } - pTiffContext->offset += (FX_DWORD)length; - return length; -} -static tsize_t _tiff_write(thandle_t context, tdata_t buf, tsize_t length) { - CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; - ASSERT(!pTiffContext->isDecoder); - if (!pTiffContext->io.out->WriteBlock(buf, pTiffContext->offset, length)) { - return 0; - } - pTiffContext->offset += (FX_DWORD)length; - return length; -} -static toff_t _tiff_seek(thandle_t context, toff_t offset, int whence) { - CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; - switch (whence) { - case 0: - pTiffContext->offset = (FX_DWORD)offset; - break; - case 1: - pTiffContext->offset += (FX_DWORD)offset; - break; - case 2: - if (pTiffContext->isDecoder) { - if (pTiffContext->io.in->GetSize() < (FX_FILESIZE)offset) { - return -1; - } - pTiffContext->offset = - (FX_DWORD)(pTiffContext->io.in->GetSize() - offset); - } else { - if (pTiffContext->io.out->GetSize() < (FX_FILESIZE)offset) { - return -1; - } - pTiffContext->offset = - (FX_DWORD)(pTiffContext->io.out->GetSize() - offset); - } - break; - default: - return -1; - } - ASSERT(pTiffContext->isDecoder ? (pTiffContext->offset <= - (FX_DWORD)pTiffContext->io.in->GetSize()) - : TRUE); - return pTiffContext->offset; -} -static int _tiff_close(thandle_t context) { - return 0; -} -static toff_t _tiff_get_size(thandle_t context) { - CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; - return pTiffContext->isDecoder ? (toff_t)pTiffContext->io.in->GetSize() - : (toff_t)pTiffContext->io.out->GetSize(); -} -static int _tiff_map(thandle_t context, tdata_t*, toff_t*) { - return 0; -} -static void _tiff_unmap(thandle_t context, tdata_t, toff_t) {} -TIFF* _tiff_open(void* context, const char* mode) { - TIFF* tif = TIFFClientOpen("Tiff Image", mode, (thandle_t)context, _tiff_read, - _tiff_write, _tiff_seek, _tiff_close, - _tiff_get_size, _tiff_map, _tiff_unmap); - if (tif) { - tif->tif_fd = (int)(intptr_t)context; - } - return tif; -} -void* _TIFFmalloc(tmsize_t size) { - return FXMEM_DefaultAlloc(size, 0); -} -void _TIFFfree(void* ptr) { - FXMEM_DefaultFree(ptr, 0); -} -void* _TIFFrealloc(void* ptr, tmsize_t size) { - return FXMEM_DefaultRealloc(ptr, size, 0); -} -void _TIFFmemset(void* ptr, int val, tmsize_t size) { - FXSYS_memset(ptr, val, (size_t)size); -} -void _TIFFmemcpy(void* des, const void* src, tmsize_t size) { - FXSYS_memcpy(des, src, (size_t)size); -} -int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size) { - return FXSYS_memcmp(ptr1, ptr2, (size_t)size); -} - -TIFFErrorHandler _TIFFwarningHandler = nullptr; -TIFFErrorHandler _TIFFerrorHandler = nullptr; - -int TIFFCmyk2Rgb(thandle_t context, - uint8 c, - uint8 m, - uint8 y, - uint8 k, - uint8* r, - uint8* g, - uint8* b) { - if (context == NULL) { - return 0; - } - CCodec_TiffContext* p = (CCodec_TiffContext*)context; - if (p->icc_ctx) { - unsigned char cmyk[4], bgr[3]; - cmyk[0] = c, cmyk[1] = m, cmyk[2] = y, cmyk[3] = k; - IccLib_TranslateImage(p->icc_ctx, bgr, cmyk, 1); - *r = bgr[2], *g = bgr[1], *b = bgr[0]; - } else { - AdobeCMYK_to_sRGB1(c, m, y, k, *r, *g, *b); - } - return 1; -} -FX_BOOL CCodec_TiffContext::InitDecoder(IFX_FileRead* file_ptr) { - io.in = file_ptr; - tif_ctx = _tiff_open(this, "r"); - if (tif_ctx == NULL) { - return FALSE; - } - return TRUE; -} -void CCodec_TiffContext::GetFrames(int32_t& frames) { - frames = frame_num = TIFFNumberOfDirectories(tif_ctx); -} -#define TIFF_EXIF_GETINFO(key, T, tag) \ - { \ - T val = (T)0; \ - TIFFGetField(tif_ctx, tag, &val); \ - if (val) { \ - (key) = FX_Alloc(uint8_t, sizeof(T)); \ - if ((key)) { \ - T* ptr = (T*)(key); \ - *ptr = val; \ - pExif->m_TagVal.SetAt(tag, (key)); \ - } \ - } \ - } \ - (key) = NULL; -#define TIFF_EXIF_GETSTRINGINFO(key, tag) \ - { \ - FX_DWORD size = 0; \ - uint8_t* buf = NULL; \ - TIFFGetField(tif_ctx, tag, &size, &buf); \ - if (size && buf) { \ - (key) = FX_Alloc(uint8_t, size); \ - if ((key)) { \ - FXSYS_memcpy((key), buf, size); \ - pExif->m_TagVal.SetAt(tag, (key)); \ - } \ - } \ - } \ - (key) = NULL; - -namespace { - -template -FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) { - T val = 0; - TIFFGetField(tif_ctx, tag, &val); - if (!val) - return FALSE; - T* ptr = FX_Alloc(T, 1); - *ptr = val; - pAttr->m_Exif[tag] = (void*)ptr; - return TRUE; -} -void Tiff_Exif_GetStringInfo(TIFF* tif_ctx, - ttag_t tag, - CFX_DIBAttribute* pAttr) { - FX_CHAR* buf = nullptr; - TIFFGetField(tif_ctx, tag, &buf); - if (!buf) - return; - FX_STRSIZE size = FXSYS_strlen(buf); - uint8_t* ptr = FX_Alloc(uint8_t, size + 1); - FXSYS_memcpy(ptr, buf, size); - ptr[size] = 0; - pAttr->m_Exif[tag] = ptr; -} - -} // namespace - -FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame, - FX_DWORD& width, - FX_DWORD& height, - FX_DWORD& comps, - FX_DWORD& bpc, - CFX_DIBAttribute* pAttribute) { - if (!TIFFSetDirectory(tif_ctx, (uint16)frame)) { - return FALSE; - } - FX_WORD tif_cs; - FX_DWORD tif_icc_size = 0; - uint8_t* tif_icc_buf = NULL; - FX_WORD tif_bpc = 0; - FX_WORD tif_cps; - FX_DWORD tif_rps; - width = height = comps = 0; - TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); - TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &comps); - TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &tif_bpc); - TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &tif_cs); - TIFFGetField(tif_ctx, TIFFTAG_COMPRESSION, &tif_cps); - TIFFGetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, &tif_rps); - TIFFGetField(tif_ctx, TIFFTAG_ICCPROFILE, &tif_icc_size, &tif_icc_buf); - if (pAttribute) { - pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_INCH; - if (TIFFGetField(tif_ctx, TIFFTAG_RESOLUTIONUNIT, - &pAttribute->m_wDPIUnit)) { - pAttribute->m_wDPIUnit -= 1; - } - Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_ORIENTATION, pAttribute); - if (Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_XRESOLUTION, pAttribute)) { - void* val = pAttribute->m_Exif[TIFFTAG_XRESOLUTION]; - FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; - pAttribute->m_nXDPI = (int32_t)(fDpi + 0.5f); - } - if (Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_YRESOLUTION, pAttribute)) { - void* val = pAttribute->m_Exif[TIFFTAG_YRESOLUTION]; - FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; - pAttribute->m_nYDPI = (int32_t)(fDpi + 0.5f); - } - Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pAttribute); - Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pAttribute); - Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pAttribute); - } - bpc = tif_bpc; - if (tif_rps > height) { - TIFFSetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, tif_rps = height); - } - return TRUE; -} -void _TiffBGRA2RGBA(uint8_t* pBuf, int32_t pixel, int32_t spp) { - for (int32_t n = 0; n < pixel; n++) { - uint8_t tmp = pBuf[0]; - pBuf[0] = pBuf[2]; - pBuf[2] = tmp; - pBuf += spp; - } -} -FX_BOOL CCodec_TiffContext::isSupport(CFX_DIBitmap* pDIBitmap) { - if (TIFFIsTiled(tif_ctx)) { - return FALSE; - } - uint16_t photometric; - if (!TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &photometric)) { - return FALSE; - } - switch (pDIBitmap->GetBPP()) { - case 1: - case 8: - if (photometric != PHOTOMETRIC_PALETTE) { - return FALSE; - } - break; - case 24: - if (photometric != PHOTOMETRIC_RGB) { - return FALSE; - } - break; - default: - return FALSE; - } - uint16_t planarconfig; - if (!TIFFGetFieldDefaulted(tif_ctx, TIFFTAG_PLANARCONFIG, &planarconfig)) { - return FALSE; - } - if (planarconfig == PLANARCONFIG_SEPARATE) { - return FALSE; - } - return TRUE; -} -void CCodec_TiffContext::SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps) { - uint16_t *red_orig, *green_orig, *blue_orig; - TIFFGetField(tif_ctx, TIFFTAG_COLORMAP, &red_orig, &green_orig, &blue_orig); - for (int32_t i = (1L << bps) - 1; i >= 0; i--) { -#define CVT(x) ((uint16_t)((x) >> 8)) - red_orig[i] = CVT(red_orig[i]); - green_orig[i] = CVT(green_orig[i]); - blue_orig[i] = CVT(blue_orig[i]); -#undef CVT - } - int32_t len = 1 << bps; - for (int32_t index = 0; index < len; index++) { - FX_DWORD r = red_orig[index] & 0xFF; - FX_DWORD g = green_orig[index] & 0xFF; - FX_DWORD b = blue_orig[index] & 0xFF; - FX_DWORD color = (uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16) | - (((uint32)0xffL) << 24); - pDIBitmap->SetPaletteEntry(index, color); - } -} -FX_BOOL CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { - if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 || - !isSupport(pDIBitmap)) { - return FALSE; - } - SetPalette(pDIBitmap, bps); - int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); - uint8_t* buf = (uint8_t*)_TIFFmalloc(size); - if (buf == NULL) { - TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); - return FALSE; - } - uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); - FX_DWORD pitch = pDIBitmap->GetPitch(); - for (int32_t row = 0; row < height; row++) { - TIFFReadScanline(tif_ctx, buf, row, 0); - for (int32_t j = 0; j < size; j++) { - bitMapbuffer[row * pitch + j] = buf[j]; - } - } - _TIFFfree(buf); - return TRUE; -} -FX_BOOL CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { - if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) || - !isSupport(pDIBitmap)) { - return FALSE; - } - SetPalette(pDIBitmap, bps); - int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); - uint8_t* buf = (uint8_t*)_TIFFmalloc(size); - if (buf == NULL) { - TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); - return FALSE; - } - uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); - FX_DWORD pitch = pDIBitmap->GetPitch(); - for (int32_t row = 0; row < height; row++) { - TIFFReadScanline(tif_ctx, buf, row, 0); - for (int32_t j = 0; j < size; j++) { - switch (bps) { - case 4: - bitMapbuffer[row * pitch + 2 * j + 0] = (buf[j] & 0xF0) >> 4; - bitMapbuffer[row * pitch + 2 * j + 1] = (buf[j] & 0x0F) >> 0; - break; - case 8: - bitMapbuffer[row * pitch + j] = buf[j]; - break; - } - } - } - _TIFFfree(buf); - return TRUE; -} -FX_BOOL CCodec_TiffContext::Decode24bppRGB(CFX_DIBitmap* pDIBitmap, - int32_t height, - int32_t width, - uint16_t bps, - uint16_t spp) { - if (pDIBitmap->GetBPP() != 24 || !isSupport(pDIBitmap)) { - return FALSE; - } - int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); - uint8_t* buf = (uint8_t*)_TIFFmalloc(size); - if (buf == NULL) { - TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); - return FALSE; - } - uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); - FX_DWORD pitch = pDIBitmap->GetPitch(); - for (int32_t row = 0; row < height; row++) { - TIFFReadScanline(tif_ctx, buf, row, 0); - for (int32_t j = 0; j < size - 2; j += 3) { - bitMapbuffer[row * pitch + j + 0] = buf[j + 2]; - bitMapbuffer[row * pitch + j + 1] = buf[j + 1]; - bitMapbuffer[row * pitch + j + 2] = buf[j + 0]; - } - } - _TIFFfree(buf); - return TRUE; -} -FX_BOOL CCodec_TiffContext::Decode(CFX_DIBitmap* pDIBitmap) { - FX_DWORD img_wid = pDIBitmap->GetWidth(); - FX_DWORD img_hei = pDIBitmap->GetHeight(); - FX_DWORD width = 0; - FX_DWORD height = 0; - TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); - TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); - if (img_wid != width || img_hei != height) { - return FALSE; - } - if (pDIBitmap->GetBPP() == 32) { - FX_WORD rotation = ORIENTATION_TOPLEFT; - TIFFGetField(tif_ctx, TIFFTAG_ORIENTATION, &rotation); - if (TIFFReadRGBAImageOriented(tif_ctx, img_wid, img_hei, - (uint32*)pDIBitmap->GetBuffer(), rotation, - 1)) { - for (FX_DWORD row = 0; row < img_hei; row++) { - uint8_t* row_buf = (uint8_t*)pDIBitmap->GetScanline(row); - _TiffBGRA2RGBA(row_buf, img_wid, 4); - } - return TRUE; - } - } - uint16_t spp, bps; - TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &spp); - TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &bps); - FX_DWORD bpp = bps * spp; - if (bpp == 1) { - return Decode1bppRGB(pDIBitmap, height, width, bps, spp); - } else if (bpp <= 8) { - return Decode8bppRGB(pDIBitmap, height, width, bps, spp); - } else if (bpp <= 24) { - return Decode24bppRGB(pDIBitmap, height, width, bps, spp); - } - return FALSE; -} -void* CCodec_TiffModule::CreateDecoder(IFX_FileRead* file_ptr) { - CCodec_TiffContext* pDecoder = new CCodec_TiffContext; - if (!pDecoder->InitDecoder(file_ptr)) { - delete pDecoder; - return NULL; - } - return pDecoder; -} -void CCodec_TiffModule::GetFrames(void* ctx, int32_t& frames) { - CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; - pDecoder->GetFrames(frames); -} -FX_BOOL CCodec_TiffModule::LoadFrameInfo(void* ctx, - int32_t frame, - FX_DWORD& width, - FX_DWORD& height, - FX_DWORD& comps, - FX_DWORD& bpc, - CFX_DIBAttribute* pAttribute) { - CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; - return pDecoder->LoadFrameInfo(frame, width, height, comps, bpc, pAttribute); -} -FX_BOOL CCodec_TiffModule::Decode(void* ctx, class CFX_DIBitmap* pDIBitmap) { - CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; - return pDecoder->Decode(pDIBitmap); -} -void CCodec_TiffModule::DestroyDecoder(void* ctx) { - CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; - delete pDecoder; -} +// 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 "core/include/fxcodec/fx_codec.h" +#include "core/include/fxge/fx_dib.h" +#include "codec_int.h" + +extern "C" { +#include "third_party/libtiff/tiffiop.h" +} + +void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, + unsigned int dwProfileSize, + int nComponents, + int intent, + FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT); +void IccLib_TranslateImage(void* pTransform, + unsigned char* pDest, + const unsigned char* pSrc, + int pixels); +void IccLib_DestroyTransform(void* pTransform); +class CCodec_TiffContext { + public: + CCodec_TiffContext(); + ~CCodec_TiffContext(); + + FX_BOOL InitDecoder(IFX_FileRead* file_ptr); + void GetFrames(int32_t& frames); + FX_BOOL LoadFrameInfo(int32_t frame, + FX_DWORD& width, + FX_DWORD& height, + FX_DWORD& comps, + FX_DWORD& bpc, + CFX_DIBAttribute* pAttribute); + FX_BOOL Decode(CFX_DIBitmap* pDIBitmap); + + union { + IFX_FileRead* in; + IFX_FileStream* out; + } io; + + FX_DWORD offset; + + TIFF* tif_ctx; + void* icc_ctx; + int32_t frame_num; + int32_t frame_cur; + FX_BOOL isDecoder; + + private: + FX_BOOL isSupport(CFX_DIBitmap* pDIBitmap); + void SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps); + FX_BOOL Decode1bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp); + FX_BOOL Decode8bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp); + FX_BOOL Decode24bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp); +}; +CCodec_TiffContext::CCodec_TiffContext() { + offset = 0; + frame_num = 0; + frame_cur = 0; + io.in = NULL; + tif_ctx = NULL; + icc_ctx = NULL; + isDecoder = TRUE; +} +CCodec_TiffContext::~CCodec_TiffContext() { + if (icc_ctx) { + IccLib_DestroyTransform(icc_ctx); + icc_ctx = NULL; + } + if (tif_ctx) { + TIFFClose(tif_ctx); + } +} +static tsize_t _tiff_read(thandle_t context, tdata_t buf, tsize_t length) { + CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; + FX_BOOL ret = FALSE; + if (pTiffContext->isDecoder) { + ret = pTiffContext->io.in->ReadBlock(buf, pTiffContext->offset, length); + } else { + ret = pTiffContext->io.out->ReadBlock(buf, pTiffContext->offset, length); + } + if (!ret) { + return 0; + } + pTiffContext->offset += (FX_DWORD)length; + return length; +} +static tsize_t _tiff_write(thandle_t context, tdata_t buf, tsize_t length) { + CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; + ASSERT(!pTiffContext->isDecoder); + if (!pTiffContext->io.out->WriteBlock(buf, pTiffContext->offset, length)) { + return 0; + } + pTiffContext->offset += (FX_DWORD)length; + return length; +} +static toff_t _tiff_seek(thandle_t context, toff_t offset, int whence) { + CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; + switch (whence) { + case 0: + pTiffContext->offset = (FX_DWORD)offset; + break; + case 1: + pTiffContext->offset += (FX_DWORD)offset; + break; + case 2: + if (pTiffContext->isDecoder) { + if (pTiffContext->io.in->GetSize() < (FX_FILESIZE)offset) { + return -1; + } + pTiffContext->offset = + (FX_DWORD)(pTiffContext->io.in->GetSize() - offset); + } else { + if (pTiffContext->io.out->GetSize() < (FX_FILESIZE)offset) { + return -1; + } + pTiffContext->offset = + (FX_DWORD)(pTiffContext->io.out->GetSize() - offset); + } + break; + default: + return -1; + } + ASSERT(pTiffContext->isDecoder ? (pTiffContext->offset <= + (FX_DWORD)pTiffContext->io.in->GetSize()) + : TRUE); + return pTiffContext->offset; +} +static int _tiff_close(thandle_t context) { + return 0; +} +static toff_t _tiff_get_size(thandle_t context) { + CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; + return pTiffContext->isDecoder ? (toff_t)pTiffContext->io.in->GetSize() + : (toff_t)pTiffContext->io.out->GetSize(); +} +static int _tiff_map(thandle_t context, tdata_t*, toff_t*) { + return 0; +} +static void _tiff_unmap(thandle_t context, tdata_t, toff_t) {} +TIFF* _tiff_open(void* context, const char* mode) { + TIFF* tif = TIFFClientOpen("Tiff Image", mode, (thandle_t)context, _tiff_read, + _tiff_write, _tiff_seek, _tiff_close, + _tiff_get_size, _tiff_map, _tiff_unmap); + if (tif) { + tif->tif_fd = (int)(intptr_t)context; + } + return tif; +} +void* _TIFFmalloc(tmsize_t size) { + return FXMEM_DefaultAlloc(size, 0); +} +void _TIFFfree(void* ptr) { + FXMEM_DefaultFree(ptr, 0); +} +void* _TIFFrealloc(void* ptr, tmsize_t size) { + return FXMEM_DefaultRealloc(ptr, size, 0); +} +void _TIFFmemset(void* ptr, int val, tmsize_t size) { + FXSYS_memset(ptr, val, (size_t)size); +} +void _TIFFmemcpy(void* des, const void* src, tmsize_t size) { + FXSYS_memcpy(des, src, (size_t)size); +} +int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size) { + return FXSYS_memcmp(ptr1, ptr2, (size_t)size); +} + +TIFFErrorHandler _TIFFwarningHandler = nullptr; +TIFFErrorHandler _TIFFerrorHandler = nullptr; + +int TIFFCmyk2Rgb(thandle_t context, + uint8 c, + uint8 m, + uint8 y, + uint8 k, + uint8* r, + uint8* g, + uint8* b) { + if (context == NULL) { + return 0; + } + CCodec_TiffContext* p = (CCodec_TiffContext*)context; + if (p->icc_ctx) { + unsigned char cmyk[4], bgr[3]; + cmyk[0] = c, cmyk[1] = m, cmyk[2] = y, cmyk[3] = k; + IccLib_TranslateImage(p->icc_ctx, bgr, cmyk, 1); + *r = bgr[2], *g = bgr[1], *b = bgr[0]; + } else { + AdobeCMYK_to_sRGB1(c, m, y, k, *r, *g, *b); + } + return 1; +} +FX_BOOL CCodec_TiffContext::InitDecoder(IFX_FileRead* file_ptr) { + io.in = file_ptr; + tif_ctx = _tiff_open(this, "r"); + if (tif_ctx == NULL) { + return FALSE; + } + return TRUE; +} +void CCodec_TiffContext::GetFrames(int32_t& frames) { + frames = frame_num = TIFFNumberOfDirectories(tif_ctx); +} +#define TIFF_EXIF_GETINFO(key, T, tag) \ + { \ + T val = (T)0; \ + TIFFGetField(tif_ctx, tag, &val); \ + if (val) { \ + (key) = FX_Alloc(uint8_t, sizeof(T)); \ + if ((key)) { \ + T* ptr = (T*)(key); \ + *ptr = val; \ + pExif->m_TagVal.SetAt(tag, (key)); \ + } \ + } \ + } \ + (key) = NULL; +#define TIFF_EXIF_GETSTRINGINFO(key, tag) \ + { \ + FX_DWORD size = 0; \ + uint8_t* buf = NULL; \ + TIFFGetField(tif_ctx, tag, &size, &buf); \ + if (size && buf) { \ + (key) = FX_Alloc(uint8_t, size); \ + if ((key)) { \ + FXSYS_memcpy((key), buf, size); \ + pExif->m_TagVal.SetAt(tag, (key)); \ + } \ + } \ + } \ + (key) = NULL; + +namespace { + +template +FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttribute* pAttr) { + T val = 0; + TIFFGetField(tif_ctx, tag, &val); + if (!val) + return FALSE; + T* ptr = FX_Alloc(T, 1); + *ptr = val; + pAttr->m_Exif[tag] = (void*)ptr; + return TRUE; +} +void Tiff_Exif_GetStringInfo(TIFF* tif_ctx, + ttag_t tag, + CFX_DIBAttribute* pAttr) { + FX_CHAR* buf = nullptr; + TIFFGetField(tif_ctx, tag, &buf); + if (!buf) + return; + FX_STRSIZE size = FXSYS_strlen(buf); + uint8_t* ptr = FX_Alloc(uint8_t, size + 1); + FXSYS_memcpy(ptr, buf, size); + ptr[size] = 0; + pAttr->m_Exif[tag] = ptr; +} + +} // namespace + +FX_BOOL CCodec_TiffContext::LoadFrameInfo(int32_t frame, + FX_DWORD& width, + FX_DWORD& height, + FX_DWORD& comps, + FX_DWORD& bpc, + CFX_DIBAttribute* pAttribute) { + if (!TIFFSetDirectory(tif_ctx, (uint16)frame)) { + return FALSE; + } + FX_WORD tif_cs; + FX_DWORD tif_icc_size = 0; + uint8_t* tif_icc_buf = NULL; + FX_WORD tif_bpc = 0; + FX_WORD tif_cps; + FX_DWORD tif_rps; + width = height = comps = 0; + TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); + TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &comps); + TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &tif_bpc); + TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &tif_cs); + TIFFGetField(tif_ctx, TIFFTAG_COMPRESSION, &tif_cps); + TIFFGetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, &tif_rps); + TIFFGetField(tif_ctx, TIFFTAG_ICCPROFILE, &tif_icc_size, &tif_icc_buf); + if (pAttribute) { + pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_INCH; + if (TIFFGetField(tif_ctx, TIFFTAG_RESOLUTIONUNIT, + &pAttribute->m_wDPIUnit)) { + pAttribute->m_wDPIUnit -= 1; + } + Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_ORIENTATION, pAttribute); + if (Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_XRESOLUTION, pAttribute)) { + void* val = pAttribute->m_Exif[TIFFTAG_XRESOLUTION]; + FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; + pAttribute->m_nXDPI = (int32_t)(fDpi + 0.5f); + } + if (Tiff_Exif_GetInfo(tif_ctx, TIFFTAG_YRESOLUTION, pAttribute)) { + void* val = pAttribute->m_Exif[TIFFTAG_YRESOLUTION]; + FX_FLOAT fDpi = val ? *reinterpret_cast(val) : 0; + pAttribute->m_nYDPI = (int32_t)(fDpi + 0.5f); + } + Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pAttribute); + Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pAttribute); + Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pAttribute); + } + bpc = tif_bpc; + if (tif_rps > height) { + TIFFSetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, tif_rps = height); + } + return TRUE; +} +void _TiffBGRA2RGBA(uint8_t* pBuf, int32_t pixel, int32_t spp) { + for (int32_t n = 0; n < pixel; n++) { + uint8_t tmp = pBuf[0]; + pBuf[0] = pBuf[2]; + pBuf[2] = tmp; + pBuf += spp; + } +} +FX_BOOL CCodec_TiffContext::isSupport(CFX_DIBitmap* pDIBitmap) { + if (TIFFIsTiled(tif_ctx)) { + return FALSE; + } + uint16_t photometric; + if (!TIFFGetField(tif_ctx, TIFFTAG_PHOTOMETRIC, &photometric)) { + return FALSE; + } + switch (pDIBitmap->GetBPP()) { + case 1: + case 8: + if (photometric != PHOTOMETRIC_PALETTE) { + return FALSE; + } + break; + case 24: + if (photometric != PHOTOMETRIC_RGB) { + return FALSE; + } + break; + default: + return FALSE; + } + uint16_t planarconfig; + if (!TIFFGetFieldDefaulted(tif_ctx, TIFFTAG_PLANARCONFIG, &planarconfig)) { + return FALSE; + } + if (planarconfig == PLANARCONFIG_SEPARATE) { + return FALSE; + } + return TRUE; +} +void CCodec_TiffContext::SetPalette(CFX_DIBitmap* pDIBitmap, uint16_t bps) { + uint16_t *red_orig, *green_orig, *blue_orig; + TIFFGetField(tif_ctx, TIFFTAG_COLORMAP, &red_orig, &green_orig, &blue_orig); + for (int32_t i = (1L << bps) - 1; i >= 0; i--) { +#define CVT(x) ((uint16_t)((x) >> 8)) + red_orig[i] = CVT(red_orig[i]); + green_orig[i] = CVT(green_orig[i]); + blue_orig[i] = CVT(blue_orig[i]); +#undef CVT + } + int32_t len = 1 << bps; + for (int32_t index = 0; index < len; index++) { + FX_DWORD r = red_orig[index] & 0xFF; + FX_DWORD g = green_orig[index] & 0xFF; + FX_DWORD b = blue_orig[index] & 0xFF; + FX_DWORD color = (uint32_t)b | ((uint32_t)g << 8) | ((uint32_t)r << 16) | + (((uint32)0xffL) << 24); + pDIBitmap->SetPaletteEntry(index, color); + } +} +FX_BOOL CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { + if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 || + !isSupport(pDIBitmap)) { + return FALSE; + } + SetPalette(pDIBitmap, bps); + int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); + uint8_t* buf = (uint8_t*)_TIFFmalloc(size); + if (buf == NULL) { + TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); + return FALSE; + } + uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); + FX_DWORD pitch = pDIBitmap->GetPitch(); + for (int32_t row = 0; row < height; row++) { + TIFFReadScanline(tif_ctx, buf, row, 0); + for (int32_t j = 0; j < size; j++) { + bitMapbuffer[row * pitch + j] = buf[j]; + } + } + _TIFFfree(buf); + return TRUE; +} +FX_BOOL CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { + if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) || + !isSupport(pDIBitmap)) { + return FALSE; + } + SetPalette(pDIBitmap, bps); + int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); + uint8_t* buf = (uint8_t*)_TIFFmalloc(size); + if (buf == NULL) { + TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); + return FALSE; + } + uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); + FX_DWORD pitch = pDIBitmap->GetPitch(); + for (int32_t row = 0; row < height; row++) { + TIFFReadScanline(tif_ctx, buf, row, 0); + for (int32_t j = 0; j < size; j++) { + switch (bps) { + case 4: + bitMapbuffer[row * pitch + 2 * j + 0] = (buf[j] & 0xF0) >> 4; + bitMapbuffer[row * pitch + 2 * j + 1] = (buf[j] & 0x0F) >> 0; + break; + case 8: + bitMapbuffer[row * pitch + j] = buf[j]; + break; + } + } + } + _TIFFfree(buf); + return TRUE; +} +FX_BOOL CCodec_TiffContext::Decode24bppRGB(CFX_DIBitmap* pDIBitmap, + int32_t height, + int32_t width, + uint16_t bps, + uint16_t spp) { + if (pDIBitmap->GetBPP() != 24 || !isSupport(pDIBitmap)) { + return FALSE; + } + int32_t size = (int32_t)TIFFScanlineSize(tif_ctx); + uint8_t* buf = (uint8_t*)_TIFFmalloc(size); + if (buf == NULL) { + TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer"); + return FALSE; + } + uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer(); + FX_DWORD pitch = pDIBitmap->GetPitch(); + for (int32_t row = 0; row < height; row++) { + TIFFReadScanline(tif_ctx, buf, row, 0); + for (int32_t j = 0; j < size - 2; j += 3) { + bitMapbuffer[row * pitch + j + 0] = buf[j + 2]; + bitMapbuffer[row * pitch + j + 1] = buf[j + 1]; + bitMapbuffer[row * pitch + j + 2] = buf[j + 0]; + } + } + _TIFFfree(buf); + return TRUE; +} +FX_BOOL CCodec_TiffContext::Decode(CFX_DIBitmap* pDIBitmap) { + FX_DWORD img_wid = pDIBitmap->GetWidth(); + FX_DWORD img_hei = pDIBitmap->GetHeight(); + FX_DWORD width = 0; + FX_DWORD height = 0; + TIFFGetField(tif_ctx, TIFFTAG_IMAGEWIDTH, &width); + TIFFGetField(tif_ctx, TIFFTAG_IMAGELENGTH, &height); + if (img_wid != width || img_hei != height) { + return FALSE; + } + if (pDIBitmap->GetBPP() == 32) { + FX_WORD rotation = ORIENTATION_TOPLEFT; + TIFFGetField(tif_ctx, TIFFTAG_ORIENTATION, &rotation); + if (TIFFReadRGBAImageOriented(tif_ctx, img_wid, img_hei, + (uint32*)pDIBitmap->GetBuffer(), rotation, + 1)) { + for (FX_DWORD row = 0; row < img_hei; row++) { + uint8_t* row_buf = (uint8_t*)pDIBitmap->GetScanline(row); + _TiffBGRA2RGBA(row_buf, img_wid, 4); + } + return TRUE; + } + } + uint16_t spp, bps; + TIFFGetField(tif_ctx, TIFFTAG_SAMPLESPERPIXEL, &spp); + TIFFGetField(tif_ctx, TIFFTAG_BITSPERSAMPLE, &bps); + FX_DWORD bpp = bps * spp; + if (bpp == 1) { + return Decode1bppRGB(pDIBitmap, height, width, bps, spp); + } else if (bpp <= 8) { + return Decode8bppRGB(pDIBitmap, height, width, bps, spp); + } else if (bpp <= 24) { + return Decode24bppRGB(pDIBitmap, height, width, bps, spp); + } + return FALSE; +} +void* CCodec_TiffModule::CreateDecoder(IFX_FileRead* file_ptr) { + CCodec_TiffContext* pDecoder = new CCodec_TiffContext; + if (!pDecoder->InitDecoder(file_ptr)) { + delete pDecoder; + return NULL; + } + return pDecoder; +} +void CCodec_TiffModule::GetFrames(void* ctx, int32_t& frames) { + CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; + pDecoder->GetFrames(frames); +} +FX_BOOL CCodec_TiffModule::LoadFrameInfo(void* ctx, + int32_t frame, + FX_DWORD& width, + FX_DWORD& height, + FX_DWORD& comps, + FX_DWORD& bpc, + CFX_DIBAttribute* pAttribute) { + CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; + return pDecoder->LoadFrameInfo(frame, width, height, comps, bpc, pAttribute); +} +FX_BOOL CCodec_TiffModule::Decode(void* ctx, class CFX_DIBitmap* pDIBitmap) { + CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; + return pDecoder->Decode(pDIBitmap); +} +void CCodec_TiffModule::DestroyDecoder(void* ctx) { + CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx; + delete pDecoder; +} diff --git a/core/src/fxcodec/lbmp/fx_bmp.cpp b/core/src/fxcodec/lbmp/fx_bmp.cpp index 00477581a1..388daa434f 100644 --- a/core/src/fxcodec/lbmp/fx_bmp.cpp +++ b/core/src/fxcodec/lbmp/fx_bmp.cpp @@ -1,975 +1,975 @@ -// 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_bmp.h" - -#include - -namespace { - -const size_t kBmpCoreHeaderSize = 12; -const size_t kBmpInfoHeaderSize = 40; - -} // namespace - -FX_DWORD _GetDWord_LSBFirst(uint8_t* p) { - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} -FX_WORD _GetWord_LSBFirst(uint8_t* p) { - return p[0] | (p[1] << 8); -} -void _SetDWord_LSBFirst(uint8_t* p, FX_DWORD v) { - p[0] = (uint8_t)v; - p[1] = (uint8_t)(v >> 8); - p[2] = (uint8_t)(v >> 16); - p[3] = (uint8_t)(v >> 24); -} -void _SetWord_LSBFirst(uint8_t* p, FX_WORD v) { - p[0] = (uint8_t)v; - p[1] = (uint8_t)(v >> 8); -} -void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg) { - if (bmp_ptr != NULL && bmp_ptr->_bmp_error_fn != NULL) { - bmp_ptr->_bmp_error_fn(bmp_ptr, err_msg); - } -} -bmp_decompress_struct_p _bmp_create_decompress() { - bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1); - if (bmp_ptr == NULL) { - return NULL; - } - FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct)); - bmp_ptr->decode_status = BMP_D_STATUS_HEADER; - bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1); - return bmp_ptr; -} -void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) { - if (bmp_ptr_ptr == NULL || *bmp_ptr_ptr == NULL) { - return; - } - bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr; - *bmp_ptr_ptr = NULL; - if (bmp_ptr->out_row_buffer != NULL) { - FX_Free(bmp_ptr->out_row_buffer); - } - if (bmp_ptr->pal_ptr != NULL) { - FX_Free(bmp_ptr->pal_ptr); - } - if (bmp_ptr->bmp_header_ptr != NULL) { - FX_Free(bmp_ptr->bmp_header_ptr); - } - FX_Free(bmp_ptr); -} -int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr) { - if (bmp_ptr == NULL) { - return 0; - } - FX_DWORD skip_size_org = bmp_ptr->skip_size; - if (bmp_ptr->decode_status == BMP_D_STATUS_HEADER) { - ASSERT(sizeof(BmpFileHeader) == 14); - BmpFileHeader* bmp_header_ptr = NULL; - if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14) == NULL) { - return 2; - } - bmp_ptr->bmp_header_ptr->bfType = - _GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType); - bmp_ptr->bmp_header_ptr->bfOffBits = - _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits); - bmp_ptr->data_size = _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize); - if (bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) { - _bmp_error(bmp_ptr, "Not A Bmp Image"); - return 0; - } - if (bmp_ptr->avail_in < sizeof(FX_DWORD)) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->img_ifh_size = - _GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size); - bmp_ptr->pal_type = 0; - static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize, - "BmpCoreHeader has wrong size"); - static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize, - "BmpInfoHeader has wrong size"); - switch (bmp_ptr->img_ifh_size) { - case kBmpCoreHeaderSize: { - bmp_ptr->pal_type = 1; - BmpCoreHeaderPtr bmp_core_header_ptr = NULL; - if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr, - bmp_ptr->img_ifh_size) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->width = (FX_DWORD)_GetWord_LSBFirst( - (uint8_t*)&bmp_core_header_ptr->bcWidth); - bmp_ptr->height = (FX_DWORD)_GetWord_LSBFirst( - (uint8_t*)&bmp_core_header_ptr->bcHeight); - bmp_ptr->bitCounts = - _GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount); - bmp_ptr->compress_flag = BMP_RGB; - bmp_ptr->imgTB_flag = FALSE; - } break; - case kBmpInfoHeaderSize: { - BmpInfoHeaderPtr bmp_info_header_ptr = NULL; - if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, - bmp_ptr->img_ifh_size) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->width = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); - bmp_ptr->height = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); - bmp_ptr->bitCounts = - _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); - bmp_ptr->compress_flag = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); - bmp_ptr->color_used = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); - bmp_ptr->dpi_x = (int32_t)_GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); - bmp_ptr->dpi_y = (int32_t)_GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); - if (bmp_ptr->height < 0) { - bmp_ptr->height = -bmp_ptr->height; - bmp_ptr->imgTB_flag = TRUE; - } - } break; - default: { - if (bmp_ptr->img_ifh_size > - std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) { - BmpInfoHeaderPtr bmp_info_header_ptr = NULL; - if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, - bmp_ptr->img_ifh_size) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - FX_WORD biPlanes; - bmp_ptr->width = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); - bmp_ptr->height = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); - bmp_ptr->bitCounts = - _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); - bmp_ptr->compress_flag = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); - bmp_ptr->color_used = - _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); - biPlanes = - _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes); - bmp_ptr->dpi_x = _GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); - bmp_ptr->dpi_y = _GetDWord_LSBFirst( - (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); - if (bmp_ptr->height < 0) { - bmp_ptr->height = -bmp_ptr->height; - bmp_ptr->imgTB_flag = TRUE; - } - if (bmp_ptr->compress_flag == BMP_RGB && biPlanes == 1 && - bmp_ptr->color_used == 0) { - break; - } - } - _bmp_error(bmp_ptr, "Unsupported Bmp File"); - return 0; - } - } - ASSERT(bmp_ptr->width > 0); - ASSERT(bmp_ptr->compress_flag <= BMP_BITFIELDS); - switch (bmp_ptr->bitCounts) { - case 1: - case 4: - case 8: - case 16: - case 24: { - if (bmp_ptr->color_used > ((FX_DWORD)1) << bmp_ptr->bitCounts) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - } - case 32: { - if (bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - } break; - default: - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts); - switch (bmp_ptr->bitCounts) { - case 1: - case 4: - case 8: - bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8); - bmp_ptr->components = 1; - break; - case 16: - case 24: - bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24); - bmp_ptr->components = 3; - break; - case 32: - bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes; - bmp_ptr->components = 4; - break; - } - if (bmp_ptr->out_row_buffer != NULL) { - FX_Free(bmp_ptr->out_row_buffer); - bmp_ptr->out_row_buffer = NULL; - } - bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes); - BMP_PTR_NOT_NULL(bmp_ptr->out_row_buffer, bmp_ptr); - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL); - } - if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) { - skip_size_org = bmp_ptr->skip_size; -#ifdef BMP_SUPPORT_BITFIELD - if (bmp_ptr->compress_flag == BMP_BITFIELDS) { - if (bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - FX_DWORD* mask; - if (_bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(FX_DWORD)) == - NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->mask_red = _GetDWord_LSBFirst((uint8_t*)&mask[0]); - bmp_ptr->mask_green = _GetDWord_LSBFirst((uint8_t*)&mask[1]); - bmp_ptr->mask_blue = _GetDWord_LSBFirst((uint8_t*)&mask[2]); - if (bmp_ptr->mask_red & bmp_ptr->mask_green || - bmp_ptr->mask_red & bmp_ptr->mask_blue || - bmp_ptr->mask_green & bmp_ptr->mask_blue) { - _bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt"); - return 0; - } - if (bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) { - bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size; - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); - return 1; - } else if (bmp_ptr->bitCounts == 16) { - bmp_ptr->mask_red = 0x7C00; - bmp_ptr->mask_green = 0x03E0; - bmp_ptr->mask_blue = 0x001F; - } -#else - if (bmp_ptr->compress_flag == BMP_BITFIELDS || bmp_ptr->bitCounts == 16) { - _bmp_error(bmp_ptr, "Unsupported Bitfield Bmp File"); - return 0; - } -#endif - bmp_ptr->pal_num = 0; - if (bmp_ptr->bitCounts < 16) { - bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts; - if (bmp_ptr->color_used != 0) { - bmp_ptr->pal_num = bmp_ptr->color_used; - } - uint8_t* src_pal_ptr = NULL; - FX_DWORD src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); - if (_bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) == - NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - if (bmp_ptr->pal_ptr != NULL) { - FX_Free(bmp_ptr->pal_ptr); - bmp_ptr->pal_ptr = NULL; - } - bmp_ptr->pal_ptr = FX_Alloc(FX_DWORD, bmp_ptr->pal_num); - BMP_PTR_NOT_NULL(bmp_ptr->pal_ptr, bmp_ptr); - int32_t src_pal_index = 0; - if (bmp_ptr->pal_type == BMP_PAL_OLD) { - while (src_pal_index < bmp_ptr->pal_num) { - bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( - 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); - src_pal_ptr += 3; - } - } else { - while (src_pal_index < bmp_ptr->pal_num) { - bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( - src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); - src_pal_ptr += 4; - } - } - } - if (bmp_ptr->bmp_header_ptr->bfOffBits < - 14 + bmp_ptr->img_ifh_size + - bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) { - bmp_ptr->bmp_header_ptr->bfOffBits = - 14 + bmp_ptr->img_ifh_size + - bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); - } - return 1; -} -int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr) { - if (bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) { - bmp_ptr->avail_in = 0; - if (!bmp_ptr->_bmp_get_data_position_fn( - bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) { - bmp_ptr->decode_status = BMP_D_STATUS_TAIL; - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset"); - return 0; - } - bmp_ptr->row_num = 0; - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); - } - if (bmp_ptr->decode_status == BMP_D_STATUS_DATA) { - switch (bmp_ptr->compress_flag) { - case BMP_RGB: - case BMP_BITFIELDS: - return _bmp_decode_rgb(bmp_ptr); - case BMP_RLE8: - return _bmp_decode_rle8(bmp_ptr); - case BMP_RLE4: - return _bmp_decode_rle4(bmp_ptr); - } - } - _bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; -} -int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) { - uint8_t* row_buf = bmp_ptr->out_row_buffer; - uint8_t* des_buf = NULL; - while (bmp_ptr->row_num < bmp_ptr->height) { - if (_bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes) == NULL) { - return 2; - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); - switch (bmp_ptr->bitCounts) { - case 1: { - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00; - } - } break; - case 4: { - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *row_buf++ = (col & 0x01) ? (des_buf[col >> 1] & 0x0F) - : ((des_buf[col >> 1] & 0xF0) >> 4); - } - } break; -#ifdef BMP_SUPPORT_BITFIELD - case 16: { - FX_WORD* buf = (FX_WORD*)des_buf; - uint8_t blue_bits = 0; - uint8_t green_bits = 0; - uint8_t red_bits = 0; - for (int32_t i = 0; i < 16; i++) { - if ((bmp_ptr->mask_blue >> i) & 0x01) { - blue_bits++; - } - if ((bmp_ptr->mask_green >> i) & 0x01) { - green_bits++; - } - if ((bmp_ptr->mask_red >> i) & 0x01) { - red_bits++; - } - } - green_bits += blue_bits; - red_bits += green_bits; - blue_bits = 8 - blue_bits; - green_bits -= 8; - red_bits -= 8; - for (int32_t col = 0; col < bmp_ptr->width; col++) { - *buf = _GetWord_LSBFirst((uint8_t*)buf); - *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits); - *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits); - *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits); - } - } break; -#endif - case 8: - case 24: - case 32: - FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes); - break; - } - row_buf = bmp_ptr->out_row_buffer; - bmp_ptr->_bmp_get_row_fn(bmp_ptr, - bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - return 1; -} -int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) { - uint8_t* first_byte_ptr = NULL; - uint8_t* second_byte_ptr = NULL; - bmp_ptr->col_num = 0; - while (TRUE) { - FX_DWORD skip_size_org = bmp_ptr->skip_size; - if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { - return 2; - } - switch (*first_byte_ptr) { - case RLE_MARKER: { - if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - switch (*first_byte_ptr) { - case RLE_EOL: { - if (bmp_ptr->row_num >= bmp_ptr->height) { - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - bmp_ptr->col_num = 0; - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); - continue; - } - case RLE_EOI: { - if (bmp_ptr->row_num < bmp_ptr->height) { - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - return 1; - } - case RLE_DELTA: { - uint8_t* delta_ptr; - if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->col_num += (int32_t)delta_ptr[0]; - int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; - if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || - bmp_row_num_next >= bmp_ptr->height) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); - return 0; - } - while (bmp_ptr->row_num < bmp_row_num_next) { - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - } - } break; - default: { - if ((int32_t)(*first_byte_ptr) > - bmp_ptr->src_row_bytes - bmp_ptr->col_num) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - if (_bmp_read_data(bmp_ptr, &second_byte_ptr, - *first_byte_ptr & 1 ? *first_byte_ptr + 1 - : *first_byte_ptr) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num, - second_byte_ptr, *first_byte_ptr); - bmp_ptr->col_num += (int32_t)(*first_byte_ptr); - } - } - } break; - default: { - if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - if ((int32_t)(*first_byte_ptr) > - bmp_ptr->src_row_bytes - bmp_ptr->col_num) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num, - *second_byte_ptr, *first_byte_ptr); - bmp_ptr->col_num += (int32_t)(*first_byte_ptr); - } - } - } - _bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; -} -int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) { - uint8_t* first_byte_ptr = NULL; - uint8_t* second_byte_ptr = NULL; - bmp_ptr->col_num = 0; - while (TRUE) { - FX_DWORD skip_size_org = bmp_ptr->skip_size; - if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { - return 2; - } - switch (*first_byte_ptr) { - case RLE_MARKER: { - if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - switch (*first_byte_ptr) { - case RLE_EOL: { - if (bmp_ptr->row_num >= bmp_ptr->height) { - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - bmp_ptr->col_num = 0; - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); - continue; - } - case RLE_EOI: { - if (bmp_ptr->row_num < bmp_ptr->height) { - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - } - _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); - return 1; - } - case RLE_DELTA: { - uint8_t* delta_ptr; - if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - bmp_ptr->col_num += (int32_t)delta_ptr[0]; - int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; - if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || - bmp_row_num_next >= bmp_ptr->height) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); - return 0; - } - while (bmp_ptr->row_num < bmp_row_num_next) { - FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); - bmp_ptr->_bmp_get_row_fn( - bmp_ptr, bmp_ptr->imgTB_flag - ? bmp_ptr->row_num++ - : (bmp_ptr->height - 1 - bmp_ptr->row_num++), - bmp_ptr->out_row_buffer); - } - } break; - default: { - uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1); - if ((int32_t)*first_byte_ptr >= - bmp_ptr->out_row_bytes - bmp_ptr->col_num) { - if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; - } - if (_bmp_read_data(bmp_ptr, &second_byte_ptr, - size & 1 ? size + 1 : size) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - for (uint8_t i = 0; i < *first_byte_ptr; i++) { - if (i & 0x01) { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - (*second_byte_ptr++ & 0x0F); - } else { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - ((*second_byte_ptr & 0xF0) >> 4); - } - } - } - } - } break; - default: { - if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) { - bmp_ptr->skip_size = skip_size_org; - return 2; - } - if ((int32_t)*first_byte_ptr > - bmp_ptr->out_row_bytes - bmp_ptr->col_num) { - uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1); - if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { - _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); - return 0; - } - *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; - } - for (uint8_t i = 0; i < *first_byte_ptr; i++) { - if (i & 0x01) { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - (*second_byte_ptr & 0x0F); - } else { - *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = - ((*second_byte_ptr & 0xF0) >> 4); - } - } - } - } - } - _bmp_error(bmp_ptr, "Any Uncontrol Error"); - return 0; -} -uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr, - uint8_t** des_buf_pp, - FX_DWORD data_size) { - if (bmp_ptr == NULL || bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) { - return NULL; - } - *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size; - bmp_ptr->skip_size += data_size; - return *des_buf_pp; -} -void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, - int32_t status) { - bmp_ptr->decode_status = status; - bmp_ptr->next_in += bmp_ptr->skip_size; - bmp_ptr->avail_in -= bmp_ptr->skip_size; - bmp_ptr->skip_size = 0; -} -void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, - uint8_t* src_buf, - FX_DWORD src_size) { - bmp_ptr->next_in = src_buf; - bmp_ptr->avail_in = src_size; - bmp_ptr->skip_size = 0; -} -FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, - uint8_t** avial_buf_ptr) { - if (avial_buf_ptr != NULL) { - *avial_buf_ptr = NULL; - if (bmp_ptr->avail_in > 0) { - *avial_buf_ptr = bmp_ptr->next_in; - } - } - return bmp_ptr->avail_in; -} -bmp_compress_struct_p _bmp_create_compress() { - bmp_compress_struct_p bmp_ptr; - bmp_ptr = FX_Alloc(bmp_compress_struct, 1); - if (bmp_ptr) { - FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct)); - } - return bmp_ptr; -} -void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr) { - if (bmp_ptr) { - if (bmp_ptr->src_free && bmp_ptr->src_buf) { - FX_Free(bmp_ptr->src_buf); - } - FX_Free(bmp_ptr); - } -} -static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf) { - FX_DWORD offset; - offset = 0; - _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType); - offset += 2; - _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize); - offset += 4; - _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1); - offset += 2; - _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2); - offset += 2; - _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits); - offset += 4; -} -static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf) { - FX_DWORD offset; - offset = sizeof(BmpFileHeader); - _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biWidth); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biHeight); - offset += 4; - _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes); - offset += 2; - _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount); - offset += 2; - _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], - (FX_DWORD)info_head_ptr->biXPelsPerMeter); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], - (FX_DWORD)info_head_ptr->biYPelsPerMeter); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed); - offset += 4; - _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant); - offset += 4; -} -#ifdef BMP_SUPPORT_BITFIELD -static void _bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size) { - if (bmp_ptr->info_header.biBitCount != 16 && - bmp_ptr->info_header.biBitCount != 32) { - return; - } - FX_DWORD size, dst_pos, i; - size = bmp_ptr->src_pitch * bmp_ptr->src_row * - bmp_ptr->info_header.biBitCount / 16; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - if (dst_buf == NULL) { - return; - } - FXSYS_memset(&dst_buf[dst_pos], 0, size); - FX_DWORD mask_red; - FX_DWORD mask_green; - FX_DWORD mask_blue; - mask_red = 0x7C00; - mask_green = 0x03E0; - mask_blue = 0x001F; - if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) { - if (bmp_ptr->bit_type == BMP_BIT_565) { - mask_red = 0xF800; - mask_green = 0x07E0; - mask_blue = 0x001F; - } - if (bmp_ptr->info_header.biBitCount == 32) { - mask_red = 0xFF0000; - mask_green = 0x00FF00; - mask_blue = 0x0000FF; - } - _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red); - dst_pos += 4; - _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green); - dst_pos += 4; - _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue); - dst_pos += 4; - bmp_ptr->file_header.bfOffBits = dst_pos; - } - uint8_t blue_bits = 0; - uint8_t green_bits = 0; - uint8_t red_bits = 0; - for (i = 0; i < bmp_ptr->info_header.biBitCount; i++) { - if ((mask_blue >> i) & 0x01) { - blue_bits++; - } - if ((mask_green >> i) & 0x01) { - green_bits++; - } - if ((mask_red >> i) & 0x01) { - red_bits++; - } - } - green_bits += blue_bits; - red_bits += green_bits; - blue_bits = 8 - blue_bits; - green_bits -= 8; - red_bits -= 8; - i = 0; - for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) { - while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) { - uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; - if (bmp_ptr->src_bpp == 32) { - i++; - } - FX_DWORD pix_val = 0; - pix_val |= (b >> blue_bits) & mask_blue; - pix_val |= (g << green_bits) & mask_green; - pix_val |= (r << red_bits) & mask_red; - if (bmp_ptr->info_header.biBitCount == 16) { - _SetWord_LSBFirst(&dst_buf[dst_pos], (FX_WORD)pix_val); - dst_pos += 2; - } else { - _SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val); - dst_pos += 4; - } - } - } - dst_size = dst_pos; -} -#endif -static void _bmp_encode_rgb(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size) { - if (bmp_ptr->info_header.biBitCount == 16) { -#ifdef BMP_SUPPORT_BITFIELD - _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); -#endif - return; - } - FX_DWORD size, dst_pos; - FX_DWORD dst_pitch = - (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4; - size = dst_pitch * bmp_ptr->src_row; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - if (dst_buf == NULL) { - return; - } - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) { - FXSYS_memcpy(&dst_buf[dst_pos], - &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch], - bmp_ptr->src_pitch); - dst_pos += dst_pitch; - } - dst_size = dst_pos; -} -static uint8_t _bmp_rle8_search(const uint8_t* buf, int32_t len) { - uint8_t num; - num = 1; - while (num < len) { - if (buf[num - 1] != buf[num] || num == 0xFF) { - break; - } - num++; - } - return num; -} -static void _bmp_encode_rle8(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size) { - FX_DWORD size, dst_pos, index; - uint8_t rle[2] = {0}; - size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - if (dst_buf == NULL) { - return; - } - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;) { - index = row_num * bmp_ptr->src_pitch; - rle[0] = _bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i); - rle[1] = bmp_ptr->src_buf[index + i]; - if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { - rle[0] = uint8_t(bmp_ptr->src_pitch - i); - if (rle[0]) { - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOL; - i = 0; - row_num--; - } else { - i += rle[0]; - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOI; - dst_size = dst_pos; -} -static uint8_t _bmp_rle4_search(const uint8_t* buf, int32_t len) { - uint8_t num; - num = 2; - while (num < len) { - if (buf[num - 2] != buf[num] || num == 0xFF) { - break; - } - num++; - } - return num; -} -static void _bmp_encode_rle4(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size) { - FX_DWORD size, dst_pos, index; - uint8_t rle[2] = {0}; - size = bmp_ptr->src_pitch * bmp_ptr->src_row; - dst_pos = bmp_ptr->file_header.bfOffBits; - dst_size += size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); - if (dst_buf == NULL) { - return; - } - FXSYS_memset(&dst_buf[dst_pos], 0, size); - for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1; - rle[1] = 0) { - index = row_num * bmp_ptr->src_pitch; - rle[0] = _bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i); - rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4; - rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f; - if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { - rle[0] = uint8_t(bmp_ptr->src_pitch - i); - if (rle[0]) { - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOL; - i = 0; - row_num--; - } else { - i += rle[0]; - dst_buf[dst_pos++] = rle[0]; - dst_buf[dst_pos++] = rle[1]; - } - } - dst_buf[dst_pos++] = RLE_MARKER; - dst_buf[dst_pos++] = RLE_EOI; - dst_size = dst_pos; -} -FX_BOOL _bmp_encode_image(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size) { - FX_DWORD head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader); - FX_DWORD pal_size = sizeof(FX_DWORD) * bmp_ptr->pal_num; - if (bmp_ptr->info_header.biClrUsed > 0 && - bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) { - pal_size = sizeof(FX_DWORD) * bmp_ptr->info_header.biClrUsed; - } - dst_size = head_size + sizeof(FX_DWORD) * bmp_ptr->pal_num; - dst_buf = FX_TryAlloc(uint8_t, dst_size); - if (dst_buf == NULL) { - return FALSE; - } - FXSYS_memset(dst_buf, 0, dst_size); - bmp_ptr->file_header.bfOffBits = head_size; - if (bmp_ptr->pal_ptr && pal_size) { - FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size); - bmp_ptr->file_header.bfOffBits += pal_size; - } - WriteInfoHeader(&bmp_ptr->info_header, dst_buf); - switch (bmp_ptr->info_header.biCompression) { - case BMP_RGB: - _bmp_encode_rgb(bmp_ptr, dst_buf, dst_size); - break; - case BMP_BITFIELDS: -#ifdef BMP_SUPPORT_BITFIELD - _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); -#endif - break; - case BMP_RLE8: - _bmp_encode_rle8(bmp_ptr, dst_buf, dst_size); - break; - case BMP_RLE4: - _bmp_encode_rle4(bmp_ptr, dst_buf, dst_size); - break; - default:; - } - bmp_ptr->file_header.bfSize = dst_size; - WriteFileHeader(&bmp_ptr->file_header, dst_buf); - return TRUE; -} +// 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_bmp.h" + +#include + +namespace { + +const size_t kBmpCoreHeaderSize = 12; +const size_t kBmpInfoHeaderSize = 40; + +} // namespace + +FX_DWORD _GetDWord_LSBFirst(uint8_t* p) { + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} +FX_WORD _GetWord_LSBFirst(uint8_t* p) { + return p[0] | (p[1] << 8); +} +void _SetDWord_LSBFirst(uint8_t* p, FX_DWORD v) { + p[0] = (uint8_t)v; + p[1] = (uint8_t)(v >> 8); + p[2] = (uint8_t)(v >> 16); + p[3] = (uint8_t)(v >> 24); +} +void _SetWord_LSBFirst(uint8_t* p, FX_WORD v) { + p[0] = (uint8_t)v; + p[1] = (uint8_t)(v >> 8); +} +void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg) { + if (bmp_ptr != NULL && bmp_ptr->_bmp_error_fn != NULL) { + bmp_ptr->_bmp_error_fn(bmp_ptr, err_msg); + } +} +bmp_decompress_struct_p _bmp_create_decompress() { + bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1); + if (bmp_ptr == NULL) { + return NULL; + } + FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct)); + bmp_ptr->decode_status = BMP_D_STATUS_HEADER; + bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1); + return bmp_ptr; +} +void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr) { + if (bmp_ptr_ptr == NULL || *bmp_ptr_ptr == NULL) { + return; + } + bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr; + *bmp_ptr_ptr = NULL; + if (bmp_ptr->out_row_buffer != NULL) { + FX_Free(bmp_ptr->out_row_buffer); + } + if (bmp_ptr->pal_ptr != NULL) { + FX_Free(bmp_ptr->pal_ptr); + } + if (bmp_ptr->bmp_header_ptr != NULL) { + FX_Free(bmp_ptr->bmp_header_ptr); + } + FX_Free(bmp_ptr); +} +int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr) { + if (bmp_ptr == NULL) { + return 0; + } + FX_DWORD skip_size_org = bmp_ptr->skip_size; + if (bmp_ptr->decode_status == BMP_D_STATUS_HEADER) { + ASSERT(sizeof(BmpFileHeader) == 14); + BmpFileHeader* bmp_header_ptr = NULL; + if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14) == NULL) { + return 2; + } + bmp_ptr->bmp_header_ptr->bfType = + _GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType); + bmp_ptr->bmp_header_ptr->bfOffBits = + _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits); + bmp_ptr->data_size = _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize); + if (bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) { + _bmp_error(bmp_ptr, "Not A Bmp Image"); + return 0; + } + if (bmp_ptr->avail_in < sizeof(FX_DWORD)) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->img_ifh_size = + _GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size); + bmp_ptr->pal_type = 0; + static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize, + "BmpCoreHeader has wrong size"); + static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize, + "BmpInfoHeader has wrong size"); + switch (bmp_ptr->img_ifh_size) { + case kBmpCoreHeaderSize: { + bmp_ptr->pal_type = 1; + BmpCoreHeaderPtr bmp_core_header_ptr = NULL; + if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr, + bmp_ptr->img_ifh_size) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->width = (FX_DWORD)_GetWord_LSBFirst( + (uint8_t*)&bmp_core_header_ptr->bcWidth); + bmp_ptr->height = (FX_DWORD)_GetWord_LSBFirst( + (uint8_t*)&bmp_core_header_ptr->bcHeight); + bmp_ptr->bitCounts = + _GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount); + bmp_ptr->compress_flag = BMP_RGB; + bmp_ptr->imgTB_flag = FALSE; + } break; + case kBmpInfoHeaderSize: { + BmpInfoHeaderPtr bmp_info_header_ptr = NULL; + if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, + bmp_ptr->img_ifh_size) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->width = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); + bmp_ptr->height = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); + bmp_ptr->bitCounts = + _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); + bmp_ptr->compress_flag = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); + bmp_ptr->color_used = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); + bmp_ptr->dpi_x = (int32_t)_GetDWord_LSBFirst( + (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); + bmp_ptr->dpi_y = (int32_t)_GetDWord_LSBFirst( + (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); + if (bmp_ptr->height < 0) { + bmp_ptr->height = -bmp_ptr->height; + bmp_ptr->imgTB_flag = TRUE; + } + } break; + default: { + if (bmp_ptr->img_ifh_size > + std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) { + BmpInfoHeaderPtr bmp_info_header_ptr = NULL; + if (_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, + bmp_ptr->img_ifh_size) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + FX_WORD biPlanes; + bmp_ptr->width = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth); + bmp_ptr->height = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight); + bmp_ptr->bitCounts = + _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount); + bmp_ptr->compress_flag = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression); + bmp_ptr->color_used = + _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed); + biPlanes = + _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes); + bmp_ptr->dpi_x = _GetDWord_LSBFirst( + (uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter); + bmp_ptr->dpi_y = _GetDWord_LSBFirst( + (uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter); + if (bmp_ptr->height < 0) { + bmp_ptr->height = -bmp_ptr->height; + bmp_ptr->imgTB_flag = TRUE; + } + if (bmp_ptr->compress_flag == BMP_RGB && biPlanes == 1 && + bmp_ptr->color_used == 0) { + break; + } + } + _bmp_error(bmp_ptr, "Unsupported Bmp File"); + return 0; + } + } + ASSERT(bmp_ptr->width > 0); + ASSERT(bmp_ptr->compress_flag <= BMP_BITFIELDS); + switch (bmp_ptr->bitCounts) { + case 1: + case 4: + case 8: + case 16: + case 24: { + if (bmp_ptr->color_used > ((FX_DWORD)1) << bmp_ptr->bitCounts) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + } + case 32: { + if (bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + } break; + default: + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts); + switch (bmp_ptr->bitCounts) { + case 1: + case 4: + case 8: + bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8); + bmp_ptr->components = 1; + break; + case 16: + case 24: + bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24); + bmp_ptr->components = 3; + break; + case 32: + bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes; + bmp_ptr->components = 4; + break; + } + if (bmp_ptr->out_row_buffer != NULL) { + FX_Free(bmp_ptr->out_row_buffer); + bmp_ptr->out_row_buffer = NULL; + } + bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes); + BMP_PTR_NOT_NULL(bmp_ptr->out_row_buffer, bmp_ptr); + FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL); + } + if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) { + skip_size_org = bmp_ptr->skip_size; +#ifdef BMP_SUPPORT_BITFIELD + if (bmp_ptr->compress_flag == BMP_BITFIELDS) { + if (bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + FX_DWORD* mask; + if (_bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(FX_DWORD)) == + NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->mask_red = _GetDWord_LSBFirst((uint8_t*)&mask[0]); + bmp_ptr->mask_green = _GetDWord_LSBFirst((uint8_t*)&mask[1]); + bmp_ptr->mask_blue = _GetDWord_LSBFirst((uint8_t*)&mask[2]); + if (bmp_ptr->mask_red & bmp_ptr->mask_green || + bmp_ptr->mask_red & bmp_ptr->mask_blue || + bmp_ptr->mask_green & bmp_ptr->mask_blue) { + _bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt"); + return 0; + } + if (bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) { + bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size; + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); + return 1; + } else if (bmp_ptr->bitCounts == 16) { + bmp_ptr->mask_red = 0x7C00; + bmp_ptr->mask_green = 0x03E0; + bmp_ptr->mask_blue = 0x001F; + } +#else + if (bmp_ptr->compress_flag == BMP_BITFIELDS || bmp_ptr->bitCounts == 16) { + _bmp_error(bmp_ptr, "Unsupported Bitfield Bmp File"); + return 0; + } +#endif + bmp_ptr->pal_num = 0; + if (bmp_ptr->bitCounts < 16) { + bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts; + if (bmp_ptr->color_used != 0) { + bmp_ptr->pal_num = bmp_ptr->color_used; + } + uint8_t* src_pal_ptr = NULL; + FX_DWORD src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); + if (_bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) == + NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + if (bmp_ptr->pal_ptr != NULL) { + FX_Free(bmp_ptr->pal_ptr); + bmp_ptr->pal_ptr = NULL; + } + bmp_ptr->pal_ptr = FX_Alloc(FX_DWORD, bmp_ptr->pal_num); + BMP_PTR_NOT_NULL(bmp_ptr->pal_ptr, bmp_ptr); + int32_t src_pal_index = 0; + if (bmp_ptr->pal_type == BMP_PAL_OLD) { + while (src_pal_index < bmp_ptr->pal_num) { + bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( + 0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); + src_pal_ptr += 3; + } + } else { + while (src_pal_index < bmp_ptr->pal_num) { + bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE( + src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]); + src_pal_ptr += 4; + } + } + } + if (bmp_ptr->bmp_header_ptr->bfOffBits < + 14 + bmp_ptr->img_ifh_size + + bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) { + bmp_ptr->bmp_header_ptr->bfOffBits = + 14 + bmp_ptr->img_ifh_size + + bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4); + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE); + } + return 1; +} +int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr) { + if (bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) { + bmp_ptr->avail_in = 0; + if (!bmp_ptr->_bmp_get_data_position_fn( + bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) { + bmp_ptr->decode_status = BMP_D_STATUS_TAIL; + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset"); + return 0; + } + bmp_ptr->row_num = 0; + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + } + if (bmp_ptr->decode_status == BMP_D_STATUS_DATA) { + switch (bmp_ptr->compress_flag) { + case BMP_RGB: + case BMP_BITFIELDS: + return _bmp_decode_rgb(bmp_ptr); + case BMP_RLE8: + return _bmp_decode_rle8(bmp_ptr); + case BMP_RLE4: + return _bmp_decode_rle4(bmp_ptr); + } + } + _bmp_error(bmp_ptr, "Any Uncontrol Error"); + return 0; +} +int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr) { + uint8_t* row_buf = bmp_ptr->out_row_buffer; + uint8_t* des_buf = NULL; + while (bmp_ptr->row_num < bmp_ptr->height) { + if (_bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes) == NULL) { + return 2; + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + switch (bmp_ptr->bitCounts) { + case 1: { + for (int32_t col = 0; col < bmp_ptr->width; col++) { + *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00; + } + } break; + case 4: { + for (int32_t col = 0; col < bmp_ptr->width; col++) { + *row_buf++ = (col & 0x01) ? (des_buf[col >> 1] & 0x0F) + : ((des_buf[col >> 1] & 0xF0) >> 4); + } + } break; +#ifdef BMP_SUPPORT_BITFIELD + case 16: { + FX_WORD* buf = (FX_WORD*)des_buf; + uint8_t blue_bits = 0; + uint8_t green_bits = 0; + uint8_t red_bits = 0; + for (int32_t i = 0; i < 16; i++) { + if ((bmp_ptr->mask_blue >> i) & 0x01) { + blue_bits++; + } + if ((bmp_ptr->mask_green >> i) & 0x01) { + green_bits++; + } + if ((bmp_ptr->mask_red >> i) & 0x01) { + red_bits++; + } + } + green_bits += blue_bits; + red_bits += green_bits; + blue_bits = 8 - blue_bits; + green_bits -= 8; + red_bits -= 8; + for (int32_t col = 0; col < bmp_ptr->width; col++) { + *buf = _GetWord_LSBFirst((uint8_t*)buf); + *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits); + *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits); + *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits); + } + } break; +#endif + case 8: + case 24: + case 32: + FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes); + break; + } + row_buf = bmp_ptr->out_row_buffer; + bmp_ptr->_bmp_get_row_fn(bmp_ptr, + bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + return 1; +} +int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr) { + uint8_t* first_byte_ptr = NULL; + uint8_t* second_byte_ptr = NULL; + bmp_ptr->col_num = 0; + while (TRUE) { + FX_DWORD skip_size_org = bmp_ptr->skip_size; + if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { + return 2; + } + switch (*first_byte_ptr) { + case RLE_MARKER: { + if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + switch (*first_byte_ptr) { + case RLE_EOL: { + if (bmp_ptr->row_num >= bmp_ptr->height) { + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + bmp_ptr->col_num = 0; + FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + continue; + } + case RLE_EOI: { + if (bmp_ptr->row_num < bmp_ptr->height) { + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + return 1; + } + case RLE_DELTA: { + uint8_t* delta_ptr; + if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->col_num += (int32_t)delta_ptr[0]; + int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; + if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || + bmp_row_num_next >= bmp_ptr->height) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); + return 0; + } + while (bmp_ptr->row_num < bmp_row_num_next) { + FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + } + } break; + default: { + if ((int32_t)(*first_byte_ptr) > + bmp_ptr->src_row_bytes - bmp_ptr->col_num) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + if (_bmp_read_data(bmp_ptr, &second_byte_ptr, + *first_byte_ptr & 1 ? *first_byte_ptr + 1 + : *first_byte_ptr) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num, + second_byte_ptr, *first_byte_ptr); + bmp_ptr->col_num += (int32_t)(*first_byte_ptr); + } + } + } break; + default: { + if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + if ((int32_t)(*first_byte_ptr) > + bmp_ptr->src_row_bytes - bmp_ptr->col_num) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num, + *second_byte_ptr, *first_byte_ptr); + bmp_ptr->col_num += (int32_t)(*first_byte_ptr); + } + } + } + _bmp_error(bmp_ptr, "Any Uncontrol Error"); + return 0; +} +int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr) { + uint8_t* first_byte_ptr = NULL; + uint8_t* second_byte_ptr = NULL; + bmp_ptr->col_num = 0; + while (TRUE) { + FX_DWORD skip_size_org = bmp_ptr->skip_size; + if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { + return 2; + } + switch (*first_byte_ptr) { + case RLE_MARKER: { + if (_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + switch (*first_byte_ptr) { + case RLE_EOL: { + if (bmp_ptr->row_num >= bmp_ptr->height) { + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + bmp_ptr->col_num = 0; + FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA); + continue; + } + case RLE_EOI: { + if (bmp_ptr->row_num < bmp_ptr->height) { + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + } + _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL); + return 1; + } + case RLE_DELTA: { + uint8_t* delta_ptr; + if (_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + bmp_ptr->col_num += (int32_t)delta_ptr[0]; + int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1]; + if (bmp_ptr->col_num >= bmp_ptr->out_row_bytes || + bmp_row_num_next >= bmp_ptr->height) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported"); + return 0; + } + while (bmp_ptr->row_num < bmp_row_num_next) { + FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes); + bmp_ptr->_bmp_get_row_fn( + bmp_ptr, bmp_ptr->imgTB_flag + ? bmp_ptr->row_num++ + : (bmp_ptr->height - 1 - bmp_ptr->row_num++), + bmp_ptr->out_row_buffer); + } + } break; + default: { + uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1); + if ((int32_t)*first_byte_ptr >= + bmp_ptr->out_row_bytes - bmp_ptr->col_num) { + if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; + } + if (_bmp_read_data(bmp_ptr, &second_byte_ptr, + size & 1 ? size + 1 : size) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + for (uint8_t i = 0; i < *first_byte_ptr; i++) { + if (i & 0x01) { + *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = + (*second_byte_ptr++ & 0x0F); + } else { + *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = + ((*second_byte_ptr & 0xF0) >> 4); + } + } + } + } + } break; + default: { + if (_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) { + bmp_ptr->skip_size = skip_size_org; + return 2; + } + if ((int32_t)*first_byte_ptr > + bmp_ptr->out_row_bytes - bmp_ptr->col_num) { + uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1); + if (size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) { + _bmp_error(bmp_ptr, "The Bmp File Is Corrupt"); + return 0; + } + *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1; + } + for (uint8_t i = 0; i < *first_byte_ptr; i++) { + if (i & 0x01) { + *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = + (*second_byte_ptr & 0x0F); + } else { + *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = + ((*second_byte_ptr & 0xF0) >> 4); + } + } + } + } + } + _bmp_error(bmp_ptr, "Any Uncontrol Error"); + return 0; +} +uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr, + uint8_t** des_buf_pp, + FX_DWORD data_size) { + if (bmp_ptr == NULL || bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) { + return NULL; + } + *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size; + bmp_ptr->skip_size += data_size; + return *des_buf_pp; +} +void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, + int32_t status) { + bmp_ptr->decode_status = status; + bmp_ptr->next_in += bmp_ptr->skip_size; + bmp_ptr->avail_in -= bmp_ptr->skip_size; + bmp_ptr->skip_size = 0; +} +void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, + uint8_t* src_buf, + FX_DWORD src_size) { + bmp_ptr->next_in = src_buf; + bmp_ptr->avail_in = src_size; + bmp_ptr->skip_size = 0; +} +FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, + uint8_t** avial_buf_ptr) { + if (avial_buf_ptr != NULL) { + *avial_buf_ptr = NULL; + if (bmp_ptr->avail_in > 0) { + *avial_buf_ptr = bmp_ptr->next_in; + } + } + return bmp_ptr->avail_in; +} +bmp_compress_struct_p _bmp_create_compress() { + bmp_compress_struct_p bmp_ptr; + bmp_ptr = FX_Alloc(bmp_compress_struct, 1); + if (bmp_ptr) { + FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct)); + } + return bmp_ptr; +} +void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr) { + if (bmp_ptr) { + if (bmp_ptr->src_free && bmp_ptr->src_buf) { + FX_Free(bmp_ptr->src_buf); + } + FX_Free(bmp_ptr); + } +} +static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf) { + FX_DWORD offset; + offset = 0; + _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType); + offset += 2; + _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize); + offset += 4; + _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1); + offset += 2; + _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2); + offset += 2; + _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits); + offset += 4; +} +static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf) { + FX_DWORD offset; + offset = sizeof(BmpFileHeader); + _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biWidth); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biHeight); + offset += 4; + _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes); + offset += 2; + _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount); + offset += 2; + _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], + (FX_DWORD)info_head_ptr->biXPelsPerMeter); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], + (FX_DWORD)info_head_ptr->biYPelsPerMeter); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed); + offset += 4; + _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant); + offset += 4; +} +#ifdef BMP_SUPPORT_BITFIELD +static void _bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size) { + if (bmp_ptr->info_header.biBitCount != 16 && + bmp_ptr->info_header.biBitCount != 32) { + return; + } + FX_DWORD size, dst_pos, i; + size = bmp_ptr->src_pitch * bmp_ptr->src_row * + bmp_ptr->info_header.biBitCount / 16; + dst_pos = bmp_ptr->file_header.bfOffBits; + dst_size += size; + dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); + if (dst_buf == NULL) { + return; + } + FXSYS_memset(&dst_buf[dst_pos], 0, size); + FX_DWORD mask_red; + FX_DWORD mask_green; + FX_DWORD mask_blue; + mask_red = 0x7C00; + mask_green = 0x03E0; + mask_blue = 0x001F; + if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) { + if (bmp_ptr->bit_type == BMP_BIT_565) { + mask_red = 0xF800; + mask_green = 0x07E0; + mask_blue = 0x001F; + } + if (bmp_ptr->info_header.biBitCount == 32) { + mask_red = 0xFF0000; + mask_green = 0x00FF00; + mask_blue = 0x0000FF; + } + _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red); + dst_pos += 4; + _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green); + dst_pos += 4; + _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue); + dst_pos += 4; + bmp_ptr->file_header.bfOffBits = dst_pos; + } + uint8_t blue_bits = 0; + uint8_t green_bits = 0; + uint8_t red_bits = 0; + for (i = 0; i < bmp_ptr->info_header.biBitCount; i++) { + if ((mask_blue >> i) & 0x01) { + blue_bits++; + } + if ((mask_green >> i) & 0x01) { + green_bits++; + } + if ((mask_red >> i) & 0x01) { + red_bits++; + } + } + green_bits += blue_bits; + red_bits += green_bits; + blue_bits = 8 - blue_bits; + green_bits -= 8; + red_bits -= 8; + i = 0; + for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) { + while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) { + uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; + uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; + uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++]; + if (bmp_ptr->src_bpp == 32) { + i++; + } + FX_DWORD pix_val = 0; + pix_val |= (b >> blue_bits) & mask_blue; + pix_val |= (g << green_bits) & mask_green; + pix_val |= (r << red_bits) & mask_red; + if (bmp_ptr->info_header.biBitCount == 16) { + _SetWord_LSBFirst(&dst_buf[dst_pos], (FX_WORD)pix_val); + dst_pos += 2; + } else { + _SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val); + dst_pos += 4; + } + } + } + dst_size = dst_pos; +} +#endif +static void _bmp_encode_rgb(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size) { + if (bmp_ptr->info_header.biBitCount == 16) { +#ifdef BMP_SUPPORT_BITFIELD + _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); +#endif + return; + } + FX_DWORD size, dst_pos; + FX_DWORD dst_pitch = + (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4; + size = dst_pitch * bmp_ptr->src_row; + dst_pos = bmp_ptr->file_header.bfOffBits; + dst_size += size; + dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); + if (dst_buf == NULL) { + return; + } + FXSYS_memset(&dst_buf[dst_pos], 0, size); + for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) { + FXSYS_memcpy(&dst_buf[dst_pos], + &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch], + bmp_ptr->src_pitch); + dst_pos += dst_pitch; + } + dst_size = dst_pos; +} +static uint8_t _bmp_rle8_search(const uint8_t* buf, int32_t len) { + uint8_t num; + num = 1; + while (num < len) { + if (buf[num - 1] != buf[num] || num == 0xFF) { + break; + } + num++; + } + return num; +} +static void _bmp_encode_rle8(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size) { + FX_DWORD size, dst_pos, index; + uint8_t rle[2] = {0}; + size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2; + dst_pos = bmp_ptr->file_header.bfOffBits; + dst_size += size; + dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); + if (dst_buf == NULL) { + return; + } + FXSYS_memset(&dst_buf[dst_pos], 0, size); + for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1;) { + index = row_num * bmp_ptr->src_pitch; + rle[0] = _bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i); + rle[1] = bmp_ptr->src_buf[index + i]; + if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { + rle[0] = uint8_t(bmp_ptr->src_pitch - i); + if (rle[0]) { + dst_buf[dst_pos++] = rle[0]; + dst_buf[dst_pos++] = rle[1]; + } + dst_buf[dst_pos++] = RLE_MARKER; + dst_buf[dst_pos++] = RLE_EOL; + i = 0; + row_num--; + } else { + i += rle[0]; + dst_buf[dst_pos++] = rle[0]; + dst_buf[dst_pos++] = rle[1]; + } + } + dst_buf[dst_pos++] = RLE_MARKER; + dst_buf[dst_pos++] = RLE_EOI; + dst_size = dst_pos; +} +static uint8_t _bmp_rle4_search(const uint8_t* buf, int32_t len) { + uint8_t num; + num = 2; + while (num < len) { + if (buf[num - 2] != buf[num] || num == 0xFF) { + break; + } + num++; + } + return num; +} +static void _bmp_encode_rle4(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size) { + FX_DWORD size, dst_pos, index; + uint8_t rle[2] = {0}; + size = bmp_ptr->src_pitch * bmp_ptr->src_row; + dst_pos = bmp_ptr->file_header.bfOffBits; + dst_size += size; + dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size); + if (dst_buf == NULL) { + return; + } + FXSYS_memset(&dst_buf[dst_pos], 0, size); + for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1; + rle[1] = 0) { + index = row_num * bmp_ptr->src_pitch; + rle[0] = _bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i); + rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4; + rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f; + if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) { + rle[0] = uint8_t(bmp_ptr->src_pitch - i); + if (rle[0]) { + dst_buf[dst_pos++] = rle[0]; + dst_buf[dst_pos++] = rle[1]; + } + dst_buf[dst_pos++] = RLE_MARKER; + dst_buf[dst_pos++] = RLE_EOL; + i = 0; + row_num--; + } else { + i += rle[0]; + dst_buf[dst_pos++] = rle[0]; + dst_buf[dst_pos++] = rle[1]; + } + } + dst_buf[dst_pos++] = RLE_MARKER; + dst_buf[dst_pos++] = RLE_EOI; + dst_size = dst_pos; +} +FX_BOOL _bmp_encode_image(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size) { + FX_DWORD head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader); + FX_DWORD pal_size = sizeof(FX_DWORD) * bmp_ptr->pal_num; + if (bmp_ptr->info_header.biClrUsed > 0 && + bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) { + pal_size = sizeof(FX_DWORD) * bmp_ptr->info_header.biClrUsed; + } + dst_size = head_size + sizeof(FX_DWORD) * bmp_ptr->pal_num; + dst_buf = FX_TryAlloc(uint8_t, dst_size); + if (dst_buf == NULL) { + return FALSE; + } + FXSYS_memset(dst_buf, 0, dst_size); + bmp_ptr->file_header.bfOffBits = head_size; + if (bmp_ptr->pal_ptr && pal_size) { + FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size); + bmp_ptr->file_header.bfOffBits += pal_size; + } + WriteInfoHeader(&bmp_ptr->info_header, dst_buf); + switch (bmp_ptr->info_header.biCompression) { + case BMP_RGB: + _bmp_encode_rgb(bmp_ptr, dst_buf, dst_size); + break; + case BMP_BITFIELDS: +#ifdef BMP_SUPPORT_BITFIELD + _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size); +#endif + break; + case BMP_RLE8: + _bmp_encode_rle8(bmp_ptr, dst_buf, dst_size); + break; + case BMP_RLE4: + _bmp_encode_rle4(bmp_ptr, dst_buf, dst_size); + break; + default:; + } + bmp_ptr->file_header.bfSize = dst_size; + WriteFileHeader(&bmp_ptr->file_header, dst_buf); + return TRUE; +} diff --git a/core/src/fxcodec/lbmp/fx_bmp.h b/core/src/fxcodec/lbmp/fx_bmp.h index d1232f1f11..06bfe1e99d 100644 --- a/core/src/fxcodec/lbmp/fx_bmp.h +++ b/core/src/fxcodec/lbmp/fx_bmp.h @@ -1,155 +1,155 @@ -// 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 - -#include "core/include/fxcrt/fx_basic.h" - -#define BMP_SUPPORT_BITFIELD -#define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4 -#define BMP_PAL_ENCODE(a, r, g, b) \ - (((FX_DWORD)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define BMP_D_STATUS_HEADER 0x01 -#define BMP_D_STATUS_PAL 0x02 -#define BMP_D_STATUS_DATA_PRE 0x03 -#define BMP_D_STATUS_DATA 0x04 -#define BMP_D_STATUS_TAIL 0x00 -#define BMP_SIGNATURE 0x4D42 -#define BMP_PAL_NEW 0 -#define BMP_PAL_OLD 1 -#define RLE_MARKER 0 -#define RLE_EOL 0 -#define RLE_EOI 1 -#define RLE_DELTA 2 -#define BMP_RGB 0L -#define BMP_RLE8 1L -#define BMP_RLE4 2L -#define BMP_BITFIELDS 3L -#define BMP_BIT_555 0 -#define BMP_BIT_565 1 -#define BMP_MAX_ERROR_SIZE 256 -#pragma pack(1) -typedef struct tagBmpFileHeader { - FX_WORD bfType; - FX_DWORD bfSize; - FX_WORD bfReserved1; - FX_WORD bfReserved2; - FX_DWORD bfOffBits; -} BmpFileHeader, *BmpFileHeaderPtr; -typedef struct tagBmpCoreHeader { - FX_DWORD bcSize; - FX_WORD bcWidth; - FX_WORD bcHeight; - FX_WORD bcPlanes; - FX_WORD bcBitCount; -} BmpCoreHeader, *BmpCoreHeaderPtr; -typedef struct tagBmpInfoHeader { - FX_DWORD biSize; - int32_t biWidth; - int32_t biHeight; - FX_WORD biPlanes; - FX_WORD biBitCount; - FX_DWORD biCompression; - FX_DWORD biSizeImage; - int32_t biXPelsPerMeter; - int32_t biYPelsPerMeter; - FX_DWORD biClrUsed; - FX_DWORD biClrImportant; -} BmpInfoHeader, *BmpInfoHeaderPtr; -#pragma pack() -typedef struct tag_bmp_decompress_struct bmp_decompress_struct; -typedef bmp_decompress_struct* bmp_decompress_struct_p; -typedef bmp_decompress_struct_p* bmp_decompress_struct_pp; -struct tag_bmp_decompress_struct { - jmp_buf jmpbuf; - FX_CHAR* err_ptr; - void (*_bmp_error_fn)(bmp_decompress_struct_p gif_ptr, - const FX_CHAR* err_msg); - - void* context_ptr; - - BmpFileHeaderPtr bmp_header_ptr; - BmpInfoHeaderPtr bmp_infoheader_ptr; - int32_t width; - int32_t height; - FX_DWORD compress_flag; - int32_t components; - int32_t src_row_bytes; - int32_t out_row_bytes; - uint8_t* out_row_buffer; - FX_WORD bitCounts; - FX_DWORD color_used; - FX_BOOL imgTB_flag; - int32_t pal_num; - int32_t pal_type; - FX_DWORD* pal_ptr; - FX_DWORD data_size; - FX_DWORD img_data_offset; - FX_DWORD img_ifh_size; - int32_t row_num; - int32_t col_num; - int32_t dpi_x; - int32_t dpi_y; -#ifdef BMP_SUPPORT_BITFIELD - FX_DWORD mask_red; - FX_DWORD mask_green; - FX_DWORD mask_blue; -#endif - - FX_BOOL (*_bmp_get_data_position_fn)(bmp_decompress_struct_p bmp_ptr, FX_DWORD cur_pos); - void (*_bmp_get_row_fn)(bmp_decompress_struct_p bmp_ptr, - int32_t row_num, - uint8_t* row_buf); - uint8_t* next_in; - FX_DWORD avail_in; - FX_DWORD skip_size; - int32_t decode_status; -}; -void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg); -bmp_decompress_struct_p _bmp_create_decompress(); -void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr); -int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr); -int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr); -int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr); -int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr); -int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr); -uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr, - uint8_t** des_buf_pp, - FX_DWORD data_size); -void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status); -void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, - uint8_t* src_buf, - FX_DWORD src_size); -FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, - uint8_t** avial_buf_ptr); -#define BMP_PTR_NOT_NULL(ptr, bmp_ptr) \ - if (ptr == NULL) { \ - _bmp_error(bmp_ptr, "Out Of Memory"); \ - return 0; \ - } -typedef struct tag_bmp_compress_struct bmp_compress_struct; -typedef bmp_compress_struct* bmp_compress_struct_p; -typedef bmp_compress_struct_p* bmp_compress_struct_pp; -struct tag_bmp_compress_struct { - BmpFileHeader file_header; - BmpInfoHeader info_header; - uint8_t* src_buf; - FX_DWORD src_pitch; - FX_DWORD src_row; - uint8_t src_bpp; - FX_DWORD src_width; - FX_BOOL src_free; - FX_DWORD* pal_ptr; - FX_WORD pal_num; -#ifdef BMP_SUPPORT_BITFIELD - uint8_t bit_type; -#endif -}; -bmp_compress_struct_p _bmp_create_compress(); -void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr); -FX_BOOL _bmp_encode_image(bmp_compress_struct_p bmp_ptr, - uint8_t*& dst_buf, - FX_DWORD& dst_size); +// 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 + +#include "core/include/fxcrt/fx_basic.h" + +#define BMP_SUPPORT_BITFIELD +#define BMP_WIDTHBYTES(width, bitCount) ((width * bitCount) + 31) / 32 * 4 +#define BMP_PAL_ENCODE(a, r, g, b) \ + (((FX_DWORD)(a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define BMP_D_STATUS_HEADER 0x01 +#define BMP_D_STATUS_PAL 0x02 +#define BMP_D_STATUS_DATA_PRE 0x03 +#define BMP_D_STATUS_DATA 0x04 +#define BMP_D_STATUS_TAIL 0x00 +#define BMP_SIGNATURE 0x4D42 +#define BMP_PAL_NEW 0 +#define BMP_PAL_OLD 1 +#define RLE_MARKER 0 +#define RLE_EOL 0 +#define RLE_EOI 1 +#define RLE_DELTA 2 +#define BMP_RGB 0L +#define BMP_RLE8 1L +#define BMP_RLE4 2L +#define BMP_BITFIELDS 3L +#define BMP_BIT_555 0 +#define BMP_BIT_565 1 +#define BMP_MAX_ERROR_SIZE 256 +#pragma pack(1) +typedef struct tagBmpFileHeader { + FX_WORD bfType; + FX_DWORD bfSize; + FX_WORD bfReserved1; + FX_WORD bfReserved2; + FX_DWORD bfOffBits; +} BmpFileHeader, *BmpFileHeaderPtr; +typedef struct tagBmpCoreHeader { + FX_DWORD bcSize; + FX_WORD bcWidth; + FX_WORD bcHeight; + FX_WORD bcPlanes; + FX_WORD bcBitCount; +} BmpCoreHeader, *BmpCoreHeaderPtr; +typedef struct tagBmpInfoHeader { + FX_DWORD biSize; + int32_t biWidth; + int32_t biHeight; + FX_WORD biPlanes; + FX_WORD biBitCount; + FX_DWORD biCompression; + FX_DWORD biSizeImage; + int32_t biXPelsPerMeter; + int32_t biYPelsPerMeter; + FX_DWORD biClrUsed; + FX_DWORD biClrImportant; +} BmpInfoHeader, *BmpInfoHeaderPtr; +#pragma pack() +typedef struct tag_bmp_decompress_struct bmp_decompress_struct; +typedef bmp_decompress_struct* bmp_decompress_struct_p; +typedef bmp_decompress_struct_p* bmp_decompress_struct_pp; +struct tag_bmp_decompress_struct { + jmp_buf jmpbuf; + FX_CHAR* err_ptr; + void (*_bmp_error_fn)(bmp_decompress_struct_p gif_ptr, + const FX_CHAR* err_msg); + + void* context_ptr; + + BmpFileHeaderPtr bmp_header_ptr; + BmpInfoHeaderPtr bmp_infoheader_ptr; + int32_t width; + int32_t height; + FX_DWORD compress_flag; + int32_t components; + int32_t src_row_bytes; + int32_t out_row_bytes; + uint8_t* out_row_buffer; + FX_WORD bitCounts; + FX_DWORD color_used; + FX_BOOL imgTB_flag; + int32_t pal_num; + int32_t pal_type; + FX_DWORD* pal_ptr; + FX_DWORD data_size; + FX_DWORD img_data_offset; + FX_DWORD img_ifh_size; + int32_t row_num; + int32_t col_num; + int32_t dpi_x; + int32_t dpi_y; +#ifdef BMP_SUPPORT_BITFIELD + FX_DWORD mask_red; + FX_DWORD mask_green; + FX_DWORD mask_blue; +#endif + + FX_BOOL (*_bmp_get_data_position_fn)(bmp_decompress_struct_p bmp_ptr, FX_DWORD cur_pos); + void (*_bmp_get_row_fn)(bmp_decompress_struct_p bmp_ptr, + int32_t row_num, + uint8_t* row_buf); + uint8_t* next_in; + FX_DWORD avail_in; + FX_DWORD skip_size; + int32_t decode_status; +}; +void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg); +bmp_decompress_struct_p _bmp_create_decompress(); +void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr); +int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr); +int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr); +int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr); +int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr); +int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr); +uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr, + uint8_t** des_buf_pp, + FX_DWORD data_size); +void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status); +void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, + uint8_t* src_buf, + FX_DWORD src_size); +FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, + uint8_t** avial_buf_ptr); +#define BMP_PTR_NOT_NULL(ptr, bmp_ptr) \ + if (ptr == NULL) { \ + _bmp_error(bmp_ptr, "Out Of Memory"); \ + return 0; \ + } +typedef struct tag_bmp_compress_struct bmp_compress_struct; +typedef bmp_compress_struct* bmp_compress_struct_p; +typedef bmp_compress_struct_p* bmp_compress_struct_pp; +struct tag_bmp_compress_struct { + BmpFileHeader file_header; + BmpInfoHeader info_header; + uint8_t* src_buf; + FX_DWORD src_pitch; + FX_DWORD src_row; + uint8_t src_bpp; + FX_DWORD src_width; + FX_BOOL src_free; + FX_DWORD* pal_ptr; + FX_WORD pal_num; +#ifdef BMP_SUPPORT_BITFIELD + uint8_t bit_type; +#endif +}; +bmp_compress_struct_p _bmp_create_compress(); +void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr); +FX_BOOL _bmp_encode_image(bmp_compress_struct_p bmp_ptr, + uint8_t*& dst_buf, + FX_DWORD& dst_size); diff --git a/core/src/fxcodec/lgif/fx_gif.cpp b/core/src/fxcodec/lgif/fx_gif.cpp index b07ebb3bc9..c00b7a74b2 100644 --- a/core/src/fxcodec/lgif/fx_gif.cpp +++ b/core/src/fxcodec/lgif/fx_gif.cpp @@ -1,1426 +1,1426 @@ -// 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(uint8_t* src_buf, FX_DWORD src_size) { - next_in = src_buf; - avail_in = src_size; -} -FX_DWORD CGifLZWDecoder::GetAvailInput() { - return avail_in; -} -void CGifLZWDecoder::InitTable(uint8_t 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_memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE); - FXSYS_memset(stack, 0, GIF_MAX_LZW_CODE); - for (FX_WORD i = 0; i < code_clear; i++) { - code_table[i].suffix = (uint8_t)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++] = (uint8_t)code; - code_first = (uint8_t)code; -} -void CGifLZWDecoder::AddCode(FX_WORD prefix_code, uint8_t 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++; - } - } -} -int32_t CGifLZWDecoder::Decode(uint8_t* 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_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size); - stack_size -= (FX_WORD)des_size; - return 3; - } - FXSYS_memcpy(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); - uint8_t 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_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], - des_size - i); - stack_size -= (FX_WORD)(des_size - i); - return 3; - } - FXSYS_memcpy(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(uint8_t*& 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(uint8_t, dst_buf, dst_len); - } - if (dst_buf == NULL) { - dst_len = size; - dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len); - if (dst_buf == NULL) { - return FALSE; - } - } - FXSYS_memset(dst_buf + len_org, 0, dst_len - len_org); - return dst_buf != NULL; - } - return TRUE; -} -static inline void _gif_cut_index(uint8_t& val, - FX_DWORD index, - uint8_t index_bit, - uint8_t index_bit_use, - uint8_t 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 uint8_t _gif_cut_buf(const uint8_t* buf, - FX_DWORD& offset, - uint8_t bit_cut, - uint8_t& bit_offset, - FX_DWORD& bit_num) { - if (bit_cut != 8) { - FX_WORD index = 0; - index |= ((1 << bit_cut) - 1) << (7 - bit_offset); - uint8_t 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_memset(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(uint8_t code_len, - const uint8_t* src_buf, - uint8_t*& 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(uint8_t*& 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_memcpy(&dst_buf[offset], index_buf, index_buf_len); - offset += index_buf_len; - FXSYS_memset(index_buf, 0, GIF_DATA_BLOCK); - index_buf_len = 0; -} -void CGifLZWEncoder::EncodeString(FX_DWORD index, - uint8_t*& dst_buf, - FX_DWORD& dst_len, - FX_DWORD& offset) { - uint8_t 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(const uint8_t* src_buf, - FX_DWORD src_len, - uint8_t*& dst_buf, - FX_DWORD& dst_len, - FX_DWORD& offset) { - uint8_t 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(const uint8_t* buf, - FX_DWORD& offset, - uint8_t& 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(uint8_t*& 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(uint8_t, sizeof(gif_decompress_struct)); - if (gif_ptr == NULL) { - return NULL; - } - FXSYS_memset(gif_ptr, 0, sizeof(gif_decompress_struct)); - gif_ptr->decode_status = GIF_D_STATUS_SIG; - gif_ptr->img_ptr_arr_ptr = new CFX_ArrayTemplate; -#ifdef GIF_SUPPORT_COMMENT_EXTENSION - gif_ptr->cmt_data_ptr = new CFX_ByteString; -#endif -#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION - gif_ptr->pt_ptr_arr_ptr = new CFX_ArrayTemplate; -#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) { - int32_t size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize(); - for (int32_t 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) { - int32_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize(); - for (int32_t 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(uint8_t, sizeof(gif_compress_struct)); - if (gif_ptr == NULL) { - return NULL; - } - FXSYS_memset(gif_ptr, 0, sizeof(gif_compress_struct)); - gif_ptr->img_encoder_ptr = new CGifLZWEncoder; - gif_ptr->header_ptr = (GifHeader*)FX_Alloc(uint8_t, sizeof(GifHeader)); - if (gif_ptr->header_ptr == NULL) { - delete (gif_ptr->img_encoder_ptr); - FX_Free(gif_ptr); - return NULL; - } - FXSYS_memcpy(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3); - FXSYS_memcpy(gif_ptr->header_ptr->version, "89a", 3); - gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(uint8_t, 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_memset(gif_ptr->lsd_ptr, 0, sizeof(GifLSD)); - gif_ptr->image_info_ptr = - (GifImageInfo*)FX_Alloc(uint8_t, 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_memset(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo)); -#ifdef GIF_SUPPORT_APPLICATION_EXTENSION - FXSYS_memcpy(gif_ptr->app_identify, "netscape", 8); - FXSYS_memcpy(gif_ptr->app_authentication, "2.0", 3); -#endif -#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION - gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, 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(uint8_t, 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_memset(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, const FX_CHAR* 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, const FX_CHAR* err_msg) {} -int32_t _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, (uint8_t**)&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, (uint8_t**)&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); - int32_t global_pal_size = gif_ptr->global_pal_num * 3; - uint8_t* 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(uint8_t, global_pal_size); - GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr); - FXSYS_memcpy(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size); - } - gif_ptr->width = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->width); - gif_ptr->height = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->height); - gif_ptr->bc_index = gif_lsd_ptr->bc_index; - gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect; - return 1; -} -int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr) { - if (gif_ptr == NULL) { - return 0; - } - int32_t ret = 1; - while (TRUE) { - switch (gif_ptr->decode_status) { - case GIF_D_STATUS_TAIL: - return 1; - case GIF_D_STATUS_SIG: { - uint8_t* 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: { - uint8_t* 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: { - int32_t 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: { - uint8_t* data_size_ptr = NULL; - uint8_t* 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 -} -int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr) { - uint8_t* data_size_ptr = NULL; - uint8_t* 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, (uint8_t**)&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) { - uint8_t 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((const uint8_t*)data_ptr, data_size); - } - FXSYS_memcpy(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8); - FXSYS_memcpy(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(uint8_t, gif_ptr->app_data_size); - GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr); - FXSYS_memcpy(gif_ptr->app_data, const uint8_t*(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) { - uint8_t 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((const FX_CHAR*)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, (uint8_t**)&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_memset(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(uint8_t, sizeof(GifPTE)); - GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr); - gif_pt_ptr->string_ptr = 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((uint8_t*)&gif_pte_ptr->grid_left); - gif_pt_ptr->pte_ptr->grid_top = - _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_top); - gif_pt_ptr->pte_ptr->grid_width = - _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_width); - gif_pt_ptr->pte_ptr->grid_height = - _GetWord_LSBFirst((uint8_t*)&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) { - uint8_t 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((const FX_CHAR*)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, (uint8_t**)&gif_gce_ptr, 6) == NULL) { - return 2; - } - if (gif_ptr->gce_ptr == NULL) { - gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, 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((uint8_t*)&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; -} -int32_t _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, (uint8_t**)&gif_img_info_ptr, 9) == NULL) { - return 2; - } - GifImage* gif_image_ptr = (GifImage*)FX_Alloc(uint8_t, sizeof(GifImage)); - GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr); - FXSYS_memset(gif_image_ptr, 0, sizeof(GifImage)); - gif_image_ptr->image_info_ptr = - (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo)); - GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr); - gif_image_ptr->image_info_ptr->left = - _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->left); - gif_image_ptr->image_info_ptr->top = - _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->top); - gif_image_ptr->image_info_ptr->width = - _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->width); - gif_image_ptr->image_info_ptr->height = - _GetWord_LSBFirst((uint8_t*)&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); - int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3; - uint8_t* 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_memcpy((uint8_t*)gif_image_ptr->local_pal_ptr, loc_pal_ptr, - loc_pal_size); - } - } - uint8_t* 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; -} -int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num) { - if (gif_ptr == NULL || frame_num < 0 || - frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize()) { - return 0; - } - uint8_t* data_size_ptr = NULL; - uint8_t* 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(uint8_t, 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; - int32_t 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, - (int32_t)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 - ? (int32_t)gif_image_ptr->image_gce_ptr->trans_index - : -1, - (int32_t)((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 = 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; - int32_t 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 >= - (int32_t)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, - int32_t 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; -} -uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr, - uint8_t** 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, - uint8_t* 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, - uint8_t** 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; -} -int32_t _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, - uint8_t*& dst_buf, - FX_DWORD& dst_len) { - if (gif_ptr->cur_offset) { - return TRUE; - } - dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF); - dst_buf = FX_TryAlloc(uint8_t, dst_len); - if (dst_buf == NULL) { - return FALSE; - } - FXSYS_memset(dst_buf, 0, dst_len); - FXSYS_memcpy(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_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size); - gif_ptr->cur_offset += size; - } - return TRUE; -} -void interlace_buf(const uint8_t* buf, FX_DWORD pitch, FX_DWORD height) { - CFX_ArrayTemplate pass[4]; - int i, j; - FX_DWORD row; - row = 0; - uint8_t* 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(uint8_t, pitch); - if (temp == NULL) { - return; - } - FXSYS_memcpy(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_memcpy((uint8_t*)&buf[pitch * row], pass[i].GetAt(j), pitch); - FX_Free(pass[i].GetAt(j)); - } - } -} -static void _gif_write_block_data(const uint8_t* src_buf, - FX_DWORD src_len, - uint8_t*& 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_memcpy(&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++] = (uint8_t)src_len; - FXSYS_memcpy(&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, - uint8_t*& 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_memcmp(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_memcpy(&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); - } - uint8_t 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_memcmp(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_memcmp(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_memcmp(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_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8); - gif_ptr->cur_offset += 8; - FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8); - gif_ptr->cur_offset += 3; - FXSYS_memcpy(&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, - uint8_t*& 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; -} +// 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(uint8_t* src_buf, FX_DWORD src_size) { + next_in = src_buf; + avail_in = src_size; +} +FX_DWORD CGifLZWDecoder::GetAvailInput() { + return avail_in; +} +void CGifLZWDecoder::InitTable(uint8_t 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_memset(code_table, 0, sizeof(tag_Table) * GIF_MAX_LZW_CODE); + FXSYS_memset(stack, 0, GIF_MAX_LZW_CODE); + for (FX_WORD i = 0; i < code_clear; i++) { + code_table[i].suffix = (uint8_t)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++] = (uint8_t)code; + code_first = (uint8_t)code; +} +void CGifLZWDecoder::AddCode(FX_WORD prefix_code, uint8_t 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++; + } + } +} +int32_t CGifLZWDecoder::Decode(uint8_t* 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_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], des_size); + stack_size -= (FX_WORD)des_size; + return 3; + } + FXSYS_memcpy(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); + uint8_t 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_memcpy(des_buf, &stack[GIF_MAX_LZW_CODE - stack_size], + des_size - i); + stack_size -= (FX_WORD)(des_size - i); + return 3; + } + FXSYS_memcpy(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(uint8_t*& 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(uint8_t, dst_buf, dst_len); + } + if (dst_buf == NULL) { + dst_len = size; + dst_buf = FX_Realloc(uint8_t, dst_buf, dst_len); + if (dst_buf == NULL) { + return FALSE; + } + } + FXSYS_memset(dst_buf + len_org, 0, dst_len - len_org); + return dst_buf != NULL; + } + return TRUE; +} +static inline void _gif_cut_index(uint8_t& val, + FX_DWORD index, + uint8_t index_bit, + uint8_t index_bit_use, + uint8_t 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 uint8_t _gif_cut_buf(const uint8_t* buf, + FX_DWORD& offset, + uint8_t bit_cut, + uint8_t& bit_offset, + FX_DWORD& bit_num) { + if (bit_cut != 8) { + FX_WORD index = 0; + index |= ((1 << bit_cut) - 1) << (7 - bit_offset); + uint8_t 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_memset(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(uint8_t code_len, + const uint8_t* src_buf, + uint8_t*& 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(uint8_t*& 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_memcpy(&dst_buf[offset], index_buf, index_buf_len); + offset += index_buf_len; + FXSYS_memset(index_buf, 0, GIF_DATA_BLOCK); + index_buf_len = 0; +} +void CGifLZWEncoder::EncodeString(FX_DWORD index, + uint8_t*& dst_buf, + FX_DWORD& dst_len, + FX_DWORD& offset) { + uint8_t 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(const uint8_t* src_buf, + FX_DWORD src_len, + uint8_t*& dst_buf, + FX_DWORD& dst_len, + FX_DWORD& offset) { + uint8_t 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(const uint8_t* buf, + FX_DWORD& offset, + uint8_t& 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(uint8_t*& 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(uint8_t, sizeof(gif_decompress_struct)); + if (gif_ptr == NULL) { + return NULL; + } + FXSYS_memset(gif_ptr, 0, sizeof(gif_decompress_struct)); + gif_ptr->decode_status = GIF_D_STATUS_SIG; + gif_ptr->img_ptr_arr_ptr = new CFX_ArrayTemplate; +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + gif_ptr->cmt_data_ptr = new CFX_ByteString; +#endif +#ifdef GIF_SUPPORT_PLAIN_TEXT_EXTENSION + gif_ptr->pt_ptr_arr_ptr = new CFX_ArrayTemplate; +#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) { + int32_t size_img_arr = gif_ptr->img_ptr_arr_ptr->GetSize(); + for (int32_t 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) { + int32_t size_pt_arr = gif_ptr->pt_ptr_arr_ptr->GetSize(); + for (int32_t 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(uint8_t, sizeof(gif_compress_struct)); + if (gif_ptr == NULL) { + return NULL; + } + FXSYS_memset(gif_ptr, 0, sizeof(gif_compress_struct)); + gif_ptr->img_encoder_ptr = new CGifLZWEncoder; + gif_ptr->header_ptr = (GifHeader*)FX_Alloc(uint8_t, sizeof(GifHeader)); + if (gif_ptr->header_ptr == NULL) { + delete (gif_ptr->img_encoder_ptr); + FX_Free(gif_ptr); + return NULL; + } + FXSYS_memcpy(gif_ptr->header_ptr->signature, GIF_SIGNATURE, 3); + FXSYS_memcpy(gif_ptr->header_ptr->version, "89a", 3); + gif_ptr->lsd_ptr = (GifLSD*)FX_Alloc(uint8_t, 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_memset(gif_ptr->lsd_ptr, 0, sizeof(GifLSD)); + gif_ptr->image_info_ptr = + (GifImageInfo*)FX_Alloc(uint8_t, 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_memset(gif_ptr->image_info_ptr, 0, sizeof(GifImageInfo)); +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + FXSYS_memcpy(gif_ptr->app_identify, "netscape", 8); + FXSYS_memcpy(gif_ptr->app_authentication, "2.0", 3); +#endif +#ifdef GIF_SUPPORT_GRAPHIC_CONTROL_EXTENSION + gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, 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(uint8_t, 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_memset(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, const FX_CHAR* 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, const FX_CHAR* err_msg) {} +int32_t _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, (uint8_t**)&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, (uint8_t**)&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); + int32_t global_pal_size = gif_ptr->global_pal_num * 3; + uint8_t* 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(uint8_t, global_pal_size); + GIF_PTR_NOT_NULL(gif_ptr->global_pal_ptr, gif_ptr); + FXSYS_memcpy(gif_ptr->global_pal_ptr, global_pal_ptr, global_pal_size); + } + gif_ptr->width = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->width); + gif_ptr->height = (int)_GetWord_LSBFirst((uint8_t*)&gif_lsd_ptr->height); + gif_ptr->bc_index = gif_lsd_ptr->bc_index; + gif_ptr->pixel_aspect = gif_lsd_ptr->pixel_aspect; + return 1; +} +int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr) { + if (gif_ptr == NULL) { + return 0; + } + int32_t ret = 1; + while (TRUE) { + switch (gif_ptr->decode_status) { + case GIF_D_STATUS_TAIL: + return 1; + case GIF_D_STATUS_SIG: { + uint8_t* 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: { + uint8_t* 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: { + int32_t 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: { + uint8_t* data_size_ptr = NULL; + uint8_t* 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 +} +int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr) { + uint8_t* data_size_ptr = NULL; + uint8_t* 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, (uint8_t**)&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) { + uint8_t 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((const uint8_t*)data_ptr, data_size); + } + FXSYS_memcpy(gif_ptr->app_identify, gif_ae_ptr->app_identify, 8); + FXSYS_memcpy(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(uint8_t, gif_ptr->app_data_size); + GIF_PTR_NOT_NULL(gif_ptr->app_data, gif_ptr); + FXSYS_memcpy(gif_ptr->app_data, const uint8_t*(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) { + uint8_t 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((const FX_CHAR*)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, (uint8_t**)&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_memset(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(uint8_t, sizeof(GifPTE)); + GIF_PTR_NOT_NULL(gif_pt_ptr->pte_ptr, gif_ptr); + gif_pt_ptr->string_ptr = 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((uint8_t*)&gif_pte_ptr->grid_left); + gif_pt_ptr->pte_ptr->grid_top = + _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_top); + gif_pt_ptr->pte_ptr->grid_width = + _GetWord_LSBFirst((uint8_t*)&gif_pte_ptr->grid_width); + gif_pt_ptr->pte_ptr->grid_height = + _GetWord_LSBFirst((uint8_t*)&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) { + uint8_t 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((const FX_CHAR*)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, (uint8_t**)&gif_gce_ptr, 6) == NULL) { + return 2; + } + if (gif_ptr->gce_ptr == NULL) { + gif_ptr->gce_ptr = (GifGCE*)FX_Alloc(uint8_t, 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((uint8_t*)&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; +} +int32_t _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, (uint8_t**)&gif_img_info_ptr, 9) == NULL) { + return 2; + } + GifImage* gif_image_ptr = (GifImage*)FX_Alloc(uint8_t, sizeof(GifImage)); + GIF_PTR_NOT_NULL(gif_image_ptr, gif_ptr); + FXSYS_memset(gif_image_ptr, 0, sizeof(GifImage)); + gif_image_ptr->image_info_ptr = + (GifImageInfo*)FX_Alloc(uint8_t, sizeof(GifImageInfo)); + GIF_PTR_NOT_NULL(gif_image_ptr->image_info_ptr, gif_ptr); + gif_image_ptr->image_info_ptr->left = + _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->left); + gif_image_ptr->image_info_ptr->top = + _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->top); + gif_image_ptr->image_info_ptr->width = + _GetWord_LSBFirst((uint8_t*)&gif_img_info_ptr->width); + gif_image_ptr->image_info_ptr->height = + _GetWord_LSBFirst((uint8_t*)&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); + int32_t loc_pal_size = (2 << gif_img_info_lf_ptr->pal_bits) * 3; + uint8_t* 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_memcpy((uint8_t*)gif_image_ptr->local_pal_ptr, loc_pal_ptr, + loc_pal_size); + } + } + uint8_t* 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; +} +int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num) { + if (gif_ptr == NULL || frame_num < 0 || + frame_num >= gif_ptr->img_ptr_arr_ptr->GetSize()) { + return 0; + } + uint8_t* data_size_ptr = NULL; + uint8_t* 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(uint8_t, 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; + int32_t 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, + (int32_t)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 + ? (int32_t)gif_image_ptr->image_gce_ptr->trans_index + : -1, + (int32_t)((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 = 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; + int32_t 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 >= + (int32_t)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, + int32_t 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; +} +uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr, + uint8_t** 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, + uint8_t* 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, + uint8_t** 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; +} +int32_t _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, + uint8_t*& dst_buf, + FX_DWORD& dst_len) { + if (gif_ptr->cur_offset) { + return TRUE; + } + dst_len = sizeof(GifHeader) + sizeof(GifLSD) + sizeof(GifGF); + dst_buf = FX_TryAlloc(uint8_t, dst_len); + if (dst_buf == NULL) { + return FALSE; + } + FXSYS_memset(dst_buf, 0, dst_len); + FXSYS_memcpy(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_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->global_pal, size); + gif_ptr->cur_offset += size; + } + return TRUE; +} +void interlace_buf(const uint8_t* buf, FX_DWORD pitch, FX_DWORD height) { + CFX_ArrayTemplate pass[4]; + int i, j; + FX_DWORD row; + row = 0; + uint8_t* 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(uint8_t, pitch); + if (temp == NULL) { + return; + } + FXSYS_memcpy(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_memcpy((uint8_t*)&buf[pitch * row], pass[i].GetAt(j), pitch); + FX_Free(pass[i].GetAt(j)); + } + } +} +static void _gif_write_block_data(const uint8_t* src_buf, + FX_DWORD src_len, + uint8_t*& 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_memcpy(&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++] = (uint8_t)src_len; + FXSYS_memcpy(&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, + uint8_t*& 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_memcmp(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_memcpy(&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); + } + uint8_t 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_memcmp(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_memcmp(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_memcmp(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_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_identify, 8); + gif_ptr->cur_offset += 8; + FXSYS_memcpy(&dst_buf[gif_ptr->cur_offset], gif_ptr->app_authentication, 8); + gif_ptr->cur_offset += 3; + FXSYS_memcpy(&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, + uint8_t*& 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 index 8b2acc86ae..3b4ec0f0e6 100644 --- a/core/src/fxcodec/lgif/fx_gif.h +++ b/core/src/fxcodec/lgif/fx_gif.h @@ -1,332 +1,332 @@ -// 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 - -#include "core/include/fxcrt/fx_basic.h" - -extern FX_WORD _GetWord_LSBFirst(uint8_t* p); -extern void _SetWord_LSBFirst(uint8_t* p, FX_WORD v); -extern void _BpcConvert(const uint8_t* src_buf, - FX_DWORD src_len, - int32_t src_bpc, - int32_t dst_bpc, - uint8_t*& 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 { - uint8_t pal_bits : 3; - uint8_t sort_flag : 1; - uint8_t color_resolution : 3; - uint8_t global_pal : 1; -} GifGF; -typedef struct tagGifLF { - uint8_t pal_bits : 3; - uint8_t reserved : 2; - uint8_t sort_flag : 1; - uint8_t interlace : 1; - uint8_t local_pal : 1; -} GifLF; -typedef struct tagGifHeader { - char signature[3]; - char version[3]; -} GifHeader; -typedef struct tagGifLSD { - FX_WORD width; - FX_WORD height; - uint8_t global_flag; - uint8_t bc_index; - uint8_t pixel_aspect; -} GifLSD; -typedef struct tagGifImageInfo { - FX_WORD left; - FX_WORD top; - FX_WORD width; - FX_WORD height; - - uint8_t local_flag; -} GifImageInfo; -typedef struct tagGifCEF { - uint8_t transparency : 1; - uint8_t user_input : 1; - uint8_t disposal_method : 3; - uint8_t reserved : 3; -} GifCEF; -typedef struct tagGifGCE { - uint8_t block_size; - uint8_t gce_flag; - FX_WORD delay_time; - uint8_t trans_index; -} GifGCE; -typedef struct tagGifPTE { - uint8_t block_size; - FX_WORD grid_left; - FX_WORD grid_top; - FX_WORD grid_width; - FX_WORD grid_height; - - uint8_t char_width; - uint8_t char_height; - - uint8_t fc_index; - uint8_t bc_index; -} GifPTE; -typedef struct tagGifAE { - uint8_t block_size; - uint8_t app_identify[8]; - uint8_t app_authentication[3]; -} GifAE; -typedef struct tagGifPalette { uint8_t r, g, b; } GifPalette; -#pragma pack() -typedef struct tagGifImage { - GifGCE* image_gce_ptr; - GifPalette* local_pal_ptr; - GifImageInfo* image_info_ptr; - uint8_t image_code_size; - FX_DWORD image_data_pos; - uint8_t* image_row_buf; - int32_t image_row_num; -} GifImage; -typedef struct tagGifPlainText { - GifGCE* gce_ptr; - GifPTE* pte_ptr; - CFX_ByteString* string_ptr; -} GifPlainText; -class CGifLZWDecoder { - public: - struct tag_Table { - FX_WORD prefix; - uint8_t suffix; - }; - CGifLZWDecoder(FX_CHAR* error_ptr = NULL) { err_msg_ptr = error_ptr; } - void InitTable(uint8_t code_len); - - int32_t Decode(uint8_t* des_buf, FX_DWORD& des_size); - - void Input(uint8_t* src_buf, FX_DWORD src_size); - FX_DWORD GetAvailInput(); - - private: - void ClearTable(); - void AddCode(FX_WORD prefix_code, uint8_t append_char); - void DecodeString(FX_WORD code); - uint8_t code_size; - uint8_t code_size_cur; - FX_WORD code_clear; - FX_WORD code_end; - FX_WORD code_next; - uint8_t code_first; - uint8_t stack[GIF_MAX_LZW_CODE]; - FX_WORD stack_size; - tag_Table code_table[GIF_MAX_LZW_CODE]; - FX_WORD code_old; - - uint8_t* next_in; - FX_DWORD avail_in; - - uint8_t bits_left; - FX_DWORD code_store; - - FX_CHAR* err_msg_ptr; -}; -class CGifLZWEncoder { - public: - struct tag_Table { - FX_WORD prefix; - uint8_t suffix; - }; - CGifLZWEncoder(); - ~CGifLZWEncoder(); - void Start(uint8_t code_len, - const uint8_t* src_buf, - uint8_t*& dst_buf, - FX_DWORD& offset); - FX_BOOL Encode(const uint8_t* src_buf, - FX_DWORD src_len, - uint8_t*& dst_buf, - FX_DWORD& dst_len, - FX_DWORD& offset); - void Finish(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); - - private: - void ClearTable(); - FX_BOOL LookUpInTable(const uint8_t* buf, - FX_DWORD& offset, - uint8_t& bit_offset); - void EncodeString(FX_DWORD index, - uint8_t*& dst_buf, - FX_DWORD& dst_len, - FX_DWORD& offset); - void WriteBlock(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); - jmp_buf jmp; - FX_DWORD src_offset; - uint8_t src_bit_offset; - uint8_t src_bit_cut; - FX_DWORD src_bit_num; - uint8_t code_size; - FX_WORD code_clear; - FX_WORD code_end; - FX_WORD index_num; - uint8_t bit_offset; - uint8_t index_bit_cur; - uint8_t index_buf[GIF_DATA_BLOCK]; - uint8_t 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 int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; -struct tag_gif_decompress_struct { - jmp_buf jmpbuf; - FX_CHAR* err_ptr; - void (*_gif_error_fn)(gif_decompress_struct_p gif_ptr, - const FX_CHAR* err_msg); - void* context_ptr; - int width; - int height; - GifPalette* global_pal_ptr; - int32_t global_pal_num; - uint8_t global_sort_flag; - uint8_t global_color_resolution; - - uint8_t bc_index; - uint8_t pixel_aspect; - CGifLZWDecoder* img_decoder_ptr; - FX_DWORD img_row_offset; - FX_DWORD img_row_avail_size; - uint8_t img_pass_num; - CFX_ArrayTemplate* img_ptr_arr_ptr; - uint8_t* (*_gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr, - int32_t pal_size); - uint8_t* next_in; - FX_DWORD avail_in; - int32_t 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, - int32_t row_num, - uint8_t* row_buf); - FX_BOOL (*_gif_get_record_position_fn)(gif_decompress_struct_p gif_ptr, FX_DWORD cur_pos, - int32_t left, int32_t top, int32_t width, int32_t height, - int32_t pal_num, void* pal_ptr, - int32_t delay_time, FX_BOOL user_input, - int32_t trans_index, int32_t disposal_method, FX_BOOL interlace); -#ifdef GIF_SUPPORT_APPLICATION_EXTENSION - uint8_t app_identify[8]; - uint8_t app_authentication[3]; - FX_DWORD app_data_size; - uint8_t* 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 { - const uint8_t* 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 - uint8_t app_identify[8]; - uint8_t app_authentication[3]; - FX_DWORD app_data_size; - uint8_t* app_data; -#endif - -#ifdef GIF_SUPPORT_COMMENT_EXTENSION - uint8_t* 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; - const uint8_t* pte_data_ptr; - FX_DWORD pte_data_len; -#endif -}; -void _gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); -void _gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* 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); -int32_t _gif_read_header(gif_decompress_struct_p gif_ptr); -int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr); -int32_t _gif_get_frame_num(gif_decompress_struct_p gif_ptr); -int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr); -int32_t _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); -int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num); -uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr, - uint8_t** des_buf_pp, - FX_DWORD data_size); -void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status); -void _gif_input_buffer(gif_decompress_struct_p gif_ptr, - uint8_t* src_buf, - FX_DWORD src_size); -FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, - uint8_t** avial_buf_ptr); -void interlace_buf(const uint8_t* buf, FX_DWORD width, FX_DWORD height); -FX_BOOL _gif_encode(gif_compress_struct_p gif_ptr, - uint8_t*& 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; \ - } +// 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 + +#include "core/include/fxcrt/fx_basic.h" + +extern FX_WORD _GetWord_LSBFirst(uint8_t* p); +extern void _SetWord_LSBFirst(uint8_t* p, FX_WORD v); +extern void _BpcConvert(const uint8_t* src_buf, + FX_DWORD src_len, + int32_t src_bpc, + int32_t dst_bpc, + uint8_t*& 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 { + uint8_t pal_bits : 3; + uint8_t sort_flag : 1; + uint8_t color_resolution : 3; + uint8_t global_pal : 1; +} GifGF; +typedef struct tagGifLF { + uint8_t pal_bits : 3; + uint8_t reserved : 2; + uint8_t sort_flag : 1; + uint8_t interlace : 1; + uint8_t local_pal : 1; +} GifLF; +typedef struct tagGifHeader { + char signature[3]; + char version[3]; +} GifHeader; +typedef struct tagGifLSD { + FX_WORD width; + FX_WORD height; + uint8_t global_flag; + uint8_t bc_index; + uint8_t pixel_aspect; +} GifLSD; +typedef struct tagGifImageInfo { + FX_WORD left; + FX_WORD top; + FX_WORD width; + FX_WORD height; + + uint8_t local_flag; +} GifImageInfo; +typedef struct tagGifCEF { + uint8_t transparency : 1; + uint8_t user_input : 1; + uint8_t disposal_method : 3; + uint8_t reserved : 3; +} GifCEF; +typedef struct tagGifGCE { + uint8_t block_size; + uint8_t gce_flag; + FX_WORD delay_time; + uint8_t trans_index; +} GifGCE; +typedef struct tagGifPTE { + uint8_t block_size; + FX_WORD grid_left; + FX_WORD grid_top; + FX_WORD grid_width; + FX_WORD grid_height; + + uint8_t char_width; + uint8_t char_height; + + uint8_t fc_index; + uint8_t bc_index; +} GifPTE; +typedef struct tagGifAE { + uint8_t block_size; + uint8_t app_identify[8]; + uint8_t app_authentication[3]; +} GifAE; +typedef struct tagGifPalette { uint8_t r, g, b; } GifPalette; +#pragma pack() +typedef struct tagGifImage { + GifGCE* image_gce_ptr; + GifPalette* local_pal_ptr; + GifImageInfo* image_info_ptr; + uint8_t image_code_size; + FX_DWORD image_data_pos; + uint8_t* image_row_buf; + int32_t image_row_num; +} GifImage; +typedef struct tagGifPlainText { + GifGCE* gce_ptr; + GifPTE* pte_ptr; + CFX_ByteString* string_ptr; +} GifPlainText; +class CGifLZWDecoder { + public: + struct tag_Table { + FX_WORD prefix; + uint8_t suffix; + }; + CGifLZWDecoder(FX_CHAR* error_ptr = NULL) { err_msg_ptr = error_ptr; } + void InitTable(uint8_t code_len); + + int32_t Decode(uint8_t* des_buf, FX_DWORD& des_size); + + void Input(uint8_t* src_buf, FX_DWORD src_size); + FX_DWORD GetAvailInput(); + + private: + void ClearTable(); + void AddCode(FX_WORD prefix_code, uint8_t append_char); + void DecodeString(FX_WORD code); + uint8_t code_size; + uint8_t code_size_cur; + FX_WORD code_clear; + FX_WORD code_end; + FX_WORD code_next; + uint8_t code_first; + uint8_t stack[GIF_MAX_LZW_CODE]; + FX_WORD stack_size; + tag_Table code_table[GIF_MAX_LZW_CODE]; + FX_WORD code_old; + + uint8_t* next_in; + FX_DWORD avail_in; + + uint8_t bits_left; + FX_DWORD code_store; + + FX_CHAR* err_msg_ptr; +}; +class CGifLZWEncoder { + public: + struct tag_Table { + FX_WORD prefix; + uint8_t suffix; + }; + CGifLZWEncoder(); + ~CGifLZWEncoder(); + void Start(uint8_t code_len, + const uint8_t* src_buf, + uint8_t*& dst_buf, + FX_DWORD& offset); + FX_BOOL Encode(const uint8_t* src_buf, + FX_DWORD src_len, + uint8_t*& dst_buf, + FX_DWORD& dst_len, + FX_DWORD& offset); + void Finish(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); + + private: + void ClearTable(); + FX_BOOL LookUpInTable(const uint8_t* buf, + FX_DWORD& offset, + uint8_t& bit_offset); + void EncodeString(FX_DWORD index, + uint8_t*& dst_buf, + FX_DWORD& dst_len, + FX_DWORD& offset); + void WriteBlock(uint8_t*& dst_buf, FX_DWORD& dst_len, FX_DWORD& offset); + jmp_buf jmp; + FX_DWORD src_offset; + uint8_t src_bit_offset; + uint8_t src_bit_cut; + FX_DWORD src_bit_num; + uint8_t code_size; + FX_WORD code_clear; + FX_WORD code_end; + FX_WORD index_num; + uint8_t bit_offset; + uint8_t index_bit_cur; + uint8_t index_buf[GIF_DATA_BLOCK]; + uint8_t 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 int32_t s_gif_interlace_step[4] = {8, 8, 4, 2}; +struct tag_gif_decompress_struct { + jmp_buf jmpbuf; + FX_CHAR* err_ptr; + void (*_gif_error_fn)(gif_decompress_struct_p gif_ptr, + const FX_CHAR* err_msg); + void* context_ptr; + int width; + int height; + GifPalette* global_pal_ptr; + int32_t global_pal_num; + uint8_t global_sort_flag; + uint8_t global_color_resolution; + + uint8_t bc_index; + uint8_t pixel_aspect; + CGifLZWDecoder* img_decoder_ptr; + FX_DWORD img_row_offset; + FX_DWORD img_row_avail_size; + uint8_t img_pass_num; + CFX_ArrayTemplate* img_ptr_arr_ptr; + uint8_t* (*_gif_ask_buf_for_pal_fn)(gif_decompress_struct_p gif_ptr, + int32_t pal_size); + uint8_t* next_in; + FX_DWORD avail_in; + int32_t 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, + int32_t row_num, + uint8_t* row_buf); + FX_BOOL (*_gif_get_record_position_fn)(gif_decompress_struct_p gif_ptr, FX_DWORD cur_pos, + int32_t left, int32_t top, int32_t width, int32_t height, + int32_t pal_num, void* pal_ptr, + int32_t delay_time, FX_BOOL user_input, + int32_t trans_index, int32_t disposal_method, FX_BOOL interlace); +#ifdef GIF_SUPPORT_APPLICATION_EXTENSION + uint8_t app_identify[8]; + uint8_t app_authentication[3]; + FX_DWORD app_data_size; + uint8_t* 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 { + const uint8_t* 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 + uint8_t app_identify[8]; + uint8_t app_authentication[3]; + FX_DWORD app_data_size; + uint8_t* app_data; +#endif + +#ifdef GIF_SUPPORT_COMMENT_EXTENSION + uint8_t* 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; + const uint8_t* pte_data_ptr; + FX_DWORD pte_data_len; +#endif +}; +void _gif_error(gif_decompress_struct_p gif_ptr, const FX_CHAR* err_msg); +void _gif_warn(gif_decompress_struct_p gif_ptr, const FX_CHAR* 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); +int32_t _gif_read_header(gif_decompress_struct_p gif_ptr); +int32_t _gif_get_frame(gif_decompress_struct_p gif_ptr); +int32_t _gif_get_frame_num(gif_decompress_struct_p gif_ptr); +int32_t _gif_decode_extension(gif_decompress_struct_p gif_ptr); +int32_t _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); +int32_t _gif_load_frame(gif_decompress_struct_p gif_ptr, int32_t frame_num); +uint8_t* _gif_read_data(gif_decompress_struct_p gif_ptr, + uint8_t** des_buf_pp, + FX_DWORD data_size); +void _gif_save_decoding_status(gif_decompress_struct_p gif_ptr, int32_t status); +void _gif_input_buffer(gif_decompress_struct_p gif_ptr, + uint8_t* src_buf, + FX_DWORD src_size); +FX_DWORD _gif_get_avail_input(gif_decompress_struct_p gif_ptr, + uint8_t** avial_buf_ptr); +void interlace_buf(const uint8_t* buf, FX_DWORD width, FX_DWORD height); +FX_BOOL _gif_encode(gif_compress_struct_p gif_ptr, + uint8_t*& 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