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

📄 jpegdecoder.c

📁 JPEG解压软件,包含PC端的测试程序,程序结构比较清晰
💻 C
字号:

#include "jpegDecoder.h"

#define DEQUANTIZE_SHIFT_BITS			( 8 - JPEG_QUANTIZE_COE_REM_BITS )

////////////////////////////////////////////////////

int readFile(JPEG_HANDLE * hJpeg, int restLen, MByte *pBufStart, MByte *pBufNow ) {

	if ( hJpeg -> restBlock > 0 ) {
		if ( restLen < 0 ) 
			return READ_JPEG_ERROR ; 
		else if (restLen > 0 )
			AMMemMove(pBufStart, pBufNow, restLen) ;

		hJpeg -> restBlock -- ; 
		hJpeg -> bufferLen	= restLen + AMStreamRead( hJpeg -> pStream, &pBufStart[restLen], JPEG_BUFFER_LEN - DECODE_BUFFER_LEN ) ;
		if ( hJpeg -> bufferLen <= 0 ) 
			return READ_JPEG_ERROR ; 
		else
			return READ_JPEG_OK ;
	}
	else
		return READ_JPEG_END ;
}

int JPG_ReadHead( JPEG_HANDLE * hJpeg )
{
	register MByte *buffer		= hJpeg -> buffer ;
	register MByte *pBuf		= buffer ;
	register MLong bufferLen	= hJpeg -> bufferLen ;
	register int len ;
	int      sign ;
	int      run	= READ_JPEG_OK ;
	int      offsetLen=0;

	{
		MByte *pBufEnd	= buffer + bufferLen;
begin:
		while (( *pBuf != 0xff ) && (pBuf < pBufEnd))
			pBuf ++ ;
		while ((*pBuf == 0xff) && (pBuf < pBufEnd)) {
			pBuf ++ ;
			if ((*pBuf != 0xd8 )&& (pBuf < pBufEnd)) {
				pBuf ++ ;
				goto begin;
			}
		}
		if (pBuf >= pBufEnd) {
			return READ_JPEG_ERROR ;
		}
	}

	pBuf ++ ;

	while( ( pBuf - buffer ) < bufferLen ) {

		while ( *pBuf == 0xff )
			pBuf ++ ;
		if ( pBuf[-1] != 0xff)
				return READ_JPEG_ERROR ;

		hJpeg -> bufferPos	= pBuf - buffer + 1 ;

		sign	= 0;

		switch( *pBuf ) {

 		case 0xdb:
			if ((hJpeg->bufferPos + 67) >= bufferLen)
				return READ_JPEG_DQT_ERROR;
			if( JPG_ReadQTable( hJpeg ) != READ_JPEG_OK )
				return READ_JPEG_DQT_ERROR ;
			pBuf	= buffer + hJpeg -> bufferPos ;
			break;
		
		case 0xc0:
			if ((hJpeg->bufferPos + 17) >= bufferLen)
				return READ_JPEG_SOF0_ERROR;
			if( JPG_ReadSOf0( hJpeg ) != READ_JPEG_OK )
				return READ_JPEG_SOF0_ERROR;
			pBuf	= buffer + hJpeg -> bufferPos ;
			break;
		case 0xc2:
			return READ_JPEG_NO_IMAGE_ERROR ;
		case 0xdd:
			if ((hJpeg->bufferPos + 4) >= bufferLen)
				return READ_JPEG_DRI_ERROR;
			if( JPG_ReadDri( hJpeg ) != READ_JPEG_OK )
				return READ_JPEG_DRI_ERROR;
			pBuf	= buffer + hJpeg -> bufferPos ;
			break;

		case 0xc4:
			if ((hJpeg->bufferPos + 20) >= bufferLen)
				return READ_JPEG_DHT_ERROR;
			if( JPG_ReadHTable( hJpeg ) != READ_JPEG_OK )
				return READ_JPEG_DHT_ERROR;
			pBuf	= buffer + hJpeg -> bufferPos ;
			break;

		case 0xda:
			if ((hJpeg->bufferPos + 8) >= bufferLen)
				return READ_JPEG_SOS_ERROR;
			if( JPG_ReadSos( hJpeg ) != READ_JPEG_OK )
				return READ_JPEG_SOS_ERROR ;
			pBuf	= buffer + hJpeg -> bufferPos ;
			if ( hJpeg -> decodeStatus == DECODING_JPEG ) {
				hJpeg -> jpegBeginPos		= hJpeg -> bufferPos ;

				return READ_JPEG_OK ;
			}
			else if ( hJpeg -> decodeStatus == DECODING_THUMBNAIL ) {
				hJpeg -> thumbnailBeginPos	= hJpeg -> bufferPos ;
				return READ_JPEG_OK ;
			}
			else
				return READ_JPEG_SOS_ERROR ;

		case 0xd9:
			return READ_JPEG_NO_IMAGE_ERROR ;

		default:
			if (*pBuf == 0xe0) {
				hJpeg -> pInfo -> type		= JPEG_TYPE_JFIF ;	
				hJpeg -> thumbnailBeginPos	= pBuf - buffer + 1;
			}
			else if (*pBuf == 0xe1) {
				hJpeg -> pInfo -> type		= JPEG_TYPE_EXIF ;
				hJpeg -> thumbnailBeginPos	= pBuf - buffer + 1;
			}

			if ( ( *pBuf != 1 ) && ( ( *pBuf & 0xf8 ) != 0xd0 ) ) {
				pBuf++ ;
				len		= ( * pBuf ++ ) << 8 ;
				len		= ( len | *pBuf ) - 1 ;
				sign	= 1 ;
			}
 			break;
		}

		if ( sign == 1 ) {
			int leny	= hJpeg -> bufferLen - (pBuf - buffer);
			if (leny >= 0) {
				int lenx	= len - leny;
				int rem		= lenx / (JPEG_BUFFER_LEN - DECODE_BUFFER_LEN);

				if (lenx < 0) {
					pBuf	+= len ;
				}
				else if ( rem == 0) {
					pBuf	+= leny ;
					offsetLen= lenx ;
				}
				else 
				{
					if ( hJpeg -> restBlock <= 0 )
						return READ_JPEG_END ;
					else if (rem > 0) {
						leny	= rem * (JPEG_BUFFER_LEN - DECODE_BUFFER_LEN) ;
						if (AMStreamSeek(hJpeg -> pStream, 0, leny + AMStreamTell(hJpeg -> pStream) ) < 0 )
							return READ_JPEG_ERROR ;
						else
							hJpeg -> restBlock -= rem ; 
					}
					else
						leny	= 0 ;

					if ( hJpeg -> restBlock > 0 ) {
						if ( (run = readFile( hJpeg, 0, buffer, pBuf )) == READ_JPEG_ERROR )
							return READ_JPEG_ERROR ;
						else {
							bufferLen	= hJpeg -> bufferLen ;
							pBuf	= buffer + lenx - leny;
						}
					}
					else
						return READ_JPEG_END ;
				}
			}
			else
				pBuf		+= len ;
		}

		len		= bufferLen - ( pBuf - buffer ) ;
		if ( ( len < DECODE_BUFFER_LEN ) && ( hJpeg -> restBlock > 0 ) ) {

			if ( (run = readFile( hJpeg, len, buffer, pBuf )) == READ_JPEG_ERROR )
				return READ_JPEG_ERROR ;
			else {
				pBuf	= buffer + offsetLen;
				offsetLen	= 0;
			}
		}

		bufferLen	= hJpeg -> bufferLen ;

	}
	return READ_JPEG_NO_IMAGE_ERROR ;
}


int JPG_ReadQTable( JPEG_HANDLE * hJpeg )
{
	MByte CoeQtablex[]	= {
		0x20,0x2c,0x2c,0x2a,0x3e,0x2a,0x25,0x3a,
		0x3a,0x25,0x20,0x34,0x37,0x34,0x20,0x19,
		0x2c,0x31,0x31,0x2c,0x19,0x11,0x23,0x2a,
		0x2c,0x2a,0x23,0x11,0x09,0x18,0x21,0x25,
		0x25,0x21,0x18,0x09,0x0c,0x17,0x1e,0x20,
		0x1e,0x17,0x0c,0x0c,0x14,0x19,0x19,0x14,
		0x0c,0x0a,0x11,0x14,0x11,0x0a,0x09,0x0e,
		0x0e,0x09,0x07,0x09,0x07,0x05,0x05,0x02
	};
	MByte zigNumx[]	= {
		 0, 1, 8,16, 9, 2, 3,10,17,24,32,25,18,11, 4, 5,
		12,19,26,33,40,48,41,34,27,20,13, 6, 7,14,21,28,
		35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,
		58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63,
		63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63
	};

	register MByte *pBuf		= hJpeg -> buffer + hJpeg -> bufferPos ;
	MByte *pBufEnd				= hJpeg -> buffer + hJpeg -> bufferLen ;
	register MByte * zigNum		= zigNumx ;

	register int *pQt ;
	register int len ;
	register int ID ;
	register int i ;
	register int zigId ;

	AMMemMove( hJpeg -> zigNum, zigNum, 64 + 16 ) ;

	len		= *pBuf++ << 8 ;
	len		= ( len | *pBuf++ ) - 2 ;
	while ( len > 0 ) {
		if ( ( ID = *pBuf & 0x0f ) > 2 )
			return READ_JPEG_DQT_ERROR ;

		len -- ;

		pQt		=  &(hJpeg -> pInfo -> Qtab[ID][0]) ;

		if ( ( ( * pBuf ++ ) & 0xf0 ) == 0 ) {

			if ((pBuf + 64) >= pBufEnd)
				return READ_JPEG_DQT_ERROR;
			for ( i = 0; i < 64; i++ ) {
				zigId		= zigNum[i] ;
				//pQt[zigId]	=  *pBuf++;
				pQt[zigId]	=  ( (*pBuf++) * CoeQtablex[i] ) >> DEQUANTIZE_SHIFT_BITS ;
			}
			len		-= 64 ;
		}
		else {
			if ((pBuf + 128) >= pBufEnd)
				return READ_JPEG_DQT_ERROR;
			for ( i = 0; i < 64; i++ ) {
				zigId		= zigNum[i] ;
				pQt[zigId]	= ( *pBuf ++ )  << 8 ;
				pQt[zigId]	=  ( ( pQt[zigNum[i]] | *pBuf ++ ) * CoeQtablex[i] ) >> DEQUANTIZE_SHIFT_BITS ;
				//pQt[zigId]	= ( *pBuf ++ )  << 8 ;
				//pQt[zigId]	=  pQt[zigId] | *pBuf ++ ;
			}
			len -= 128 ;
		}
	}
	if( len != 0 )
		return READ_JPEG_DQT_ERROR;
	else {
		if (pBuf >= pBufEnd)
			return READ_JPEG_DQT_ERROR;
		hJpeg -> bufferPos	= pBuf - hJpeg -> buffer ;
		return READ_JPEG_OK;
	}
}

