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

📄 jpegbitstreamprocess.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
📖 第 1 页 / 共 2 页
字号:
    a = JpgDecGetOneChar();
    b = JpgDecGetOneChar();

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

int GetNextIFDOffset(int EndianMode)
{
    int NextIFDOffset;

    if (EndianMode == INTEL_ALIGN)
    {
        NextIFDOffset = IntelGetDword();
    }
    else
    {
        NextIFDOffset = MotoGetDword();
    }

    return NextIFDOffset;
}

int GetNumberDirectoryEntry(int EndianMode)
{
    int NumberDirectoryEntry;

    if (EndianMode == INTEL_ALIGN)
    {
        NumberDirectoryEntry = IntelGetWord();
    }
    else
    {
        NumberDirectoryEntry = MotoGetWord();
    }

    return NumberDirectoryEntry;
}

unsigned short GetDirectoryEntryTag(int EndianMode)
{
    unsigned short tag;

    if (EndianMode == INTEL_ALIGN)
    {
        tag = IntelGetWord();
    }
    else
    {
        tag = MotoGetWord();
    }

    return tag;
}

unsigned long GetDirectoryEntryValue(int EndianMode)
{
    unsigned short data_format;
    unsigned long number_of_components, data_value, value = 0;

    if (EndianMode == INTEL_ALIGN)
    {
        data_format    = IntelGetWord();
        number_of_components = IntelGetDword();
        data_value    = IntelGetDword();

    }
    else
    {
        data_format    = MotoGetWord();
        number_of_components = MotoGetDword();
        data_value    = MotoGetDword();
    }

    //assert(data_format==UNSIGNED_SHORT_TYPE || data_format==UNSIGNED_LONG_TYPE);
    //assert(number_of_components == 1);

    switch (data_format)
    {
        case UNSIGNED_SHORT_TYPE:
            if (EndianMode == INTEL_ALIGN)
                value = data_value & 0xFFFF;
            else
                value = data_value >> 16;
            break;

        case UNSIGNED_LONG_TYPE:
            value = data_value;
            break;

        default:
            break;
    }

    return value;
}

void SkipDirectoryEntry(void)
{
    int i;

    for (i = 0; i < DIRECTORY_ENTRY_LENGTH - 2; i++)
    {
        JpgDecGetOneChar();
    }
}

// 检查Exif标记
int CheckExifMaker(void)
{
    unsigned char a, b, c, d;

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

    if (a == 'E' && b == 'x' && c == 'i' && d == 'f')
    {
        return JPG_SUCCESS;
    }

    return JPG_FAIL;
}

// 判断数据是以little endian 还是 big endian 形式
int JugeEndianMode(int *pEndianMode)
{
    unsigned char a, b;

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

    if (a == 'I' && b == 'I')
    {
        *pEndianMode = INTEL_ALIGN;
    }
    else if (a == 'M' && b == 'M')
    {
        *pEndianMode = MOTO_ALIGN;
    }
    else
    {
        return JPG_FAIL;
    }

    return JPG_SUCCESS;
}

/*----------------------------------------------------------------------
Name  :  SearchThumbnailImageInExif
Desc  :
Params:  OUT  [pcbOffset]      --   ThumbnailImage相对于Exif的偏移
         OUT  [pcbLen]         --   ThumbnailImage的长度
Return:
         0: 成功找到;1: 失败
注意:    目前只提取APP1中的缩略图信息,没有提取APP0
----------------------------------------------------------------------*/
int SearchThumbnailImageInExif(int *pcbOffset, int *pcbLen)
{
    int left, i;
    int EndianMode;
    int NextIFDOffset;
    int NumberDirectoryEntry;
    unsigned short Tag;
    int CompressionMode;

    left = (((short)JpgDecGetOneChar() << 8) & 0xFF00) | ((short)JpgDecGetOneChar() & 0xFF);
    if (left < 2)
    {
        return JPG_FAIL;
    }
    left -= 2;

    if (CheckExifMaker() != JPG_SUCCESS)
    {
        return JPG_FAIL;
    }

    if (JugeEndianMode(&EndianMode) != JPG_SUCCESS)
    {
        return JPG_FAIL;
    }

    // 读取NextIFDOffset
    NextIFDOffset = GetNextIFDOffset(EndianMode);
    if (NextIFDOffset <= 0)
    {
        return JPG_FAIL;
    }

    // 跳到下一个IFD
    FSFileSeek(pImageFile, Jpg_gExifBegOffset + NextIFDOffset, SEEK_SET);
    JpgDecBitStreamInitAfterSeek();

    do
    {
        NumberDirectoryEntry = GetNumberDirectoryEntry(EndianMode);
        if (NumberDirectoryEntry < 0)
        {
            return JPG_FAIL;
        }

        for (i = 0; i < NumberDirectoryEntry; i++)
        {
            Tag = GetDirectoryEntryTag(EndianMode);

            switch (Tag)
            {
                case 0x0103: // Compression
                    {
                        CompressionMode = GetDirectoryEntryValue(EndianMode);
                        if (CompressionMode != JPEG_COMPRESS)
                        {
                            return JPG_FAIL; // 目前只提取JPEG压缩的ThumbnailImage
                        }
                        break;
                    }

                case 0x0201: // JpegIFOffset
                    {
                        *pcbOffset = GetDirectoryEntryValue(EndianMode);
                        break;
                    }

                case 0x0202: // JpegIFByteCount
                    {
                        *pcbLen = GetDirectoryEntryValue(EndianMode);
                        break;
                    }

                default:
                    {
                        SkipDirectoryEntry();
                        break;
                    }
            }
        }

        if (*pcbOffset > 0 && *pcbLen > 0)
        {
            break;// 已经提取了想要的信息
        }

        // 读取NextIFDOffset
        NextIFDOffset = GetNextIFDOffset(EndianMode);

        // 跳到下一个IFD
        FSFileSeek(pImageFile, Jpg_gExifBegOffset + NextIFDOffset, SEEK_SET);
        JpgDecBitStreamInitAfterSeek();

    }
    while (NextIFDOffset > 0);

    if (*pcbOffset <= 0 || *pcbLen <= 0)
        return JPG_FAIL;

    return JPG_SUCCESS;
}

/*----------------------------------------------------------------------
Name  :  SearchThumbnailImageInJpegHeader
Desc  :
Params:  OUT  [pcbOffset]      --   ThumbnailImage在文件中的偏移
         OUT  [pcbLen]         --   ThumbnailImage的长度
Return:
         0: 成功找到;1: 失败
----------------------------------------------------------------------*/
int SearchThumbnailImageInJpegHeader(int *pcbOffset, int *pcbLen)
{
    int r = JPG_FAIL;
    int c;
    int cbHeader = 0;
    int curParseOffset = 0;

    *pcbOffset = 0;
    *pcbLen = 0;

    //FSFileSeek(pImageFile, 0 , SEEK_SET);

    // 先计算Jpg 头的长度
    if (JpgDecFindImageDataBeginOffset(&cbHeader) != JPG_SUCCESS)
    {
        return JPG_FAIL;

    }

    // 然后在Jpg 头里查找ThumbnailImage
    JpgDecBitStreamInit();

    FSFileSeek(pImageFile, 0 , SEEK_SET);

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

    while (1)
    {
        c = JpgDecNextMarker();

        switch (c)
        {
            case M_APP1: // Exif
                {
                    // 找到Exif, 从其中找ThumbnailImage

                    curParseOffset = Jpg_gTotalBytesRead - Jpg_gActualCacheDataLen + Jpg_gBitStreamOffset;
                    Jpg_gExifBegOffset = curParseOffset + 2 + 6;

                    if (SearchThumbnailImageInExif(pcbOffset, pcbLen) != JPG_SUCCESS)
                    {
                        return JPG_FAIL;
                    }

                    *pcbOffset += Jpg_gExifBegOffset;
                    return JPG_SUCCESS;
                }
            default:
                {
                    r = JpgDecSkipVariableMarker();
                    if (r != JPG_SUCCESS)
                        return JPG_FAIL;
                    break;
                }

        }

        if (Jpg_gTotalBytesRead - Jpg_gActualCacheDataLen + Jpg_gBitStreamOffset >= cbHeader)
        {
            // 只在头文件里找
            break;
        }
    }

    return JPG_FAIL;
}

⌨️ 快捷键说明

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