📄 exif.c
字号:
{
return 0;
}
FSAL_SetBuffer(&exif_FSAL, EXIF_PARSER_BUFFER_SIZE,exif_parser_buffer);
eFSALRet = FSAL_Direct_GetFileSize(&exif_FSAL,&exif_FileSize);
if(eFSALRet !=FSAL_OK)
{
return 0;
}
/* Check if it's a jpeg file */
if(FSAL_Read_Bytes(&exif_FSAL, byte,2)==FSAL_OK)
{
if(byte[0]!=0xff || byte[1]!=0xD8)
return 0;
}
while(!Exif_Found && exif_getNextMarker(&marker))
{
//printf("exif_FSAL.uFileOffset: %d, marker:%x\n",exif_FSAL.uFileOffset,marker);
if(marker>0xffe1 && marker<= 0xffef)
marker=0xffe0;
switch(marker)
{
case 0xffe0:
if(exif_direct_read_uint16(&JumpDest)!=FSAL_OK) return 0;
JumpDest-=2;
exif_seek_buffer(JumpDest,FS_FILE_CURRENT);
break;
case 0xffe1:
if(exif_direct_read_uint16(&JumpDest)!=FSAL_OK) return 0;
//JumpDest+=(exif_FSAL.uFileOffset-2);
JumpDest-=2;
Exif_Found=KAL_TRUE;
for(i=0;i<6;i++)
{
if(exif_read_uint8(&byte0)!=FSAL_OK) return 0;
Exif_Found &=(byte0 == exif_Header[i+4]);
}
if(!Exif_Found)
{
exif_seek_buffer(JumpDest,FS_FILE_CURRENT);
Exif_Found=KAL_FALSE;
break;
}
if(exif_direct_read_uint16(&exif_ByteOrder)!=FSAL_OK) return 0;
if(exif_ByteOrder!= EXIF_BIG_ENDIAN && exif_ByteOrder!= EXIF_LITTLE_ENDIAN)
{
exif_seek_buffer(JumpDest,FS_FILE_CURRENT);
Exif_Found=KAL_FALSE;
break;
}
if(exif_read_uint16(&halfword)!=FSAL_OK) return 0;
if(halfword !=0x002a)
{
exif_seek_buffer(JumpDest,FS_FILE_CURRENT);
Exif_Found=KAL_FALSE;
}
break;
case 0xffdb:
case 0xffc0:
return 0;
default :
break;
}
}
//-- Exif Found!! --
exif_TiffOffset=exif_FSAL.uFileOffset-4;
if(exif_read_uint32(&IFD0_entry_pos)!=FSAL_OK) return 0;
if(exif_read_uint16(&IFD0_entry_num)!=FSAL_OK) return 0;
IFD0_entry_pos+=exif_TiffOffset;
//printf("IFD0_pos:%x, IFD0 num:%x\n",IFD0_entry_pos,IFD0_entry_num);
exif_ReqBufferSize=0;
ExifIFD_entry_pos=0;
ExifIFD_entry_num=0;
//--acc IFD0--
for(i=0;i<IFD0_entry_num;i++)
{
if(exif_read_uint16(&tag)!=FSAL_OK) return 0;
if(exif_read_uint16(&type)!=FSAL_OK) return 0;
exif_decoder_acc_tag(tag,type);
//printf("IFD0 tag:%x, type:%d ,Reqsize:%d\n",tag,type,exif_ReqBufferSize);
if(tag==0x8769)
{
exif_seek_buffer(4,FS_FILE_CURRENT);
if(exif_read_uint32(&ExifIFD_entry_pos)!=FSAL_OK) return 0;
ExifIFD_entry_pos+=exif_TiffOffset;
}
else
exif_seek_buffer(8,FS_FILE_CURRENT);
}
//--acc ExifIFD--
if(ExifIFD_entry_pos>0)
{
exif_seek_buffer(ExifIFD_entry_pos,FS_FILE_BEGIN);
if(exif_read_uint16(&ExifIFD_entry_num)!=FSAL_OK) return 0;
}
for(i=0;i<ExifIFD_entry_num;i++)
{
if(exif_read_uint16(&tag)!=FSAL_OK) return 0;
if(exif_read_uint16(&type)!=FSAL_OK) return 0;
exif_decoder_acc_tag(tag,type);
//printf("IFD0 tag:%x, type:%d ,Reqsize:%d\n",tag,type,exif_ReqBufferSize);
exif_seek_buffer(8,FS_FILE_CURRENT);
}
exif_ReqBufferSize+=(sizeof(tag) * (IFD0_entry_num+ExifIFD_entry_num));
exif_ReqBufferSize+=(sizeof(void*) * (IFD0_entry_num+ExifIFD_entry_num));
/* Force to 4 byte align */
exif_ReqBufferSize+=3;
exif_decoder_state=EXIF_DECODER_PREPROCESS_DONE_STATE;
return exif_ReqBufferSize;
}
kal_bool exif_getNextMarker(kal_uint16* marker)
{
kal_uint8 byte0=0,byte1=0;
//printf("exif_FileSize:%d\n",exif_FileSize);
if(exif_FSAL.uFileOffset>exif_FileSize) return KAL_FALSE;
while(FSAL_Read_Bytes(&exif_FSAL, &byte1,1)==FSAL_OK)
{
//printf("exif_FSAL.uFileOffset: %x, byte0:%x, byte1:%x\n",exif_FSAL.uFileOffset,byte0,byte1);
if(byte0==0xff && byte1!=0xff)
{
(*marker)=(byte0<<8) | byte1 ;
//printf(" getMarker %x%x\n",byte0,byte1);
return KAL_TRUE;
}
byte0=byte1;
}
return KAL_FALSE;
}
void exif_decoder_acc_tag(kal_uint16 tag,kal_uint16 type)
{
/* These tags are with built in info */
switch(tag)
{
case exif_tag_Orientation:
exif_ReqBufferSize+=EXIF_DEC_Orientation_MAX_LEN;
return;
case exif_tag_ResolutionUnit:
exif_ReqBufferSize+=EXIF_DEC_ResolutionUnit_MAX_LEN;
return;
case exif_tag_YCbCrPositioning:
exif_ReqBufferSize+=EXIF_DEC_YCbCrPositioning_MAX_LEN;
return;
case exif_tag_ExposureProgram:
exif_ReqBufferSize+=EXIF_DEC_ExposureProgram_MAX_LEN;
return;
case exif_tag_ComponentsConfig:
exif_ReqBufferSize+=EXIF_DEC_ComponentsConfig_MAX_LEN;
return;
case exif_tag_MeteringMode:
exif_ReqBufferSize+=EXIF_DEC_MeteringMode_MAX_LEN;
return;
case exif_tag_LightSource:
exif_ReqBufferSize+=EXIF_DEC_LightSource_MAX_LEN;
return;
case exif_tag_Flash:
exif_ReqBufferSize+=EXIF_DEC_Flash_MAX_LEN;
return;
case exif_tag_ColorSpace:
exif_ReqBufferSize+=EXIF_DEC_ColorSpace_MAX_LEN;
return;
case exif_tag_ExposureMode:
exif_ReqBufferSize+=EXIF_DEC_ExposureMode_MAX_LEN;
return;
case exif_tag_SceneCaptureType:
exif_ReqBufferSize+=EXIF_DEC_SceneCaptureType_MAX_LEN;
return;
default :
break;
}
switch(type)
{
case EXIF_BYTE:
exif_ReqBufferSize+=EXIF_BYTE_SHOW_LEN;
break;
case EXIF_ASCII:
exif_ReqBufferSize+=EXIF_ASCII_SHOW_LEN;
break;
case EXIF_SHORT:
exif_ReqBufferSize+=EXIF_SHORT_SHOW_LEN;
break;
case EXIF_LONG:
exif_ReqBufferSize+=EXIF_LONG_SHOW_LEN;
break;
case EXIF_RATIONAL:
exif_ReqBufferSize+=EXIF_RATIONAL_SHOW_LEN;
break;
case EXIF_SRATIONAL:
exif_ReqBufferSize+=EXIF_SRATIONAL_SHOW_LEN;
break;
case EXIF_SLONG:
exif_ReqBufferSize+=EXIF_SLONG_SHOW_LEN;
break;
case EXIF_UNDEFINED:
exif_ReqBufferSize+=EXIF_UNDEFINED_SHOW_LEN;
break;
}
}
/*************************************************************************
* FUNCTION
* exif_parse_jpeg_file()
*
* DESCRIPTION
* This function is to parse the exif header of a jpeg file.
* Before calling this function, one should move the decoder state to
* EXIF_DECODER_PREPROCESS_DONE_STATE by calling exif_open_jpeg_file().
*
* PARAMETERS
* R_Buffer (Required Buffer for storing the result)
*
* RETURNS
* Whether the parsing procedure finshied succeffuly
*
* GLOBALS AFFECTED
*
*************************************************************************/
EXIF_DEC_RESULT exif_parse_jpeg_file(kal_uint8* const R_Buffer,kal_uint32 BufferSize)
{
kal_uint16 i;
exif_dec_entry_struct Exif_entry;
if(exif_decoder_state!=EXIF_DECODER_PREPROCESS_DONE_STATE)
return EXIF_FILE_NOT_OPEN;
if(BufferSize < exif_ReqBufferSize)
return EXIF_DEC_BUFFER_OVERFLOW;
exif_tagArr=(kal_uint16*)R_Buffer;
/* force to 4 byte align */
exif_valueArr=(kal_char**)((((kal_uint32)R_Buffer+2*(IFD0_entry_num+ExifIFD_entry_num)+3)>>2)<<2);
exif_UsedBufferSize=(sizeof(Exif_entry.tag)+ sizeof(void*)) * (IFD0_entry_num+ExifIFD_entry_num)+4;
//printf("R_Buffer:%d tagArr:%d, valueArr:%d, value_offset:%d\n",R_Buffer,tagArr,valueArr,value_offset);
//printf("IFD0_entry_num:%d ExifIFD_entry_num:%d\n",IFD0_entry_num,ExifIFD_entry_num);
for(i=0;i<IFD0_entry_num;i++)
{
exif_valueArr[i]=0;
exif_seek_buffer(IFD0_entry_pos+2+i*12,FS_FILE_BEGIN);
if(exif_read_uint16(&Exif_entry.tag)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint16(&Exif_entry.type)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint32(&Exif_entry.count)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint32(&Exif_entry.value)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
exif_tagArr[i]=Exif_entry.tag;
//printf("IFD0, tag:%x, type:%d, count:%d\n",Exif_entry.tag,Exif_entry.type,Exif_entry.count);
exif_UsedBufferSize+=exif_set_entry(&exif_valueArr[i],(kal_char*)(R_Buffer+exif_UsedBufferSize),&Exif_entry);
//printf("value_offset:%d\n",value_offset);
}
for(i=IFD0_entry_num;i<IFD0_entry_num+ExifIFD_entry_num;i++)
{
exif_valueArr[i]=0;
exif_seek_buffer(ExifIFD_entry_pos+2+(i-IFD0_entry_num)*12,FS_FILE_BEGIN);
if(exif_read_uint16(&Exif_entry.tag)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint16(&Exif_entry.type)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint32(&Exif_entry.count)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
if(exif_read_uint32(&Exif_entry.value)!=FSAL_OK) return EXIF_DEC_FILE_READ_ERROR;
exif_tagArr[i]=Exif_entry.tag;
//printf("ExifIFD, tag:%x, type:%d, count:%d",Exif_entry.tag,Exif_entry.type,Exif_entry.count);
exif_UsedBufferSize+=exif_set_entry(&exif_valueArr[i],(kal_char*)(R_Buffer+exif_UsedBufferSize),&Exif_entry);
//printf("value_offset:%d\n",value_offset);
}
exif_decoder_state=EXIF_DECODER_PARSE_DONE_STATE;
return EXIF_DEC_DONE;
}
kal_uint32 exif_set_entry(kal_char** str,kal_char* buffer,exif_dec_entry_struct* Exif_entry)
{
float fp;
kal_uint32 len=0,count=0,value,value1;
kal_uint16 value16;
kal_uint8 value8;
kal_uint8* valueHex;
kal_int32 Svalue,Svalue1;
if((Exif_entry->tag==0x927c) && (Exif_entry->count>12))
{
exif_MakerNote_size=Exif_entry->count;
exif_MakerNote_pos=Exif_entry->value+exif_TiffOffset;
}
if(Exif_entry->count<1) return 0;
if(exif_ByteOrder==EXIF_LITTLE_ENDIAN)
{
value16=Exif_entry->value & 0xffff;
}
else
{
value16=(Exif_entry->value>>16);
}
switch(Exif_entry->tag)
{
case exif_tag_Orientation:
if(value16<9)
{
*str=buffer;
while(len<strlen(exif_Orientation_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_Orientation_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_ResolutionUnit:
if(value16<4)
{
*str=buffer;
while(len<strlen(exif_ResolutionUnit_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_ResolutionUnit_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_YCbCrPositioning:
if(value16<3)
{
*str=buffer;
while(len<strlen(exif_YCbCrPositioning_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_YCbCrPositioning_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_ExposureProgram:
if(value16<8)
{
*str=buffer;
while(len<strlen(exif_ExposureProgram_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_ExposureProgram_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_ComponentsConfig:
if((exif_ByteOrder==EXIF_LITTLE_ENDIAN && Exif_entry->value==0x030201) ||
(exif_ByteOrder==EXIF_BIG_ENDIAN && Exif_entry->value==0x01020300))
{
*str=buffer;
while(len<strlen(exif_ComponentsConfig_table[0]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_ComponentsConfig_table[0][len];
len++;
}
buffer[len++]=0;
return len;
}
else if((exif_ByteOrder==EXIF_LITTLE_ENDIAN && Exif_entry->value==0x060504) ||
(exif_ByteOrder==EXIF_BIG_ENDIAN && Exif_entry->value==0x04050600))
{
*str=buffer;
while(len<strlen(exif_ComponentsConfig_table[1]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_ComponentsConfig_table[1][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_MeteringMode:
if(value16<7)
{
*str=buffer;
while(len<strlen(exif_MeteringMode_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_MeteringMode_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_LightSource:
if(value16<23)
{
*str=buffer;
while(len<strlen(exif_LightSource_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_LightSource_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_Flash:
if(value16<8)
{
*str=buffer;
while(len<strlen(exif_Flash_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_Flash_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_ColorSpace:
if(value16==1)
{
*str="sRGB";
return 0;
}
else if(value16==0xffff)
{
*str="Uncalibrated";
return 0;
}
break;
case exif_tag_ExposureMode:
if(value16<8)
{
*str=buffer;
while(len<strlen(exif_ExposureMode_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_ExposureMode_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_SceneCaptureType:
if(value16<4)
{
*str=buffer;
while(len<strlen(exif_SceneCaptureType_table[value16]) && len<EXIF_ASCII_SHOW_LEN-1)
{
buffer[len]=exif_SceneCaptureType_table[value16][len];
len++;
}
buffer[len++]=0;
return len;
}
break;
case exif_tag_FlashpixVersion:
case exif_tag_ExifVersion:
{
if(exif_seek_buffer(exif_FSAL.uFileOffset-4,FS_FILE_BEGIN)!=FSAL_OK)
return 0;
*str=buffer;
exif_read_uint8(&value8);
if(value8!='0')
buffer[len++]=value8;
exif_read_uint8(&value8);
buffer[len++]=value8;
buffer[len++]='.';
exif_read_uint8(&value8);
buffer[len++]=value8;
exif_read_uint8(&value8);
if(value8!='0')
buffer[len++]=value8;
buffer[len++]=0;
return len;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -