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