int JPG_ReadSOf0( JPEG_HANDLE * hJpeg )
{
	register MByte *pBuf		= hJpeg -> buffer + hJpeg -> bufferPos ;
	register MLong i ;
	register int Wsamp, Hsamp ;
	register int Height, Width ;
	register MLong len ;
	register MByte c ;

	len			= ( *pBuf ++ )  << 8 ;
	len			= ( len | ( *pBuf ++ ) ) - 2 ;

	if ( ( len <= 0 ) || ( ( *pBuf++ ) != 8 ) )   //every color precision=8 bits
		return READ_JPEG_SOF0_ERROR ;

	Height		= ( *pBuf ++ )  << 8 ;
	Height		|= *pBuf ++ ;

	Width		= ( *pBuf ++ )  << 8 ;
	Width		|= *pBuf ++ ;
 	
 	if( Width == 0 || Height == 0 )
		return READ_JPEG_SOF0_ERROR ;

	hJpeg -> pInfo -> Width		= Width ;
	hJpeg -> pInfo -> Height	= Height ;

	len			= *pBuf ++ ;    //components=1, white and black
	                            //3, YCbCr
	                            //4, cmyk
    if ( len == 1 )
		hJpeg -> pInfo -> colorBits		= 8 ;
	else
		hJpeg -> pInfo -> colorBits		= 24 ;

	for( i = len; i > 0; i -- ) {

		pBuf ++ ;
		c = len - i + 1;

		Wsamp	= *pBuf >> 4 ;
		Hsamp	= ( *pBuf++ ) & 0x0f ;

 		hJpeg -> pInfo -> qtID[c - 1]		= *pBuf++ ;

		if(Wsamp == 0 || Hsamp == 0)
			return READ_JPEG_SOF0_ERROR ;

		hJpeg -> pInfo -> WideSamp[c - 1]	= Wsamp ;
		hJpeg -> pInfo -> HighSamp[c - 1]	= Hsamp ;
	}
	
	hJpeg -> bufferPos	= pBuf - hJpeg -> buffer ;
	if (hJpeg->bufferPos >= hJpeg->bufferLen)
		return READ_JPEG_SOF0_ERROR;
	else
		return READ_JPEG_OK;
} 

