📄 jpeg.c
字号:
#include "jpegDecoder.h"
#include "decolor.h"
#include "deHuffman.h"
#include "idct.h"
#include "sample.h"
// for test
#ifndef RELEASE_VERSION
#include <windows.h>
int CT_List[16] ;
int CT_Temp ;
int nIndex = 0 ;
#define CountTime_Start() { \
CT_Temp = GetTickCount() ; \
}
#define CountTime_End(nIndex) { \
CT_List[nIndex] += GetTickCount()-CT_Temp ; \
}
#else
#define CountTime_Start()
#define CountTime_End(nIndex)
#endif
/////////////////////////////////////////////
/////////////////////////////////////////////
#ifdef _PALM_OS_
#include "CallBack.h"
extern EmulStateRef g_emulStateP ;
#define CALL_CALLBACK_FUNCTION( lpProc , pCallbackParam ) Call68KFunction( g_emulStateP, lpProc , pCallbackParam )
#else
#define CALL_CALLBACK_FUNCTION( lpProc , pCallbackParam ) lpProc( pCallbackParam )
#endif
#ifdef __WIN32__
#define BitsRoundTo4Bytes(bits) (((bits) + 31) / 32 * 4)
#endif
/////////
int GetInfo(JPEG_HANDLE *hJpeg, HMSTREAM pStream, LPJPG_INFO pJpgInfo) ;
int OpenFileAndGetInfo( JPEG_HANDLE *hJpeg, HMSTREAM stream_handle );
int getColorLimitTable( JPEG_HANDLE *hJpeg ) ;
void InitHuffmanVar( JPEG_HANDLE *hJpeg ) ;
int InitResampleVar( JPEG_HANDLE *hJpeg, int lWidth, int lHeight ) ;
int hJpegInit( JPEG_HANDLE **hJpeg, HMSTREAM stream_handle, MLong *lWidth, MLong *lHeight ) ;
int huffmanDecodeInfoInit( JPEG_HANDLE *hJpeg, HUFFMAN_QT_DECODER_INFO ** pDecoderInfo ) ;
int colorInfoInit( JPEG_HANDLE *hJpeg, DECOLOR_PARAM ** pDecolorParam, JPG_CALLBACK_PARAM *pCallbackParam, int lWidth ) ;
int callbackInfoInit(JPG_CALLBACK_PARAM **pCallbackParam, JPEG_HANDLE *hJpeg, int lWidth, int lHeight, MLong lUserParam ) ;
#define Resample( addrW, addrH, inData, outData, lineBytes, LineCount, lWidth ) {\
{\
if ( LineCount >= 0 ) {\
int i = LineCount ;\
MByte * inDatax = inData ;\
MByte * outDatax = outData ;\
MShort * addrHx = addrH ;\
while (-- i >= 0 ) {\
register MByte * out = outDatax ;\
register MByte * in = inDatax + ( * addrHx ++ ) * lineBytes;\
register MShort * addrWx = addrW ;\
register int j = lWidth ; \
while( --j >= 0 )\
* out ++ = in[ * addrWx ++ ] ;\
outDatax += lWidth ;\
}\
}\
}\
}
/////////
MLong JPG_GetInfo( HMSTREAM stream_handle, LPJPG_INFO pJpgInfo ) {
JPEG_HANDLE *hJpeg ;
int releaseReturn = READ_JPEG_OK ;
hJpeg = ( JPEG_HANDLE * ) AMMemAlloc ( MNull, sizeof ( JPEG_HANDLE ) ) ;
if ( !hJpeg )
return NO_ENOUGH_MEMORY ;
AMMemSet( hJpeg, 0 , sizeof ( JPEG_HANDLE ) ) ;
if ( !stream_handle ) {
releaseReturn = READ_IMAGE_ERROR ;
goto releaseBuffer1 ;
}
if ( ( hJpeg -> fileSize = AMStreamGetSize(stream_handle) ) <= 0 ) {
releaseReturn = READ_IMAGE_ERROR ;
goto releaseBuffer1 ;
}
releaseReturn = GetInfo(hJpeg, stream_handle, pJpgInfo) ;
releaseBuffer1:
releaseJpegHandle( hJpeg ) ;
return releaseReturn ;
}
///////////////////////////////////////////////////
MLong JPG_Decompress(HMSTREAM stream_handle, MLong lOutWidth, MLong lOutHeight,
ARCSOFT_JPEG_CALLBACK_PROC lpProc, MBool bReadThumbnail, MLong lUserParam) {
int releaseReturn = READ_JPEG_OK ;
MLong lWidth = lOutWidth ;
MLong lHeight = lOutHeight ;
/***************** used by hJpegInit *****************/
JPEG_HANDLE *hJpeg = MNull ;
/*********** used by huffmanDecodeInfoInit ***********/
HUFFMAN_QT_DECODER_INFO * pDecoderInfo = MNull ;
/************** used by callbackInfoInit *************/
LPJPG_CALLBACK_PARAM pCallbackParam = MNull ;
/**************** used by colorInfoInit **************/
LPDECOLOR_PARAM pDecolorParam = MNull ;
int StripsForCallback = 0 ;
if (stream_handle == MNull)
return READ_IMAGE_ERROR ;
if ( ( releaseReturn = hJpegInit( &hJpeg, stream_handle, &lWidth, &lHeight ) ) != READ_JPEG_OK )
goto releaseReturn3 ;
if ( ( releaseReturn = huffmanDecodeInfoInit( hJpeg, &pDecoderInfo ) ) != READ_JPEG_OK )
goto releaseReturn3 ;
if ( ( releaseReturn = callbackInfoInit(&pCallbackParam, hJpeg, lWidth, lHeight, lUserParam ) ) != READ_JPEG_OK )
goto releaseReturn3 ;
if ( !CALL_CALLBACK_FUNCTION( lpProc , pCallbackParam ) ) {
releaseReturn = NO_ENOUGH_MEMORY;
goto releaseReturn3;
}
if ( ( releaseReturn = colorInfoInit( hJpeg, &pDecolorParam, pCallbackParam, lWidth ) ) != READ_JPEG_OK )
goto releaseReturn3 ;
{
int stripsCount = 0 ;
int offset = 0 ;
int lastHeight = 0 ;
int runx = READ_JPEG_OK ;
int nResampledSize, nValidHigh, nDecodedWidth[3] ;
int nCurWidth = 0 ;
int nCurHeight = 0 ;
int YinHigh = 0 ;
int CinHigh = 0 ;
int Height = hJpeg -> pInfo -> Height ;
int Width = hJpeg -> pInfo -> Width ;
MShort * CresamleAddrH ;
MShort * CresamleAddrW ;
MShort * CnewHBegin ;
MShort * CnewHEnd ;
int *WideSamp = &( hJpeg -> pInfo -> WideSamp[0] ) ;
int *HighSamp = &( hJpeg -> pInfo -> HighSamp[0] ) ;
int oneMcuWidth = WideSamp[0] << 3 ;
int oneMcuHigh = HighSamp[0] << 3 ;
int nLineMCUCount = ( Width + oneMcuWidth - 1 ) >> (WideSamp[0]+2) ;
MBool bTerminated = MFalse ;
MByte *pYBuf, *pCbBuf, *pCrBuf, *pYResampled, *pCbResampled, *pCrResampled ;
MByte *index[3] ;
int YOneMcuBlockNumber = ( WideSamp[0] * HighSamp[0] ) << 6 ;
int COneMcuBlockNumber = ( WideSamp[1] * HighSamp[1] ) << 6 ;
int OneMcuBufferLen = ( YOneMcuBlockNumber + (COneMcuBlockNumber<<1) ) * sizeof(int) ;
int imageNewSize = 3 * lWidth * lHeight ;
int resetCount = hJpeg->pInfo->ResetLen;
#ifdef __WIN32__
int nExtra = BitsRoundTo4Bytes(lWidth*24) - lWidth*3 ;
#endif
float rateW = (float)Width/(float)lWidth;
float rateH = (float)Height/(float)lHeight;
int idctTag;
if (rateW < rateH)
rateW = rateH;
if (rateW < 1.7)
idctTag = 0;
else if (rateW < 3.5)
idctTag = 1;
else if (rateW < 7.0)
idctTag = 2;
else
idctTag = 3;
if (pCallbackParam->nextBufferSize >= imageNewSize ) {
StripsForCallback = Height / oneMcuHigh;
}
else {
StripsForCallback = (Height * pCallbackParam->nextBufferSize) / (oneMcuHigh * imageNewSize);
{
long l = oneMcuHigh * lHeight;
long n = (l * 1000) / Height;
long m = n / 1000;
if ((n - m * 1000) > 0) {
if (m > 0)
StripsForCallback -= 2 ;
else
StripsForCallback -= (Height +l - 1) / l + 1 ;
}
}
}
if (StripsForCallback <= 0) {
if (oneMcuHigh > lHeight) {
if (pCallbackParam->nextBufferSize >= ((lHeight * imageNewSize + Height - 1) / Height))
StripsForCallback = 1 ;
else {
releaseReturn = IMAGE_BUFFER_TOO_SMALL;
goto releaseReturn3;
}
}
else if (pCallbackParam->nextBufferSize >= ((oneMcuHigh * imageNewSize + Height - 1) / Height))
StripsForCallback = 1 ;
else {
releaseReturn = IMAGE_BUFFER_TOO_SMALL;
goto releaseReturn3;
}
}
pDecolorParam -> outRGB = pCallbackParam -> pBuffer ;
nDecodedWidth[0] = ((Width + (WideSamp[0]<<3)-1) >> (WideSamp[0]+2)) << (WideSamp[0]+2) ;
nDecodedWidth[2] = nDecodedWidth[1] = nDecodedWidth[0]>>(WideSamp[0]-1) ;
if ( HighSamp[0] == 2 ) {
CnewHBegin = hJpeg -> newH2Begin ;
CnewHEnd = hJpeg -> newH2End ;
CresamleAddrH = hJpeg -> resamleAddrH2 ;
}
else {
CnewHBegin = hJpeg -> newHBegin ;
CnewHEnd = hJpeg -> newHEnd ;
CresamleAddrH = hJpeg -> resamleAddrH ;
}
if ( WideSamp[0] == 2 )
CresamleAddrW = hJpeg -> resamleAddrW2 ;
else
CresamleAddrW = hJpeg -> resamleAddrW ;
pYBuf = ( MByte * )AMMemAlloc(MNull, YOneMcuBlockNumber * nLineMCUCount ) ;
pCbBuf = ( MByte * )AMMemAlloc(MNull, COneMcuBlockNumber * nLineMCUCount ) ;
pCrBuf = ( MByte * )AMMemAlloc(MNull, COneMcuBlockNumber * nLineMCUCount ) ;
nResampledSize = lWidth * oneMcuHigh;
pYResampled = (MByte*)AMMemAlloc(MNull, nResampledSize);
pCbResampled = (MByte*)AMMemAlloc(MNull, nResampledSize);
pCrResampled = (MByte*)AMMemAlloc(MNull, nResampledSize);
if ( !pYBuf || !pCbBuf || !pCrBuf || !pYResampled || !pCbResampled || !pCrResampled ) {
releaseReturn = NO_ENOUGH_MEMORY;
goto releaseReturn2;
}
index[0] = pYBuf ;
index[1] = pCbBuf ;
index[2] = pCrBuf ;
pCallbackParam -> lStatus = JPG_CALLBACK_RETURNIMGDATA ;
while( 1 )
{
int * data ;
MByte * pTmp ;
long i, j ;
int run ;
i = hJpeg -> bufferLen - pDecoderInfo -> dataPos;
if (runx != READ_JPEG_END) {
if ( ( i - DECODE_BUFFER_LEN ) <= 0 ) {
if ( ( runx = readFile(hJpeg, i, hJpeg->buffer, &hJpeg->buffer[pDecoderInfo -> dataPos] ) ) == READ_JPEG_ERROR ){
run = READ_IMAGE_ERROR ;
bTerminated = MTrue ;
goto breakWhile ;
}
else if ( runx == READ_JPEG_OK ) {
hJpeg -> bufferPos = 0 ;
pDecoderInfo -> dataPos = 0 ;
}
}
}
else {
if ((i = hJpeg -> bufferLen - pDecoderInfo -> dataPos) < 0 ) {
bTerminated = MTrue ;
goto breakWhile ;
}
}
data = hJpeg -> data ;
AMMemSet( data, 0 , OneMcuBufferLen ) ;
if (hJpeg->pInfo->ResetLen) {
if (resetCount <= 0) {
MByte valueByte;
if (hJpeg -> buffer[pDecoderInfo -> dataPos]==0xff) {
if (((valueByte=hJpeg -> buffer[pDecoderInfo -> dataPos+1])&0xd8)==0xd0) {
pDecoderInfo -> CurrentData = hJpeg -> buffer[pDecoderInfo -> dataPos + 2];
pDecoderInfo -> dataPos += 3;
if ( pDecoderInfo -> CurrentData == 0xff ) {
if ( hJpeg -> buffer[pDecoderInfo -> dataPos] != 0x00 ) {
bTerminated = MTrue;
goto breakWhile ;
}
else
pDecoderInfo -> dataPos ++;
}
pDecoderInfo -> bitPos = 8;
hJpeg -> Dc0[0]=0;
hJpeg -> Dc0[1]=0;
hJpeg -> Dc0[2]=0;
hJpeg -> Dc0[3]=0;
resetCount = hJpeg->pInfo->ResetLen ;
}
else if ( valueByte != 0x00 ) {
bTerminated = MTrue;
goto breakWhile ;
}
}
}
}
run = decode_MCU( hJpeg, pDecoderInfo ) ;
resetCount -- ;
if ( run == DECODE_JPEG_OK ) {
// for( i = 0 ; i < pDecoderInfo -> HuffTabNum ; i ++ ) {
if (idctTag == 3) {
for( i = 0 ; i < 3 ; i ++ ) {
int k ;
for (j=0 ; j<HighSamp[i] ; j++) {
pTmp = index[i] + (nDecodedWidth[i]<<3)*j ;
for (k=0 ; k<WideSamp[i] ; k++) {
JPG_IdctIntFast1x1(pDecoderInfo -> Qtab[i], data, hJpeg -> ColorLimitTable, pTmp, nDecodedWidth[i]) ;
pTmp += 8 ;
data += 64 ;
}
}
}
}
else if (idctTag == 2) {
for( i = 0 ; i < 3 ; i ++ ) {
int k ;
for (j=0 ; j<HighSamp[i] ; j++) {
pTmp = index[i] + (nDecodedWidth[i]<<3)*j ;
for (k=0 ; k<WideSamp[i] ; k++) {
JPG_IdctIntFast2x2(pDecoderInfo -> Qtab[i], data, hJpeg -> ColorLimitTable, pTmp, nDecodedWidth[i]) ;
pTmp += 8 ;
data += 64 ;
}
}
}
}
else if (idctTag == 1) {
for( i = 0 ; i < 3 ; i ++ ) {
int k ;
for (j=0 ; j<HighSamp[i] ; j++) {
pTmp = index[i] + (nDecodedWidth[i]<<3)*j ;
for (k=0 ; k<WideSamp[i] ; k++) {
JPG_IdctIntFast4x4(pDecoderInfo -> Qtab[i], data, hJpeg -> ColorLimitTable, pTmp, nDecodedWidth[i]) ;
pTmp += 8 ;
data += 64 ;
}
}
}
}
else {
for( i = 0 ; i < 3 ; i ++ ) {
int k ;
for (j=0 ; j<HighSamp[i] ; j++) {
pTmp = index[i] + (nDecodedWidth[i]<<3)*j ;
for (k=0 ; k<WideSamp[i] ; k++) {
JPG_IdctIntFast(pDecoderInfo -> Qtab[i], data, hJpeg -> ColorLimitTable, pTmp, nDecodedWidth[i]) ;
pTmp += 8 ;
data += 64 ;
}
}
}
}
index[0] += oneMcuWidth ;
index[1] += 8 ;
index[2] += 8 ;
nCurWidth += oneMcuWidth ;
}
else if ( ( run == DECODE_JPEG_END ) || ( run == DECODE_JPEG_HUFFMAN_ERROR ) ) {
bTerminated = MTrue;
}
//
// call decolorchange and callback function if a lines block is finished
if(nCurWidth >= nDecodedWidth[0] || bTerminated) {
//
// resample and decolorchange to get RGB data of a lines block
int lineStart = hJpeg -> newHBegin[YinHigh] ;
MShort * addrH = hJpeg -> resamleAddrH + lineStart ;
nValidHigh = hJpeg -> newHEnd[YinHigh + oneMcuHigh - 1] - lineStart ;
if ( * addrH < YinHigh )
addrH ++ ;
else
nValidHigh ++ ;
if (nValidHigh > 0)
resample( hJpeg -> resamleAddrW, addrH, pYBuf - YinHigh * nDecodedWidth[0], pYResampled, nDecodedWidth[0], nValidHigh, lWidth ) ;
YinHigh += oneMcuHigh ;
pDecolorParam -> pY = pYResampled;
i = lWidth * nValidHigh;
#ifdef __WIN32__
pDecolorParam -> OutLineCount = nValidHigh ;
#endif
if (COneMcuBlockNumber) { // 24 bits image
// for test speed
// CountTime_Start() ;
addrH = CresamleAddrH + CnewHBegin[CinHigh] ;
if ( * addrH < CinHigh )
addrH ++ ;
j = CinHigh * nDecodedWidth[1];
if (nValidHigh > 0) {
resample( CresamleAddrW, addrH, pCbBuf - j, pCbResampled, nDecodedWidth[1], nValidHigh, lWidth ) ;
resample( CresamleAddrW, addrH, pCrBuf - j, pCrResampled, nDecodedWidth[1], nValidHigh, lWidth ) ;
}
CinHigh += 8 ;
pDecolorParam -> pCb = pCbResampled;
pDecolorParam -> pCr = pCrResampled;
if (pDecoderInfo->HuffTabNum == 4) {
JPG_YCMK_DeColor( i, pDecolorParam, offset) ;
}
else {
JPG_TrueColor_DeColor( hJpeg -> ColorLimitTable, i, pDecolorParam, offset) ;
}
// for test speed
// CountTime_End(nIndex) ;
}
else { // grayscale image
JPG_GrayScale_DeColor( i, pDecolorParam, offset) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -