📄 jpegbitstreamprocess.c
字号:
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 + -