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

📄 jpegdecoder.c

📁 jpeg图像文件软件解码器的arm版本的源代码程序
💻 C
📖 第 1 页 / 共 2 页
字号:
///////////////////////////////////////////////////////////////////////////////
//
//  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 + -