int JPG_ReadDri( JPEG_HANDLE * hJpeg ) {

	register MByte *pBuf	= hJpeg -> buffer + hJpeg -> bufferPos ;

	if ( ( pBuf[0] != 0 ) || ( pBuf[1] != 4 ) )
		return READ_JPEG_DRI_ERROR ;

 	hJpeg -> pInfo -> ResetLen	= (pBuf[2] << 8 ) | pBuf[3];
	hJpeg -> bufferPos			+= 4;

	if (hJpeg->bufferPos >= hJpeg->bufferLen)
		return READ_JPEG_DRI_ERROR;
	else
		return READ_JPEG_OK;

}

int JPG_ReadHTable( JPEG_HANDLE * hJpeg ) {

	register MByte *pBuf	= hJpeg -> buffer + hJpeg -> bufferPos ;
	MByte *pBufEnd			= hJpeg -> buffer + hJpeg -> bufferLen ;
	register int len ;
	register int i ;

	register int go ;
	register int point ;
	register unsigned int hcode ;

	register int * HufTail ;
	register int * HufOffset ;
	register int * HufTab ;
	
	len		= ( *pBuf ++ )  << 8 ;
	len		= ( len | ( *pBuf ++ ) ) - 2 ;

	while( len > 0 ) {

		len		-= 17 ;
		go		= * pBuf & 0x0f ;
		i		= * pBuf ++ >> 4 ;
		if( go > 2 )
			return READ_JPEG_DHT_ERROR ;

		hcode	= 0 ;
		if( i == 0 ) {
			point	= 0 ;
			if ((pBuf + 16) >= pBufEnd)
				return READ_JPEG_DHT_ERROR;

			HufTail		= hJpeg -> pJpegInfo -> HufDcTail[go];
			HufOffset	= hJpeg -> pInfo -> HufDcOffset[go];

			AMMemSet(HufTail, -1 , 16 * sizeof(int) ) ;
			HufTail[16]	= 0x100000;

			for ( i = 0; i < 16; i++ ) {
 				//HufTail[i]	= * pBuf ;
           		if ( *pBuf > 0 ) {
					HufOffset[i]= point - hcode ;
					hcode	+= * pBuf ;
					HufTail[i]	= hcode - 1 ;
					if ( point == 0 ) {
						hJpeg -> pInfo -> minDcBits[go] = i + 1 ;
					}
					point	+= * pBuf ++ ;
            		hcode <<= 1 ;
            	}
				else {
					hcode <<= 1 ;
					pBuf ++ ;
				}
			}

			len		-= point ;

			if ((pBuf + point) >= pBufEnd)
				return READ_JPEG_DHT_ERROR;
			HufTab	= hJpeg -> pInfo -> HufTabDc[go];
			for (i = 0; i < point; i++ ) {
				HufTab[i]	= * pBuf ++ ;
			}
		}
		else {
			point	= 0 ;
			if ((pBuf + 16) >= pBufEnd)
				return READ_JPEG_DHT_ERROR;

			HufTail		= hJpeg -> pJpegInfo -> HufAcTail[go];
			HufOffset	= hJpeg -> pInfo -> HufAcOffset[go];

			AMMemSet(HufTail, -1 , 16 * sizeof(int) ) ; 
			HufTail[16]	= 0x100000;
			for ( i = 0; i < 16; i++ ) {
 				//HufTail[i]	= * pBuf ;
            	if ( * pBuf > 0 ) {
					HufOffset[i]= point - hcode ;
					hcode	+= * pBuf ;
					HufTail[i]	= hcode - 1 ;
					if ( point == 0 ) {
						hJpeg -> pInfo -> minAcBits[go] = i + 1 ;
					}
					point	+= * pBuf ++ ;
            		hcode	<<= 1 ;
				}
				else {
					hcode	<<= 1 ;
					pBuf ++ ;
				}
			}
			len		-= point ;
			if ((pBuf + point) >= pBufEnd)
				return READ_JPEG_DHT_ERROR;
			HufTab	= hJpeg -> pInfo -> HufTabAc[go];
			for ( i = 0; i < point; i++ ) {
				HufTab[i]	= * pBuf ++ ;
			}
		}
	}
	if ( len != 0 ) 
		return READ_JPEG_DHT_ERROR ;
	
	hJpeg -> bufferPos	= pBuf - hJpeg -> buffer ;
	if (hJpeg->bufferPos >= hJpeg->bufferLen)
		return READ_JPEG_DHT_ERROR;
	else
		return READ_JPEG_OK;
}

