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

📄 jpegbitstreamprocess.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
📖 第 1 页 / 共 2 页
字号:
//
//
// 去掉Jpeg码流中"FF00"中的"00"(不包括Jpeg头),用于ARM上,为ZSP准备的码流
//
//
//
//#include <stdio.h>
//#include <memory.h>
#include "JpegBitstreamProcess.h"
#include "JpgDecFillBuf.h"
#include "../../ImageWin/ImageDecodeMain.h"


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

unsigned char Jpg_gBitStreamBuf[JPG_FILE_READ_CACHE_SIZE];
int Jpg_gBitStreamOffset;
int Jpg_gTotalBytesRead;
int Jpg_gTotalByteParsed;
int Jpg_gActualCacheDataLen;
int Jpg_gcbHeader;
int Jpg_gHasRemainAByte;
int Jpg_gRemainByte;
int Jpg_gExifBegOffset;
unsigned char thisChar;
unsigned char lastChar;

tThumbnailImageInf Jpg_gThumbnailImageInf;

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

// 交换字节
void JpgSwapChar(unsigned char *pbuf, int cb)
{
    int i;
    unsigned short *p = (unsigned short*)pbuf;

    for (i = 0; i < cb; i++)
    {
#if 1
        *p++ = ((unsigned short)pbuf[2*i] << 8) | ((unsigned short)pbuf[2*i+1] & 0xFF);
#else
        *p++ = ((unsigned short)pbuf[2*i+1] << 8) | ((unsigned short)pbuf[2*i] & 0xFF);
#endif
    }
}

// 从缓存读取特定码流(去掉Jpeg码流中"FF00"中的"00", 并交换前后字节)
int JpgDecGetGivenBitStream(unsigned char *pbuf, int cb)
{
    int j = 0;
    int cbGet = 0;

    while (1)
    {
        Jpg_gTotalByteParsed++;
        if (Jpg_gBitStreamOffset >= JPG_FILE_READ_CACHE_SIZE)
        {
            Jpg_gBitStreamOffset = 0;
            Jpg_gActualCacheDataLen = FSFileRead(Jpg_gBitStreamBuf, JPG_FILE_READ_CACHE_SIZE, pImageFile);
            //Jpg_gTotalBytesRead += Jpg_gActualCacheDataLen;
        }

        thisChar = Jpg_gBitStreamBuf[Jpg_gBitStreamOffset++];

        // 去掉码流中"FF00"中的"00", 不包括JPG头
        if ((lastChar == 0xFF) && (thisChar == 0x00) && (Jpg_gTotalByteParsed > Jpg_gcbHeader))
        {
            lastChar = thisChar;
            continue;
        }
        lastChar = thisChar;
        pbuf[j] = thisChar;

        if (++j >= cb)
        {
            cbGet = cb;
            break;// 已经获得了cb 字节的码流
        }

        if (Jpg_gBitStreamOffset > Jpg_gActualCacheDataLen)
        {
            cbGet = j; // j-1
            break;// 文件已经读完
        }

        if (Jpg_gThumbnailImageInf.fHasThumbnailImage)
        {
            if (Jpg_gTotalByteParsed > Jpg_gThumbnailImageInf.cbLen)
            {
                // 解ThumbnailImage 时,此时已经读完ThumbnailImage 数据
                cbGet = cb - 1;
                break;
            }
        }
    }

    // 交换高低字节
    JpgSwapChar(pbuf, (cbGet + 1) / 2);

    return cbGet;
}

void JpgDecBitStreamInit(void)
{
    Jpg_gBitStreamOffset = JPG_FILE_READ_CACHE_SIZE;
    Jpg_gTotalBytesRead = 0;
    Jpg_gActualCacheDataLen = 0;
    Jpg_gTotalByteParsed = 0;
    thisChar = 0;
    thisChar = 0;
    Jpg_gHasRemainAByte = 0;
    Jpg_gRemainByte = 0;
    Jpg_gExifBegOffset = 0;
}

// fseek 后需要重新初始
void JpgDecBitStreamInitAfterSeek(void)
{
    Jpg_gBitStreamOffset = JPG_FILE_READ_CACHE_SIZE;
    Jpg_gTotalBytesRead = 0;
    Jpg_gActualCacheDataLen = 0;
    Jpg_gTotalByteParsed = 0;
    thisChar = 0;
    thisChar = 0;
    Jpg_gHasRemainAByte = 0;
    Jpg_gRemainByte = 0;
}

// 从码流中读出一个字节
unsigned char JpgDecGetOneChar(void)
{
    unsigned char c;

    if (Jpg_gBitStreamOffset >= JPG_FILE_READ_CACHE_SIZE)
    {
        // BitStreamBuf 里的数据已经消耗完,需要从文件系统里读取新数据
        Jpg_gActualCacheDataLen = FSFileRead(Jpg_gBitStreamBuf, JPG_FILE_READ_CACHE_SIZE, pImageFile);

        Jpg_gBitStreamOffset = 0;
        Jpg_gTotalBytesRead += Jpg_gActualCacheDataLen;
    }

    c = Jpg_gBitStreamBuf[Jpg_gBitStreamOffset++];

    return c;
}

// Finds the start of image (SOI) marker.
// This code is rather defensive: it only checks the first 512 bytes to avoid
// false positives.
int JpgDecLocateSoiMarker(void)
{
    unsigned char lastchar, thischar;
    int bytesleft;

    lastchar = JpgDecGetOneChar();

    thischar = JpgDecGetOneChar();

    /* ok if it's a normal JPEG file without a special header */

    if ((lastchar == 0xFF) && (thischar == M_SOI))
        return JPG_SUCCESS;

    bytesleft = 512;

    for (; ;)
    {
        if (--bytesleft == 0)
        {
            return JPG_FAIL;
        }

        lastchar = thischar;

        thischar = JpgDecGetOneChar();

        if ((lastchar == 0xFF) && (thischar == M_SOI))
            break;
    }

    /* Check the next character after marker: if it's not 0xFF, it can't
    be the start of the next marker, so it probably isn't a JPEG */

    thischar = JpgDecGetOneChar();//(Jpg_gBitBuf >> 8) & 0xFF;

    if (thischar != 0xFF)
    {
        return JPG_FAIL;
    }

    return JPG_SUCCESS;
}

// Finds the next marker.
int JpgDecNextMarker(void)
{
    unsigned char c, bytes;

    bytes = 0;

    do
    {
        do
        {
            bytes++;

            c = JpgDecGetOneChar();

        }
        while (c != 0xFF);

        do
        {
            c = JpgDecGetOneChar();

        }
        while (c == 0xFF);

    }
    while (c == 0);

    // If bytes > 0 here, there where extra bytes before the marker (not good).

    return c;
}

// Used to skip unrecognized markers.
int JpgDecSkipVariableMarker(void)
{
    int left;

    left = (((short)JpgDecGetOneChar() << 8) & 0xFF00) | ((short)JpgDecGetOneChar() & 0xFF);

    if (left < 2)
    {
        return JPG_FAIL;
    }

    left -= 2;

    while (left)
    {
        JpgDecGetOneChar();
        left--;
    }

    return JPG_SUCCESS;
}

// 找到JPG文件bitstream开始位置,也就是JPG头的长度
// [pcbOffset] -- JPG bitstream开始位置, 单位为字节
int JpgDecFindImageDataBeginOffset(int *pcbOffset)
{
    int r = JPG_FAIL;
    int c;

    JpgDecBitStreamInit();

    r = JpgDecLocateSoiMarker();
    if (r != JPG_SUCCESS)
    {
        return JPG_FAIL;
    }

    while (1)
    {
        c = JpgDecNextMarker();

        switch (c)
        {
            case M_SOS:
                {
                    r = JpgDecSkipVariableMarker();
                    if (r != JPG_SUCCESS)
                        return JPG_FAIL;

                    *pcbOffset = Jpg_gTotalBytesRead - Jpg_gActualCacheDataLen + Jpg_gBitStreamOffset;

                    return JPG_SUCCESS;
                }
            default:    /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
                {
                    r = JpgDecSkipVariableMarker();
                    if (r != JPG_SUCCESS)
                        return JPG_FAIL;
                    break;
                }
        }

        //  注意避免死循环
        if (/*(Jpg_gActualCacheDataLen<JPG_FILE_READ_CACHE_SIZE) && */(Jpg_gBitStreamOffset > Jpg_gActualCacheDataLen))
        {
            break; // 文件已经读完
        }
    }

    return r;
}


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

// 以little endian形式读dword
unsigned long IntelGetDword(void)
{
    unsigned char a, b, c, d;

    a = JpgDecGetOneChar();
    b = JpgDecGetOneChar();
    c = JpgDecGetOneChar();
    d = JpgDecGetOneChar();

    return (((unsigned long)a) + ((unsigned long)b << 8) + ((unsigned long)c << 16) + ((unsigned long)d << 24));
}

unsigned short IntelGetWord(void)
{
    unsigned char a, b;

    a = JpgDecGetOneChar();
    b = JpgDecGetOneChar();

    return (unsigned short)(((unsigned long)a) + ((unsigned long)b << 8));
}

// 以big endian形式读dword
unsigned long MotoGetDword(void)
{
    unsigned char a, b, c, d;

    a = JpgDecGetOneChar();
    b = JpgDecGetOneChar();
    c = JpgDecGetOneChar();
    d = JpgDecGetOneChar();

    return (((unsigned long)d) + ((unsigned long)c << 8) + ((unsigned long)b << 16) + ((unsigned long)a << 24));
}

unsigned short MotoGetWord(void)
{
    unsigned char a, b;

⌨️ 快捷键说明

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