📄 jpegdecoder.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 + -