blob: 542ac681e64ad3ced42732a1e1d14908c839f290 [file] [log] [blame]
// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "../../../include/fxge/fx_dib.h"
#include "../../../include/fxcodec/fx_codec.h"
#include "fx_codec_progress.h"
void CFXCODEC_WeightTable::Calc(int dest_len, int dest_min, int dest_max, int src_len, int src_min, int src_max, FX_BOOL bInterpol)
{
if (m_pWeightTables) {
FX_Free(m_pWeightTables);
}
double scale, base;
scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len));
if (dest_len < 0) {
base = (FX_FLOAT)(src_len);
} else {
base = 0.0f;
}
m_ItemSize = (int)(sizeof(int) * 2 + sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + 1));
m_DestMin = dest_min;
m_pWeightTables = FX_Alloc(FX_BYTE, (dest_max - dest_min) * m_ItemSize + 4);
if(m_pWeightTables == NULL) {
return;
}
if (FXSYS_fabs((FX_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)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2);
pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_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((FX_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)FXSYS_floor((FX_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)FXSYS_floor((FX_FLOAT)src_start);
end_i = (int)FXSYS_ceil((FX_FLOAT)src_end);
} else {
start_i = (int)FXSYS_floor((FX_FLOAT)src_end);
end_i = (int)FXSYS_ceil((FX_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 = FXSYS_Div((FX_FLOAT)(j) - base, scale);
double dest_end = FXSYS_Div((FX_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 > (FX_FLOAT)(dest_pixel) ? dest_start : (FX_FLOAT)(dest_pixel);
double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) ? (FX_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((FX_FLOAT)(weight * 65536));
}
}
}
void CFXCODEC_HorzTable::Calc(int dest_len, int src_len, FX_BOOL bInterpol)
{
if (m_pWeightTables) {
FX_Free(m_pWeightTables);
}
double scale = (double)dest_len / (double)src_len;
m_ItemSize = sizeof(int) * 4;
int size = dest_len * m_ItemSize + 4;
m_pWeightTables = FX_Alloc(FX_BYTE, size);
if(m_pWeightTables == NULL) {
return;
}
FXSYS_memset32(m_pWeightTables, 0, size);
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((FX_FLOAT)des_col_f);
PixelWeight* pWeight = (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize);
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 = (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize);
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 = (PixelWeight*)(m_pWeightTables + des_col_index * m_ItemSize);
pWeight->m_SrcStart = src_col - 1;
pWeight->m_SrcEnd = src_col;
pWeight->m_Weights[0] = bInterpol ? FXSYS_round((FX_FLOAT)
(
((FX_FLOAT)des_col - (FX_FLOAT)des_col_index)
/ (FX_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((FX_FLOAT)src_col_f);
PixelWeight* pWeight = (PixelWeight*)(m_pWeightTables + des_col * m_ItemSize);
pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
pWeight->m_Weights[0] = 65536;
pWeight->m_Weights[1] = 0;
}
}
void CFXCODEC_VertTable::Calc(int dest_len, int src_len)
{
if (m_pWeightTables) {
FX_Free(m_pWeightTables);
}
double scale = (double)dest_len / (double)src_len;
m_ItemSize = sizeof(int) * 4;
int size = dest_len * m_ItemSize + 4;
m_pWeightTables = FX_Alloc(FX_BYTE, size);
if(m_pWeightTables == NULL) {
return;
}
FXSYS_memset32(m_pWeightTables, 0, size);
if(scale > 1) {
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 = (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize);
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 = (PixelWeight*)(m_pWeightTables + start_step * m_ItemSize);
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 = (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize);
pWeight->m_SrcStart = start_step;
pWeight->m_SrcEnd = end_step;
pWeight->m_Weights[0] = FXSYS_round((FX_FLOAT)(end_step - des_row) / (FX_FLOAT)length * 65536);
pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
}
}
} else {
for (int des_row = 0; des_row < dest_len; des_row++) {
PixelWeight* pWeight = (PixelWeight*)(m_pWeightTables + des_row * m_ItemSize);
pWeight->m_SrcStart = des_row;
pWeight->m_SrcEnd = des_row;
pWeight->m_Weights[0] = 65536;
pWeight->m_Weights[1] = 0;
}
}
}
CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder(CCodec_ModuleMgr* pCodecMgr)
{
m_pFile = NULL;
m_pJpegContext = NULL;
m_pPngContext = NULL;
m_pGifContext = NULL;
m_pBmpContext = NULL;
m_pTiffContext = NULL;
m_pCodecMgr = NULL;
m_pSrcBuf = NULL;
m_pDecodeBuf = NULL;
m_pDeviceBitmap = NULL;
m_pSrcPalette = NULL;
m_pCodecMgr = pCodecMgr;
m_offSet = 0;
m_SrcSize = 0;
m_ScanlineSize = 0;
m_SrcWidth = 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 = NULL;
m_GifTransIndex = -1;
m_GifFrameRect = FX_RECT(0, 0, 0, 0);
m_BmpIsTopBottom = FALSE;
}
CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder()
{
m_pFile = NULL;
if(m_pJpegContext != NULL) {
m_pCodecMgr->GetJpegModule()->Finish(m_pJpegContext);
}
if(m_pPngContext != NULL) {
m_pCodecMgr->GetPngModule()->Finish(m_pPngContext);
}
if(m_pGifContext != NULL) {
m_pCodecMgr->GetGifModule()->Finish(m_pGifContext);
}
if(m_pBmpContext != NULL) {
m_pCodecMgr->GetBmpModule()->Finish(m_pBmpContext);
}
if(m_pTiffContext != NULL) {
m_pCodecMgr->GetTiffModule()->DestroyDecoder(m_pTiffContext);
}
if(m_pSrcBuf != NULL) {
FX_Free(m_pSrcBuf);
}
if(m_pDecodeBuf != NULL) {
FX_Free(m_pDecodeBuf);
}
if(m_pSrcPalette != NULL) {
FX_Free(m_pSrcPalette);
}
}
FX_BOOL CCodec_ProgressiveDecoder::JpegReadMoreData(ICodec_JpegModule* pJpegModule, FXCODEC_STATUS& err_status)
{
FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize();
if (dwSize <= m_offSet) {
return FALSE;
}
dwSize = dwSize - m_offSet;
FX_DWORD dwAvail = pJpegModule->GetAvailInput(m_pJpegContext, NULL);
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(FX_BYTE, m_pSrcBuf, m_SrcSize);
if (!m_pSrcBuf) {
err_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
} else {
FX_DWORD dwConsume = m_SrcSize - dwAvail;
if (dwAvail) {
FXSYS_memcpy32(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;
}
FX_BOOL CCodec_ProgressiveDecoder::PngReadHeaderFunc(void* pModule, int width, int height, int bpc, int pass, int* color_type, double* gamma)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
if(pCodec->m_pDeviceBitmap == NULL) {
pCodec->m_SrcWidth = width;
pCodec->m_SrcHeight = height;
pCodec->m_SrcBPC = bpc;
pCodec->m_SrcPassNumber = pass;
pCodec->m_SrcComponents = *color_type == 0 ? 1 :
*color_type == 2 ? 3 :
*color_type == 3 ? 4 :
*color_type == 4 ? 2 :
*color_type == 6 ? 4 : 0;
pCodec->m_clipBox = FX_RECT(0, 0, width, height);
return FALSE;
}
FXDIB_Format format = pCodec->m_pDeviceBitmap->GetFormat();
switch(format) {
case FXDIB_1bppMask:
case FXDIB_1bppRgb:
ASSERT(FALSE);
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:
ASSERT(FALSE);
return FALSE;
}
*gamma = FXCODEC_PNG_GAMMA;
return TRUE;
}
FX_BOOL CCodec_ProgressiveDecoder::PngAskScanlineBufFunc(void* pModule, int line, FX_LPBYTE& src_buf)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
ASSERT(pDIBitmap != NULL);
if(pDIBitmap == NULL) {
return FALSE;
}
if(line >= pCodec->m_clipBox.top && line < pCodec->m_clipBox.bottom) {
double scale_y = (double)pCodec->m_sizeY / (double)pCodec->m_clipBox.Height();
FX_INT32 row = (FX_INT32)((line - pCodec->m_clipBox.top) * scale_y) + pCodec->m_startY;
FX_LPBYTE src_scan = (FX_LPBYTE)pDIBitmap->GetScanline(row);
FX_LPBYTE des_scan = pCodec->m_pDecodeBuf;
src_buf = pCodec->m_pDecodeBuf;
FX_INT32 src_Bpp = pDIBitmap->GetBPP() >> 3;
FX_INT32 des_Bpp = (pCodec->m_SrcFormat & 0xff) >> 3;
FX_INT32 src_left = pCodec->m_startX;
FX_INT32 des_left = pCodec->m_clipBox.left;
src_scan += src_left * src_Bpp;
des_scan += des_left * des_Bpp;
for (FX_INT32 src_col = 0; src_col < pCodec->m_sizeX; src_col++) {
PixelWeight* pPixelWeights = pCodec->m_WeightHorzOO.GetPixelWeight(src_col);
if(pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) {
continue;
}
switch(pDIBitmap->GetFormat()) {
case FXDIB_1bppMask:
case FXDIB_1bppRgb:
ASSERT(FALSE);
return FALSE;
case FXDIB_8bppMask:
case FXDIB_8bppRgb: {
if(pDIBitmap->GetPalette() != NULL) {
return FALSE;
}
FX_DWORD des_g = 0;
des_g += pPixelWeights->m_Weights[0] * src_scan[src_col];
des_scan[pPixelWeights->m_SrcStart] = (FX_BYTE)(des_g >> 16);
}
break;
case FXDIB_Rgb:
case FXDIB_Rgb32: {
FX_DWORD des_b = 0, des_g = 0, des_r = 0;
FX_LPCBYTE 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);
FX_LPBYTE pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
*pDes++ = (FX_BYTE)((des_b) >> 16);
*pDes++ = (FX_BYTE)((des_g) >> 16);
*pDes = (FX_BYTE)((des_r) >> 16);
}
break;
case FXDIB_Argb: {
FX_DWORD des_r = 0, des_g = 0, des_b = 0;
FX_LPCBYTE 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++);
FX_LPBYTE pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
*pDes++ = (FX_BYTE)((des_b) >> 16);
*pDes++ = (FX_BYTE)((des_g) >> 16);
*pDes++ = (FX_BYTE)((des_r) >> 16);
*pDes = *p;
}
break;
default:
return FALSE;
}
}
}
return TRUE;
}
void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz(CFX_DIBitmap* pDeviceBitmap, FX_INT32 des_line, FX_LPBYTE src_scan, FXCodec_Format src_format)
{
FX_LPBYTE des_scan = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_line);
FX_INT32 src_Bpp = (m_SrcFormat & 0xff) >> 3;
FX_INT32 des_Bpp = pDeviceBitmap->GetBPP() >> 3;
FX_INT32 src_left = m_clipBox.left;
FX_INT32 des_left = m_startX;
src_scan += src_left * src_Bpp;
des_scan += des_left * des_Bpp;
for (FX_INT32 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:
ASSERT(FALSE);
return;
case FXDIB_8bppMask:
case FXDIB_8bppRgb: {
if(pDeviceBitmap->GetPalette() != NULL) {
return;
}
FX_DWORD 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++ = (FX_BYTE)(des_g >> 16);
}
break;
case FXDIB_Rgb:
case FXDIB_Rgb32: {
FX_DWORD des_b = 0, des_g = 0, des_r = 0;
FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
des_scan += des_Bpp - 3;
}
break;
case FXDIB_Argb: {
FX_DWORD des_a = 0, des_b = 0, des_g = 0, des_r = 0;
FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
*des_scan++ = (FX_BYTE)((des_a) >> 16);
}
break;
default:
return;
}
}
}
void CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc(void* pModule, int pass, int line)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
ASSERT(pDIBitmap != NULL);
int src_top = pCodec->m_clipBox.top;
int src_bottom = pCodec->m_clipBox.bottom;
int des_top = pCodec->m_startY;
int src_hei = pCodec->m_clipBox.Height();
int des_hei = pCodec->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;
}
pCodec->PngOneOneMapResampleHorz(pDIBitmap, des_row, pCodec->m_pDecodeBuf, pCodec->m_SrcFormat);
if(pCodec->m_SrcPassNumber == 1 && scale_y > 1.0) {
pCodec->ResampleVert(pDIBitmap, scale_y, des_row);
return;
}
if(pass == 6 && scale_y > 1.0) {
pCodec->ResampleVert(pDIBitmap, scale_y, des_row);
}
}
}
FX_BOOL CCodec_ProgressiveDecoder::GifReadMoreData(ICodec_GifModule* pGifModule, FXCODEC_STATUS& err_status)
{
FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize();
if (dwSize <= m_offSet) {
return FALSE;
}
dwSize = dwSize - m_offSet;
FX_DWORD dwAvail = pGifModule->GetAvailInput(m_pGifContext, NULL);
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(FX_BYTE, m_pSrcBuf, m_SrcSize);
if (!m_pSrcBuf) {
err_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
} else {
FX_DWORD dwConsume = m_SrcSize - dwAvail;
if (dwAvail) {
FXSYS_memcpy32(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, m_pSrcBuf, dwSize + dwAvail);
return TRUE;
}
void CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback(void* pModule, FX_DWORD& cur_pos)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
FX_DWORD remain_size = pCodec->m_pCodecMgr->GetGifModule()->GetAvailInput(pCodec->m_pGifContext);
cur_pos = pCodec->m_offSet - remain_size;
}
FX_LPBYTE CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback(void* pModule, FX_INT32 frame_num, FX_INT32 pal_size)
{
return FX_Alloc(FX_BYTE, pal_size);
}
FX_BOOL CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback(void* pModule, FX_DWORD rcd_pos, const FX_RECT& img_rc,
FX_INT32 pal_num, void* pal_ptr,
FX_INT32 delay_time, FX_BOOL user_input,
FX_INT32 trans_index, FX_INT32 disposal_method, FX_BOOL interlace)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
pCodec->m_offSet = rcd_pos;
FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
if(!pCodec->GifReadMoreData(pCodec->m_pCodecMgr->GetGifModule(), error_status)) {
return FALSE;
}
FX_LPBYTE pPalette = NULL;
if(pal_num != 0 && pal_ptr) {
pPalette = (FX_LPBYTE)pal_ptr;
} else {
pal_num = pCodec->m_GifPltNumber;
pPalette = pCodec->m_pGifPalette;
}
if(pCodec->m_pSrcPalette == NULL) {
pCodec->m_pSrcPalette = FX_Alloc(FX_ARGB, pal_num);
} else if(pal_num > pCodec->m_SrcPaletteNumber) {
pCodec->m_pSrcPalette = FX_Realloc(FX_ARGB, pCodec->m_pSrcPalette, pal_num);
}
if(pCodec->m_pSrcPalette == NULL) {
return FALSE;
}
pCodec->m_SrcPaletteNumber = pal_num;
for (int i = 0; i < pal_num; i++) {
register FX_DWORD j = i * 3;
pCodec->m_pSrcPalette[i] =
ArgbEncode(0xff, pPalette[j], pPalette[j + 1], pPalette[j + 2]);
}
pCodec->m_GifTransIndex = trans_index;
pCodec->m_GifFrameRect = img_rc;
pCodec->m_SrcPassNumber = interlace ? 4 : 1;
FX_INT32 pal_index = pCodec->m_GifBgIndex;
CFX_DIBitmap* pDevice = pCodec->m_pDeviceBitmap;
if (trans_index >= pal_num) {
trans_index = -1;
}
if (trans_index != -1) {
pCodec->m_pSrcPalette[trans_index] &= 0x00ffffff;
if (pDevice->HasAlpha()) {
pal_index = trans_index;
}
}
int startX = pCodec->m_startX;
int startY = pCodec->m_startY;
int sizeX = pCodec->m_sizeX;
int sizeY = pCodec->m_sizeY;
int Bpp = pDevice->GetBPP() / 8;
FX_ARGB argb = pCodec->m_pSrcPalette[pal_index];
for (int row = 0; row < sizeY; row ++) {
FX_LPBYTE pScanline = (FX_LPBYTE)pDevice->GetScanline(row + startY) + startX * Bpp;
switch(pCodec->m_TransMethod) {
case 3: {
FX_BYTE gray = FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
FXSYS_memset8(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::GifReadScanlineCallback(void* pModule, FX_INT32 row_num, FX_LPBYTE row_buf)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
ASSERT(pDIBitmap != NULL);
FX_INT32 img_width = pCodec->m_GifFrameRect.Width();
if (!pDIBitmap->HasAlpha()) {
FX_LPBYTE byte_ptr = row_buf;
for (int i = 0; i < img_width; i++ ) {
if(*byte_ptr == pCodec->m_GifTransIndex) {
*byte_ptr = pCodec->m_GifBgIndex;
}
byte_ptr++;
}
}
FX_INT32 pal_index = pCodec->m_GifBgIndex;
if (pCodec->m_GifTransIndex != -1 && pCodec->m_pDeviceBitmap->HasAlpha()) {
pal_index = pCodec->m_GifTransIndex;
}
FXSYS_memset8(pCodec->m_pDecodeBuf, pal_index, pCodec->m_SrcWidth);
FX_BOOL bLastPass = ((row_num % 2) == 1) ? TRUE : FALSE;
FX_INT32 line = row_num + pCodec->m_GifFrameRect.top;
FX_INT32 left = pCodec->m_GifFrameRect.left;
FXSYS_memcpy32(pCodec->m_pDecodeBuf + left, row_buf, img_width);
int src_top = pCodec->m_clipBox.top;
int src_bottom = pCodec->m_clipBox.bottom;
int des_top = pCodec->m_startY;
int src_hei = pCodec->m_clipBox.Height();
int des_hei = pCodec->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;
}
pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, pCodec->m_SrcFormat);
if(scale_y > 1.0 && (!pCodec->m_bInterpol || pCodec->m_SrcPassNumber == 1)) {
pCodec->ResampleVert(pDIBitmap, scale_y, des_row);
return;
}
if(scale_y > 1.0) {
int des_bottom = des_top + pCodec->m_sizeY;
int des_Bpp = pDIBitmap->GetBPP() >> 3;
FX_DWORD des_ScanOffet = pCodec->m_startX * des_Bpp;
if(des_row + (int)scale_y >= des_bottom - 1) {
FX_LPBYTE scan_src = (FX_LPBYTE)pDIBitmap->GetScanline(des_row) + des_ScanOffet;
int cur_row = des_row;
while (++cur_row < des_bottom) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDIBitmap->GetScanline(cur_row) + des_ScanOffet;
FX_DWORD size = pCodec->m_sizeX * des_Bpp;
FXSYS_memcpy32(scan_des, scan_src, size);
}
}
if(bLastPass) {
pCodec->GifDoubleLineResampleVert(pDIBitmap, scale_y, des_row);
}
}
}
}
void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row)
{
int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
FX_DWORD des_ScanOffet = m_startX * des_Bpp;
int des_top = m_startY;
int des_row_1 = des_row - int(2 * scale_y);
if(des_row_1 < des_top) {
des_row_1 = des_top;
}
for (; des_row_1 < des_row; des_row_1++) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
FX_LPCBYTE 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() != NULL) {
return;
}
int des_g = 0;
des_g += pWeight->m_Weights[0] * (*scan_src1++);
des_g += pWeight->m_Weights[1] * (*scan_src2++);
*scan_des++ = (FX_BYTE)(des_g >> 16);
}
break;
case FXDIB_Rgb:
case FXDIB_Rgb32: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
scan_des += des_Bpp - 3;
}
break;
case FXDIB_Argb: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
*scan_des++ = (FX_BYTE)((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);
}
}
FX_BOOL CCodec_ProgressiveDecoder::BmpReadMoreData(ICodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status)
{
FX_DWORD dwSize = (FX_DWORD)m_pFile->GetSize();
if (dwSize <= m_offSet) {
return FALSE;
}
dwSize = dwSize - m_offSet;
FX_DWORD dwAvail = pBmpModule->GetAvailInput(m_pBmpContext, NULL);
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(FX_BYTE, m_pSrcBuf, m_SrcSize);
if (!m_pSrcBuf) {
err_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
} else {
FX_DWORD dwConsume = m_SrcSize - dwAvail;
if (dwAvail) {
FXSYS_memcpy32(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;
}
FX_BOOL CCodec_ProgressiveDecoder::BmpInputImagePositionBufCallback(void* pModule, FX_DWORD rcd_pos)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
pCodec->m_offSet = rcd_pos;
FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
if(!pCodec->BmpReadMoreData(pCodec->m_pCodecMgr->GetBmpModule(), error_status)) {
return FALSE;
}
return TRUE;
}
void CCodec_ProgressiveDecoder::BmpReadScanlineCallback(void* pModule, FX_INT32 row_num, FX_LPBYTE row_buf)
{
CCodec_ProgressiveDecoder* pCodec = (CCodec_ProgressiveDecoder*)pModule;
CFX_DIBitmap* pDIBitmap = pCodec->m_pDeviceBitmap;
ASSERT(pDIBitmap != NULL);
FXSYS_memcpy32(pCodec->m_pDecodeBuf, row_buf, pCodec->m_ScanlineSize);
int src_top = pCodec->m_clipBox.top;
int src_bottom = pCodec->m_clipBox.bottom;
int des_top = pCodec->m_startY;
int src_hei = pCodec->m_clipBox.Height();
int des_hei = pCodec->m_sizeY;
if(row_num >= src_top && row_num < src_bottom) {
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;
}
pCodec->ReSampleScanline(pDIBitmap, des_row, pCodec->m_pDecodeBuf, pCodec->m_SrcFormat);
if(scale_y > 1.0) {
if(pCodec->m_BmpIsTopBottom || !pCodec->m_bInterpol) {
pCodec->ResampleVert(pDIBitmap, scale_y, des_row);
return;
} else {
pCodec->ResampleVertBT(pDIBitmap, scale_y, des_row);
}
}
}
}
void CCodec_ProgressiveDecoder::ResampleVertBT(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row)
{
int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
FX_DWORD des_ScanOffet = m_startX * des_Bpp;
int des_top = m_startY;
int des_bottom = m_startY + m_sizeY;
int des_row_1 = des_row + int(scale_y);
if(des_row_1 >= des_bottom - 1) {
FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
while (++des_row < des_bottom) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
FX_DWORD size = m_sizeX * des_Bpp;
FXSYS_memcpy32(scan_des, scan_src, size);
}
return;
}
for (; des_row_1 > des_row; des_row_1--) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
FX_LPCBYTE 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() != NULL) {
return;
}
int des_g = 0;
des_g += pWeight->m_Weights[0] * (*scan_src1++);
des_g += pWeight->m_Weights[1] * (*scan_src2++);
*scan_des++ = (FX_BYTE)(des_g >> 16);
}
break;
case FXDIB_Rgb:
case FXDIB_Rgb32: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
scan_des += des_Bpp - 3;
}
break;
case FXDIB_Argb: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
*scan_des++ = (FX_BYTE)((des_a) >> 16);
}
break;
default:
return;
}
}
}
}
FX_BOOL CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute)
{
m_offSet = 0;
FX_DWORD size = (FX_DWORD)m_pFile->GetSize();
if(size > FXCODEC_BLOCK_SIZE) {
size = FXCODEC_BLOCK_SIZE;
}
if(m_pSrcBuf != NULL) {
FX_Free(m_pSrcBuf);
m_pSrcBuf = NULL;
}
m_pSrcBuf = FX_Alloc(FX_BYTE, size);
if(m_pSrcBuf == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FXSYS_memset32(m_pSrcBuf, 0, size);
m_SrcSize = size;
switch(imageType) {
case FXCODEC_IMAGE_BMP: {
ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
if(pBmpModule == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
pBmpModule->InputImagePositionBufCallback = BmpInputImagePositionBufCallback;
pBmpModule->ReadScanlineCallback = BmpReadScanlineCallback;
m_pBmpContext = pBmpModule->Start((void*)this);
if(m_pBmpContext == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FX_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);
FX_DWORD* pPalette = NULL;
FX_INT32 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);
if(m_pSrcPalette != NULL) {
FX_Free(m_pSrcPalette);
m_pSrcPalette = NULL;
}
if (m_SrcPaletteNumber) {
m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber);
if(m_pSrcPalette == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FXSYS_memcpy32(m_pSrcPalette, pPalette, m_SrcPaletteNumber * sizeof(FX_DWORD));
}
return TRUE;
}
if(m_pBmpContext != NULL) {
pBmpModule->Finish(m_pBmpContext);
m_pBmpContext = NULL;
}
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
break;
case FXCODEC_IMAGE_JPG: {
ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
if(pJpegModule == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
m_pJpegContext = pJpegModule->Start();
if(m_pJpegContext == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FX_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);
FX_INT32 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 != NULL) {
pJpegModule->Finish(m_pJpegContext);
m_pJpegContext = NULL;
}
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
break;
case FXCODEC_IMAGE_PNG: {
ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
if(pPngModule == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
pPngModule->ReadHeaderCallback = CCodec_ProgressiveDecoder::PngReadHeaderFunc;
pPngModule->AskScanlineBufCallback = CCodec_ProgressiveDecoder::PngAskScanlineBufFunc;
pPngModule->FillScanlineBufCompletedCallback = CCodec_ProgressiveDecoder::PngFillScanlineBufCompletedFunc;
m_pPngContext = pPngModule->Start((void*)this);
if(m_pPngContext == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FX_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) {
FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet;
FX_DWORD input_size = remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
if(input_size == 0) {
if(m_pPngContext != NULL) {
pPngModule->Finish(m_pPngContext);
}
m_pPngContext = NULL;
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
if(m_pSrcBuf != NULL && input_size > m_SrcSize) {
FX_Free(m_pSrcBuf);
m_pSrcBuf = FX_Alloc(FX_BYTE, input_size);
if(m_pSrcBuf == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FXSYS_memset32(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 != NULL) {
pPngModule->Finish(m_pPngContext);
m_pPngContext = NULL;
}
if(m_SrcPassNumber == 0) {
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
}
break;
case FXCODEC_IMAGE_GIF: {
ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
if(pGifModule == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
pGifModule->RecordCurrentPositionCallback = CCodec_ProgressiveDecoder::GifRecordCurrentPositionCallback;
pGifModule->AskLocalPaletteBufCallback = CCodec_ProgressiveDecoder::GifAskLocalPaletteBufCallback;
pGifModule->InputRecordPositionBufCallback = CCodec_ProgressiveDecoder::GifInputRecordPositionBufCallback;
pGifModule->ReadScanlineCallback = CCodec_ProgressiveDecoder::GifReadScanlineCallback;
m_pGifContext = pGifModule->Start((void*)this);
if(m_pGifContext == NULL) {
m_status = FXCODEC_STATUS_ERR_MEMORY;
return FALSE;
}
FX_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, m_pSrcBuf, size);
m_SrcComponents = 1;
FX_INT32 readResult = pGifModule->ReadHeader(m_pGifContext, &m_SrcWidth, &m_SrcHeight,
&m_GifPltNumber, (void**)&m_pGifPalette, &m_GifBgIndex);
while(readResult == 2) {
FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
if(!GifReadMoreData(pGifModule, error_status)) {
m_status = error_status;
return FALSE;
}
readResult = pGifModule->ReadHeader(m_pGifContext, &m_SrcWidth, &m_SrcHeight,
&m_GifPltNumber, (void**)&m_pGifPalette, &m_GifBgIndex);
}
if(readResult == 1) {
m_SrcBPC = 8;
m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
return TRUE;
}
if(m_pGifContext != NULL) {
pGifModule->Finish(m_pGifContext);
m_pGifContext = NULL;
}
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
break;
case FXCODEC_IMAGE_TIF: {
ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
if(pTiffModule == NULL) {
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
m_pTiffContext = pTiffModule->CreateDecoder(m_pFile);
if(m_pTiffContext == NULL) {
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
FX_INT32 frames = 0;
pTiffModule->GetFrames(m_pTiffContext, frames);
FX_DWORD bpc;
FX_BOOL ret = pTiffModule->LoadFrameInfo(m_pTiffContext, 0, (FX_DWORD&)m_SrcWidth, (FX_DWORD&)m_SrcHeight, (FX_DWORD&)m_SrcComponents, bpc, pAttribute);
m_SrcComponents = 4;
m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
if(!ret) {
pTiffModule->DestroyDecoder(m_pTiffContext);
(m_pTiffContext = NULL);
(m_status = FXCODEC_STATUS_ERR_FORMAT);
return FALSE;
}
}
break;
default:
m_status = FXCODEC_STATUS_ERR_FORMAT;
return FALSE;
}
return TRUE;
}
FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo(IFX_FileRead* pFile, FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute* pAttribute)
{
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:
;
}
if(pFile == NULL) {
m_status = FXCODEC_STATUS_ERR_PARAMS;
m_pFile = NULL;
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;
}
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 = NULL;
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;
}
if(clip->left < 0) {
clip->left = 0;
}
if(clip->right > m_SrcWidth) {
clip->right = m_SrcWidth;
}
if(clip->top < 0) {
clip->top = 0;
}
if(clip->bottom > m_SrcHeight) {
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 _RGB2BGR(FX_LPBYTE buffer, int width = 1)
{
if (buffer && width > 0) {
FX_BYTE 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;
}
}
}
void CCodec_ProgressiveDecoder::ReSampleScanline(CFX_DIBitmap* pDeviceBitmap, int des_line, FX_LPBYTE src_scan, FXCodec_Format src_format)
{
int src_left = m_clipBox.left;
int des_left = m_startX;
FX_LPBYTE 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: {
FX_DWORD 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++ = (FX_BYTE)(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 * (FX_BYTE)(argb >> 16);
des_g += pixel_weight * (FX_BYTE)(argb >> 8);
des_b += pixel_weight * (FX_BYTE)argb;
}
*des_scan++ = (FX_BYTE)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
}
break;
case 4: {
FX_DWORD 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];
FX_LPCBYTE 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++ = (FX_BYTE)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
}
break;
case 5: {
FX_DWORD 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];
FX_LPCBYTE src_pixel = src_scan + j * src_Bpp;
FX_BYTE 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++ = (FX_BYTE)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
}
break;
case 6:
return;
case 7: {
FX_DWORD 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];
}
FXSYS_memset8(des_scan, (FX_BYTE)(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 * (FX_BYTE)(argb >> 16);
des_g += pixel_weight * (FX_BYTE)(argb >> 8);
des_b += pixel_weight * (FX_BYTE)argb;
}
*des_scan++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((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 * (FX_BYTE)(argb >> 16);
des_g += pixel_weight * (FX_BYTE)(argb >> 8);
des_b += pixel_weight * (FX_BYTE)argb;
}
*des_scan++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((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 * (FX_BYTE)(argb >> 24);
des_r += pixel_weight * (FX_BYTE)(argb >> 16);
des_g += pixel_weight * (FX_BYTE)(argb >> 8);
des_b += pixel_weight * (FX_BYTE)argb;
}
*des_scan++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
*des_scan++ = (FX_BYTE)((des_a) >> 16);
}
}
break;
case 9: {
FX_DWORD 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];
FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
des_scan += des_Bpp - 3;
}
break;
case 10: {
FX_DWORD 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];
FX_LPCBYTE src_pixel = src_scan + j * src_Bpp;
FX_BYTE 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++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
des_scan += des_Bpp - 3;
}
break;
case 11: {
FX_DWORD 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];
FX_LPCBYTE 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++ = (FX_BYTE)((des_b) >> 16);
*des_scan++ = (FX_BYTE)((des_g) >> 16);
*des_scan++ = (FX_BYTE)((des_r) >> 16);
*des_scan++ = (FX_BYTE)((des_alpha * 255) >> 16);
}
break;
default:
return;
}
}
}
void CCodec_ProgressiveDecoder::ResampleVert(CFX_DIBitmap* pDeviceBitmap, double scale_y, int des_row)
{
int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
FX_DWORD des_ScanOffet = m_startX * des_Bpp;
if(m_bInterpol) {
int des_top = m_startY;
int des_row_1 = des_row - int(scale_y);
if(des_row_1 < des_top) {
int des_bottom = des_top + m_sizeY;
if(des_row + (int)scale_y >= des_bottom - 1) {
FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
while (++des_row < des_bottom) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
FX_DWORD size = m_sizeX * des_Bpp;
FXSYS_memcpy32(scan_des, scan_src, size);
}
}
return;
}
for (; des_row_1 < des_row; des_row_1++) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
FX_LPCBYTE scan_src1 = pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) + des_ScanOffet;
FX_LPCBYTE 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() != NULL) {
return;
}
int des_g = 0;
des_g += pWeight->m_Weights[0] * (*scan_src1++);
des_g += pWeight->m_Weights[1] * (*scan_src2++);
*scan_des++ = (FX_BYTE)(des_g >> 16);
}
break;
case FXDIB_Rgb:
case FXDIB_Rgb32: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
scan_des += des_Bpp - 3;
}
break;
case FXDIB_Argb: {
FX_DWORD 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++ = (FX_BYTE)((des_b) >> 16);
*scan_des++ = (FX_BYTE)((des_g) >> 16);
*scan_des++ = (FX_BYTE)((des_r) >> 16);
*scan_des++ = (FX_BYTE)((des_a) >> 16);
}
break;
default:
return;
}
}
}
int des_bottom = des_top + m_sizeY;
if(des_row + (int)scale_y >= des_bottom - 1) {
FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
while (++des_row < des_bottom) {
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
FX_DWORD size = m_sizeX * des_Bpp;
FXSYS_memcpy32(scan_des, scan_src, size);
}
}
return;
}
int multiple = (int)FXSYS_ceil((FX_FLOAT)scale_y - 1);
if(multiple > 0) {
FX_LPBYTE scan_src = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
for (int i = 1; i <= multiple; i++) {
if(des_row + i >= m_startY + m_sizeY) {
return;
}
FX_LPBYTE scan_des = (FX_LPBYTE)pDeviceBitmap->GetScanline(des_row + i) + des_ScanOffet;
FX_DWORD size = m_sizeX * des_Bpp;
FXSYS_memcpy32(scan_des, scan_src, size);
}
}
}
void CCodec_ProgressiveDecoder::Resample(CFX_DIBitmap* pDeviceBitmap, FX_INT32 src_line, FX_LPBYTE 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(FX_INT32& frames, IFX_Pause* pPause)
{
if(!(m_status == FXCODEC_STATUS_FRAME_READY || m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) {
return FXCODEC_STATUS_ERROR;
}
switch(m_imagType) {
case FXCODEC_IMAGE_BMP:
case FXCODEC_IMAGE_JPG:
case FXCODEC_IMAGE_PNG:
case FXCODEC_IMAGE_TIF:
frames = m_FrameNumber = 1;
return m_status = FXCODEC_STATUS_DECODE_READY;
case FXCODEC_IMAGE_GIF: {
ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
while (TRUE) {
FX_INT32 readResult = pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber);
while(readResult == 2) {
FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ;
if(!GifReadMoreData(pGifModule, error_status)) {
return error_status;
}
if(pPause && pPause->NeedToPauseNow()) {
return m_status = FXCODEC_STATUS_FRAME_TOBECONTINUE;
}
readResult = pGifModule->LoadFrameInfo(m_pGifContext, &m_FrameNumber);
}
if(readResult == 1) {
frames = m_FrameNumber;
return m_status = FXCODEC_STATUS_DECODE_READY;
}
if(m_pGifContext != NULL) {
pGifModule->Finish(m_pGifContext);
m_pGifContext = NULL;
}
return m_status = FXCODEC_STATUS_ERROR;
}
}
break;
default:
;
}
return FXCODEC_STATUS_ERROR;
}
FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(CFX_DIBitmap* pDIBitmap,
int start_x, int start_y, int size_x, int size_y,
FX_INT32 frames, FX_BOOL bInterpol)
{
if(m_status != FXCODEC_STATUS_DECODE_READY) {
return FXCODEC_STATUS_ERROR;
}
if(pDIBitmap == NULL || 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);
FX_INT32 out_range_x = device_rc.right - pDIBitmap->GetWidth();
FX_INT32 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) {
FX_FLOAT scaleX = (FX_FLOAT)m_clipBox.Width() / (FX_FLOAT)size_x;
if(start_x < 0) {
m_clipBox.left -= (FX_INT32)FXSYS_ceil((FX_FLOAT)start_x * scaleX);
}
if(out_range_x > 0) {
m_clipBox.right -= (FX_INT32)FXSYS_floor((FX_FLOAT)out_range_x * scaleX);
}
}
if(start_y < 0 || out_range_y > 0) {
FX_FLOAT scaleY = (FX_FLOAT)m_clipBox.Height() / (FX_FLOAT)size_y;
if(start_y < 0) {
m_clipBox.top -= (FX_INT32)FXSYS_ceil((FX_FLOAT)start_y * scaleY);
}
if(out_range_y > 0) {
m_clipBox.bottom -= (FX_INT32)FXSYS_floor((FX_FLOAT)out_range_y * scaleY);
}
}
if(m_clipBox.IsEmpty()) {
return FXCODEC_STATUS_ERR_PARAMS;
}
switch(m_imagType) {
case FXCODEC_IMAGE_JPG: {
ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
int down_scale = 1;
GetDownScale(down_scale);
FX_BOOL bStart = pJpegModule->StartScanline(m_pJpegContext, down_scale);
while(!bStart) {
FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
if(!JpegReadMoreData(pJpegModule, error_status)) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = error_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;
if(m_pDecodeBuf != NULL) {
FX_Free(m_pDecodeBuf);
m_pDecodeBuf = NULL;
}
m_pDecodeBuf = FX_Alloc(FX_BYTE, scanline_size);
if(m_pDecodeBuf == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
FXSYS_memset32(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);
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
break;
case FXCODEC_IMAGE_PNG: {
ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
if(pPngModule == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
if(m_pPngContext != NULL) {
pPngModule->Finish(m_pPngContext);
m_pPngContext = NULL;
}
m_pPngContext = pPngModule->Start((void*)this);
if(m_pPngContext == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
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 = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_PARAMS;
}
}
GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4;
if(m_pDecodeBuf != NULL) {
FX_Free(m_pDecodeBuf);
m_pDecodeBuf = NULL;
}
m_pDecodeBuf = FX_Alloc(FX_BYTE, scanline_size);
if(m_pDecodeBuf == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
FXSYS_memset32(m_pDecodeBuf, 0, scanline_size);
m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width(), m_bInterpol);
m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
break;
case FXCODEC_IMAGE_GIF: {
ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
if(pGifModule == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
m_SrcFormat = FXCodec_8bppRgb;
GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
int scanline_size = (m_SrcWidth + 3) / 4 * 4;
if(m_pDecodeBuf != NULL) {
FX_Free(m_pDecodeBuf);
m_pDecodeBuf = NULL;
}
m_pDecodeBuf = FX_Alloc(FX_BYTE, scanline_size);
if(m_pDecodeBuf == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
FXSYS_memset32(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;
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
break;
case FXCODEC_IMAGE_BMP: {
ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
if(pBmpModule == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
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;
if(m_pDecodeBuf != NULL) {
FX_Free(m_pDecodeBuf);
m_pDecodeBuf = NULL;
}
m_pDecodeBuf = FX_Alloc(FX_BYTE, m_ScanlineSize);
if(m_pDecodeBuf == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
FXSYS_memset32(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());
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
break;
case FXCODEC_IMAGE_TIF:
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
default:
break;
}
return FXCODEC_STATUS_ERROR;
}
FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode(IFX_Pause* pPause)
{
if(m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) {
return FXCODEC_STATUS_ERROR;
}
switch(m_imagType) {
case FXCODEC_IMAGE_JPG: {
ICodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
while(TRUE) {
FX_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 = NULL;
m_pFile = NULL;
return m_status = error_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 = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_DECODE_FINISH;
}
Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat);
m_SrcRow++;
if(pPause && pPause->NeedToPauseNow()) {
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
}
}
break;
case FXCODEC_IMAGE_PNG: {
ICodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
while (TRUE) {
FX_DWORD remain_size = (FX_DWORD)m_pFile->GetSize() - m_offSet;
FX_DWORD input_size = remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
if(input_size == 0) {
if(m_pPngContext != NULL) {
pPngModule->Finish(m_pPngContext);
}
m_pPngContext = NULL;
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_DECODE_FINISH;
}
if(m_pSrcBuf != NULL && input_size > m_SrcSize) {
FX_Free(m_pSrcBuf);
m_pSrcBuf = FX_Alloc(FX_BYTE, input_size);
if(m_pSrcBuf == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
FXSYS_memset32(m_pSrcBuf, 0, input_size);
m_SrcSize = input_size;
}
FX_BOOL bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size);
if(!bResult) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_READ;
}
m_offSet += input_size;
bResult = pPngModule->Input(m_pPngContext, m_pSrcBuf, input_size);
if(!bResult) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERROR;
}
if(pPause && pPause->NeedToPauseNow()) {
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
}
}
break;
case FXCODEC_IMAGE_GIF: {
ICodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
while(TRUE) {
FX_INT32 readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur);
while(readRes == 2) {
FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
if(!GifReadMoreData(pGifModule, error_status)) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = error_status;
}
if(pPause && pPause->NeedToPauseNow()) {
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
readRes = pGifModule->LoadFrame(m_pGifContext, m_FrameCur);
}
if(readRes == 1) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_DECODE_FINISH;
}
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERROR;
}
}
break;
case FXCODEC_IMAGE_BMP: {
ICodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
while(TRUE) {
FX_INT32 readRes = pBmpModule->LoadImage(m_pBmpContext);
while(readRes == 2) {
FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
if(!BmpReadMoreData(pBmpModule, error_status)) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = error_status;
}
if(pPause && pPause->NeedToPauseNow()) {
return m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
}
readRes = pBmpModule->LoadImage(m_pBmpContext);
}
if(readRes == 1) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_DECODE_FINISH;
}
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERROR;
}
}
break;
case FXCODEC_IMAGE_TIF: {
ICodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
FX_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, m_pDeviceBitmap);
m_pDeviceBitmap = NULL;
m_pFile = NULL;
if(!ret) {
return m_status = FXCODEC_STATUS_ERROR;
}
return m_status = FXCODEC_STATUS_DECODE_FINISH;
} else {
CFX_DIBitmap* pDIBitmap = FX_NEW CFX_DIBitmap;
if(pDIBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb);
if(pDIBitmap->GetBuffer() == NULL) {
delete pDIBitmap;
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
ret = pTiffModule->Decode(m_pTiffContext, pDIBitmap);
if(!ret) {
delete pDIBitmap;
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERROR;
}
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(pDIBitmap != pClipBitmap) {
delete pDIBitmap;
}
if(pClipBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
CFX_DIBitmap* pFormatBitmap = NULL;
switch(m_pDeviceBitmap->GetFormat()) {
case FXDIB_8bppRgb:
pFormatBitmap = FX_NEW CFX_DIBitmap;
if(pFormatBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_8bppRgb);
break;
case FXDIB_8bppMask:
pFormatBitmap = FX_NEW CFX_DIBitmap;
if(pFormatBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_8bppMask);
break;
case FXDIB_Rgb:
pFormatBitmap = FX_NEW CFX_DIBitmap;
if(pFormatBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_Rgb);
break;
case FXDIB_Rgb32:
pFormatBitmap = FX_NEW CFX_DIBitmap;
if(pFormatBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), FXDIB_Rgb32);
break;
case FXDIB_Argb:
pFormatBitmap = pClipBitmap;
break;
default:
;
}
switch(m_pDeviceBitmap->GetFormat()) {
case FXDIB_8bppRgb:
case FXDIB_8bppMask: {
for (FX_INT32 row = 0; row < pClipBitmap->GetHeight(); row++) {
FX_LPBYTE src_line = (FX_LPBYTE)pClipBitmap->GetScanline(row);
FX_LPBYTE des_line = (FX_LPBYTE)pFormatBitmap->GetScanline(row);
for (FX_INT32 col = 0; col < pClipBitmap->GetWidth(); col++) {
FX_BYTE _a = 255 - src_line[3];
FX_BYTE b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
FX_BYTE g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
FX_BYTE 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: {
FX_INT32 desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
for (FX_INT32 row = 0; row < pClipBitmap->GetHeight(); row++) {
FX_LPBYTE src_line = (FX_LPBYTE)pClipBitmap->GetScanline(row);
FX_LPBYTE des_line = (FX_LPBYTE)pFormatBitmap->GetScanline(row);
for (FX_INT32 col = 0; col < pClipBitmap->GetWidth(); col++) {
FX_BYTE _a = 255 - src_line[3];
FX_BYTE b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
FX_BYTE g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
FX_BYTE 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:
;
}
if(pClipBitmap != pFormatBitmap) {
delete pClipBitmap;
}
if(pFormatBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
CFX_DIBitmap* pStrechBitmap = pFormatBitmap->StretchTo(m_sizeX, m_sizeY, m_bInterpol ? FXDIB_INTERPOL : FXDIB_DOWNSAMPLE);
delete pFormatBitmap;
pFormatBitmap = NULL;
if(pStrechBitmap == NULL) {
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_ERR_MEMORY;
}
m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, pStrechBitmap, 0, 0);
delete pStrechBitmap;
pStrechBitmap = NULL;
m_pDeviceBitmap = NULL;
m_pFile = NULL;
return m_status = FXCODEC_STATUS_DECODE_FINISH;
}
}
break;
default:
break;
}
return FXCODEC_STATUS_ERROR;
}
ICodec_ProgressiveDecoder* CCodec_ModuleMgr::CreateProgressiveDecoder()
{
return FX_NEW CCodec_ProgressiveDecoder(this);
}