| // 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" | |
| } | |
| void* IccLib_CreateTransform_sRGB(const unsigned char* pProfileData, unsigned int dwProfileSize, int nComponents, int intent, FX_DWORD dwSrcFormat = Icc_FORMAT_DEFAULT); | |
| void IccLib_TranslateImage(void* pTransform, unsigned char* pDest, const unsigned char* pSrc, int pixels); | |
| void IccLib_DestroyTransform(void* pTransform); | |
| class CCodec_TiffContext | |
| { | |
| public: | |
| CCodec_TiffContext(); | |
| ~CCodec_TiffContext(); | |
| FX_BOOL InitDecoder(IFX_FileRead* file_ptr); | |
| void GetFrames(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(icc_ctx) { | |
| IccLib_DestroyTransform(icc_ctx); | |
| icc_ctx = NULL; | |
| } | |
| if(tif_ctx) { | |
| TIFFClose(tif_ctx); | |
| } | |
| } | |
| static tsize_t _tiff_read(thandle_t context, tdata_t buf, tsize_t length) | |
| { | |
| CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
| FX_BOOL ret = FALSE; | |
| if(pTiffContext->isDecoder) { | |
| ret = pTiffContext->io.in->ReadBlock(buf, pTiffContext->offset, length); | |
| } else { | |
| ret = pTiffContext->io.out->ReadBlock(buf, pTiffContext->offset, length); | |
| } | |
| if(!ret) { | |
| return 0; | |
| } | |
| pTiffContext->offset += (FX_DWORD)length; | |
| return length; | |
| } | |
| static tsize_t _tiff_write(thandle_t context, tdata_t buf, tsize_t length) | |
| { | |
| CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
| ASSERT(!pTiffContext->isDecoder); | |
| if(!pTiffContext->io.out->WriteBlock(buf, pTiffContext->offset, length)) { | |
| return 0; | |
| } | |
| pTiffContext->offset += (FX_DWORD)length; | |
| return length; | |
| } | |
| static toff_t _tiff_seek(thandle_t context, toff_t offset, int whence) | |
| { | |
| CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
| switch(whence) { | |
| case 0: | |
| pTiffContext->offset = (FX_DWORD)offset; | |
| break; | |
| case 1: | |
| pTiffContext->offset += (FX_DWORD)offset; | |
| break; | |
| case 2: | |
| if(pTiffContext->isDecoder) { | |
| if(pTiffContext->io.in->GetSize() < (FX_FILESIZE)offset) { | |
| return -1; | |
| } | |
| pTiffContext->offset = (FX_DWORD)(pTiffContext->io.in->GetSize() - offset); | |
| } else { | |
| if(pTiffContext->io.out->GetSize() < (FX_FILESIZE)offset) { | |
| return -1; | |
| } | |
| pTiffContext->offset = (FX_DWORD)(pTiffContext->io.out->GetSize() - offset); | |
| } | |
| break; | |
| default: | |
| return -1; | |
| } | |
| ASSERT(pTiffContext->isDecoder ? | |
| (pTiffContext->offset <= (FX_DWORD)pTiffContext->io.in->GetSize()) : | |
| TRUE); | |
| return pTiffContext->offset; | |
| } | |
| static int _tiff_close(thandle_t context) | |
| { | |
| return 0; | |
| } | |
| static toff_t _tiff_get_size(thandle_t context) | |
| { | |
| CCodec_TiffContext* pTiffContext = (CCodec_TiffContext*)context; | |
| return pTiffContext->isDecoder ? | |
| (toff_t)pTiffContext->io.in->GetSize() : | |
| (toff_t)pTiffContext->io.out->GetSize(); | |
| } | |
| static int _tiff_map(thandle_t context, tdata_t*, toff_t*) | |
| { | |
| return 0; | |
| } | |
| static void _tiff_unmap(thandle_t context, tdata_t, toff_t) {} | |
| TIFF* _tiff_open(void* context, const char* mode) | |
| { | |
| TIFF* tif = TIFFClientOpen("Tiff Image", mode, | |
| (thandle_t)context, | |
| _tiff_read, _tiff_write, _tiff_seek, _tiff_close, | |
| _tiff_get_size, _tiff_map, _tiff_unmap); | |
| if(tif) { | |
| tif->tif_fd = (int)(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(p->icc_ctx) { | |
| unsigned char cmyk[4], bgr[3]; | |
| cmyk[0] = c, cmyk[1] = m, cmyk[2] = y, cmyk[3] = k; | |
| IccLib_TranslateImage(p->icc_ctx, bgr, cmyk, 1); | |
| *r = bgr[2], *g = bgr[1], *b = bgr[0]; | |
| } else { | |
| AdobeCMYK_to_sRGB1(c, m, y, k, *r, *g, *b); | |
| } | |
| return 1; | |
| } | |
| FX_BOOL CCodec_TiffContext::InitDecoder(IFX_FileRead* file_ptr) | |
| { | |
| io.in = file_ptr; | |
| tif_ctx = _tiff_open(this, "r"); | |
| if(tif_ctx == NULL) { | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| void CCodec_TiffContext::GetFrames(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 = new CCodec_TiffContext; | |
| 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; | |
| } |