Home | History | Annotate | Download | only in codec
      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.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../../../include/fxcodec/fx_codec.h"
      8 #include "codec_int.h"
      9 CCodec_ModuleMgr::CCodec_ModuleMgr()
     10 {
     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_pFlateModule = FX_NEW CCodec_FlateModule;
     18 }
     19 CCodec_ModuleMgr::~CCodec_ModuleMgr()
     20 {
     21     delete m_pBasicModule;
     22     delete m_pFaxModule;
     23     delete m_pJpegModule;
     24     delete m_pFlateModule;
     25     delete m_pJpxModule;
     26     delete m_pJbig2Module;
     27     delete m_pIccModule;
     28 }
     29 void CCodec_ModuleMgr::InitJbig2Decoder()
     30 {
     31 }
     32 void CCodec_ModuleMgr::InitJpxDecoder()
     33 {
     34 }
     35 void CCodec_ModuleMgr::InitIccDecoder()
     36 {
     37 }
     38 CCodec_ScanlineDecoder::CCodec_ScanlineDecoder()
     39 {
     40     m_NextLine = -1;
     41     m_pDataCache = NULL;
     42     m_pLastScanline = NULL;
     43 }
     44 CCodec_ScanlineDecoder::~CCodec_ScanlineDecoder()
     45 {
     46     if (m_pDataCache) {
     47         FX_Free(m_pDataCache);
     48     }
     49 }
     50 FX_LPBYTE CCodec_ScanlineDecoder::GetScanline(int line)
     51 {
     52     if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
     53         return &m_pDataCache->m_Data + line * m_Pitch;
     54     }
     55     if (m_NextLine == line + 1) {
     56         return m_pLastScanline;
     57     }
     58     if (m_NextLine < 0 || m_NextLine > line) {
     59         if (!v_Rewind()) {
     60             return NULL;
     61         }
     62         m_NextLine = 0;
     63     }
     64     while (m_NextLine < line) {
     65         ReadNextLine();
     66         m_NextLine ++;
     67     }
     68     m_pLastScanline = ReadNextLine();
     69     m_NextLine ++;
     70     return m_pLastScanline;
     71 }
     72 FX_BOOL CCodec_ScanlineDecoder::SkipToScanline(int line, IFX_Pause* pPause)
     73 {
     74     if (m_pDataCache && line < m_pDataCache->m_nCachedLines) {
     75         return FALSE;
     76     }
     77     if (m_NextLine == line || m_NextLine == line + 1) {
     78         return FALSE;
     79     }
     80     if (m_NextLine < 0 || m_NextLine > line) {
     81         v_Rewind();
     82         m_NextLine = 0;
     83     }
     84     m_pLastScanline = NULL;
     85     while (m_NextLine < line) {
     86         m_pLastScanline = ReadNextLine();
     87         m_NextLine ++;
     88         if (pPause && pPause->NeedToPauseNow()) {
     89             return TRUE;
     90         }
     91     }
     92     return FALSE;
     93 }
     94 FX_LPBYTE CCodec_ScanlineDecoder::ReadNextLine()
     95 {
     96     FX_LPBYTE pLine = v_GetNextLine();
     97     if (pLine == NULL) {
     98         return NULL;
     99     }
    100     if (m_pDataCache && m_NextLine == m_pDataCache->m_nCachedLines) {
    101         FXSYS_memcpy32(&m_pDataCache->m_Data + m_NextLine * m_Pitch, pLine, m_Pitch);
    102         m_pDataCache->m_nCachedLines ++;
    103     }
    104     return pLine;
    105 }
    106 void CCodec_ScanlineDecoder::DownScale(int dest_width, int dest_height)
    107 {
    108     if (dest_width < 0) {
    109         dest_width = -dest_width;
    110     }
    111     if (dest_height < 0) {
    112         dest_height = -dest_height;
    113     }
    114     v_DownScale(dest_width, dest_height);
    115     if (m_pDataCache) {
    116         if (m_pDataCache->m_Height == m_OutputHeight && m_pDataCache->m_Width == m_OutputWidth) {
    117             return;
    118         }
    119         FX_Free(m_pDataCache);
    120         m_pDataCache = NULL;
    121     }
    122     m_pDataCache = (CCodec_ImageDataCache*)FXMEM_DefaultAlloc(
    123                        sizeof(CCodec_ImageDataCache) + m_Pitch * m_OutputHeight, FXMEM_NONLEAVE);
    124     if (m_pDataCache == NULL) {
    125         return;
    126     }
    127     m_pDataCache->m_Height = m_OutputHeight;
    128     m_pDataCache->m_Width = m_OutputWidth;
    129     m_pDataCache->m_nCachedLines = 0;
    130 }
    131 FX_BOOL CCodec_BasicModule::RunLengthEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
    132         FX_DWORD& dest_size)
    133 {
    134     return FALSE;
    135 }
    136 extern "C" double FXstrtod(const char* nptr, char** endptr)
    137 {
    138     double ret = 0.0;
    139     const char* ptr = nptr;
    140     const char* exp_ptr = NULL;
    141     int	e_number = 0,
    142         e_signal = 0,
    143         e_point = 0,
    144         is_negative = 0;
    145     int exp_ret = 0, exp_sig = 1,
    146         fra_ret = 0, fra_count = 0, fra_base = 1;
    147     if(nptr == NULL) {
    148         return 0.0;
    149     }
    150     for (;; ptr++) {
    151         if(!e_number && !e_point && (*ptr == '\t' || *ptr == ' ')) {
    152             continue;
    153         }
    154         if(*ptr >= '0' && *ptr <= '9') {
    155             if(!e_number) {
    156                 e_number = 1;
    157             }
    158             if(!e_point) {
    159                 ret *= 10;
    160                 ret += (*ptr - '0');
    161             } else {
    162                 fra_count++;
    163                 fra_ret *= 10;
    164                 fra_ret += (*ptr - '0');
    165             }
    166             continue;
    167         }
    168         if(!e_point && *ptr == '.') {
    169             e_point = 1;
    170             continue;
    171         }
    172         if(!e_number && !e_point && !e_signal) {
    173             switch(*ptr) {
    174                 case '-':
    175                     is_negative = 1;
    176                 case '+':
    177                     e_signal = 1;
    178                     continue;
    179             }
    180         }
    181         if(e_number && (*ptr == 'e' || *ptr == 'E')) {
    182 #define EXPONENT_DETECT(ptr)	\
    183     for(;;ptr++){		\
    184         if(*ptr < '0' || *ptr > '9'){	\
    185             if(endptr)	*endptr = (char*)ptr;	\
    186             break;	\
    187         }else{		\
    188             exp_ret *= 10;	\
    189             exp_ret += (*ptr - '0');	\
    190             continue;		\
    191         }	\
    192     }
    193             exp_ptr = ptr++;
    194             if(*ptr == '+' || *ptr == '-') {
    195                 exp_sig = (*ptr++ == '+') ? 1 : -1;
    196                 if(*ptr < '0' || *ptr > '9') {
    197                     if(endptr)	{
    198                         *endptr = (char*)exp_ptr;
    199                     }
    200                     break;
    201                 }
    202                 EXPONENT_DETECT(ptr);
    203             } else if(*ptr >= '0' && *ptr <= '9') {
    204                 EXPONENT_DETECT(ptr);
    205             } else {
    206                 if(endptr)	{
    207                     *endptr = (char*)exp_ptr;
    208                 }
    209                 break;
    210             }
    211 #undef EXPONENT_DETECT
    212             break;
    213         }
    214         if(ptr != nptr && !e_number) {
    215             if(endptr)	{
    216                 *endptr = (char*)nptr;
    217             }
    218             break;
    219         }
    220         if(endptr)	{
    221             *endptr = (char*)ptr;
    222         }
    223         break;
    224     }
    225     while(fra_count--) {
    226         fra_base *= 10;
    227     }
    228     ret += (double)fra_ret / (double)fra_base;
    229     if(exp_sig == 1) {
    230         while(exp_ret--) {
    231             ret *= 10.0;
    232         }
    233     } else {
    234         while(exp_ret--) {
    235             ret /= 10.0;
    236         }
    237     }
    238     return is_negative ? -ret : ret;
    239 }
    240 FX_BOOL CCodec_BasicModule::A85Encode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf,
    241                                       FX_DWORD& dest_size)
    242 {
    243     return FALSE;
    244 }
    245 CCodec_ModuleMgr* CCodec_ModuleMgr::Create()
    246 {
    247     return FX_NEW CCodec_ModuleMgr;
    248 }
    249 void CCodec_ModuleMgr::Destroy()
    250 {
    251     delete this;
    252 }
    253 class CCodec_RLScanlineDecoder : public CCodec_ScanlineDecoder
    254 {
    255 public:
    256     CCodec_RLScanlineDecoder();
    257     virtual ~CCodec_RLScanlineDecoder();
    258     FX_BOOL				Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc);
    259     virtual void		v_DownScale(int dest_width, int dest_height) {}
    260     virtual FX_BOOL		v_Rewind();
    261     virtual FX_LPBYTE	v_GetNextLine();
    262     virtual FX_DWORD	GetSrcOffset()
    263     {
    264         return m_SrcOffset;
    265     }
    266 protected:
    267     FX_BOOL				CheckDestSize();
    268     void				GetNextOperator();
    269     void				UpdateOperator(FX_BYTE used_bytes);
    270 
    271     FX_LPBYTE			m_pScanline;
    272     FX_LPCBYTE			m_pSrcBuf;
    273     FX_DWORD			m_SrcSize;
    274     FX_DWORD			m_dwLineBytes;
    275     FX_DWORD			m_SrcOffset;
    276     FX_BOOL				m_bEOD;
    277     FX_BYTE				m_Operator;
    278 };
    279 CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder()
    280     : m_pScanline(NULL)
    281     , m_pSrcBuf(NULL)
    282     , m_SrcSize(0)
    283     , m_dwLineBytes(0)
    284     , m_SrcOffset(0)
    285     , m_bEOD(FALSE)
    286     , m_Operator(0)
    287 {
    288 }
    289 CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder()
    290 {
    291     if (m_pScanline) {
    292         FX_Free(m_pScanline);
    293     }
    294 }
    295 FX_BOOL CCodec_RLScanlineDecoder::CheckDestSize()
    296 {
    297     FX_DWORD i = 0;
    298     FX_DWORD old_size = 0;
    299     FX_DWORD dest_size = 0;
    300     while (i < m_SrcSize) {
    301         if (m_pSrcBuf[i] < 128) {
    302             old_size = dest_size;
    303             dest_size += m_pSrcBuf[i] + 1;
    304             if (dest_size < old_size) {
    305                 return FALSE;
    306             }
    307             i += m_pSrcBuf[i] + 2;
    308         } else if (m_pSrcBuf[i] > 128) {
    309             old_size = dest_size;
    310             dest_size += 257 - m_pSrcBuf[i];
    311             if (dest_size < old_size) {
    312                 return FALSE;
    313             }
    314             i += 2;
    315         } else {
    316             break;
    317         }
    318     }
    319     if (((FX_DWORD)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > dest_size) {
    320         return FALSE;
    321     }
    322     return TRUE;
    323 }
    324 FX_BOOL CCodec_RLScanlineDecoder::Create(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, int nComps, int bpc)
    325 {
    326     m_pSrcBuf = src_buf;
    327     m_SrcSize = src_size;
    328     m_OutputWidth = m_OrigWidth = width;
    329     m_OutputHeight = m_OrigHeight = height;
    330     m_nComps = nComps;
    331     m_bpc = bpc;
    332     m_bColorTransformed = FALSE;
    333     m_DownScale = 1;
    334     m_Pitch = (width * nComps * bpc + 31) / 32 * 4;
    335     m_dwLineBytes = (width * nComps * bpc + 7) / 8;
    336     m_pScanline = FX_Alloc(FX_BYTE, m_Pitch);
    337     if (m_pScanline == NULL) {
    338         return FALSE;
    339     }
    340     FXSYS_memset32(m_pScanline, 0, m_Pitch);
    341     return CheckDestSize();
    342 }
    343 FX_BOOL CCodec_RLScanlineDecoder::v_Rewind()
    344 {
    345     FXSYS_memset32(m_pScanline, 0, m_Pitch);
    346     m_SrcOffset = 0;
    347     m_bEOD = FALSE;
    348     m_Operator = 0;
    349     return TRUE;
    350 }
    351 FX_LPBYTE CCodec_RLScanlineDecoder::v_GetNextLine()
    352 {
    353     if (m_SrcOffset == 0) {
    354         GetNextOperator();
    355     } else {
    356         if (m_bEOD) {
    357             return NULL;
    358         }
    359     }
    360     FXSYS_memset32(m_pScanline, 0, m_Pitch);
    361     FX_DWORD col_pos = 0;
    362     FX_BOOL	eol = FALSE;
    363     while (m_SrcOffset < m_SrcSize && !eol) {
    364         if (m_Operator < 128) {
    365             FX_DWORD copy_len = m_Operator + 1;
    366             if (col_pos + copy_len >= m_dwLineBytes) {
    367                 copy_len = m_dwLineBytes - col_pos;
    368                 eol = TRUE;
    369             }
    370             if (copy_len >= m_SrcSize - m_SrcOffset) {
    371                 copy_len = m_SrcSize - m_SrcOffset;
    372                 m_bEOD = TRUE;
    373             }
    374             FXSYS_memcpy32(m_pScanline + col_pos, m_pSrcBuf + m_SrcOffset, copy_len);
    375             col_pos += copy_len;
    376             UpdateOperator((FX_BYTE)copy_len);
    377         } else if (m_Operator > 128) {
    378             int fill = 0;
    379             if (m_SrcOffset - 1 < m_SrcSize - 1) {
    380                 fill = m_pSrcBuf[m_SrcOffset];
    381             }
    382             FX_DWORD duplicate_len = 257 - m_Operator;
    383             if (col_pos + duplicate_len >= m_dwLineBytes) {
    384                 duplicate_len = m_dwLineBytes - col_pos;
    385                 eol = TRUE;
    386             }
    387             FXSYS_memset8(m_pScanline + col_pos, fill, duplicate_len);
    388             col_pos += duplicate_len;
    389             UpdateOperator((FX_BYTE)duplicate_len);
    390         } else {
    391             m_bEOD = TRUE;
    392             break;
    393         }
    394     }
    395     return m_pScanline;
    396 }
    397 void CCodec_RLScanlineDecoder::GetNextOperator()
    398 {
    399     if (m_SrcOffset >= m_SrcSize) {
    400         m_Operator = 128;
    401         return;
    402     }
    403     m_Operator = m_pSrcBuf[m_SrcOffset];
    404     m_SrcOffset ++;
    405 }
    406 void CCodec_RLScanlineDecoder::UpdateOperator(FX_BYTE used_bytes)
    407 {
    408     if (used_bytes == 0) {
    409         return;
    410     }
    411     if (m_Operator < 128) {
    412         FXSYS_assert((FX_DWORD)m_Operator + 1 >= used_bytes);
    413         if (used_bytes == m_Operator + 1) {
    414             m_SrcOffset += used_bytes;
    415             GetNextOperator();
    416             return;
    417         }
    418         m_Operator -= used_bytes;
    419         m_SrcOffset += used_bytes;
    420         if (m_SrcOffset >= m_SrcSize) {
    421             m_Operator = 128;
    422         }
    423         return;
    424     }
    425     FX_BYTE count = 257 - m_Operator;
    426     FXSYS_assert((FX_DWORD)count >= used_bytes);
    427     if (used_bytes == count) {
    428         m_SrcOffset ++;
    429         GetNextOperator();
    430         return;
    431     }
    432     count -= used_bytes;
    433     m_Operator = 257 - count;
    434 }
    435 ICodec_ScanlineDecoder* CCodec_BasicModule::CreateRunLengthDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height,
    436         int nComps, int bpc)
    437 {
    438     CCodec_RLScanlineDecoder* pRLScanlineDecoder = FX_NEW CCodec_RLScanlineDecoder;
    439     if (pRLScanlineDecoder == NULL) {
    440         return NULL;
    441     }
    442     if (!pRLScanlineDecoder->Create(src_buf, src_size, width, height, nComps, bpc)) {
    443         delete pRLScanlineDecoder;
    444         return NULL;
    445     }
    446     return pRLScanlineDecoder;
    447 }
    448