| // 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 "core/fxcodec/codec/ccodec_progressivedecoder.h" |
| |
| #include <algorithm> |
| #include <memory> |
| |
| #include "core/fxcodec/fx_codec.h" |
| #include "core/fxge/dib/cfx_dibitmap.h" |
| #include "core/fxge/fx_dib.h" |
| #include "third_party/base/logging.h" |
| #include "third_party/base/numerics/safe_math.h" |
| #include "third_party/base/ptr_util.h" |
| |
| #define FXCODEC_BLOCK_SIZE 4096 |
| |
| namespace { |
| |
| #if _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ |
| const double kPngGamma = 1.7; |
| #else // _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ |
| const double kPngGamma = 2.2; |
| #endif // _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_ |
| |
| void RGB2BGR(uint8_t* buffer, int width = 1) { |
| if (buffer && width > 0) { |
| uint8_t 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; |
| } |
| } |
| } |
| |
| } // namespace |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::CFXCODEC_WeightTable() {} |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::~CFXCODEC_WeightTable() {} |
| |
| void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, |
| int dest_min, |
| int dest_max, |
| int src_len, |
| int src_min, |
| int src_max, |
| bool bInterpol) { |
| double scale, base; |
| scale = (float)src_len / (float)dest_len; |
| if (dest_len < 0) { |
| base = (float)(src_len); |
| } else { |
| base = 0.0f; |
| } |
| m_ItemSize = |
| (int)(sizeof(int) * 2 + sizeof(int) * (ceil(fabs((float)scale)) + 1)); |
| m_DestMin = dest_min; |
| m_pWeightTables.resize((dest_max - dest_min) * m_ItemSize + 4); |
| if (fabs((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)floor((float)src_pos - 1.0f / 2); |
| pixel_weights.m_SrcEnd = (int)floor((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( |
| (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)floor((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)floor((float)src_start); |
| end_i = (int)ceil((float)src_end); |
| } else { |
| start_i = (int)floor((float)src_end); |
| end_i = (int)ceil((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 = ((float)j - base) / scale; |
| double dest_end = ((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 > (float)(dest_pixel) ? dest_start : (float)(dest_pixel); |
| double area_end = dest_end > (float)(dest_pixel + 1) |
| ? (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((float)(weight * 65536)); |
| } |
| } |
| } |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::CFXCODEC_HorzTable() {} |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::~CFXCODEC_HorzTable() {} |
| |
| void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, |
| int src_len, |
| bool bInterpol) { |
| double scale = (double)dest_len / (double)src_len; |
| m_ItemSize = sizeof(int) * 4; |
| int size = dest_len * m_ItemSize + 4; |
| m_pWeightTables.resize(size, 0); |
| 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((float)des_col_f); |
| PixelWeight* pWeight = GetPixelWeight(des_col); |
| 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 = GetPixelWeight(des_col_index); |
| 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 = GetPixelWeight(des_col_index); |
| pWeight->m_SrcStart = src_col - 1; |
| pWeight->m_SrcEnd = src_col; |
| pWeight->m_Weights[0] = |
| bInterpol |
| ? FXSYS_round((float)(((float)des_col - (float)des_col_index) / |
| (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((float)src_col_f); |
| PixelWeight* pWeight = GetPixelWeight(des_col); |
| pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col; |
| pWeight->m_Weights[0] = 65536; |
| pWeight->m_Weights[1] = 0; |
| } |
| } |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_VertTable::CFXCODEC_VertTable() {} |
| |
| CCodec_ProgressiveDecoder::CFXCODEC_VertTable::~CFXCODEC_VertTable() {} |
| |
| void CCodec_ProgressiveDecoder::CFXCODEC_VertTable::Calc(int dest_len, |
| int src_len) { |
| double scale = (double)dest_len / (double)src_len; |
| m_ItemSize = sizeof(int) * 4; |
| int size = dest_len * m_ItemSize + 4; |
| m_pWeightTables.resize(size, 0); |
| if (scale <= 1) { |
| for (int des_row = 0; des_row < dest_len; des_row++) { |
| PixelWeight* pWeight = GetPixelWeight(des_row); |
| pWeight->m_SrcStart = des_row; |
| pWeight->m_SrcEnd = des_row; |
| pWeight->m_Weights[0] = 65536; |
| pWeight->m_Weights[1] = 0; |
| } |
| return; |
| } |
| |
| 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 = GetPixelWeight(des_row); |
| 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 = GetPixelWeight(start_step); |
| 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 = GetPixelWeight(des_row); |
| pWeight->m_SrcStart = start_step; |
| pWeight->m_SrcEnd = end_step; |
| pWeight->m_Weights[0] = |
| FXSYS_round((float)(end_step - des_row) / (float)length * 65536); |
| pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0]; |
| } |
| } |
| } |
| |
| CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder( |
| CCodec_ModuleMgr* pCodecMgr) { |
| m_pFile = nullptr; |
| m_pJpegContext = nullptr; |
| m_pPngContext = nullptr; |
| m_pBmpContext = nullptr; |
| m_pTiffContext = nullptr; |
| m_pCodecMgr = nullptr; |
| m_pSrcBuf = nullptr; |
| m_pDecodeBuf = nullptr; |
| m_pDeviceBitmap = nullptr; |
| m_pSrcPalette = nullptr; |
| m_pCodecMgr = pCodecMgr; |
| m_offSet = 0; |
| m_SrcSize = 0; |
| m_ScanlineSize = 0; |
| m_SrcWidth = 0; |
| 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 = nullptr; |
| m_GifTransIndex = -1; |
| m_GifFrameRect = FX_RECT(0, 0, 0, 0); |
| m_BmpIsTopBottom = false; |
| } |
| |
| CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { |
| m_pFile = nullptr; |
| if (m_pJpegContext) |
| m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext); |
| if (m_pBmpContext) |
| m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext); |
| if (m_pPngContext) |
| m_pCodecMgr->GetPngModule()->Finish(m_pPngContext); |
| if (m_pTiffContext) |
| m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext.Get()); |
| FX_Free(m_pSrcBuf); |
| FX_Free(m_pDecodeBuf); |
| FX_Free(m_pSrcPalette); |
| } |
| |
| bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, |
| FXCODEC_STATUS& err_status) { |
| uint32_t dwSize = (uint32_t)m_pFile->GetSize(); |
| if (dwSize <= m_offSet) { |
| return false; |
| } |
| dwSize = dwSize - m_offSet; |
| uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext, nullptr); |
| 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(uint8_t, m_pSrcBuf, m_SrcSize); |
| if (!m_pSrcBuf) { |
| err_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| } else { |
| uint32_t dwConsume = m_SrcSize - dwAvail; |
| if (dwAvail) { |
| memmove(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; |
| } |
| |
| bool CCodec_ProgressiveDecoder::PngReadHeader(int width, |
| int height, |
| int bpc, |
| int pass, |
| int* color_type, |
| double* gamma) { |
| if (!m_pDeviceBitmap) { |
| m_SrcWidth = width; |
| m_SrcHeight = height; |
| m_SrcBPC = bpc; |
| m_SrcPassNumber = pass; |
| switch (*color_type) { |
| case 0: |
| m_SrcComponents = 1; |
| break; |
| case 4: |
| m_SrcComponents = 2; |
| break; |
| case 2: |
| m_SrcComponents = 3; |
| break; |
| case 3: |
| case 6: |
| m_SrcComponents = 4; |
| break; |
| default: |
| m_SrcComponents = 0; |
| break; |
| } |
| m_clipBox = FX_RECT(0, 0, width, height); |
| return false; |
| } |
| FXDIB_Format format = m_pDeviceBitmap->GetFormat(); |
| switch (format) { |
| case FXDIB_1bppMask: |
| case FXDIB_1bppRgb: |
| NOTREACHED(); |
| 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: |
| NOTREACHED(); |
| return false; |
| } |
| *gamma = kPngGamma; |
| return true; |
| } |
| |
| bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t*& src_buf) { |
| CFX_RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap; |
| if (!pDIBitmap) { |
| NOTREACHED(); |
| return false; |
| } |
| if (line >= m_clipBox.top && line < m_clipBox.bottom) { |
| double scale_y = (double)m_sizeY / (double)m_clipBox.Height(); |
| int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY; |
| uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row); |
| uint8_t* des_scan = m_pDecodeBuf; |
| src_buf = m_pDecodeBuf; |
| int32_t src_Bpp = pDIBitmap->GetBPP() >> 3; |
| int32_t des_Bpp = (m_SrcFormat & 0xff) >> 3; |
| int32_t src_left = m_startX; |
| int32_t des_left = m_clipBox.left; |
| src_scan += src_left * src_Bpp; |
| des_scan += des_left * des_Bpp; |
| for (int32_t src_col = 0; src_col < m_sizeX; src_col++) { |
| PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(src_col); |
| if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) { |
| continue; |
| } |
| switch (pDIBitmap->GetFormat()) { |
| case FXDIB_1bppMask: |
| case FXDIB_1bppRgb: |
| NOTREACHED(); |
| return false; |
| case FXDIB_8bppMask: |
| case FXDIB_8bppRgb: { |
| if (pDIBitmap->GetPalette()) { |
| return false; |
| } |
| uint32_t des_g = 0; |
| des_g += pPixelWeights->m_Weights[0] * src_scan[src_col]; |
| des_scan[pPixelWeights->m_SrcStart] = (uint8_t)(des_g >> 16); |
| } break; |
| case FXDIB_Rgb: |
| case FXDIB_Rgb32: { |
| uint32_t des_b = 0, des_g = 0, des_r = 0; |
| const uint8_t* 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); |
| uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; |
| *pDes++ = (uint8_t)((des_b) >> 16); |
| *pDes++ = (uint8_t)((des_g) >> 16); |
| *pDes = (uint8_t)((des_r) >> 16); |
| } break; |
| case FXDIB_Argb: { |
| uint32_t des_r = 0, des_g = 0, des_b = 0; |
| const uint8_t* 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++); |
| uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp]; |
| *pDes++ = (uint8_t)((des_b) >> 16); |
| *pDes++ = (uint8_t)((des_g) >> 16); |
| *pDes++ = (uint8_t)((des_r) >> 16); |
| *pDes = *p; |
| } break; |
| default: |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| int32_t des_line, |
| uint8_t* src_scan, |
| FXCodec_Format src_format) { |
| uint8_t* des_scan = (uint8_t*)pDeviceBitmap->GetScanline(des_line); |
| int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; |
| int32_t des_Bpp = pDeviceBitmap->GetBPP() >> 3; |
| int32_t src_left = m_clipBox.left; |
| int32_t des_left = m_startX; |
| src_scan += src_left * src_Bpp; |
| des_scan += des_left * des_Bpp; |
| for (int32_t 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: |
| NOTREACHED(); |
| return; |
| case FXDIB_8bppMask: |
| case FXDIB_8bppRgb: { |
| if (pDeviceBitmap->GetPalette()) { |
| return; |
| } |
| uint32_t 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++ = (uint8_t)(des_g >> 16); |
| } break; |
| case FXDIB_Rgb: |
| case FXDIB_Rgb32: { |
| uint32_t des_b = 0, des_g = 0, des_r = 0; |
| const uint8_t* 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++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| des_scan += des_Bpp - 3; |
| } break; |
| case FXDIB_Argb: { |
| uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0; |
| const uint8_t* 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++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| *des_scan++ = (uint8_t)((des_a) >> 16); |
| } break; |
| default: |
| return; |
| } |
| } |
| } |
| |
| void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, |
| int line) { |
| CFX_RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap; |
| ASSERT(pDIBitmap); |
| int src_top = m_clipBox.top; |
| int src_bottom = m_clipBox.bottom; |
| int des_top = m_startY; |
| int src_hei = m_clipBox.Height(); |
| int des_hei = 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; |
| } |
| PngOneOneMapResampleHorz(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat); |
| if (m_SrcPassNumber == 1 && scale_y > 1.0) { |
| ResampleVert(pDIBitmap, scale_y, des_row); |
| return; |
| } |
| if (pass == 6 && scale_y > 1.0) { |
| ResampleVert(pDIBitmap, scale_y, des_row); |
| } |
| } |
| } |
| |
| bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, |
| FXCODEC_STATUS& err_status) { |
| uint32_t dwSize = (uint32_t)m_pFile->GetSize(); |
| if (dwSize <= m_offSet) { |
| return false; |
| } |
| dwSize = dwSize - m_offSet; |
| uint32_t dwAvail = pGifModule->GetAvailInput(m_pGifContext.get(), nullptr); |
| 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(uint8_t, m_pSrcBuf, m_SrcSize); |
| if (!m_pSrcBuf) { |
| err_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| } else { |
| uint32_t dwConsume = m_SrcSize - dwAvail; |
| if (dwAvail) { |
| memmove(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.get(), m_pSrcBuf, dwSize + dwAvail); |
| return true; |
| } |
| |
| void CCodec_ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) { |
| uint32_t remain_size = |
| m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get()); |
| cur_pos = m_offSet - remain_size; |
| } |
| |
| bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf( |
| uint32_t rcd_pos, |
| const FX_RECT& img_rc, |
| int32_t pal_num, |
| void* pal_ptr, |
| int32_t delay_time, |
| bool user_input, |
| int32_t trans_index, |
| int32_t disposal_method, |
| bool interlace) { |
| m_offSet = rcd_pos; |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; |
| if (!GifReadMoreData(m_pCodecMgr->GetGifModule(), error_status)) { |
| return false; |
| } |
| uint8_t* pPalette = nullptr; |
| if (pal_num != 0 && pal_ptr) { |
| pPalette = (uint8_t*)pal_ptr; |
| } else { |
| pal_num = m_GifPltNumber; |
| pPalette = m_pGifPalette; |
| } |
| if (!m_pSrcPalette) |
| m_pSrcPalette = FX_Alloc(FX_ARGB, pal_num); |
| else if (pal_num > m_SrcPaletteNumber) |
| m_pSrcPalette = FX_Realloc(FX_ARGB, m_pSrcPalette, pal_num); |
| if (!m_pSrcPalette) |
| return false; |
| |
| m_SrcPaletteNumber = pal_num; |
| for (int i = 0; i < pal_num; i++) { |
| uint32_t j = i * 3; |
| m_pSrcPalette[i] = |
| ArgbEncode(0xff, pPalette[j], pPalette[j + 1], pPalette[j + 2]); |
| } |
| m_GifTransIndex = trans_index; |
| m_GifFrameRect = img_rc; |
| m_SrcPassNumber = interlace ? 4 : 1; |
| int32_t pal_index = m_GifBgIndex; |
| CFX_RetainPtr<CFX_DIBitmap> pDevice = m_pDeviceBitmap; |
| if (trans_index >= pal_num) |
| trans_index = -1; |
| if (trans_index != -1) { |
| m_pSrcPalette[trans_index] &= 0x00ffffff; |
| if (pDevice->HasAlpha()) |
| pal_index = trans_index; |
| } |
| if (pal_index >= pal_num) |
| return false; |
| |
| int startX = m_startX; |
| int startY = m_startY; |
| int sizeX = m_sizeX; |
| int sizeY = m_sizeY; |
| int Bpp = pDevice->GetBPP() / 8; |
| FX_ARGB argb = m_pSrcPalette[pal_index]; |
| for (int row = 0; row < sizeY; row++) { |
| uint8_t* pScanline = |
| (uint8_t*)pDevice->GetScanline(row + startY) + startX * Bpp; |
| switch (m_TransMethod) { |
| case 3: { |
| uint8_t gray = |
| FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb)); |
| memset(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::GifReadScanline(int32_t row_num, |
| uint8_t* row_buf) { |
| CFX_RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap; |
| ASSERT(pDIBitmap); |
| int32_t img_width = m_GifFrameRect.Width(); |
| if (!pDIBitmap->HasAlpha()) { |
| uint8_t* byte_ptr = row_buf; |
| for (int i = 0; i < img_width; i++) { |
| if (*byte_ptr == m_GifTransIndex) { |
| *byte_ptr = m_GifBgIndex; |
| } |
| byte_ptr++; |
| } |
| } |
| int32_t pal_index = m_GifBgIndex; |
| if (m_GifTransIndex != -1 && m_pDeviceBitmap->HasAlpha()) { |
| pal_index = m_GifTransIndex; |
| } |
| memset(m_pDecodeBuf, pal_index, m_SrcWidth); |
| bool bLastPass = (row_num % 2) == 1; |
| int32_t line = row_num + m_GifFrameRect.top; |
| int32_t left = m_GifFrameRect.left; |
| memcpy(m_pDecodeBuf + left, row_buf, img_width); |
| int src_top = m_clipBox.top; |
| int src_bottom = m_clipBox.bottom; |
| int des_top = m_startY; |
| int src_hei = m_clipBox.Height(); |
| int des_hei = m_sizeY; |
| if (line < src_top || line >= src_bottom) |
| return; |
| |
| 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; |
| |
| ReSampleScanline(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat); |
| if (scale_y > 1.0 && (!m_bInterpol || m_SrcPassNumber == 1)) { |
| ResampleVert(pDIBitmap, scale_y, des_row); |
| return; |
| } |
| if (scale_y <= 1.0) |
| return; |
| |
| int des_bottom = des_top + m_sizeY; |
| int des_Bpp = pDIBitmap->GetBPP() >> 3; |
| uint32_t des_ScanOffet = m_startX * des_Bpp; |
| if (des_row + (int)scale_y >= des_bottom - 1) { |
| uint8_t* scan_src = |
| (uint8_t*)pDIBitmap->GetScanline(des_row) + des_ScanOffet; |
| int cur_row = des_row; |
| while (++cur_row < des_bottom) { |
| uint8_t* scan_des = |
| (uint8_t*)pDIBitmap->GetScanline(cur_row) + des_ScanOffet; |
| uint32_t size = m_sizeX * des_Bpp; |
| memmove(scan_des, scan_src, size); |
| } |
| } |
| if (bLastPass) |
| GifDoubleLineResampleVert(pDIBitmap, scale_y, des_row); |
| } |
| |
| void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| double scale_y, |
| int des_row) { |
| int des_Bpp = pDeviceBitmap->GetBPP() >> 3; |
| uint32_t des_ScanOffet = m_startX * des_Bpp; |
| int des_top = m_startY; |
| pdfium::base::CheckedNumeric<double> scale_y2 = scale_y; |
| scale_y2 *= 2; |
| pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row; |
| check_des_row_1 -= scale_y2.ValueOrDie(); |
| int des_row_1 = check_des_row_1.ValueOrDie(); |
| des_row_1 = std::max(des_row_1, des_top); |
| for (; des_row_1 < des_row; des_row_1++) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; |
| PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); |
| const uint8_t* scan_src1 = |
| pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + |
| des_ScanOffet; |
| const uint8_t* 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()) { |
| return; |
| } |
| int des_g = 0; |
| des_g += pWeight->m_Weights[0] * (*scan_src1++); |
| des_g += pWeight->m_Weights[1] * (*scan_src2++); |
| *scan_des++ = (uint8_t)(des_g >> 16); |
| } break; |
| case FXDIB_Rgb: |
| case FXDIB_Rgb32: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| scan_des += des_Bpp - 3; |
| } break; |
| case FXDIB_Argb: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| *scan_des++ = (uint8_t)((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); |
| } |
| } |
| |
| bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, |
| FXCODEC_STATUS& err_status) { |
| uint32_t dwSize = (uint32_t)m_pFile->GetSize(); |
| if (dwSize <= m_offSet) |
| return false; |
| |
| dwSize = dwSize - m_offSet; |
| uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext, nullptr); |
| 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(uint8_t, m_pSrcBuf, m_SrcSize); |
| if (!m_pSrcBuf) { |
| err_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| } else { |
| uint32_t dwConsume = m_SrcSize - dwAvail; |
| if (dwAvail) { |
| memmove(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; |
| } |
| |
| bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) { |
| m_offSet = rcd_pos; |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; |
| return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), error_status); |
| } |
| |
| void CCodec_ProgressiveDecoder::BmpReadScanline(int32_t row_num, |
| uint8_t* row_buf) { |
| CFX_RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap; |
| ASSERT(pDIBitmap); |
| memcpy(m_pDecodeBuf, row_buf, m_ScanlineSize); |
| int src_top = m_clipBox.top; |
| int src_bottom = m_clipBox.bottom; |
| int des_top = m_startY; |
| int src_hei = m_clipBox.Height(); |
| int des_hei = m_sizeY; |
| if (row_num < src_top || row_num >= src_bottom) |
| return; |
| |
| 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; |
| |
| ReSampleScanline(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat); |
| if (scale_y <= 1.0) |
| return; |
| |
| if (m_BmpIsTopBottom || !m_bInterpol) { |
| ResampleVert(pDIBitmap, scale_y, des_row); |
| return; |
| } |
| ResampleVertBT(pDIBitmap, scale_y, des_row); |
| } |
| |
| void CCodec_ProgressiveDecoder::ResampleVertBT( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| double scale_y, |
| int des_row) { |
| int des_Bpp = pDeviceBitmap->GetBPP() >> 3; |
| uint32_t des_ScanOffet = m_startX * des_Bpp; |
| int des_top = m_startY; |
| int des_bottom = m_startY + m_sizeY; |
| pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row; |
| check_des_row_1 += pdfium::base::checked_cast<int>(scale_y); |
| int des_row_1 = check_des_row_1.ValueOrDie(); |
| if (des_row_1 >= des_bottom - 1) { |
| uint8_t* scan_src = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| while (++des_row < des_bottom) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| uint32_t size = m_sizeX * des_Bpp; |
| memmove(scan_des, scan_src, size); |
| } |
| return; |
| } |
| for (; des_row_1 > des_row; des_row_1--) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; |
| PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); |
| const uint8_t* scan_src1 = |
| pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + |
| des_ScanOffet; |
| const uint8_t* 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()) { |
| return; |
| } |
| int des_g = 0; |
| des_g += pWeight->m_Weights[0] * (*scan_src1++); |
| des_g += pWeight->m_Weights[1] * (*scan_src2++); |
| *scan_des++ = (uint8_t)(des_g >> 16); |
| } break; |
| case FXDIB_Rgb: |
| case FXDIB_Rgb32: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| scan_des += des_Bpp - 3; |
| } break; |
| case FXDIB_Argb: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| *scan_des++ = (uint8_t)((des_a) >> 16); |
| } break; |
| default: |
| return; |
| } |
| } |
| } |
| } |
| |
| bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, |
| CFX_DIBAttribute* pAttribute) { |
| m_offSet = 0; |
| uint32_t size = (uint32_t)m_pFile->GetSize(); |
| if (size > FXCODEC_BLOCK_SIZE) { |
| size = FXCODEC_BLOCK_SIZE; |
| } |
| FX_Free(m_pSrcBuf); |
| m_pSrcBuf = FX_Alloc(uint8_t, size); |
| memset(m_pSrcBuf, 0, size); |
| m_SrcSize = size; |
| switch (imageType) { |
| case FXCODEC_IMAGE_BMP: { |
| CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); |
| if (!pBmpModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| pBmpModule->SetDelegate(this); |
| m_pBmpContext = pBmpModule->Start(); |
| if (!m_pBmpContext) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| 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); |
| uint32_t* pPalette = nullptr; |
| int32_t 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); |
| FX_Free(m_pSrcPalette); |
| if (m_SrcPaletteNumber) { |
| m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber); |
| memcpy(m_pSrcPalette, pPalette, |
| m_SrcPaletteNumber * sizeof(uint32_t)); |
| } else { |
| m_pSrcPalette = nullptr; |
| } |
| return true; |
| } |
| if (m_pBmpContext) { |
| pBmpModule->Finish(m_pBmpContext); |
| m_pBmpContext = nullptr; |
| } |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| case FXCODEC_IMAGE_JPG: { |
| CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); |
| m_pJpegContext = pJpegModule->Start(); |
| if (!m_pJpegContext) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| 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); |
| int32_t 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) { |
| pJpegModule->Finish(m_pJpegContext); |
| m_pJpegContext = nullptr; |
| } |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| case FXCODEC_IMAGE_PNG: { |
| CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); |
| if (!pPngModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| pPngModule->SetDelegate(this); |
| m_pPngContext = pPngModule->Start(); |
| if (!m_pPngContext) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| 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) { |
| uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; |
| uint32_t input_size = |
| remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; |
| if (input_size == 0) { |
| if (m_pPngContext) { |
| pPngModule->Finish(m_pPngContext); |
| } |
| m_pPngContext = nullptr; |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| if (m_pSrcBuf && input_size > m_SrcSize) { |
| FX_Free(m_pSrcBuf); |
| m_pSrcBuf = FX_Alloc(uint8_t, input_size); |
| memset(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) { |
| pPngModule->Finish(m_pPngContext); |
| m_pPngContext = nullptr; |
| } |
| if (m_SrcPassNumber == 0) { |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| return true; |
| } |
| case FXCODEC_IMAGE_GIF: { |
| CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); |
| if (!pGifModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return false; |
| } |
| pGifModule->SetDelegate(this); |
| m_pGifContext = pGifModule->Start(); |
| 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.get(), m_pSrcBuf, size); |
| m_SrcComponents = 1; |
| GifDecodeStatus readResult = pGifModule->ReadHeader( |
| m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, |
| (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); |
| while (readResult == GifDecodeStatus::Unfinished) { |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; |
| if (!GifReadMoreData(pGifModule, error_status)) { |
| m_status = error_status; |
| return false; |
| } |
| readResult = pGifModule->ReadHeader( |
| m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, |
| (void**)&m_pGifPalette, &m_GifBgIndex, nullptr); |
| } |
| if (readResult == GifDecodeStatus::Success) { |
| m_SrcBPC = 8; |
| m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); |
| return true; |
| } |
| m_pGifContext = nullptr; |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| case FXCODEC_IMAGE_TIF: { |
| CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); |
| if (!pTiffModule) { |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); |
| if (!m_pTiffContext) { |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| int32_t dummy_bpc; |
| bool ret = pTiffModule->LoadFrameInfo( |
| m_pTiffContext.Get(), 0, &m_SrcWidth, &m_SrcHeight, &m_SrcComponents, |
| &dummy_bpc, pAttribute); |
| m_SrcComponents = 4; |
| m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); |
| if (!ret) { |
| pTiffModule->DestroyDecoder(m_pTiffContext.Get()); |
| m_pTiffContext = nullptr; |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| return true; |
| } |
| default: |
| m_status = FXCODEC_STATUS_ERR_FORMAT; |
| return false; |
| } |
| } |
| |
| FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( |
| const CFX_RetainPtr<IFX_SeekableReadStream>& pFile, |
| FXCODEC_IMAGE_TYPE imageType, |
| CFX_DIBAttribute* pAttribute, |
| bool bSkipImageTypeCheck) { |
| 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: |
| break; |
| } |
| if (!pFile) { |
| m_status = FXCODEC_STATUS_ERR_PARAMS; |
| m_pFile = nullptr; |
| 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; |
| } |
| // If we got here then the image data does not match the requested decoder. |
| // If we're skipping the type check then bail out at this point and return |
| // the failed status. |
| if (bSkipImageTypeCheck) |
| 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 = nullptr; |
| 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; |
| } |
| clip->left = std::max(clip->left, 0); |
| clip->right = std::min(clip->right, m_SrcWidth); |
| clip->top = std::max(clip->top, 0); |
| clip->bottom = std::min(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 CCodec_ProgressiveDecoder::ReSampleScanline( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| int des_line, |
| uint8_t* src_scan, |
| FXCodec_Format src_format) { |
| int src_left = m_clipBox.left; |
| int des_left = m_startX; |
| uint8_t* 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: { |
| uint32_t 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++ = (uint8_t)(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 * (uint8_t)(argb >> 16); |
| des_g += pixel_weight * (uint8_t)(argb >> 8); |
| des_b += pixel_weight * (uint8_t)argb; |
| } |
| *des_scan++ = |
| (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); |
| } break; |
| case 4: { |
| uint32_t 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]; |
| const uint8_t* 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++ = |
| (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); |
| } break; |
| case 5: { |
| uint32_t 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]; |
| const uint8_t* src_pixel = src_scan + j * src_Bpp; |
| uint8_t 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++ = |
| (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16)); |
| } break; |
| case 6: |
| return; |
| case 7: { |
| uint32_t 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]; |
| } |
| memset(des_scan, (uint8_t)(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 * (uint8_t)(argb >> 16); |
| des_g += pixel_weight * (uint8_t)(argb >> 8); |
| des_b += pixel_weight * (uint8_t)argb; |
| } |
| *des_scan++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((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 * (uint8_t)(argb >> 16); |
| des_g += pixel_weight * (uint8_t)(argb >> 8); |
| des_b += pixel_weight * (uint8_t)argb; |
| } |
| *des_scan++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((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 * (uint8_t)(argb >> 24); |
| des_r += pixel_weight * (uint8_t)(argb >> 16); |
| des_g += pixel_weight * (uint8_t)(argb >> 8); |
| des_b += pixel_weight * (uint8_t)argb; |
| } |
| *des_scan++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| *des_scan++ = (uint8_t)((des_a) >> 16); |
| } |
| } break; |
| case 9: { |
| uint32_t 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]; |
| const uint8_t* 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++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| des_scan += des_Bpp - 3; |
| } break; |
| case 10: { |
| uint32_t 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]; |
| const uint8_t* src_pixel = src_scan + j * src_Bpp; |
| uint8_t 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++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| des_scan += des_Bpp - 3; |
| } break; |
| case 11: { |
| uint32_t 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]; |
| const uint8_t* 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++ = (uint8_t)((des_b) >> 16); |
| *des_scan++ = (uint8_t)((des_g) >> 16); |
| *des_scan++ = (uint8_t)((des_r) >> 16); |
| *des_scan++ = (uint8_t)((des_alpha * 255) >> 16); |
| } break; |
| default: |
| return; |
| } |
| } |
| } |
| |
| void CCodec_ProgressiveDecoder::ResampleVert( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| double scale_y, |
| int des_row) { |
| int des_Bpp = pDeviceBitmap->GetBPP() >> 3; |
| uint32_t des_ScanOffet = m_startX * des_Bpp; |
| if (m_bInterpol) { |
| int des_top = m_startY; |
| pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row; |
| check_des_row_1 -= pdfium::base::checked_cast<int>(scale_y); |
| int des_row_1 = check_des_row_1.ValueOrDie(); |
| if (des_row_1 < des_top) { |
| int des_bottom = des_top + m_sizeY; |
| if (des_row + (int)scale_y >= des_bottom - 1) { |
| uint8_t* scan_src = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| while (++des_row < des_bottom) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| uint32_t size = m_sizeX * des_Bpp; |
| memmove(scan_des, scan_src, size); |
| } |
| } |
| return; |
| } |
| for (; des_row_1 < des_row; des_row_1++) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet; |
| PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top); |
| const uint8_t* scan_src1 = |
| pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + |
| des_ScanOffet; |
| const uint8_t* 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()) { |
| return; |
| } |
| int des_g = 0; |
| des_g += pWeight->m_Weights[0] * (*scan_src1++); |
| des_g += pWeight->m_Weights[1] * (*scan_src2++); |
| *scan_des++ = (uint8_t)(des_g >> 16); |
| } break; |
| case FXDIB_Rgb: |
| case FXDIB_Rgb32: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| scan_des += des_Bpp - 3; |
| } break; |
| case FXDIB_Argb: { |
| uint32_t 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++ = (uint8_t)((des_b) >> 16); |
| *scan_des++ = (uint8_t)((des_g) >> 16); |
| *scan_des++ = (uint8_t)((des_r) >> 16); |
| *scan_des++ = (uint8_t)((des_a) >> 16); |
| } break; |
| default: |
| return; |
| } |
| } |
| } |
| int des_bottom = des_top + m_sizeY; |
| if (des_row + (int)scale_y >= des_bottom - 1) { |
| uint8_t* scan_src = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| while (++des_row < des_bottom) { |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| uint32_t size = m_sizeX * des_Bpp; |
| memmove(scan_des, scan_src, size); |
| } |
| } |
| return; |
| } |
| int multiple = (int)ceil((float)scale_y - 1); |
| if (multiple > 0) { |
| uint8_t* scan_src = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet; |
| for (int i = 1; i <= multiple; i++) { |
| if (des_row + i >= m_startY + m_sizeY) { |
| return; |
| } |
| uint8_t* scan_des = |
| (uint8_t*)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet; |
| uint32_t size = m_sizeX * des_Bpp; |
| memmove(scan_des, scan_src, size); |
| } |
| } |
| } |
| |
| void CCodec_ProgressiveDecoder::Resample( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDeviceBitmap, |
| int32_t src_line, |
| uint8_t* 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(int32_t& frames) { |
| if (!(m_status == FXCODEC_STATUS_FRAME_READY || |
| m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { |
| return FXCODEC_STATUS_ERROR; |
| } |
| switch (m_imagType) { |
| case FXCODEC_IMAGE_JPG: |
| case FXCODEC_IMAGE_BMP: |
| case FXCODEC_IMAGE_PNG: |
| case FXCODEC_IMAGE_TIF: |
| frames = m_FrameNumber = 1; |
| m_status = FXCODEC_STATUS_DECODE_READY; |
| return m_status; |
| case FXCODEC_IMAGE_GIF: { |
| CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); |
| if (!pGifModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| while (true) { |
| GifDecodeStatus readResult = |
| pGifModule->LoadFrameInfo(m_pGifContext.get(), &m_FrameNumber); |
| while (readResult == GifDecodeStatus::Unfinished) { |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; |
| if (!GifReadMoreData(pGifModule, error_status)) |
| return error_status; |
| |
| readResult = |
| pGifModule->LoadFrameInfo(m_pGifContext.get(), &m_FrameNumber); |
| } |
| if (readResult == GifDecodeStatus::Success) { |
| frames = m_FrameNumber; |
| m_status = FXCODEC_STATUS_DECODE_READY; |
| return m_status; |
| } |
| m_pGifContext = nullptr; |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| } |
| default: |
| return FXCODEC_STATUS_ERROR; |
| } |
| } |
| |
| FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( |
| const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap, |
| int start_x, |
| int start_y, |
| int size_x, |
| int size_y, |
| int32_t frames, |
| bool bInterpol) { |
| if (m_status != FXCODEC_STATUS_DECODE_READY) |
| return FXCODEC_STATUS_ERROR; |
| |
| if (!pDIBitmap || 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); |
| int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth(); |
| int32_t 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) { |
| float scaleX = (float)m_clipBox.Width() / (float)size_x; |
| if (start_x < 0) { |
| m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX); |
| } |
| if (out_range_x > 0) { |
| m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX); |
| } |
| } |
| if (start_y < 0 || out_range_y > 0) { |
| float scaleY = (float)m_clipBox.Height() / (float)size_y; |
| if (start_y < 0) { |
| m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY); |
| } |
| if (out_range_y > 0) { |
| m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY); |
| } |
| } |
| if (m_clipBox.IsEmpty()) { |
| return FXCODEC_STATUS_ERR_PARAMS; |
| } |
| switch (m_imagType) { |
| case FXCODEC_IMAGE_JPG: { |
| int down_scale = 1; |
| GetDownScale(down_scale); |
| CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); |
| bool bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale); |
| while (!bStart) { |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; |
| if (!JpegReadMoreData(pJpegModule, error_status)) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = error_status; |
| return m_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; |
| FX_Free(m_pDecodeBuf); |
| m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); |
| memset(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); |
| m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; |
| return m_status; |
| } |
| case FXCODEC_IMAGE_PNG: { |
| CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); |
| if (!pPngModule) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| if (m_pPngContext) { |
| pPngModule->Finish(m_pPngContext); |
| m_pPngContext = nullptr; |
| } |
| m_pPngContext = pPngModule->Start(); |
| if (!m_pPngContext) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| 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 = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_PARAMS; |
| return m_status; |
| } |
| } |
| GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); |
| int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; |
| FX_Free(m_pDecodeBuf); |
| m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); |
| memset(m_pDecodeBuf, 0, scanline_size); |
| m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width(), m_bInterpol); |
| m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); |
| m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; |
| return m_status; |
| } |
| case FXCODEC_IMAGE_GIF: { |
| CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); |
| if (!pGifModule) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| m_SrcFormat = FXCodec_8bppRgb; |
| GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); |
| int scanline_size = (m_SrcWidth + 3) / 4 * 4; |
| FX_Free(m_pDecodeBuf); |
| m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); |
| memset(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; |
| m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; |
| return m_status; |
| } |
| case FXCODEC_IMAGE_BMP: { |
| CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); |
| if (!pBmpModule) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| 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; |
| FX_Free(m_pDecodeBuf); |
| m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); |
| memset(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()); |
| m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; |
| return m_status; |
| } |
| case FXCODEC_IMAGE_TIF: |
| m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; |
| return m_status; |
| default: |
| return FXCODEC_STATUS_ERROR; |
| } |
| } |
| |
| FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { |
| if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) |
| return FXCODEC_STATUS_ERROR; |
| |
| switch (m_imagType) { |
| case FXCODEC_IMAGE_JPG: { |
| CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); |
| while (true) { |
| 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 = nullptr; |
| m_pFile = nullptr; |
| m_status = error_status; |
| return m_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 = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); |
| m_SrcRow++; |
| } |
| } |
| case FXCODEC_IMAGE_PNG: { |
| CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); |
| if (!pPngModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| while (true) { |
| uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; |
| uint32_t input_size = |
| remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; |
| if (input_size == 0) { |
| if (m_pPngContext) { |
| pPngModule->Finish(m_pPngContext); |
| } |
| m_pPngContext = nullptr; |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| if (m_pSrcBuf && input_size > m_SrcSize) { |
| FX_Free(m_pSrcBuf); |
| m_pSrcBuf = FX_Alloc(uint8_t, input_size); |
| memset(m_pSrcBuf, 0, input_size); |
| m_SrcSize = input_size; |
| } |
| bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); |
| if (!bResult) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_READ; |
| return m_status; |
| } |
| m_offSet += input_size; |
| bResult = |
| pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size, nullptr); |
| if (!bResult) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| } |
| } |
| case FXCODEC_IMAGE_GIF: { |
| CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); |
| if (!pGifModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| while (true) { |
| GifDecodeStatus readRes = |
| pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); |
| while (readRes == GifDecodeStatus::Unfinished) { |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; |
| if (!GifReadMoreData(pGifModule, error_status)) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = error_status; |
| return m_status; |
| } |
| readRes = |
| pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); |
| } |
| if (readRes == GifDecodeStatus::Success) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| } |
| case FXCODEC_IMAGE_BMP: { |
| CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); |
| if (!pBmpModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| while (true) { |
| int32_t readRes = pBmpModule->LoadImage(m_pBmpContext); |
| while (readRes == 2) { |
| FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; |
| if (!BmpReadMoreData(pBmpModule, error_status)) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = error_status; |
| return m_status; |
| } |
| readRes = pBmpModule->LoadImage(m_pBmpContext); |
| } |
| if (readRes == 1) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| } |
| case FXCODEC_IMAGE_TIF: { |
| CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); |
| if (!pTiffModule) { |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| 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.Get(), m_pDeviceBitmap); |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| if (!ret) { |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| |
| auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); |
| pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); |
| if (!pDIBitmap->GetBuffer()) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| ret = pTiffModule->Decode(m_pTiffContext.Get(), pDIBitmap); |
| if (!ret) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERROR; |
| return m_status; |
| } |
| CFX_RetainPtr<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 (!pClipBitmap) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| CFX_RetainPtr<CFX_DIBitmap> pFormatBitmap; |
| switch (m_pDeviceBitmap->GetFormat()) { |
| case FXDIB_8bppRgb: |
| pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); |
| pFormatBitmap->Create(pClipBitmap->GetWidth(), |
| pClipBitmap->GetHeight(), FXDIB_8bppRgb); |
| break; |
| case FXDIB_8bppMask: |
| pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); |
| pFormatBitmap->Create(pClipBitmap->GetWidth(), |
| pClipBitmap->GetHeight(), FXDIB_8bppMask); |
| break; |
| case FXDIB_Rgb: |
| pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); |
| pFormatBitmap->Create(pClipBitmap->GetWidth(), |
| pClipBitmap->GetHeight(), FXDIB_Rgb); |
| break; |
| case FXDIB_Rgb32: |
| pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); |
| pFormatBitmap->Create(pClipBitmap->GetWidth(), |
| pClipBitmap->GetHeight(), FXDIB_Rgb32); |
| break; |
| case FXDIB_Argb: |
| pFormatBitmap = pClipBitmap; |
| break; |
| default: |
| break; |
| } |
| switch (m_pDeviceBitmap->GetFormat()) { |
| case FXDIB_8bppRgb: |
| case FXDIB_8bppMask: { |
| for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { |
| uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); |
| uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); |
| for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { |
| uint8_t _a = 255 - src_line[3]; |
| uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; |
| uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; |
| uint8_t 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: { |
| int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; |
| for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { |
| uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); |
| uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row); |
| for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { |
| uint8_t _a = 255 - src_line[3]; |
| uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; |
| uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; |
| uint8_t 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: |
| break; |
| } |
| if (!pFormatBitmap) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| CFX_RetainPtr<CFX_DIBitmap> pStrechBitmap = pFormatBitmap->StretchTo( |
| m_sizeX, m_sizeY, m_bInterpol ? FXDIB_INTERPOL : FXDIB_DOWNSAMPLE, |
| nullptr); |
| pFormatBitmap = nullptr; |
| if (!pStrechBitmap) { |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_ERR_MEMORY; |
| return m_status; |
| } |
| m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, |
| pStrechBitmap, 0, 0); |
| m_pDeviceBitmap = nullptr; |
| m_pFile = nullptr; |
| m_status = FXCODEC_STATUS_DECODE_FINISH; |
| return m_status; |
| } |
| default: |
| return FXCODEC_STATUS_ERROR; |
| } |
| } |
| |
| std::unique_ptr<CCodec_ProgressiveDecoder> |
| CCodec_ModuleMgr::CreateProgressiveDecoder() { |
| return pdfium::MakeUnique<CCodec_ProgressiveDecoder>(this); |
| } |