📄 jpegdecoder.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// JPEGDecoder.c
//
// DESCRIPTION
// Top level interfaces for JPEG decoder.
//
//
///////////////////////////////////////////////////////////////////////////////
#include "irom_PlatformDefines.h"
#include "JPEGFieldDec.h"
#include "YCbCr444.h"
#include "YCbCr422.h"
#include "YCbCr420.h"
#include "JPEGDecoder.h"
#include "JPEGHuffmanDec.h"
#include "irom_JPEGTable.h"
#include "JPEGIDCT.h"
#include "irom_jpegheader.h"
// -------------------------------------------------------------------------
// JPEGSaveMCU FindSaveMCUFunction
//
// Find an appropriate function for saving the decoded MCUs to the buffer
// for decoded image.
// -------------------------------------------------------------------------
JPEGSaveMCU FindSaveMCUFunction
(
JPEGFieldDec *decodedImage
)
{
JPEGSaveMCU SaveMCUFunction;
// instead, we have to use a non-MMX function
switch (decodedImage->outputCSF)
{
case CSF_OUTPUT_RGB:
switch (decodedImage->numBits)
{
#if SUPPORT_RGB555
case 16:
switch (decodedImage->jpegCSF)
{
#if SUPPORT_YUV444
case CSF_JPEG_YCBCR_444:
SaveMCUFunction = YCbCr444ToRGB555;
break;
#endif
#if SUPPORT_YUV422
case CSF_JPEG_YCBCR_422:
SaveMCUFunction = YCbCr422ToRGB555;
break;
#endif
#if SUPPORT_YUV420
case CSF_JPEG_YCBCR_420:
SaveMCUFunction = YCbCr420ToRGB555;
break;
#endif
}
break;
#endif
#if SUPPORT_RGB24
case 24:
switch (decodedImage->jpegCSF)
{
#if SUPPORT_YUV444
case CSF_JPEG_YCBCR_444:
SaveMCUFunction = YCbCr444ToRGB24;
break;
#endif
#if SUPPORT_YUV422
case CSF_JPEG_YCBCR_422:
SaveMCUFunction = YCbCr422ToRGB24;
break;
#endif
#if SUPPORT_YUV420
case CSF_JPEG_YCBCR_420:
SaveMCUFunction = YCbCr420ToRGB24;
break;
#endif
}
break;
#endif
#if SUPPORT_RGB32
case 32:
switch (decodedImage->jpegCSF)
{
#if SUPPORT_YUV444
case CSF_JPEG_YCBCR_444:
SaveMCUFunction = YCbCr444ToRGB32;
break;
#endif
#if SUPPORT_YUV422
case CSF_JPEG_YCBCR_422:
SaveMCUFunction = YCbCr422ToRGB32;
break;
#endif
#if SUPPORT_YUV420
case CSF_JPEG_YCBCR_420:
SaveMCUFunction = YCbCr420ToRGB32;
break;
#endif
}
break;
#endif
default:
break;
}
break;
#if SUPPORT_RGB565
case CSF_OUTPUT_RGB565:
switch (decodedImage->jpegCSF)
{
#if SUPPORT_YUV444
case CSF_JPEG_YCBCR_444:
SaveMCUFunction = YCbCr444ToRGB565;
break;
#endif
#if SUPPORT_YUV422
case CSF_JPEG_YCBCR_422:
SaveMCUFunction = YCbCr422ToRGB565;
break;
#endif
#if SUPPORT_YUV420
case CSF_JPEG_YCBCR_420:
SaveMCUFunction = YCbCr420ToRGB565;
break;
#endif
default:
SaveMCUFunction = NullFunction;
}
break;
#endif
default:
SaveMCUFunction = NullFunction;
break;
}
return SaveMCUFunction;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGDecoderConstruct
//
// DESCRIPTION
// Construct an JPEG decoder. This function must be called before the
// JPEG decoder can be used.
//
// INPUTS
// jpegDecoder - pointer to JPEGDecoder structure
//
// OUTPUTS
// jpegDecoder - initializes fields in this structure
//
// RETURN VALUE
// Always returns JPEG_OK
//
/////////////////////////////////////////////////////////////////////////////
int JPEGDecoderConstruct
(
JPEGDecoder *jpegDecoder
)
{
JPEGSegmentsConstruct(&jpegDecoder->jpegSegments);
JPEGReadHuffTable((OP_UINT8 *)JPEGDHTSeg + 4, 0x01A0, &jpegDecoder->jpegSegments,
jpegDecoder->AllocateMemory, jpegDecoder->Deallocate);
// construct Huffman table that will be used in decoding
JPEGPrepareHuffTables(&jpegDecoder->jpegSegments, jpegDecoder->AllocateMemory,
jpegDecoder->Deallocate);
JPEGMCUConstruct(&jpegDecoder->jpegMCU);
return JPEG_OK;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGDecoderRelease
//
// DESCRIPTION
// Release an JPEG decoder. This should be last function called if the
// client non longer needs the JPEG decoder.
//
// INPUTS
// jpegDecoder - pointer to JPEGDecoder structure
//
// OUTPUTS
// jpegDecoder - free memory in this structure
//
// RETURN VALUE
// Always returns JPEG_OK
//
/////////////////////////////////////////////////////////////////////////////
int JPEGDecoderRelease
(
JPEGDecoder *jpegDecoder
)
{
JPEGSegmentsRelease(&jpegDecoder->jpegSegments, jpegDecoder->Deallocate);
return JPEG_OK;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// FirstFrameInitialize
//
// DESCRIPTION
// Perform the initialization on the decoder based on the format of the
// decoded frame. The decoder may be reuqired to decode a frame to
// different formats. This function is called whenever the decodedFormat
// is not equal to the format of the previous decoded frame.
//
// INPUTS
// jpegDecoder - pointer to JPEGDecoder structure
// decodedFormat - output image format
// numBits - number of bits per pixel
// sizex - width of output image
// sizey - height of output image
// interlaced - whether the image is interlaced
//
// OUTPUTS
// jpegDecoder - initializes fields in this structure
//
// RETURN VALUE
// Returns JPEG_OK if successful, returns an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
int FirstFrameInitialize
(
JPEGDecoder *jpegDecoder,
int decodedFormat,
int numBits,
int sizex,
int sizey,
int interlaced
)
{
int errCode;
JPEGFrameHeader *pFrameHeader;
JPEGFieldDec *decodedImage;
// have shorter notation
decodedImage = &(jpegDecoder->decodedImage);
// config the objects within JPEG decoder
JPEGMCUConfig(&jpegDecoder->jpegSegments, &jpegDecoder->jpegMCU);
// config the MCU storing structure
decodedImage->outputCSF = decodedFormat;
decodedImage->numBits = numBits;
pFrameHeader = &(jpegDecoder->jpegSegments.frameHeader);
errCode = JPEGFieldDecConfig(decodedImage, pFrameHeader, sizex, sizey, interlaced);
if (errCode != JPEG_OK)
{
return errCode;
}
return JPEG_OK;
}
/////////////////////////////////////////////////////////////////////////////
// NAME
// JPEGFieldDecode
//
// DESCRIPTION
// Decode one field of an JPEG frame.
//
// INPUTS
// byteBuffer - pointer to input byte buffer
// jpegDecoder - pointer to JPEGDecoder structure
//
// OUTPUTS
// jpegDecoder - initializes fields in this structure
//
// RETURN VALUE
// Returns JPEG_OK if successful, returns an error code otherwise.
//
/////////////////////////////////////////////////////////////////////////////
int JPEGFieldDecode
(
ByteBuffer *byteBuffer,
JPEGDecoder *jpegDecoder,
OP_BOOLEAN func(OP_UINT16 x, OP_UINT16 y)
)
{
OP_UINT8 *imageBlocks;
OP_UINT16 x;
OP_UINT16 y;
OP_UINT32 restartInterval;
OP_UINT32 prevRSTMarker;
OP_UINT32 numAllMCUs;
OP_UINT32 numMCUsDecoded;
JPEGSegments *jpegSegments;
JPEGMCU *jpegMCU;
JPEGFieldDec *decodedImage;
JPEGSaveMCU SaveMCUFunction;
jpegSegments = &jpegDecoder->jpegSegments;
jpegMCU = &jpegDecoder->jpegMCU;
decodedImage = &jpegDecoder->decodedImage;
SaveMCUFunction = jpegDecoder->SaveMCUFunction;
restartInterval = jpegSegments->restartInterval;
numAllMCUs = decodedImage->numMCUs;
numMCUsDecoded = 0;
x = 0;
y = 0;
if (restartInterval == 0)
{
restartInterval = numAllMCUs;
}
// decode the
prevRSTMarker = JPEG_MARKER_RST7;
JPEGMCUInitialize(jpegMCU);
imageBlocks = jpegMCU->imageMCUBuf;
while (numMCUsDecoded < numAllMCUs)
{
int nextChar;
int rstIndex;
rstIndex = 0;
do
{
// check if we should continue
if(func != OP_NULL)
{
if(!func(x, y))
{
return JPEG_OK;
}
}
// decode one MCU, Huffman -> de-quantization -> IDCT
JPEGMCUDecode(byteBuffer, jpegMCU, jpegNaturalOrder, JPEGDecodeRareSymbol,
JPEGIDCT_int, NextByteFromBuf);
// perform color space conversion and save the MCU
SaveMCUFunction(imageBlocks, decodedImage);
// update decoded pixel coordinate
x = x + decodedImage->mcuSizeX;
if (decodedImage->mcuBuf >= decodedImage->mcuBufRowEnd)
{
// jump to next MCU row
decodedImage->mcuBufRow += decodedImage->mcuRowWidth; // 8 lines
decodedImage->mcuBufRowEnd += decodedImage->mcuRowWidth; // 8 lines
decodedImage->mcuBuf = decodedImage->mcuBufRow;
// update y coordinate
y = y + decodedImage->mcuSizeY;
// reset x coordinate
x = 0;
}
numMCUsDecoded++;
if (numMCUsDecoded == numAllMCUs)
{
break;
}
rstIndex++;
} while (rstIndex < restartInterval);
// read the marker, only handle RSTn marker or EOI marker
// skip all other segment
nextChar = GetByteFromBuf(byteBuffer);
if (nextChar != 0xFF)
{
// search for next marker
do
{
if ((nextChar = GetByteFromBuf(byteBuffer)) < 0)
{
return JPEG_ERR_EOI_MISSING;
}
} while (nextChar != 0xFF);
}
nextChar = GetByteFromBuf(byteBuffer);
if (nextChar == JPEG_MARKER_EOI)
{
if (numMCUsDecoded == numAllMCUs)
{
break;
}
else
{
// decoding stops earlier than expected
return JPEG_ERR_FATAL;
}
}
else if ((nextChar >= JPEG_MARKER_RST0) && (nextChar <= JPEG_MARKER_RST7))
{
// this a restart marker
int thisRSTMarker;
int distance;
thisRSTMarker = nextChar;
if (thisRSTMarker <= prevRSTMarker)
{
distance = thisRSTMarker + 8 - prevRSTMarker;
}
else
{
distance = thisRSTMarker - prevRSTMarker;
}
if (distance > 1)
{
return JPEG_ERR_RST_OUTOFORDER;
}
else
{
prevRSTMarker = thisRSTMarker;
}
JPEGMCUInitialize(jpegMCU);
}
// ignore all application specific markers
else if(nextChar > JPEG_MARKER_APP0)
{
continue;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -