summaryrefslogtreecommitdiff
path: root/core/src/fxcodec/codec
diff options
context:
space:
mode:
authorBo Xu <bo_xu@foxitsoftware.com>2014-10-28 23:03:33 -0700
committerBo Xu <bo_xu@foxitsoftware.com>2014-11-03 11:10:11 -0800
commitfdc00a7042d912aafaabddae4d9c84199921ef23 (patch)
tree32ab8ac91cc68d2cd15b9168782a71b3f3f5e7b9 /core/src/fxcodec/codec
parente9b38fa38de2c95d8260be31c57d9272c4d127ed (diff)
downloadpdfium-fdc00a7042d912aafaabddae4d9c84199921ef23.tar.xz
Merge XFA to PDFium master at 4dc95e7 on 10/28/2014
Diffstat (limited to 'core/src/fxcodec/codec')
-rw-r--r--core/src/fxcodec/codec/codec_int.h89
-rw-r--r--core/src/fxcodec/codec/fx_codec.cpp341
-rw-r--r--core/src/fxcodec/codec/fx_codec_bmp.cpp124
-rw-r--r--core/src/fxcodec/codec/fx_codec_gif.cpp176
-rw-r--r--core/src/fxcodec/codec/fx_codec_jpeg.cpp78
-rw-r--r--core/src/fxcodec/codec/fx_codec_png.cpp245
-rw-r--r--core/src/fxcodec/codec/fx_codec_progress.cpp2263
-rw-r--r--core/src/fxcodec/codec/fx_codec_progress.h206
-rw-r--r--core/src/fxcodec/codec/fx_codec_tiff.cpp532
9 files changed, 4051 insertions, 3 deletions
diff --git a/core/src/fxcodec/codec/codec_int.h b/core/src/fxcodec/codec/codec_int.h
index 78672e62ee..3cbdce9265 100644
--- a/core/src/fxcodec/codec/codec_int.h
+++ b/core/src/fxcodec/codec/codec_int.h
@@ -142,13 +142,67 @@ public:
virtual void* Start();
virtual void Finish(void* pContext);
virtual void Input(void* pContext, FX_LPCBYTE src_buf, FX_DWORD src_size);
- virtual int ReadHeader(void* pContext, int* width, int* height, int* nComps);
+ virtual int ReadHeader(void* pContext, int* width, int* height, int* nComps, CFX_DIBAttribute* pAttribute = NULL);
virtual FX_BOOL StartScanline(void* pContext, int down_scale);
virtual FX_BOOL ReadScanline(void* pContext, FX_LPBYTE dest_buf);
virtual FX_DWORD GetAvailInput(void* pContext, FX_LPBYTE* avail_buf_ptr);
protected:
IFX_JpegProvider* m_pExtProvider;
};
+#define PNG_ERROR_SIZE 256
+class CCodec_PngModule : public ICodec_PngModule
+{
+public:
+ CCodec_PngModule()
+ {
+ FXSYS_memset8(m_szLastError, '\0', PNG_ERROR_SIZE);
+ }
+
+ virtual void* Start(void* pModule);
+ virtual void Finish(void* pContext);
+ virtual FX_BOOL Input(void* pContext, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_DIBAttribute* pAttribute);
+protected:
+ FX_CHAR m_szLastError[PNG_ERROR_SIZE];
+};
+class CCodec_GifModule : public ICodec_GifModule
+{
+public:
+ CCodec_GifModule()
+ {
+ FXSYS_memset8(m_szLastError, '\0', 256);
+ }
+ virtual void* Start(void* pModule);
+ virtual void Finish(void* pContext);
+ virtual FX_DWORD GetAvailInput(void* pContext, FX_LPBYTE* avail_buf_ptr);
+ virtual void Input(void* pContext, FX_LPCBYTE src_buf, FX_DWORD src_size);
+
+ virtual FX_INT32 ReadHeader(void* pContext, int* width, int* height,
+ int* pal_num, void** pal_pp, int* bg_index, CFX_DIBAttribute* pAttribute);
+
+ virtual FX_INT32 LoadFrameInfo(void* pContext, int* frame_num);
+
+ virtual FX_INT32 LoadFrame(void* pContext, int frame_num, CFX_DIBAttribute* pAttribute);
+
+protected:
+ FX_CHAR m_szLastError[256];
+};
+class CCodec_BmpModule : public ICodec_BmpModule
+{
+public:
+ CCodec_BmpModule()
+ {
+ FXSYS_memset8(m_szLastError, '\0', 256);
+ }
+ virtual void* Start(void* pModule);
+ virtual void Finish(void* pContext);
+ virtual FX_DWORD GetAvailInput(void* pContext, FX_LPBYTE* avail_buf_ptr);
+ virtual void Input(void* pContext, FX_LPCBYTE src_buf, FX_DWORD src_size);
+ virtual FX_INT32 ReadHeader(void* pContext, FX_INT32* width, FX_INT32* height, FX_BOOL* tb_flag, FX_INT32* components, FX_INT32* pal_num, FX_DWORD** pal_pp, CFX_DIBAttribute* pAttribute);
+ virtual FX_INT32 LoadImage(void* pContext);
+
+protected:
+ FX_CHAR m_szLastError[256];
+};
class CCodec_IccModule : public ICodec_IccModule
{
public:
@@ -196,6 +250,15 @@ public:
FX_BOOL Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets);
void DestroyDecoder(void* ctx);
};
+class CCodec_TiffModule : public ICodec_TiffModule
+{
+public:
+ virtual FX_LPVOID CreateDecoder(IFX_FileRead* file_ptr);
+ virtual void GetFrames(FX_LPVOID ctx, FX_INT32& frames);
+ virtual FX_BOOL LoadFrameInfo(FX_LPVOID ctx, FX_INT32 frame, FX_DWORD& width, FX_DWORD& height, FX_DWORD& comps, FX_DWORD& bpc, CFX_DIBAttribute* pAttribute = NULL);
+ virtual FX_BOOL Decode(FX_LPVOID ctx, class CFX_DIBitmap* pDIBitmap);
+ virtual void DestroyDecoder(FX_LPVOID ctx);
+};
#include "../jbig2/JBig2_Context.h"
class CPDF_Jbig2Interface : public CFX_Object, public CJBig2_Module
{
@@ -270,3 +333,27 @@ public:
CPDF_Jbig2Interface m_Module;
private:
};
+class CFX_DIBAttributeExif : public IFX_DIBAttributeExif
+{
+public:
+ CFX_DIBAttributeExif();
+ ~CFX_DIBAttributeExif();
+ virtual FX_BOOL GetInfo(FX_WORD tag, FX_LPVOID val);
+
+ FX_BOOL ParseExif(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pHead, FX_LPBYTE data, FX_DWORD len, CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pVal);
+
+ typedef FX_WORD (*_Read2Bytes)(FX_LPBYTE data);
+ typedef FX_DWORD (*_Read4Bytes)(FX_LPBYTE data);
+ FX_LPBYTE ParseExifIFH(FX_LPBYTE data, FX_DWORD len, _Read2Bytes* pReadWord, _Read4Bytes* pReadDword);
+ FX_BOOL ParseExifIFD(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pMap, FX_LPBYTE data, FX_DWORD len);
+
+ FX_LPBYTE m_pExifData;
+
+ FX_DWORD m_dwExifDataLen;
+
+ void clear();
+ _Read2Bytes m_readWord;
+ _Read4Bytes m_readDword;
+ CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE> m_TagHead;
+ CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE> m_TagVal;
+};
diff --git a/core/src/fxcodec/codec/fx_codec.cpp b/core/src/fxcodec/codec/fx_codec.cpp
index 456ec40fea..b2f70c73d1 100644
--- a/core/src/fxcodec/codec/fx_codec.cpp
+++ b/core/src/fxcodec/codec/fx_codec.cpp
@@ -14,6 +14,10 @@ CCodec_ModuleMgr::CCodec_ModuleMgr()
m_pJpxModule = FX_NEW CCodec_JpxModule;
m_pJbig2Module = FX_NEW CCodec_Jbig2Module;
m_pIccModule = FX_NEW CCodec_IccModule;
+ m_pPngModule = FX_NEW CCodec_PngModule;
+ m_pGifModule = FX_NEW CCodec_GifModule;
+ m_pBmpModule = FX_NEW CCodec_BmpModule;
+ m_pTiffModule = FX_NEW CCodec_TiffModule;
m_pFlateModule = FX_NEW CCodec_FlateModule;
}
CCodec_ModuleMgr::~CCodec_ModuleMgr()
@@ -249,6 +253,343 @@ void CCodec_ModuleMgr::Destroy()
{
delete this;
}
+CFX_DIBAttribute::CFX_DIBAttribute()
+{
+ FXSYS_memset32(this, 0, sizeof(CFX_DIBAttribute));
+ m_nXDPI = -1;
+ m_nYDPI = -1;
+ m_fAspectRatio = -1.0f;
+ m_pExif = FX_NEW CFX_DIBAttributeExif;
+}
+CFX_DIBAttribute::~CFX_DIBAttribute()
+{
+ if (m_pExif) {
+ delete m_pExif;
+ }
+}
+CFX_DIBAttributeExif::CFX_DIBAttributeExif()
+{
+ m_pExifData = NULL;
+ m_dwExifDataLen = 0;
+}
+CFX_DIBAttributeExif::~CFX_DIBAttributeExif()
+{
+ clear();
+}
+void CFX_DIBAttributeExif::clear()
+{
+ if (m_pExifData) {
+ FX_Free(m_pExifData);
+ }
+ m_pExifData = NULL;
+ FX_DWORD key = 0;
+ FX_LPBYTE buf = NULL;
+ FX_POSITION pos = NULL;
+ pos = m_TagHead.GetStartPosition();
+ while (pos) {
+ m_TagHead.GetNextAssoc(pos, key, buf);
+ if (buf) {
+ FX_Free(buf);
+ }
+ }
+ m_TagHead.RemoveAll();
+ pos = m_TagVal.GetStartPosition();
+ while (pos) {
+ m_TagVal.GetNextAssoc(pos, key, buf);
+ if (buf) {
+ FX_Free(buf);
+ }
+ }
+ m_TagVal.RemoveAll();
+}
+static FX_WORD _Read2BytesL(FX_LPBYTE data)
+{
+ ASSERT(data);
+ return data[0] | (data[1] << 8);
+}
+static FX_WORD _Read2BytesB(FX_LPBYTE data)
+{
+ ASSERT(data);
+ return data[1] | (data[0] << 8);
+}
+static FX_DWORD _Read4BytesL(FX_LPBYTE data)
+{
+ return _Read2BytesL(data) | (_Read2BytesL(data + 2) << 16);
+}
+static FX_DWORD _Read4BytesB(FX_LPBYTE data)
+{
+ return _Read2BytesB(data + 2) | (_Read2BytesB(data) << 16);
+}
+typedef FX_WORD (*_Read2Bytes) (FX_LPBYTE data);
+typedef FX_DWORD (*_Read4Bytes) (FX_LPBYTE data);
+typedef void (*_Write2Bytes) (FX_LPBYTE data, FX_WORD val);
+typedef void (*_Write4Bytes) (FX_LPBYTE data, FX_DWORD val);
+FX_LPBYTE CFX_DIBAttributeExif::ParseExifIFH(FX_LPBYTE data, FX_DWORD len, _Read2Bytes* pReadWord, _Read4Bytes* pReadDword)
+{
+ if (len > 8) {
+ FX_BOOL tag = FALSE;
+ if (FXSYS_memcmp32(data, "\x49\x49\x2a\x00", 4) == 0) {
+ if (pReadWord) {
+ *pReadWord = _Read2BytesL;
+ }
+ if (pReadDword) {
+ *pReadDword = _Read4BytesL;
+ }
+ tag = TRUE;
+ } else if (FXSYS_memcmp32(data, "\x4d\x4d\x00\x2a", 4) == 0) {
+ if (pReadWord) {
+ *pReadWord = _Read2BytesB;
+ }
+ if (pReadDword) {
+ *pReadDword = _Read4BytesB;
+ }
+ tag = TRUE;
+ }
+ if (tag) {
+ data += 4;
+ if (pReadDword) {
+ data += (*pReadDword)(data) - 4;
+ } else {
+ data += 4;
+ }
+ }
+ }
+ return data;
+}
+FX_BOOL CFX_DIBAttributeExif::ParseExifIFD(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pMap, FX_LPBYTE data, FX_DWORD len)
+{
+ if (pMap && data) {
+ if (len > 8) {
+ FX_WORD wTagNum = m_readWord(data);
+ data += 2;
+ FX_DWORD wTag;
+ FX_LPBYTE buf;
+ while (wTagNum--) {
+ wTag = m_readWord(data);
+ data += 2;
+ if (!pMap->Lookup(wTag, buf)) {
+ buf = FX_Alloc(FX_BYTE, 10);
+ if (buf == NULL) {
+ return FALSE;
+ }
+ FXSYS_memcpy32(buf, data, 10);
+ pMap->SetAt(wTag, buf);
+ }
+ data += 10;
+ }
+ FX_DWORD dwIFDOffset;
+ dwIFDOffset = m_readDword(data);
+ while (dwIFDOffset && dwIFDOffset < len) {
+ data = m_pExifData + dwIFDOffset;
+ wTagNum = m_readWord(data);
+ data += 2;
+ while (wTagNum--) {
+ wTag = m_readWord(data);
+ data += 2;
+ if (!pMap->Lookup(wTag, buf)) {
+ buf = FX_Alloc(FX_BYTE, 10);
+ if (buf == NULL) {
+ return FALSE;
+ }
+ FXSYS_memcpy32(buf, data, 10);
+ pMap->SetAt(wTag, buf);
+ }
+ data += 10;
+ }
+ dwIFDOffset = m_readDword(data);
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+enum FX_ExifDataType {
+ FX_UnsignedByte = 1,
+ FX_AscString,
+ FX_UnsignedShort,
+ FX_UnsignedLong,
+ FX_UnsignedRation,
+ FX_SignedByte,
+ FX_Undefined,
+ FX_SignedShort,
+ FX_SignedLong,
+ FX_SignedRation,
+ FX_SignedFloat,
+ FX_DoubleFloat
+};
+FX_BOOL CFX_DIBAttributeExif::ParseExif(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pHead, FX_LPBYTE data, FX_DWORD len, CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pVal)
+{
+ if (pHead && data && pVal) {
+ if (len > 8) {
+ FX_LPBYTE old_data = data;
+ data = ParseExifIFH(data, len, &m_readWord, &m_readDword);
+ if (data == old_data) {
+ return FALSE;
+ }
+ if (pHead->GetCount() == 0) {
+ if (!ParseExifIFD(pHead, data, len)) {
+ return FALSE;
+ }
+ }
+ FX_DWORD dwModuleNum;
+ FX_WORD type;
+ FX_DWORD dwSize;
+ FX_DWORD tag;
+ FX_LPBYTE head;
+ FX_POSITION pos = pHead->GetStartPosition();
+ while (pos) {
+ pHead->GetNextAssoc(pos, tag, head);
+ FX_LPBYTE val = NULL, buf = NULL, temp = NULL;
+ int i;
+ if (head) {
+ type = m_readWord(head);
+ head += 2;
+ dwModuleNum = m_readDword(head);
+ head += 4;
+ switch (type) {
+ case FX_UnsignedByte:
+ case FX_AscString:
+ case FX_SignedByte:
+ case FX_Undefined:
+ dwSize = dwModuleNum;
+ val = FX_Alloc(FX_BYTE, dwSize);
+ if (val == NULL) {
+ return FALSE;
+ }
+ if (dwSize > 4) {
+ FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
+ } else {
+ FXSYS_memcpy32(val, head, dwSize);
+ }
+ break;
+ case FX_UnsignedShort:
+ case FX_SignedShort:
+ dwSize = dwModuleNum << 1;
+ val = FX_Alloc(FX_BYTE, dwSize);
+ if (val == NULL) {
+ return FALSE;
+ }
+ if (dwSize > 4) {
+ FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
+ } else {
+ FXSYS_memcpy32(val, head, dwSize);
+ }
+ buf = val;
+ for(i = 0; i < (int)dwModuleNum; i ++) {
+ *(FX_WORD*)buf = m_readWord(buf);
+ buf += 2;
+ }
+ break;
+ case FX_UnsignedLong:
+ case FX_SignedLong:
+ case FX_SignedFloat:
+ dwSize = dwModuleNum << 2;
+ val = FX_Alloc(FX_BYTE, dwSize);
+ if (val == NULL) {
+ return FALSE;
+ }
+ if (dwSize > 4) {
+ FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
+ } else {
+ FXSYS_memcpy32(val, head, dwSize);
+ }
+ buf = val;
+ for(i = 0; i < (int)dwModuleNum; i ++) {
+ *(FX_DWORD*)buf = m_readDword(buf);
+ buf += 4;
+ }
+ break;
+ case FX_UnsignedRation:
+ case FX_SignedRation: {
+ dwSize = dwModuleNum << 3;
+ buf = FX_Alloc(FX_BYTE, dwSize);
+ if (buf == NULL) {
+ return FALSE;
+ }
+ if (dwSize > 4) {
+ FXSYS_memcpy32(buf, old_data + m_readDword(head), dwSize);
+ } else {
+ FXSYS_memcpy32(buf, head, dwSize);
+ }
+ temp = buf;
+ val = FX_Alloc(FX_BYTE, dwSize / 2);
+ if (val == NULL) {
+ FX_Free(buf);
+ return FALSE;
+ }
+ for(i = 0; i < (int)dwModuleNum; i ++) {
+ *(FX_DWORD*)temp = m_readDword(temp);
+ *(FX_DWORD*)(temp + 4) = m_readDword(temp + 4);
+ FX_DWORD* lNumerator = (FX_DWORD*)temp;
+ FX_DWORD* lNenominator = (FX_DWORD*)(temp + 4);
+ *(FX_FLOAT*)(val + i * 4) = (FX_FLOAT)(*lNumerator) / (FX_FLOAT)(*lNenominator);
+ temp += 8;
+ }
+ FX_Free(buf);
+ }
+ break;
+ case FX_DoubleFloat:
+ dwSize = dwModuleNum << 3;
+ val = FX_Alloc(FX_BYTE, dwSize);
+ if (val == NULL) {
+ return FALSE;
+ }
+ if (dwSize > 4) {
+ FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
+ } else {
+ FXSYS_memcpy32(val, head, dwSize);
+ }
+ buf = val;
+ for(i = 0; i < (int)dwModuleNum; i ++) {
+ *(FX_DWORD*)buf = m_readDword(buf);
+ *(FX_DWORD*)(buf + 4) = m_readDword(buf + 4);
+ buf += 8;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ pVal->SetAt(tag, val);
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#define FXEXIF_INFOCONVERT(T) {T* src = (T*)ptr; T* dst = (T*)val; *dst = *src;}
+FX_BOOL CFX_DIBAttributeExif::GetInfo( FX_WORD tag, FX_LPVOID val )
+{
+ if (m_TagVal.GetCount() == 0) {
+ if (!ParseExif(&m_TagHead, m_pExifData, m_dwExifDataLen, &m_TagVal)) {
+ return FALSE;
+ }
+ }
+ FX_LPBYTE ptr = NULL;
+ if (m_TagVal.Lookup(tag, ptr)) {
+ switch (tag) {
+ case EXIFTAG_USHORT_RESUNIT:
+ FXEXIF_INFOCONVERT(FX_WORD);
+ {
+ FX_WORD* ptr = (FX_WORD*)val;
+ *ptr -= 1;
+ }
+ break;
+ case EXIFTAG_FLOAT_DPIX:
+ case EXIFTAG_FLOAT_DPIY:
+ FXEXIF_INFOCONVERT(FX_FLOAT);
+ break;
+ case EXIFTAG_USHORT_ORIENTATION:
+ FXEXIF_INFOCONVERT(FX_WORD);
+ break;
+ default: {
+ FX_LPBYTE* dst = (FX_LPBYTE*)val;
+ *dst = ptr;
+ }
+ }
+ }
+ return TRUE;
+}
class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
{
public:
diff --git a/core/src/fxcodec/codec/fx_codec_bmp.cpp b/core/src/fxcodec/codec/fx_codec_bmp.cpp
new file mode 100644
index 0000000000..4e974e2124
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_bmp.cpp
@@ -0,0 +1,124 @@
+// 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/fxcodec/fx_codec.h"
+#include "../../../include/fxge/fx_dib.h"
+#include "codec_int.h"
+#include "../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, FX_LPCSTR 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, FX_INT32 row_num, FX_LPBYTE 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(FX_BYTE, sizeof(FXBMP_Context));
+ if (p == NULL) {
+ return NULL;
+ }
+ FXSYS_memset32(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);
+ }
+}
+FX_INT32 CCodec_BmpModule::ReadHeader(void* pContext, FX_INT32* width, FX_INT32* height, FX_BOOL* tb_flag, FX_INT32* components, FX_INT32* pal_num, FX_DWORD** pal_pp, CFX_DIBAttribute* pAttribute)
+{
+ FXBMP_Context* p = (FXBMP_Context*)pContext;
+ if(setjmp(p->bmp_ptr->jmpbuf)) {
+ return 0;
+ }
+ FX_INT32 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;
+}
+FX_INT32 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, FX_LPBYTE* 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, FX_LPCBYTE src_buf, FX_DWORD src_size)
+{
+ FXBMP_Context* p = (FXBMP_Context*)pContext;
+ _bmp_input_buffer(p->bmp_ptr, (FX_LPBYTE)src_buf, src_size);
+}
diff --git a/core/src/fxcodec/codec/fx_codec_gif.cpp b/core/src/fxcodec/codec/fx_codec_gif.cpp
new file mode 100644
index 0000000000..1fc708db5c
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_gif.cpp
@@ -0,0 +1,176 @@
+// 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/fxcodec/fx_codec.h"
+#include "../../../include/fxge/fx_dib.h"
+#include "codec_int.h"
+#include "../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, FX_LPCSTR err_msg)
+{
+ FXSYS_strncpy((char*)gif_ptr->err_ptr, err_msg, GIF_MAX_ERROR_SIZE - 1);
+ longjmp(gif_ptr->jmpbuf, 1);
+}
+static FX_LPBYTE _gif_ask_buf_for_pal(gif_decompress_struct_p gif_ptr, FX_INT32 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, FX_INT32 row_num, FX_LPBYTE 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,
+ FX_INT32 left, FX_INT32 top, FX_INT32 width, FX_INT32 height,
+ FX_INT32 pal_num, void* pal_ptr,
+ FX_INT32 delay_time, FX_BOOL user_input,
+ FX_INT32 trans_index, FX_INT32 disposal_method, FX_BOOL interlace)
+{
+ 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(FX_BYTE, sizeof(FXGIF_Context));
+ if (p == NULL) {
+ return NULL;
+ }
+ FXSYS_memset32(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);
+ }
+}
+FX_INT32 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;
+ }
+ FX_INT32 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;
+}
+FX_INT32 CCodec_GifModule::LoadFrameInfo(void* pContext, int* frame_num)
+{
+ FXGIF_Context* p = (FXGIF_Context*)pContext;
+ if(setjmp(p->gif_ptr->jmpbuf)) {
+ return 0;
+ }
+ FX_INT32 ret = _gif_get_frame(p->gif_ptr);
+ if (ret != 1) {
+ return ret;
+ }
+ *frame_num = _gif_get_frame_num(p->gif_ptr);
+ return 1;
+}
+FX_INT32 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;
+ }
+ FX_INT32 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) {
+ FX_LPCBYTE buf = (FX_LPCBYTE)p->gif_ptr->cmt_data_ptr->GetBuffer(0);
+ FX_DWORD len = p->gif_ptr->cmt_data_ptr->GetLength();
+ if (len > 21) {
+ FX_BYTE size = *buf++;
+ if (size) {
+ pAttribute->m_strAuthor = CFX_ByteString(buf, size);
+ } else {
+ pAttribute->m_strAuthor.Empty();
+ }
+ buf += size;
+ size = *buf++;
+ if (size == 20) {
+ FXSYS_memcpy32(pAttribute->m_strTime, buf, size);
+ }
+ }
+ }
+ }
+ }
+ return ret;
+}
+FX_DWORD CCodec_GifModule::GetAvailInput(void* pContext, FX_LPBYTE* 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, FX_LPCBYTE src_buf, FX_DWORD src_size)
+{
+ FXGIF_Context* p = (FXGIF_Context*)pContext;
+ _gif_input_buffer(p->gif_ptr, (FX_LPBYTE)src_buf, src_size);
+}
diff --git a/core/src/fxcodec/codec/fx_codec_jpeg.cpp b/core/src/fxcodec/codec/fx_codec_jpeg.cpp
index 489f099bf8..95770ea26e 100644
--- a/core/src/fxcodec/codec/fx_codec_jpeg.cpp
+++ b/core/src/fxcodec/codec/fx_codec_jpeg.cpp
@@ -73,6 +73,68 @@ extern "C" {
#define JPEG_MARKER_AUTHORTIME (JPEG_APP0 + 3)
#define JPEG_MARKER_MAXSIZE 0xFFFF
#define JPEG_OVERHEAD_LEN 14
+static FX_BOOL _JpegIsIccMarker(jpeg_saved_marker_ptr marker)
+{
+ if (marker->marker == JPEG_MARKER_ICC &&
+ marker->data_length >= JPEG_OVERHEAD_LEN &&
+ (FXSYS_memcmp32(marker->data, "\x49\x43\x43\x5f\x50\x52\x4f\x46\x49\x4c\x45\x00", 12) == 0)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL _JpegLoadIccProfile(j_decompress_ptr cinfo, FX_LPBYTE* icc_buf_ptr, FX_DWORD* icc_length)
+{
+ if(icc_buf_ptr == NULL || icc_length == NULL) {
+ return FALSE;
+ }
+ *icc_buf_ptr = NULL;
+ *icc_length = 0;
+ FX_LPBYTE icc_data_ptr = NULL;
+ FX_DWORD icc_data_len = 0;
+ FX_BYTE count_icc_marker = 0;
+ FX_BYTE num_icc_marker = 0;
+ jpeg_saved_marker_ptr marker_list[256] = {NULL};
+ for (jpeg_saved_marker_ptr cur_marker = cinfo->marker_list;
+ cur_marker != NULL;
+ cur_marker = cur_marker->next) {
+ if(_JpegIsIccMarker(cur_marker)) {
+ if(count_icc_marker == 0) {
+ num_icc_marker = cur_marker->data[13];
+ } else if(num_icc_marker != cur_marker->data[13]) {
+ return FALSE;
+ }
+ int sn = cur_marker->data[12] - 1;
+ if(sn < 0 || sn >= num_icc_marker) {
+ return FALSE;
+ }
+ if(marker_list[sn] == NULL) {
+ marker_list[sn] = cur_marker;
+ } else {
+ return FALSE;
+ }
+ count_icc_marker ++;
+ icc_data_len += (cur_marker->data_length - JPEG_OVERHEAD_LEN);
+ }
+ }
+ if(count_icc_marker != num_icc_marker) {
+ return FALSE;
+ }
+ if(num_icc_marker == 0) {
+ return TRUE;
+ }
+ icc_data_ptr = FX_Alloc(FX_BYTE, icc_data_len);
+ if(icc_buf_ptr == NULL) {
+ return FALSE;
+ }
+ *icc_buf_ptr = icc_data_ptr;
+ *icc_length = icc_data_len;
+ for (int idx = 0; idx < num_icc_marker; idx++) {
+ icc_data_len = marker_list[idx]->data_length - JPEG_OVERHEAD_LEN;
+ FXSYS_memcpy32(icc_data_ptr, marker_list[idx]->data + JPEG_OVERHEAD_LEN, icc_data_len);
+ icc_data_ptr += icc_data_len;
+ }
+ return TRUE;
+}
static FX_BOOL _JpegEmbedIccProfile(j_compress_ptr cinfo, FX_LPCBYTE icc_buf_ptr, FX_DWORD icc_length)
{
if(icc_buf_ptr == NULL || icc_length == 0) {
@@ -207,6 +269,17 @@ static void _JpegEncode(const CFX_DIBSource* pSource, FX_LPBYTE& dest_buf, FX_ST
}
dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer;
}
+static void _JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, CFX_DIBAttribute* pAttribute)
+{
+ if (pInfo == NULL || pAttribute == NULL) {
+ return;
+ }
+ if (pAttribute) {
+ pAttribute->m_nXDPI = pInfo->X_density;
+ pAttribute->m_nYDPI = pInfo->Y_density;
+ pAttribute->m_wDPIUnit = pInfo->density_unit;
+ }
+}
static FX_BOOL _JpegLoadInfo(FX_LPCBYTE src_buf, FX_DWORD src_size, int& width, int& height,
int& num_components, int& bits_per_components, FX_BOOL& color_transform,
FX_LPBYTE* icc_buf_ptr, FX_DWORD* icc_length)
@@ -613,10 +686,10 @@ void CCodec_JpegModule::Input(void* pContext, const unsigned char* src_buf, FX_D
p->m_SrcMgr.next_input_byte = src_buf;
p->m_SrcMgr.bytes_in_buffer = src_size;
}
-int CCodec_JpegModule::ReadHeader(void* pContext, int* width, int* height, int* nComps)
+int CCodec_JpegModule::ReadHeader(void* pContext, int* width, int* height, int* nComps, CFX_DIBAttribute* pAttribute)
{
if (m_pExtProvider) {
- return m_pExtProvider->ReadHeader(pContext, width, height, nComps);
+ return m_pExtProvider->ReadHeader(pContext, width, height, nComps, pAttribute);
}
FXJPEG_Context* p = (FXJPEG_Context*)pContext;
if (setjmp(p->m_JumpMark) == -1) {
@@ -632,6 +705,7 @@ int CCodec_JpegModule::ReadHeader(void* pContext, int* width, int* height, int*
*width = p->m_Info.image_width;
*height = p->m_Info.image_height;
*nComps = p->m_Info.num_components;
+ _JpegLoadAttribute(&p->m_Info, pAttribute);
return 0;
}
FX_BOOL CCodec_JpegModule::StartScanline(void* pContext, int down_scale)
diff --git a/core/src/fxcodec/codec/fx_codec_png.cpp b/core/src/fxcodec/codec/fx_codec_png.cpp
new file mode 100644
index 0000000000..0ddae7a7cd
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_png.cpp
@@ -0,0 +1,245 @@
+// 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/fxcodec/fx_codec.h"
+#include "../../../include/fxge/fx_dib.h"
+#include "codec_int.h"
+extern "C" {
+#undef FAR
+#include "../fx_lpng/include/fx_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_memset32(pAttribute->m_strTime, 0, 20);
+ FXSYS_sprintf((FX_LPSTR)pAttribute->m_strTime, "%4d:%2d:%2d %2d:%2d:%2d", t->year, t->month, t->day, t->hour, t->minute, t->second);
+ bTime = 1;
+ }
+#endif
+#if defined(PNG_TEXT_SUPPORTED)
+ int i;
+ FX_DWORD len;
+ FX_LPCSTR 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 = (FX_DWORD)FXSYS_strlen(text[i].key);
+ buf = "Time";
+ if (!FXSYS_memcmp32(buf, text[i].key, FX_MIN(len, FXSYS_strlen(buf)))) {
+ if (!bTime) {
+ FXSYS_memset32(pAttribute->m_strTime, 0, 20);
+ FXSYS_memcpy32(pAttribute->m_strTime, text[i].text, text[i].text_length);
+ }
+ } else {
+ buf = "Author";
+ if (!FXSYS_memcmp32(buf, text[i].key, FX_MIN(len, FXSYS_strlen(buf)))) {
+ pAttribute->m_strAuthor.Empty();
+ pAttribute->m_strAuthor.Load((FX_LPBYTE)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;
+ FX_LPBYTE 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(FX_BYTE, 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, FX_LPCBYTE 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, (FX_LPBYTE)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
new file mode 100644
index 0000000000..542ac681e6
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_progress.cpp
@@ -0,0 +1,2263 @@
+// 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/fxge/fx_dib.h"
+#include "../../../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(FX_BYTE, (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(FX_BYTE, size);
+ if(m_pWeightTables == NULL) {
+ return;
+ }
+ FXSYS_memset32(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(FX_BYTE, size);
+ if(m_pWeightTables == NULL) {
+ return;
+ }
+ FXSYS_memset32(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(FX_BYTE, 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_memcpy32(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, FX_LPBYTE& 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();
+ FX_INT32 row = (FX_INT32)((line - pCodec->m_clipBox.top) * scale_y) + pCodec->m_startY;
+ FX_LPBYTE src_scan = (FX_LPBYTE)pDIBitmap->GetScanline(row);
+ FX_LPBYTE des_scan = pCodec->m_pDecodeBuf;
+ src_buf = pCodec->m_pDecodeBuf;
+ FX_INT32 src_Bpp = pDIBitmap->GetBPP() >> 3;
+ FX_INT32 des_Bpp = (pCodec->m_SrcFormat & 0xff) >> 3;
+ FX_INT32 src_left = pCodec->m_startX;
+ FX_INT32 des_left = pCodec->m_clipBox.left;
+ src_scan += src_left * src_Bpp;
+ des_scan += des_left * des_Bpp;
+ for (FX_INT32 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] = (FX_BYTE)(des_g >> 16);
+ }
+ break;
+ case FXDIB_Rgb:
+ case FXDIB_Rgb32: {
+ FX_DWORD des_b = 0, des_g = 0, des_r = 0;
+ FX_LPCBYTE 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);
+ FX_LPBYTE pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
+ *pDes++ = (FX_BYTE)((des_b) >> 16);
+ *pDes++ = (FX_BYTE)((des_g) >> 16);
+ *pDes = (FX_BYTE)((des_r) >> 16);
+ }
+ break;
+ case FXDIB_Argb: {
+ FX_DWORD des_r = 0, des_g = 0, des_b = 0;
+ FX_LPCBYTE 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++);
+ FX_LPBYTE pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
+ *pDes++ = (FX_BYTE)((des_b) >> 16);
+ *pDes++ = (FX_BYTE)((des_g) >> 16);
+ *pDes++ = (FX_BYTE)((des_r) >> 16);
+ *pDes = *p;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, FX_INT32 des_line, FX_LPBYTE src_scan, FXCodec_Format src_format)
+{
+ FX_LPBYTE des_scan = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_line);
+ FX_INT32 src_Bpp = (m_SrcFormat & 0xff) >> 3;
+ FX_INT32 des_Bpp = pDeviceBitmap->GetBPP() >> 3;
+ FX_INT32 src_left = m_clipBox.left;
+ FX_INT32 des_left = m_startX;
+ src_scan += src_left * src_Bpp;
+ des_scan += des_left * des_Bpp;
+ for (FX_INT32 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++ = (FX_BYTE)(des_g >> 16);
+ }
+ break;
+ case FXDIB_Rgb:
+ case FXDIB_Rgb32: {
+ FX_DWORD des_b = 0, des_g = 0, des_r = 0;
+ FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((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;
+ FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((des_r) >> 16);
+ *des_scan++ = (FX_BYTE)((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(FX_BYTE, 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_memcpy32(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;
+}
+FX_LPBYTE CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback(void* pModule, FX_INT32 frame_num, FX_INT32 pal_size)
+{
+ return FX_Alloc(FX_BYTE, pal_size);
+}
+FX_BOOL CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback(void* pModule, FX_DWORD rcd_pos, const FX_RECT& img_rc,
+ FX_INT32 pal_num, void* pal_ptr,
+ FX_INT32 delay_time, FX_BOOL user_input,
+ FX_INT32 trans_index, FX_INT32 disposal_method, FX_BOOL interlace)
+{
+ 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;
+ }
+ FX_LPBYTE pPalette = NULL;
+ if(pal_num != 0 && pal_ptr) {
+ pPalette = (FX_LPBYTE)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++) {
+ register 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;
+ FX_INT32 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 ++) {
+ FX_LPBYTE pScanline = (FX_LPBYTE)pDevice->GetScanline(row + startY) + startX * Bpp;
+ switch(pCodec->m_TransMethod) {
+ case 3: {
+ FX_BYTE gray = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
+ FXSYS_memset8(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, FX_INT32 row_num, FX_LPBYTE row_buf)
+{
+ CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
+ CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
+ ASSERT(pDIBitmap != NULL);
+ FX_INT32 img_width = pCodec->m_GifFrameRect.Width();
+ if (!pDIBitmap->HasAlpha()) {
+ FX_LPBYTE 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++;
+ }
+ }
+ FX_INT32 pal_index = pCodec->m_GifBgIndex;
+ if (pCodec->m_GifTransIndex != -1 && pCodec->m_pDeviceBitmap->HasAlpha()) {
+ pal_index = pCodec->m_GifTransIndex;
+ }
+ FXSYS_memset8(pCodec->m_pDecodeBuf, pal_index, pCodec->m_SrcWidth);
+ FX_BOOL bLastPass = ((row_num % 2) == 1) ? TRUE : FALSE;
+ FX_INT32 line = row_num + pCodec->m_GifFrameRect.top;
+ FX_INT32 left = pCodec->m_GifFrameRect.left;
+ FXSYS_memcpy32(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) {
+ FX_LPBYTE scan_src = (FX_LPBYTE)pDIBitmap->GetScanline(des_row) + des_ScanOffet;
+ int cur_row = des_row;
+ while (++cur_row < des_bottom) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDIBitmap->GetScanline(cur_row) + des_ScanOffet;
+ FX_DWORD size = pCodec->m_sizeX * des_Bpp;
+ FXSYS_memcpy32(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++) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
+ PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
+ FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
+ FX_LPCBYTE 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++ = (FX_BYTE)(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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((des_r) >> 16);
+ *scan_des++ = (FX_BYTE)((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(FX_BYTE, 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_memcpy32(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, FX_INT32 row_num, FX_LPBYTE row_buf)
+{
+ CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
+ CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
+ ASSERT(pDIBitmap != NULL);
+ FXSYS_memcpy32(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) {
+ FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ while (++des_row < des_bottom) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ FX_DWORD size = m_sizeX * des_Bpp;
+ FXSYS_memcpy32(scan_des, scan_src, size);
+ }
+ return;
+ }
+ for (; des_row_1 > des_row; des_row_1--) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
+ PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
+ FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
+ FX_LPCBYTE 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++ = (FX_BYTE)(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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((des_r) >> 16);
+ *scan_des++ = (FX_BYTE)((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(FX_BYTE, size);
+ if(m_pSrcBuf == NULL) {
+ m_status = FXCODEC_STATUS_ERR_MEMORY;
+ return FALSE;
+ }
+ FXSYS_memset32(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;
+ FX_INT32 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_memcpy32(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);
+ FX_INT32 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(FX_BYTE, input_size);
+ if(m_pSrcBuf == NULL) {
+ m_status = FXCODEC_STATUS_ERR_MEMORY;
+ return FALSE;
+ }
+ FXSYS_memset32(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;
+ FX_INT32 readResult = pGifModule->ReadHeader(m_pGifContext, &m_SrcWidth, &m_SrcHeight,
+ &m_GifPltNumber, (void**)&m_pGifPalette, &m_GifBgIndex);
+ 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);
+ }
+ 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;
+ }
+ FX_INT32 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(FX_LPBYTE buffer, int width = 1)
+{
+ if (buffer && width > 0) {
+ FX_BYTE 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, FX_LPBYTE src_scan, FXCodec_Format src_format)
+{
+ int src_left = m_clipBox.left;
+ int des_left = m_startX;
+ FX_LPBYTE 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++ = (FX_BYTE)(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 * (FX_BYTE)(argb >> 16);
+ des_g += pixel_weight * (FX_BYTE)(argb >> 8);
+ des_b += pixel_weight * (FX_BYTE)argb;
+ }
+ *des_scan++ = (FX_BYTE)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];
+ FX_LPCBYTE 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++ = (FX_BYTE)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];
+ FX_LPCBYTE src_pixel = src_scan + j * src_Bpp;
+ FX_BYTE 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++ = (FX_BYTE)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_memset8(des_scan, (FX_BYTE)(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 * (FX_BYTE)(argb >> 16);
+ des_g += pixel_weight * (FX_BYTE)(argb >> 8);
+ des_b += pixel_weight * (FX_BYTE)argb;
+ }
+ *des_scan++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((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 * (FX_BYTE)(argb >> 16);
+ des_g += pixel_weight * (FX_BYTE)(argb >> 8);
+ des_b += pixel_weight * (FX_BYTE)argb;
+ }
+ *des_scan++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((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 * (FX_BYTE)(argb >> 24);
+ des_r += pixel_weight * (FX_BYTE)(argb >> 16);
+ des_g += pixel_weight * (FX_BYTE)(argb >> 8);
+ des_b += pixel_weight * (FX_BYTE)argb;
+ }
+ *des_scan++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((des_r) >> 16);
+ *des_scan++ = (FX_BYTE)((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];
+ FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((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];
+ FX_LPCBYTE src_pixel = src_scan + j * src_Bpp;
+ FX_BYTE 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++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((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];
+ FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
+ *des_scan++ = (FX_BYTE)((des_g) >> 16);
+ *des_scan++ = (FX_BYTE)((des_r) >> 16);
+ *des_scan++ = (FX_BYTE)((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) {
+ FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ while (++des_row < des_bottom) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ FX_DWORD size = m_sizeX * des_Bpp;
+ FXSYS_memcpy32(scan_des, scan_src, size);
+ }
+ }
+ return;
+ }
+ for (; des_row_1 < des_row; des_row_1++) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
+ PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
+ FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
+ FX_LPCBYTE 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++ = (FX_BYTE)(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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((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++ = (FX_BYTE)((des_b) >> 16);
+ *scan_des++ = (FX_BYTE)((des_g) >> 16);
+ *scan_des++ = (FX_BYTE)((des_r) >> 16);
+ *scan_des++ = (FX_BYTE)((des_a) >> 16);
+ }
+ break;
+ default:
+ return;
+ }
+ }
+ }
+ int des_bottom = des_top + m_sizeY;
+ if(des_row + (int)scale_y >= des_bottom - 1) {
+ FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ while (++des_row < des_bottom) {
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ FX_DWORD size = m_sizeX * des_Bpp;
+ FXSYS_memcpy32(scan_des, scan_src, size);
+ }
+ }
+ return;
+ }
+ int multiple = (int)FXSYS_ceil((FX_FLOAT)scale_y - 1);
+ if(multiple > 0) {
+ FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
+ for (int i = 1; i <= multiple; i++) {
+ if(des_row + i >= m_startY + m_sizeY) {
+ return;
+ }
+ FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet;
+ FX_DWORD size = m_sizeX * des_Bpp;
+ FXSYS_memcpy32(scan_des, scan_src, size);
+ }
+ }
+}
+void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, FX_INT32 src_line, FX_LPBYTE 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(FX_INT32& 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) {
+ FX_INT32 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,
+ FX_INT32 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);
+ FX_INT32 out_range_x = device_rc.right - pDIBitmap->GetWidth();
+ FX_INT32 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 -= (FX_INT32)FXSYS_ceil((FX_FLOAT)start_x * scaleX);
+ }
+ if(out_range_x > 0) {
+ m_clipBox.right -= (FX_INT32)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 -= (FX_INT32)FXSYS_ceil((FX_FLOAT)start_y * scaleY);
+ }
+ if(out_range_y > 0) {
+ m_clipBox.bottom -= (FX_INT32)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(FX_BYTE, scanline_size);
+ if(m_pDecodeBuf == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ FXSYS_memset32(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(FX_BYTE, scanline_size);
+ if(m_pDecodeBuf == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ FXSYS_memset32(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(FX_BYTE, scanline_size);
+ if(m_pDecodeBuf == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ FXSYS_memset32(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(FX_BYTE, m_ScanlineSize);
+ if(m_pDecodeBuf == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ FXSYS_memset32(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(FX_BYTE, input_size);
+ if(m_pSrcBuf == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ FXSYS_memset32(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);
+ 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) {
+ FX_INT32 readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur);
+ 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);
+ }
+ 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) {
+ FX_INT32 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 = FX_NEW CFX_DIBitmap;
+ if(pDIBitmap == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ 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 = FX_NEW CFX_DIBitmap;
+ if(pFormatBitmap == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_8bppRgb);
+ break;
+ case FXDIB_8bppMask:
+ pFormatBitmap = FX_NEW CFX_DIBitmap;
+ if(pFormatBitmap == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_8bppMask);
+ break;
+ case FXDIB_Rgb:
+ pFormatBitmap = FX_NEW CFX_DIBitmap;
+ if(pFormatBitmap == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_Rgb);
+ break;
+ case FXDIB_Rgb32:
+ pFormatBitmap = FX_NEW CFX_DIBitmap;
+ if(pFormatBitmap == NULL) {
+ m_pDeviceBitmap = NULL;
+ m_pFile = NULL;
+ return m_status = FXCODEC_STATUS_ERR_MEMORY;
+ }
+ 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 (FX_INT32 row = 0; row < pClipBitmap->GetHeight(); row++) {
+ FX_LPBYTE src_line = (FX_LPBYTE)pClipBitmap->GetScanline(row);
+ FX_LPBYTE des_line = (FX_LPBYTE)pFormatBitmap->GetScanline(row);
+ for (FX_INT32 col = 0; col < pClipBitmap->GetWidth(); col++) {
+ FX_BYTE _a = 255 - src_line[3];
+ FX_BYTE b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
+ FX_BYTE g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
+ FX_BYTE 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: {
+ FX_INT32 desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
+ for (FX_INT32 row = 0; row < pClipBitmap->GetHeight(); row++) {
+ FX_LPBYTE src_line = (FX_LPBYTE)pClipBitmap->GetScanline(row);
+ FX_LPBYTE des_line = (FX_LPBYTE)pFormatBitmap->GetScanline(row);
+ for (FX_INT32 col = 0; col < pClipBitmap->GetWidth(); col++) {
+ FX_BYTE _a = 255 - src_line[3];
+ FX_BYTE b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
+ FX_BYTE g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
+ FX_BYTE 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 FX_NEW CCodec_ProgressiveDecoder(this);
+}
diff --git a/core/src/fxcodec/codec/fx_codec_progress.h b/core/src/fxcodec/codec/fx_codec_progress.h
new file mode 100644
index 0000000000..6a618e2f51
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_progress.h
@@ -0,0 +1,206 @@
+// 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 CFX_Object
+{
+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;
+ FX_LPBYTE m_pWeightTables;
+};
+class CFXCODEC_HorzTable : public CFX_Object
+{
+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;
+ FX_LPBYTE m_pWeightTables;
+};
+class CFXCODEC_VertTable : public CFX_Object
+{
+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;
+ FX_LPBYTE 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);
+ virtual ~CCodec_ProgressiveDecoder();
+
+public:
+ virtual FXCODEC_STATUS LoadImageInfo(IFX_FileRead* pFile, FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute);
+
+ virtual FXCODEC_IMAGE_TYPE GetType()
+ {
+ return m_imagType;
+ }
+ virtual FX_INT32 GetWidth()
+ {
+ return m_SrcWidth;
+ }
+ virtual FX_INT32 GetHeight()
+ {
+ return m_SrcHeight;
+ }
+ virtual FX_INT32 GetNumComponents()
+ {
+ return m_SrcComponents;
+ }
+ virtual FX_INT32 GetBPC()
+ {
+ return m_SrcBPC;
+ }
+ virtual void SetClipBox(FX_RECT* clip);
+ virtual FXCODEC_STATUS GetFrames(FX_INT32& frames, IFX_Pause* pPause);
+
+ virtual FXCODEC_STATUS StartDecode(CFX_DIBitmap* pDIBitmap,
+ int start_x, int start_y, int size_x, int size_y,
+ FX_INT32 frames, FX_BOOL bInterpol);
+
+ virtual FXCODEC_STATUS ContinueDecode(IFX_Pause* pPause);
+
+protected:
+ FX_BOOL DetectImageType(FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute = NULL);
+ void GetDownScale(int& down_scale);
+ void GetTransMethod(FXDIB_Format des_format, FXCodec_Format src_format);
+ void ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, FX_INT32 des_line, FX_LPBYTE src_scan, FXCodec_Format src_format);
+ void Resample(CFX_DIBitmap* pDeviceBitmap, FX_INT32 src_line, FX_LPBYTE 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);
+ 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, FX_LPBYTE& src_buf);
+ static void PngFillScanlineBufCompletedFunc(void* pModule, int pass, int line);
+ void PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, FX_INT32 des_line, FX_LPBYTE src_scan, FXCodec_Format src_format);
+
+ FX_BOOL GifReadMoreData(ICodec_GifModule* pGifModule, FXCODEC_STATUS& err_status);
+ static void GifRecordCurrentPositionCallback(void* pModule, FX_DWORD& cur_pos);
+ static FX_LPBYTE GifAskLocalPaletteBufCallback(void* pModule, FX_INT32 frame_num, FX_INT32 pal_size);
+ static FX_BOOL GifInputRecordPositionBufCallback(void* pModule, FX_DWORD rcd_pos, const FX_RECT& img_rc,
+ FX_INT32 pal_num, void* pal_ptr,
+ FX_INT32 delay_time, FX_BOOL user_input,
+ FX_INT32 trans_index, FX_INT32 disposal_method, FX_BOOL interlace);
+ static void GifReadScanlineCallback(void* pModule, FX_INT32 row_num, FX_LPBYTE row_buf);
+ void GifDoubleLineResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row);
+ FX_BOOL BmpReadMoreData(ICodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status);
+ static FX_BOOL BmpInputImagePositionBufCallback(void* pModule, FX_DWORD rcd_pos);
+ static void BmpReadScanlineCallback(void* pModule, FX_INT32 row_num, FX_LPBYTE row_buf);
+ void ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row);
+public:
+ IFX_FileRead* m_pFile;
+ CCodec_ModuleMgr* m_pCodecMgr;
+ FX_LPVOID m_pJpegContext;
+ FX_LPVOID m_pPngContext;
+ FX_LPVOID m_pGifContext;
+ FX_LPVOID m_pBmpContext;
+ FX_LPVOID m_pTiffContext;
+ FXCODEC_IMAGE_TYPE m_imagType;
+ FX_DWORD m_offSet;
+ FX_LPBYTE m_pSrcBuf;
+ FX_DWORD m_SrcSize;
+ FX_LPBYTE 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;
+ FX_LPBYTE m_pGifPalette;
+ FX_INT32 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
new file mode 100644
index 0000000000..c90de7a74f
--- /dev/null
+++ b/core/src/fxcodec/codec/fx_codec_tiff.cpp
@@ -0,0 +1,532 @@
+// 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/fxcodec/fx_codec.h"
+#include "../../../include/fxge/fx_dib.h"
+#include "codec_int.h"
+extern "C" {
+#include "../fx_tiff/include/fx_tiffiop.h"
+}
+#if !defined(_FPDFAPI_MINI_)
+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);
+#endif
+class CCodec_TiffContext : public CFX_Object
+{
+public:
+ CCodec_TiffContext();
+ ~CCodec_TiffContext();
+
+ FX_BOOL InitDecoder(IFX_FileRead* file_ptr);
+ void GetFrames(FX_INT32& frames);
+ FX_BOOL LoadFrameInfo(FX_INT32 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;
+ FX_INT32 frame_num;
+ FX_INT32 frame_cur;
+ FX_BOOL isDecoder;
+private:
+ FX_BOOL isSupport(CFX_DIBitmap* pDIBitmap);
+ void SetPalette(CFX_DIBitmap* pDIBitmap, FX_UINT16 bps);
+ FX_BOOL Decode1bppRGB(CFX_DIBitmap* pDIBitmap, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 spp);
+ FX_BOOL Decode8bppRGB(CFX_DIBitmap* pDIBitmap, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 spp);
+ FX_BOOL Decode24bppRGB(CFX_DIBitmap* pDIBitmap, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 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 !defined(_FPDFAPI_MINI_)
+ if(icc_ctx) {
+ IccLib_DestroyTransform(icc_ctx);
+ icc_ctx = NULL;
+ }
+#endif
+ 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)(FX_INTPTR)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_memset8(ptr, val, (size_t)size);
+}
+void _TIFFmemcpy(void* des, const void* src, tmsize_t size)
+{
+ FXSYS_memcpy32(des, src, (size_t)size);
+}
+int _TIFFmemcmp(const void* ptr1, const void* ptr2, tmsize_t size)
+{
+ return FXSYS_memcmp32(ptr1, ptr2, (size_t)size);
+}
+static void _tiff_warning_ext(thandle_t context, const char* module, const char* fmt, va_list ap)
+{
+ if(module != NULL) {
+ }
+}
+TIFFErrorHandlerExt _TIFFwarningHandlerExt = _tiff_warning_ext;
+static void _tiff_error_ext(thandle_t context, const char* module, const char* fmt, va_list ap)
+{
+ if(module != NULL) {
+ }
+}
+TIFFErrorHandlerExt _TIFFerrorHandlerExt = _tiff_error_ext;
+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 !defined(_FPDFAPI_MINI_)
+ 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 {
+#endif
+ AdobeCMYK_to_sRGB1(c, m, y, k, *r, *g, *b);
+#if !defined(_FPDFAPI_MINI_)
+ }
+#endif
+ 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(FX_INT32& 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(FX_BYTE,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;\
+ FX_LPBYTE buf = NULL;\
+ TIFFGetField(tif_ctx,tag,&size, &buf);\
+ if (size && buf) {\
+ (key) = FX_Alloc(FX_BYTE,size);\
+ if ((key)) {\
+ FXSYS_memcpy32((key),buf,size);\
+ pExif->m_TagVal.SetAt(tag,(key));}}}\
+ (key) = NULL;
+template <class T>
+static FX_BOOL Tiff_Exif_GetInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttributeExif* pExif)
+{
+ FX_LPBYTE key = NULL;
+ T val = (T)0;
+ TIFFGetField(tif_ctx, tag, &val);
+ if (val) {
+ (key) = FX_Alloc(FX_BYTE, sizeof(T));
+ if ((key) == NULL) {
+ return FALSE;
+ }
+ T* ptr = (T*)(key);
+ *ptr = val;
+ pExif->m_TagVal.SetAt(tag, (key));
+ return TRUE;
+ }
+ return FALSE;
+}
+static void Tiff_Exif_GetStringInfo(TIFF* tif_ctx, ttag_t tag, CFX_DIBAttributeExif* pExif)
+{
+ FX_LPSTR buf = NULL;
+ FX_LPBYTE key = NULL;
+ TIFFGetField(tif_ctx, tag, &buf);
+ if (buf) {
+ FX_INT32 size = (FX_INT32)FXSYS_strlen(buf);
+ (key) = FX_Alloc(FX_BYTE, size + 1);
+ if ((key) == NULL) {
+ return;
+ }
+ FXSYS_memcpy32((key), buf, size);
+ key[size] = 0;
+ pExif->m_TagVal.SetAt(tag, (key));
+ }
+}
+FX_BOOL CCodec_TiffContext::LoadFrameInfo(FX_INT32 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;
+ FX_LPBYTE 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;
+ }
+ CFX_DIBAttributeExif* pExif = (CFX_DIBAttributeExif*)pAttribute->m_pExif;
+ pExif->clear();
+ Tiff_Exif_GetInfo<FX_WORD>(tif_ctx, TIFFTAG_ORIENTATION, pExif);
+ if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_XRESOLUTION, pExif)) {
+ FX_FLOAT fDpi = 0;
+ pExif->GetInfo(TIFFTAG_XRESOLUTION, &fDpi);
+ pAttribute->m_nXDPI = (FX_INT32)(fDpi + 0.5f);
+ }
+ if (Tiff_Exif_GetInfo<FX_FLOAT>(tif_ctx, TIFFTAG_YRESOLUTION, pExif)) {
+ FX_FLOAT fDpi = 0;
+ pExif->GetInfo(TIFFTAG_YRESOLUTION, &fDpi);
+ pAttribute->m_nYDPI = (FX_INT32)(fDpi + 0.5f);
+ }
+ Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_IMAGEDESCRIPTION, pExif);
+ Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MAKE, pExif);
+ Tiff_Exif_GetStringInfo(tif_ctx, TIFFTAG_MODEL, pExif);
+ }
+ bpc = tif_bpc;
+ if(tif_rps > height) {
+ TIFFSetField(tif_ctx, TIFFTAG_ROWSPERSTRIP, tif_rps = height);
+ }
+ return TRUE;
+}
+void _TiffBGRA2RGBA(FX_LPBYTE pBuf, FX_INT32 pixel, FX_INT32 spp)
+{
+ register FX_BYTE tmp;
+ for (FX_INT32 n = 0; n < pixel; n++) {
+ 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;
+ }
+ FX_UINT16 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;
+ }
+ FX_UINT16 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, FX_UINT16 bps)
+{
+ FX_UINT16 *red_orig, *green_orig, *blue_orig;
+ TIFFGetField(tif_ctx, TIFFTAG_COLORMAP, &red_orig, &green_orig, &blue_orig);
+ for (FX_INT32 i = (1L << bps) - 1; i >= 0; i--) {
+#define CVT(x) ((FX_UINT16)((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
+ }
+ FX_INT32 len = 1 << bps;
+ for(FX_INT32 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 = (FX_UINT32)b | ((FX_UINT32)g << 8) | ((FX_UINT32)r << 16) | (((uint32)0xffL) << 24);
+ pDIBitmap->SetPaletteEntry(index, color);
+ }
+}
+FX_BOOL CCodec_TiffContext::Decode1bppRGB(CFX_DIBitmap* pDIBitmap, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 spp)
+{
+ if (pDIBitmap->GetBPP() != 1 || spp != 1 || bps != 1 || !isSupport(pDIBitmap)) {
+ return FALSE;
+ }
+ SetPalette(pDIBitmap, bps);
+ FX_INT32 size = (FX_INT32)TIFFScanlineSize(tif_ctx);
+ FX_LPBYTE buf = (FX_LPBYTE)_TIFFmalloc(size);
+ if (buf == NULL) {
+ TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer");
+ return FALSE;
+ }
+ FX_LPBYTE bitMapbuffer = (FX_LPBYTE)pDIBitmap->GetBuffer();
+ FX_DWORD pitch = pDIBitmap->GetPitch();
+ for(FX_INT32 row = 0; row < height; row++) {
+ TIFFReadScanline(tif_ctx, buf, row, 0);
+ for(FX_INT32 j = 0; j < size; j++) {
+ bitMapbuffer[row * pitch + j] = buf[j];
+ }
+ }
+ _TIFFfree(buf);
+ return TRUE;
+}
+FX_BOOL CCodec_TiffContext::Decode8bppRGB(CFX_DIBitmap* pDIBitmap, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 spp)
+{
+ if (pDIBitmap->GetBPP() != 8 || spp != 1 || (bps != 4 && bps != 8) || !isSupport(pDIBitmap)) {
+ return FALSE;
+ }
+ SetPalette(pDIBitmap, bps);
+ FX_INT32 size = (FX_INT32)TIFFScanlineSize(tif_ctx);
+ FX_LPBYTE buf = (FX_LPBYTE)_TIFFmalloc(size);
+ if (buf == NULL) {
+ TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer");
+ return FALSE;
+ }
+ FX_LPBYTE bitMapbuffer = (FX_LPBYTE)pDIBitmap->GetBuffer();
+ FX_DWORD pitch = pDIBitmap->GetPitch();
+ for(FX_INT32 row = 0; row < height; row++) {
+ TIFFReadScanline(tif_ctx, buf, row, 0);
+ for(FX_INT32 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, FX_INT32 height, FX_INT32 width, FX_UINT16 bps, FX_UINT16 spp)
+{
+ if (pDIBitmap->GetBPP() != 24 || !isSupport(pDIBitmap)) {
+ return FALSE;
+ }
+ FX_INT32 size = (FX_INT32)TIFFScanlineSize(tif_ctx);
+ FX_LPBYTE buf = (FX_LPBYTE)_TIFFmalloc(size);
+ if (buf == NULL) {
+ TIFFError(TIFFFileName(tif_ctx), "No space for scanline buffer");
+ return FALSE;
+ }
+ FX_LPBYTE bitMapbuffer = (FX_LPBYTE)pDIBitmap->GetBuffer();
+ FX_DWORD pitch = pDIBitmap->GetPitch();
+ for(FX_INT32 row = 0; row < height; row++) {
+ TIFFReadScanline(tif_ctx, buf, row, 0);
+ for(FX_INT32 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++) {
+ FX_LPBYTE row_buf = (FX_LPBYTE)pDIBitmap->GetScanline(row);
+ _TiffBGRA2RGBA(row_buf, img_wid, 4);
+ }
+ return TRUE;
+ }
+ }
+ FX_UINT16 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;
+}
+FX_LPVOID CCodec_TiffModule::CreateDecoder(IFX_FileRead* file_ptr)
+{
+ CCodec_TiffContext* pDecoder = FX_NEW CCodec_TiffContext;
+ if (pDecoder == NULL) {
+ return NULL;
+ }
+ if (!pDecoder->InitDecoder(file_ptr)) {
+ delete pDecoder;
+ return NULL;
+ }
+ return pDecoder;
+}
+void CCodec_TiffModule::GetFrames(FX_LPVOID ctx, FX_INT32& frames)
+{
+ CCodec_TiffContext* pDecoder = (CCodec_TiffContext*)ctx;
+ pDecoder->GetFrames(frames);
+}
+FX_BOOL CCodec_TiffModule::LoadFrameInfo(FX_LPVOID ctx, FX_INT32 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;
+}