int JPG_ReadSos( JPEG_HANDLE * hJpeg ) {

	register MByte *pBuf		= hJpeg -> buffer + hJpeg -> bufferPos ;
	register int i ;
	register MByte c ;
	register int hufDcID ;
	register int hufAcID	;
	int HuffTabNum ;
	int len ;

	len		= ( *pBuf ++ )  << 8 ;
	len		= ( len | ( *pBuf ++ ) ) - 2 ;

	HuffTabNum	= *pBuf ++ ;
	if( HuffTabNum < 1 || HuffTabNum > 4 )
		return READ_JPEG_SOS_ERROR ;

	hJpeg -> pInfo -> HuffTabNum = HuffTabNum ;

	for( i = HuffTabNum; i > 0 ; i-- ) {
		
		pBuf ++ ;
		c = HuffTabNum - i + 1;

		hufDcID	= * pBuf >> 4 ;
		hufAcID	= ( * pBuf ++ ) & 0x0f ;
		if ( hufDcID > 2 || hufAcID > 2 )
			return READ_JPEG_SOS_ERROR ;		
		hJpeg -> pInfo -> hufDcID[c - 1]	= hufDcID ;
		hJpeg -> pInfo -> hufAcID[c - 1]	= hufAcID ;
	}

	pBuf += 3 ;
	hJpeg -> bufferPos	= pBuf - hJpeg -> buffer ;
	if (hJpeg->bufferPos >= hJpeg->bufferLen)
		return READ_JPEG_SOS_ERROR;
	else
		return READ_JPEG_OK;
}


