1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../../../include/fxcodec/fx_codec.h"
9 CCodec_ModuleMgr::CCodec_ModuleMgr()
11 m_pBasicModule = FX_NEW CCodec_BasicModule;
12 m_pFaxModule = FX_NEW CCodec_FaxModule;
13 m_pJpegModule = FX_NEW CCodec_JpegModule;
14 m_pJpxModule = FX_NEW CCodec_JpxModule;
15 m_pJbig2Module = FX_NEW CCodec_Jbig2Module;
16 m_pIccModule = FX_NEW CCodec_IccModule;
17 m_pPngModule = FX_NEW CCodec_PngModule;
\r
18 m_pGifModule = FX_NEW CCodec_GifModule;
\r
19 m_pBmpModule = FX_NEW CCodec_BmpModule;
\r
20 m_pTiffModule = FX_NEW CCodec_TiffModule;
\r
21 m_pFlateModule = FX_NEW CCodec_FlateModule;
23 CCodec_ModuleMgr::~CCodec_ModuleMgr()
25 delete m_pBasicModule;
28 delete m_pFlateModule;
30 delete m_pJbig2Module;
33 void CCodec_ModuleMgr::InitJbig2Decoder()
36 void CCodec_ModuleMgr::InitJpxDecoder()
39 void CCodec_ModuleMgr::InitIccDecoder()
42 CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
46 m_pLastScanline = NULL;
48 CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder()
51 FX_Free(m_pDataCache);
54 FX_LPBYTE CCodec_ScanlineDecoder::GetScanline(int line)
56 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
57 return &m_pDataCache->m_Data + line * m_Pitch;
59 if (m_NextLine == line + 1) {
60 return m_pLastScanline;
62 if (m_NextLine < 0 || m_NextLine > line) {
68 while (m_NextLine < line) {
72 m_pLastScanline = ReadNextLine();
74 return m_pLastScanline;
76 FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause)
78 if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
81 if (m_NextLine == line || m_NextLine == line + 1) {
84 if (m_NextLine < 0 || m_NextLine > line) {
88 m_pLastScanline = NULL;
89 while (m_NextLine < line) {
90 m_pLastScanline = ReadNextLine();
92 if (pPause && pPause->NeedToPauseNow()) {
98 FX_LPBYTE CCodec_ScanlineDecoder::ReadNextLine()
100 FX_LPBYTE pLine = v_GetNextLine();
104 if (m_pDataCache && m_NextLine == m_pDataCache->m_nCachedLines) {
105 FXSYS_memcpy32(&m_pDataCache->m_Data + m_NextLine * m_Pitch, pLine, m_Pitch);
106 m_pDataCache->m_nCachedLines ++;
110 void CCodec_ScanlineDecoder::DownScale(int dest_width, int dest_height)
112 if (dest_width < 0) {
113 dest_width = -dest_width;
115 if (dest_height < 0) {
116 dest_height = -dest_height;
118 v_DownScale(dest_width, dest_height);
120 if (m_pDataCache->m_Height == m_OutputHeight && m_pDataCache->m_Width == m_OutputWidth) {
123 FX_Free(m_pDataCache);
126 m_pDataCache = (CCodec_ImageDataCache*)FX_AllocNL(FX_BYTE, sizeof(CCodec_ImageDataCache) + m_Pitch * m_OutputHeight);
127 if (m_pDataCache == NULL) {
130 m_pDataCache->m_Height = m_OutputHeight;
131 m_pDataCache->m_Width = m_OutputWidth;
132 m_pDataCache->m_nCachedLines = 0;
134 FX_BOOL CCodec_BasicModule::RunLengthEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
139 extern "C" double FXstrtod(const char* nptr, char** endptr)
142 const char* ptr = nptr;
143 const char* exp_ptr = NULL;
148 int exp_ret = 0, exp_sig = 1,
149 fra_ret = 0, fra_count = 0, fra_base = 1;
154 if(!e_number && !e_point && (*ptr == '\t' || *ptr == ' ')) {
157 if(*ptr >= '0' && *ptr <= '9') {
167 fra_ret += (*ptr - '0');
171 if(!e_point && *ptr == '.') {
175 if(!e_number && !e_point && !e_signal) {
184 if(e_number && (*ptr == 'e' || *ptr == 'E')) {
185 #define EXPONENT_DETECT(ptr) \
187 if(*ptr < '0' || *ptr > '9'){ \
188 if(endptr) *endptr = (char*)ptr; \
192 exp_ret += (*ptr - '0'); \
197 if(*ptr == '+' || *ptr == '-') {
198 exp_sig = (*ptr++ == '+') ? 1 : -1;
199 if(*ptr < '0' || *ptr > '9') {
201 *endptr = (char*)exp_ptr;
205 EXPONENT_DETECT(ptr);
206 } else if(*ptr >= '0' && *ptr <= '9') {
207 EXPONENT_DETECT(ptr);
210 *endptr = (char*)exp_ptr;
214 #undef EXPONENT_DETECT
217 if(ptr != nptr && !e_number) {
219 *endptr = (char*)nptr;
224 *endptr = (char*)ptr;
231 ret += (double)fra_ret / (double)fra_base;
241 return is_negative ? -ret : ret;
243 FX_BOOL CCodec_BasicModule::A85Encode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
248 CCodec_ModuleMgr* CCodec_ModuleMgr::Create()
250 return FX_NEW CCodec_ModuleMgr;
252 void CCodec_ModuleMgr::Destroy()
256 CFX_DIBAttribute::CFX_DIBAttribute()
\r
258 FXSYS_memset32(this, 0, sizeof(CFX_DIBAttribute));
\r
261 m_fAspectRatio = -1.0f;
\r
262 m_pExif = FX_NEW CFX_DIBAttributeExif;
\r
264 CFX_DIBAttribute::~CFX_DIBAttribute()
\r
270 CFX_DIBAttributeExif::CFX_DIBAttributeExif()
\r
272 m_pExifData = NULL;
\r
273 m_dwExifDataLen = 0;
\r
275 CFX_DIBAttributeExif::~CFX_DIBAttributeExif()
\r
279 void CFX_DIBAttributeExif::clear()
\r
282 FX_Free(m_pExifData);
\r
284 m_pExifData = NULL;
\r
286 FX_LPBYTE buf = NULL;
\r
287 FX_POSITION pos = NULL;
\r
288 pos = m_TagHead.GetStartPosition();
\r
290 m_TagHead.GetNextAssoc(pos, key, buf);
\r
295 m_TagHead.RemoveAll();
\r
296 pos = m_TagVal.GetStartPosition();
\r
298 m_TagVal.GetNextAssoc(pos, key, buf);
\r
303 m_TagVal.RemoveAll();
\r
305 static FX_WORD _Read2BytesL(FX_LPBYTE data)
\r
308 return data[0] | (data[1] << 8);
\r
310 static FX_WORD _Read2BytesB(FX_LPBYTE data)
\r
313 return data[1] | (data[0] << 8);
\r
315 static FX_DWORD _Read4BytesL(FX_LPBYTE data)
\r
317 return _Read2BytesL(data) | (_Read2BytesL(data + 2) << 16);
\r
319 static FX_DWORD _Read4BytesB(FX_LPBYTE data)
\r
321 return _Read2BytesB(data + 2) | (_Read2BytesB(data) << 16);
\r
323 typedef FX_WORD (*_Read2Bytes) (FX_LPBYTE data);
\r
324 typedef FX_DWORD (*_Read4Bytes) (FX_LPBYTE data);
\r
325 typedef void (*_Write2Bytes) (FX_LPBYTE data, FX_WORD val);
\r
326 typedef void (*_Write4Bytes) (FX_LPBYTE data, FX_DWORD val);
\r
327 FX_LPBYTE CFX_DIBAttributeExif::ParseExifIFH(FX_LPBYTE data, FX_DWORD len, _Read2Bytes* pReadWord, _Read4Bytes* pReadDword)
\r
330 FX_BOOL tag = FALSE;
\r
331 if (FXSYS_memcmp32(data, "\x49\x49\x2a\x00", 4) == 0) {
\r
333 *pReadWord = _Read2BytesL;
\r
336 *pReadDword = _Read4BytesL;
\r
339 } else if (FXSYS_memcmp32(data, "\x4d\x4d\x00\x2a", 4) == 0) {
\r
341 *pReadWord = _Read2BytesB;
\r
344 *pReadDword = _Read4BytesB;
\r
351 data += (*pReadDword)(data) - 4;
\r
359 FX_BOOL CFX_DIBAttributeExif::ParseExifIFD(CFX_MapPtrTemplate<FX_DWORD, FX_LPBYTE>* pMap, FX_LPBYTE data, FX_DWORD len)
\r
361 if (pMap && data) {
\r
363 FX_WORD wTagNum = m_readWord(data);
\r
367 while (wTagNum--) {
\r
368 wTag = m_readWord(data);
\r
370 if (!pMap->Lookup(wTag, buf)) {
\r
371 buf = FX_Alloc(FX_BYTE, 10);
\r
375 FXSYS_memcpy32(buf, data, 10);
\r
376 pMap->SetAt(wTag, buf);
\r
380 FX_DWORD dwIFDOffset;
\r
381 dwIFDOffset = m_readDword(data);
\r
382 while (dwIFDOffset && dwIFDOffset < len) {
\r
383 data = m_pExifData + dwIFDOffset;
\r
384 wTagNum = m_readWord(data);
\r
386 while (wTagNum--) {
\r
387 wTag = m_readWord(data);
\r
389 if (!pMap->Lookup(wTag, buf)) {
\r
390 buf = FX_Alloc(FX_BYTE, 10);
\r
394 FXSYS_memcpy32(buf, data, 10);
\r
395 pMap->SetAt(wTag, buf);
\r
399 dwIFDOffset = m_readDword(data);
\r
406 enum FX_ExifDataType {
\r
407 FX_UnsignedByte = 1,
\r
420 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)
\r
422 if (pHead && data && pVal) {
\r
424 FX_LPBYTE old_data = data;
\r
425 data = ParseExifIFH(data, len, &m_readWord, &m_readDword);
\r
426 if (data == old_data) {
\r
429 if (pHead->GetCount() == 0) {
\r
430 if (!ParseExifIFD(pHead, data, len)) {
\r
434 FX_DWORD dwModuleNum;
\r
439 FX_POSITION pos = pHead->GetStartPosition();
\r
441 pHead->GetNextAssoc(pos, tag, head);
\r
442 FX_LPBYTE val = NULL, buf = NULL, temp = NULL;
\r
445 type = m_readWord(head);
\r
447 dwModuleNum = m_readDword(head);
\r
450 case FX_UnsignedByte:
\r
452 case FX_SignedByte:
\r
454 dwSize = dwModuleNum;
\r
455 val = FX_Alloc(FX_BYTE, dwSize);
\r
460 FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
\r
462 FXSYS_memcpy32(val, head, dwSize);
\r
465 case FX_UnsignedShort:
\r
466 case FX_SignedShort:
\r
467 dwSize = dwModuleNum << 1;
\r
468 val = FX_Alloc(FX_BYTE, dwSize);
\r
473 FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
\r
475 FXSYS_memcpy32(val, head, dwSize);
\r
478 for(i = 0; i < (int)dwModuleNum; i ++) {
\r
479 *(FX_WORD*)buf = m_readWord(buf);
\r
483 case FX_UnsignedLong:
\r
484 case FX_SignedLong:
\r
485 case FX_SignedFloat:
\r
486 dwSize = dwModuleNum << 2;
\r
487 val = FX_Alloc(FX_BYTE, dwSize);
\r
492 FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
\r
494 FXSYS_memcpy32(val, head, dwSize);
\r
497 for(i = 0; i < (int)dwModuleNum; i ++) {
\r
498 *(FX_DWORD*)buf = m_readDword(buf);
\r
502 case FX_UnsignedRation:
\r
503 case FX_SignedRation: {
\r
504 dwSize = dwModuleNum << 3;
\r
505 buf = FX_Alloc(FX_BYTE, dwSize);
\r
510 FXSYS_memcpy32(buf, old_data + m_readDword(head), dwSize);
\r
512 FXSYS_memcpy32(buf, head, dwSize);
\r
515 val = FX_Alloc(FX_BYTE, dwSize / 2);
\r
520 for(i = 0; i < (int)dwModuleNum; i ++) {
\r
521 *(FX_DWORD*)temp = m_readDword(temp);
\r
522 *(FX_DWORD*)(temp + 4) = m_readDword(temp + 4);
\r
523 FX_DWORD* lNumerator = (FX_DWORD*)temp;
\r
524 FX_DWORD* lNenominator = (FX_DWORD*)(temp + 4);
\r
525 *(FX_FLOAT*)(val + i * 4) = (FX_FLOAT)(*lNumerator) / (FX_FLOAT)(*lNenominator);
\r
531 case FX_DoubleFloat:
\r
532 dwSize = dwModuleNum << 3;
\r
533 val = FX_Alloc(FX_BYTE, dwSize);
\r
538 FXSYS_memcpy32(val, old_data + m_readDword(head), dwSize);
\r
540 FXSYS_memcpy32(val, head, dwSize);
\r
543 for(i = 0; i < (int)dwModuleNum; i ++) {
\r
544 *(FX_DWORD*)buf = m_readDword(buf);
\r
545 *(FX_DWORD*)(buf + 4) = m_readDword(buf + 4);
\r
553 pVal->SetAt(tag, val);
\r
560 #define FXEXIF_INFOCONVERT(T) {T* src = (T*)ptr; T* dst = (T*)val; *dst = *src;}
\r
561 FX_BOOL CFX_DIBAttributeExif::GetInfo( FX_WORD tag, FX_LPVOID val )
\r
563 if (m_TagVal.GetCount() == 0) {
\r
564 if (!ParseExif(&m_TagHead, m_pExifData, m_dwExifDataLen, &m_TagVal)) {
\r
568 FX_LPBYTE ptr = NULL;
\r
569 if (m_TagVal.Lookup(tag, ptr)) {
\r
571 case EXIFTAG_USHORT_RESUNIT:
\r
572 FXEXIF_INFOCONVERT(FX_WORD);
\r
574 FX_WORD* ptr = (FX_WORD*)val;
\r
578 case EXIFTAG_FLOAT_DPIX:
\r
579 case EXIFTAG_FLOAT_DPIY:
\r
580 FXEXIF_INFOCONVERT(FX_FLOAT);
\r
582 case EXIFTAG_USHORT_ORIENTATION:
\r
583 FXEXIF_INFOCONVERT(FX_WORD);
\r
586 FX_LPBYTE* dst = (FX_LPBYTE*)val;
\r
593 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
596 CCodec_RLScanlineDecoder();
597 virtual ~CCodec_RLScanlineDecoder();
598 FX_BOOL Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc);
599 virtual void v_DownScale(int dest_width, int dest_height) {}
600 virtual FX_BOOL v_Rewind();
601 virtual FX_LPBYTE v_GetNextLine();
602 virtual FX_DWORD GetSrcOffset()
607 FX_BOOL CheckDestSize();
608 void GetNextOperator();
609 void UpdateOperator(FX_BYTE used_bytes);
611 FX_LPBYTE m_pScanline;
612 FX_LPCBYTE m_pSrcBuf;
614 FX_DWORD m_dwLineBytes;
615 FX_DWORD m_SrcOffset;
619 CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder()
629 CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder()
632 FX_Free(m_pScanline);
635 FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize()
638 FX_DWORD old_size = 0;
639 FX_DWORD dest_size = 0;
640 while (i < m_SrcSize) {
641 if (m_pSrcBuf[i] < 128) {
642 old_size = dest_size;
643 dest_size += m_pSrcBuf[i] + 1;
644 if (dest_size < old_size) {
647 i += m_pSrcBuf[i] + 2;
648 } else if (m_pSrcBuf[i] > 128) {
649 old_size = dest_size;
650 dest_size += 257 - m_pSrcBuf[i];
651 if (dest_size < old_size) {
659 if (((FX_DWORD)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > dest_size) {
664 FX_BOOL CCodec_RLScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc)
667 m_SrcSize = src_size;
668 m_OutputWidth = m_OrigWidth = width;
669 m_OutputHeight = m_OrigHeight = height;
672 m_bColorTransformed = FALSE;
674 m_Pitch = (width * nComps * bpc + 31) / 32 * 4;
675 m_dwLineBytes = (width * nComps * bpc + 7) / 8;
676 m_pScanline = FX_Alloc(FX_BYTE, m_Pitch);
677 if (m_pScanline == NULL) {
680 return CheckDestSize();
682 FX_BOOL CCodec_RLScanlineDecoder::v_Rewind()
684 FXSYS_memset32(m_pScanline, 0, m_Pitch);
690 FX_LPBYTE CCodec_RLScanlineDecoder::v_GetNextLine()
692 if (m_SrcOffset == 0) {
699 FXSYS_memset32(m_pScanline, 0, m_Pitch);
700 FX_DWORD col_pos = 0;
702 while (m_SrcOffset < m_SrcSize && !eol) {
703 if (m_Operator < 128) {
704 FX_DWORD copy_len = m_Operator + 1;
705 if (col_pos + copy_len >= m_dwLineBytes) {
706 copy_len = m_dwLineBytes - col_pos;
709 if (copy_len >= m_SrcSize - m_SrcOffset) {
710 copy_len = m_SrcSize - m_SrcOffset;
713 FXSYS_memcpy32(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len);
715 UpdateOperator((FX_BYTE)copy_len);
716 } else if (m_Operator > 128) {
718 if (m_SrcOffset - 1 < m_SrcSize - 1) {
719 fill = m_pSrcBuf[m_SrcOffset];
721 FX_DWORD duplicate_len = 257 - m_Operator;
722 if (col_pos + duplicate_len >= m_dwLineBytes) {
723 duplicate_len = m_dwLineBytes - col_pos;
726 FXSYS_memset8(m_pScanline + col_pos, fill, duplicate_len);
727 col_pos += duplicate_len;
728 UpdateOperator((FX_BYTE)duplicate_len);
736 void CCodec_RLScanlineDecoder::GetNextOperator()
738 if (m_SrcOffset >= m_SrcSize) {
742 m_Operator = m_pSrcBuf[m_SrcOffset];
745 void CCodec_RLScanlineDecoder::UpdateOperator(FX_BYTE used_bytes)
747 if (used_bytes == 0) {
750 if (m_Operator < 128) {
751 FXSYS_assert((FX_DWORD)m_Operator + 1 >= used_bytes);
752 if (used_bytes == m_Operator + 1) {
753 m_SrcOffset += used_bytes;
757 m_Operator -= used_bytes;
758 m_SrcOffset += used_bytes;
759 if (m_SrcOffset >= m_SrcSize) {
764 FX_BYTE count = 257 - m_Operator;
765 FXSYS_assert((FX_DWORD)count >= used_bytes);
766 if (used_bytes == count) {
772 m_Operator = 257 - count;
774 ICodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
777 CCodec_RLScanlineDecoder* pRLScanlineDecoder = FX_NEW CCodec_RLScanlineDecoder;
778 if (pRLScanlineDecoder == NULL) {
781 if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps, bpc)) {
782 delete pRLScanlineDecoder;
785 return pRLScanlineDecoder;