⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpeg.c

📁 JPEG解压软件,包含PC端的测试程序,程序结构比较清晰
💻 C
📖 第 1 页 / 共 2 页
字号:

#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 + -