MVoid JPG_ReadJfifHead( JPEG_HANDLE * hJpeg ) {

	/*
	MByte	* pBuf	= hJpeg -> buffer + hJpeg -> thumbnailBeginPos ;
	MLong	len ;

	len				= ( *pBuf ++ )  << 8 ;
	len				= ( len | ( *pBuf ++ ) ) - 2 ;

	if ( ( *pBuf == 0x4a ) && 
		( *( pBuf + 1 ) == 0x46 ) && 
		( *( pBuf + 4 ) == 0x00 ) ) {

		if 	( ( *( pBuf + 2 ) == 0x49 ) && 
			( *( pBuf + 3 ) == 0x46 ) &&
			( *( pBuf + 5 ) == 0x01 ) &&
			( *( pBuf + 6 ) == 0x02 ) ) {
			pBuf		+= 7 + 5 ;
	
			hJpeg -> thumbWidth			= *pBuf++ ;
			hJpeg -> thumbHeight		= *pBuf++ ;
			if ( ( hJpeg -> thumbWidth == 0 ) || ( hJpeg -> thumbHeight == 0 ) ) {
				hJpeg -> thumbWidth		= 0 ;
				hJpeg -> thumbHeight	= 0 ;
				return ;
			}
			hJpeg -> thumbnailStatus	= MTrue;
			hJpeg -> thumbnailBeginPos	= pBuf - hJpeg -> buffer ;
			hJpeg -> thumbBitsStatus	= THUMBNAIL_STATUS_3_BYTES ;
			return ;
		}
		else if ( ( *( pBuf + 2 ) == 0x58 ) && 
			( *( pBuf + 3 ) == 0x58 ) ) {
			pBuf			+= 5 ;
			hJpeg -> thumbBitsStatus	= *pBuf++ ;
			hJpeg -> thumbnailStatus	= MTrue;
			hJpeg -> thumbnailBeginPos	= pBuf - hJpeg -> buffer ;
			if ( hJpeg -> thumbBitsStatus == THUMBNAIL_STATUS_JPEG ) {

			}
			else if ( hJpeg -> thumbBitsStatus == THUMBNAIL_STATUS_1_BYTE ) {

			}
			else if ( hJpeg -> thumbBitsStatus == THUMBNAIL_STATUS_3_BYTES) {

			}
			else {
				hJpeg -> thumbnailStatus	= MFalse;
				hJpeg -> thumbnailBeginPos	= 0 ;
				hJpeg -> thumbBitsStatus	= 0 ;
				return ;
			}
		}
		else
			return ;
	}
	else
		return ;
		*/
}

MVoid JPG_ReadExifHead( JPEG_HANDLE * hJpeg ) {
}
MBool JPG_GetJfifThumbnail( JPEG_HANDLE * hJpeg ) {
	return 1;
}
MBool JPG_GetExifThumbnail( JPEG_HANDLE * hJpeg ) {
	return 1;
}

MVoid releaseJpegHandle( JPEG_HANDLE * hJpeg ) {

	JpegMemFree(hJpeg->buffer);
	JpegMemFree(hJpeg->pJpegInfo);
	JpegMemFree(hJpeg->ColorLimitTable);
	JpegMemFree(hJpeg->resamleAddrH);
	JpegMemFree(hJpeg->resamleAddrW);
	JpegMemFree(hJpeg->newHBegin);
	JpegMemFree(hJpeg->newHEnd);
	JpegMemFree(hJpeg->resamleAddrH2);
	JpegMemFree(hJpeg->resamleAddrW2);
	JpegMemFree(hJpeg->newH2Begin);
	JpegMemFree(hJpeg->newH2End);
	JpegMemFree(hJpeg);

}

MVoid JpegMemFree(MVoid *pMem) {
	if (pMem)
		AMMemFree(MNull, pMem);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -