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