📄 exif.c
字号:
/*****************************************************************************
* Copyright Statement:
* --------------------
* This software is protected by Copyright and the information contained
* herein is confidential. The software may not be copied and the information
* contained herein may not be used or disclosed except with the written
* permission of MediaTek Inc. (C) 2005
*
* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*****************************************************************************
*
* Filename:
* ---------
* exif.c
*
* Project:
* --------
* MT6226,MT6227,MT6228,MT6229
*
* Description:
* ------------
* This file is intends for Exif encoder.
*
* Author:
* -------
* -------
*
*============================================================================
* HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*------------------------------------------------------------------------------
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*
* removed!
* removed!
* removed!
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
*============================================================================
****************************************************************************/
#include <stdio.h>
#include <string.h>
#if (defined(EXIF_SUPPORT))
#include "exif.h"
#include "exif_table.h"
#include "Drm_gprot.h"
#include "kal_release.h"
#include "FSAL.h"
#include "rtc_sw.h"
extern void RTC_GetTime(t_rtc *rtctime);
extern kal_char* release_verno(void);
extern void exif_update_MTK_para_struct(exif_MTK_para_struct *exif_MTK_para);
/* Global variables */
kal_uint32 exif_IFD0_Entry_Switch= 0x0080; /* Switch off all cam &cus entries as default */
kal_uint32 exif_ExifIFD_Entry_Switch= 0x0000; /* Switch off all cam & cus entries as default */
kal_uint32 exif_ExIFD_Entry_Switch=0x0000;
kal_bool cam_para_get=KAL_FALSE;
kal_bool cus_para_get=KAL_FALSE;
kal_bool exif_AscOrder;
kal_uint8 exif_next_ExIFD_entry;
exif_cam_para_struct exif_cam_para;
exif_MTK_para_struct exif_MTK_para;
exif_LONG exif_ExifIFD_Offset;
kal_uint16 IFD0_Entry_Size;
kal_uint16 IFD0_Value_Size;
kal_uint16 ExifIFD_Entry_Size;
kal_uint16 ExifIFD_Value_Size;
kal_uint16 IFD_TiffHeader_Offset;
/* Number of entries of each IFD */
kal_uint16 exif_IFD0_count;
kal_uint16 exif_ExifIFD_count;
/* Buffer pointer*/
kal_uint8* exif_Buffer;
/* Required Buffer Size for EXIF encoding*/
kal_uint16 exif_BufferSize;
exif_extend_entry_struct* ExIFD;
kal_uint8 ExIFD_Number_of_Entry=0;
/* tables */
exif_entry_struct IFD0[IFD0_Number_of_Entry]=
{
//{exif_tag_Make, EXIF_ASCII, 0, &exif_cus_para.Make},
//{exif_tag_Model, EXIF_ASCII, 0, &exif_cus_para.Model},
{exif_tag_Orientation, EXIF_SHORT, 1, &exif_cam_para.Orientation},
{exif_tag_XResolution, EXIF_RATIONAL, 1, &exif_cam_para.XResolution},
{exif_tag_YResolution, EXIF_RATIONAL, 1, &exif_cam_para.YResolution},
{exif_tag_ResolutionUnit, EXIF_SHORT, 1, &exif_cam_para.ResolutionUnit},
{exif_tag_Software, EXIF_ASCII, 0, &exif_cam_para.Software},
{exif_tag_DateTime, EXIF_ASCII, 0, &exif_cam_para.DateTime},
{exif_tag_YCbCrPositioning, EXIF_SHORT, 1, &exif_cam_para.YCbCrPositioning},
{exif_tag_ExifIFD, EXIF_LONG, 1, &exif_ExifIFD_Offset}
};
exif_entry_struct ExifIFD[ExifIFD_Number_of_Entry]=
{
{exif_tag_ExposureTime, EXIF_RATIONAL, 1, &exif_cam_para.ExposureTime},
{exif_tag_FNumber, EXIF_RATIONAL, 1, &exif_cam_para.FNumber},
{exif_tag_ExposureProgram, EXIF_SHORT, 1, &exif_cam_para.ExposureProgram},
{exif_tag_ISOSpeedRatings, EXIF_SHORT, 1, &exif_cam_para.ISOSpeedRatings},
{exif_tag_ExifVersion, EXIF_UNDEFINED, 4, &exif_cam_para.ExifVersion},
{exif_tag_DateTimeOriginal, EXIF_ASCII, 0, &exif_cam_para.DateTimeOriginal},
{exif_tag_DateTimeDigitized,EXIF_ASCII, 0, &exif_cam_para.DateTimeDigitized},
{exif_tag_ComponentsConfig, EXIF_UNDEFINED, 4, &exif_cam_para.ComponentsConfig},
{exif_tag_ExposureBiasValue,EXIF_SRATIONAL, 1, &exif_cam_para.ExposureBiasValue},
{exif_tag_MeteringMode, EXIF_SHORT, 1, &exif_cam_para.MeteringMode},
{exif_tag_LightSource, EXIF_SHORT, 1, &exif_cam_para.LightSource},
{exif_tag_Flash, EXIF_SHORT, 1, &exif_cam_para.Flash},
{exif_tag_MakerNote, EXIF_UNDEFINED, sizeof(exif_MTK_para_struct),&exif_MTK_para},
//{exif_tag_UserComment, EXIF_UNDEFINED, exif_Count_UserComment,&exif_cus_para.UserComment},
{exif_tag_FlashpixVersion, EXIF_UNDEFINED, 4, &exif_cam_para.FlashpixVersion},
{exif_tag_ColorSpace, EXIF_SHORT, 1, &exif_cam_para.ColorSpace},
{exif_tag_PixelXDimension, EXIF_LONG, 1, &exif_cam_para.PixelXDimension},
{exif_tag_PixelYDimension, EXIF_LONG, 1, &exif_cam_para.PixelYDimension},
{exif_tag_ExposureMode, EXIF_SHORT, 1, &exif_cam_para.ExposureMode},
{exif_tag_DigitalZoomRatio, EXIF_RATIONAL, 1, &exif_cam_para.DigitalZoomRatio},
{exif_tag_SceneCaptureType, EXIF_SHORT, 1, &exif_cam_para.SceneCaptureType}
};
/* Exif Headers */
kal_uint8 exif_Header[exif_header_size]={0xff,0xe1,0x00,0x00,'E','x','i','f','\0',0};
const kal_uint8 exif_tiffHeader[tiff_header_size]={0x49,0x49,0x2a,0x00,0x08,0x00,0x00,0x00};
kal_uint16 exif_Accumulate_ASCII(char* str,kal_uint16* IFD_Value_Size);
kal_bool exif_Acc_IFD_Size(exif_entry_struct* Exif_entry,kal_uint16* IFD_count,kal_uint16* IFD_Entry_Size,kal_uint16* IFD_Value_Size);
void exif_Fillin_tag(exif_entry_struct* Exif_entry,kal_uint16* IFD_entry_offset,kal_uint16* IFD_value_offset);
void exif_Fillin_32(kal_uint8* Buffer, kal_uint16* Offset, kal_uint32 Value);
void exif_Fillin_16(kal_uint8* Buffer, kal_uint16* Offset, kal_uint16 Value);
void exif_Fillin_ASCII(kal_uint8* Buffer, kal_uint16* Offset, kal_char* Value,kal_uint32 count);
void exif_switch_cam_entry(kal_uint8 action);
void exif_switch_cus_entry(kal_uint8 action);
kal_bool exif_is_switched_on(kal_uint8 IFD,kal_uint8 Entry);
void exif_check_ExIFD_data(void);
kal_uint16 exif_Calculate_Buffer_Size(kal_uint32 BufferOffset);
kal_uint8 exif_get_next_extended_tag(kal_uint8 IFD,kal_uint16 MinTag);
exif_ASCII exif_sys_time[20]={'y','y','y','y',':','m','m',':','d','d',' ','h','h',':','m','m',':','s','s','\0'};
//exif_ASCII* exif_sys_time="yyyy:mm:dd hh:mm:ss";
void exif_uint8_to_char(kal_uint8 val,kal_char* h, kal_char* l)
{
if(val>=100)
{
*h='9';
*l='9';
return;
}
*h=val/10;
*l=val%10;
return;
}
void exif_get_sys_time()
{
t_rtc exif_time;
RTC_GetTime(&exif_time);
exif_sys_time[0]='2';
if(exif_time.rtc_year>=100)
{
exif_sys_time[1]='1';
exif_time.rtc_year-=100;
}
else
exif_sys_time[1]='0';
exif_sys_time[2]=(exif_time.rtc_year/10)+48;
exif_sys_time[3]=(exif_time.rtc_year%10)+48;
exif_sys_time[5]=(exif_time.rtc_mon/10)+48;
exif_sys_time[6]=(exif_time.rtc_mon%10)+48;
exif_sys_time[8]=(exif_time.rtc_day/10)+48;
exif_sys_time[9]=(exif_time.rtc_day%10)+48;
exif_sys_time[11]=(exif_time.rtc_hour/10)+48;
exif_sys_time[12]=(exif_time.rtc_hour%10)+48;
exif_sys_time[14]=(exif_time.rtc_min/10)+48;
exif_sys_time[15]=(exif_time.rtc_min%10)+48;
exif_sys_time[17]=(exif_time.rtc_sec/10)+48;
exif_sys_time[18]=(exif_time.rtc_sec%10)+48;
}
/* Set preDefined values to some of the IFD entries */
exif_cam_para_struct* exif_get_cam_para_struct(void)
{
exif_get_sys_time();
exif_cam_para.Orientation=1;
exif_cam_para.XResolution[0]=72;
exif_cam_para.XResolution[1]=1;
exif_cam_para.YResolution[0]=72;
exif_cam_para.YResolution[1]=1;
exif_cam_para.ResolutionUnit=2; /* inches */
exif_cam_para.Software=(kal_char*)release_verno();
exif_cam_para.DateTime=exif_sys_time; //"yyyy:mm:dd hh:mm:ss";
exif_cam_para.YCbCrPositioning=2;/* co-siteded */
/* Exif IFD default values */
exif_cam_para.ExposureTime[0]=0;
exif_cam_para.ExposureTime[1]=0;
exif_cam_para.FNumber[0]=0;
exif_cam_para.FNumber[1]=0;
exif_cam_para.ExposureProgram=0; /* Unknown*/
exif_cam_para.ISOSpeedRatings=0;
exif_cam_para.ExifVersion[3]='0';/* Supported Exif Version: 2.2*/
exif_cam_para.ExifVersion[2]='2';
exif_cam_para.ExifVersion[1]='2';
exif_cam_para.ExifVersion[0]='0';
exif_cam_para.DateTimeOriginal=0;
exif_cam_para.DateTimeDigitized=0;
exif_cam_para.ComponentsConfig[0]=1; /* YCbCr */
exif_cam_para.ComponentsConfig[1]=2;
exif_cam_para.ComponentsConfig[2]=3;
exif_cam_para.ComponentsConfig[3]=0;
exif_cam_para.ExposureBiasValue[0]=0;
exif_cam_para.ExposureBiasValue[1]=1;
exif_cam_para.MeteringMode=0;
exif_cam_para.LightSource=0;
exif_cam_para.Flash=0;
exif_cam_para.FlashpixVersion[3]='0';
exif_cam_para.FlashpixVersion[2]='0';
exif_cam_para.FlashpixVersion[1]='1';
exif_cam_para.FlashpixVersion[0]='0';
exif_cam_para.ColorSpace=1; /* sRGB */
exif_cam_para.PixelXDimension=0;
exif_cam_para.PixelYDimension=0;
exif_cam_para.ExposureMode=0; /* auto exposure */
exif_cam_para.DigitalZoomRatio[0]=1;
exif_cam_para.DigitalZoomRatio[1]=1;
exif_cam_para.SceneCaptureType=0; /* standard */
cam_para_get=KAL_TRUE;
exif_switch_cam_entry(EXIF_SWITCH_ON);
/* Temporly switch FNumber off*/
exif_switch_IFD_entry(EXIF_EXIFIFD,EXIF_FNUMBER,EXIF_SWITCH_OFF);
return &exif_cam_para;
}
exif_MTK_para_struct* exif_get_MTK_para_struct(void)
{
strcpy(exif_MTK_para.title,"MediaTek");
exif_MTK_para.version[0]=exif_MTK_specific_ver_main;
exif_MTK_para.version[1]=exif_MTK_specific_ver_fraction;
exif_update_MTK_para_struct(&exif_MTK_para);
cam_para_get=KAL_TRUE;
exif_switch_IFD_entry(EXIF_EXIFIFD,EXIF_MAKER_NOTE,EXIF_SWITCH_ON);
return &exif_MTK_para;
}
kal_uint16 exif_Fillin_Buffer(kal_uint8* Buffer,kal_uint32 BufferOffset)
{
kal_uint16 BufferSize;
ExIFD=exif_get_custom_specific_IFD(&ExIFD_Number_of_Entry);
exif_check_ExIFD_data();
BufferSize=exif_Calculate_Buffer_Size(BufferOffset);
if(BufferSize==0)
return BufferSize;
else if(BufferSize>EXIF_MAXIMUM_SIZE)
ASSERT(0);
exif_Fillin_Header(Buffer,BufferOffset);
return BufferSize;
}
/* Used for MT6227*/
kal_uint16 exif_get_custom_IFD_and_buffer_size(kal_uint32 BufferOffset)
{
kal_uint16 BufferSize;
ExIFD=exif_get_custom_specific_IFD(&ExIFD_Number_of_Entry);
exif_check_ExIFD_data();
BufferSize=exif_Calculate_Buffer_Size(BufferOffset);
if(BufferSize>EXIF_MAXIMUM_SIZE)
ASSERT(0);
return BufferSize;
}
/* Accumulate the Exif Buffer Size */
kal_uint16 exif_Calculate_Buffer_Size(kal_uint32 BufferOffset)
{
kal_uint8 i;
kal_uint32 mask=1;
if(!cam_para_get && !cus_para_get)
return 0;
//return exif_Overlap_Offset;
IFD0_Entry_Size=0;
IFD0_Value_Size=0;
ExifIFD_Entry_Size=0;
ExifIFD_Value_Size=0;
exif_IFD0_count=0;
exif_ExifIFD_count=0;
//--Acc ExifIFD--
if(exif_is_switched_on(EXIF_IFD0,EXIF_EXIF_IFD))
{
mask=1;
for(i=0;i<ExifIFD_Number_of_Entry;i++)
{
if((exif_ExifIFD_Entry_Switch & mask)==0)// This entry is switched off
{
mask<<=1;
continue;
}
exif_Acc_IFD_Size(&ExifIFD[i],&exif_ExifIFD_count,&ExifIFD_Entry_Size,&ExifIFD_Value_Size);
mask<<=1;
}
}
//--Acc ExIFD--
for(i=0;i<ExIFD_Number_of_Entry;i++)
{
if(ExIFD[i].exif_IFD_type==EXIF_IFD0)
exif_Acc_IFD_Size(&ExIFD[i].entry,&exif_IFD0_count,&IFD0_Entry_Size,&IFD0_Value_Size);
else if(ExIFD[i].exif_IFD_type==EXIF_EXIFIFD && exif_is_switched_on(EXIF_IFD0,EXIF_EXIF_IFD))
exif_Acc_IFD_Size(&ExIFD[i].entry,&exif_ExifIFD_count,&ExifIFD_Entry_Size,&ExifIFD_Value_Size);
}
//--Acc IFD0--
mask=1;
for(i=0;i<EXIF_EXIF_IFD;i++)
{
if((exif_IFD0_Entry_Switch & mask)==0)// This entry is switched off
{
mask<<=1;
continue;
}
exif_Acc_IFD_Size(&IFD0[i],&exif_IFD0_count,&IFD0_Entry_Size,&IFD0_Value_Size);
mask<<=1;
}
//--Acc ExifIFD entry of IFD0--
if(exif_ExifIFD_count>0 && exif_is_switched_on(EXIF_IFD0,EXIF_EXIF_IFD))
exif_Acc_IFD_Size(&IFD0[EXIF_EXIF_IFD],&exif_IFD0_count,&IFD0_Entry_Size,&IFD0_Value_Size);
if(exif_IFD0_count==0 && exif_ExifIFD_count==0)
return 0;
//return exif_Overlap_Offset;
if(exif_IFD0_count>0)
IFD0_Entry_Size+=(2+4);
if(exif_ExifIFD_count>0)
ExifIFD_Entry_Size+=(2+4);
/*-- Get TiffHeaderOffset --*/
IFD_TiffHeader_Offset=BufferOffset+exif_header_size;
exif_BufferSize=exif_header_size+tiff_header_size+IFD0_Entry_Size+IFD0_Value_Size+ExifIFD_Entry_Size+ExifIFD_Value_Size;
/*//-- 4 bytes align--
if(exif_BufferSize & 0x03 !=0)
exif_BufferSize=((exif_BufferSize+4)>>2)<<2;
*/
/*--Fill in the length field of app0 marker--*/
exif_Header[2]=(exif_BufferSize-2)>>8 & 0xff;
exif_Header[3]=(exif_BufferSize-2) & 0xff;
/*--Fill IFD0 ExifIFD entry. 12: jpeg SOI marker and exif header, 8: Tiff Header --*/
exif_ExifIFD_Offset=BufferOffset+exif_header_size+tiff_header_size+IFD0_Entry_Size+IFD0_Value_Size-IFD_TiffHeader_Offset;
return exif_BufferSize;
}
kal_bool exif_Acc_IFD_Size(exif_entry_struct* Exif_entry,kal_uint16* IFD_entry_count,kal_uint16* IFD_Entry_Size,kal_uint16* IFD_Value_Size)
{
if(Exif_entry->type!=EXIF_ASCII && Exif_entry->count==0)
ASSERT(0);
switch(Exif_entry->type)
{
case EXIF_ASCII:
if(*((char**)Exif_entry->value)!=0)
{
(*IFD_Entry_Size)+=12;
Exif_entry->count=exif_Accumulate_ASCII(*((char**)Exif_entry->value),IFD_Value_Size);
(*IFD_entry_count)++;
}
break;
case EXIF_SRATIONAL:
case EXIF_RATIONAL:
(*IFD_Entry_Size)+=12;
//(*IFD_Value_Size)+=8;
(*IFD_Value_Size)+=(8*Exif_entry->count);
(*IFD_entry_count)++;
break;
case EXIF_SHORT:
(*IFD_Entry_Size)+=12;
if(Exif_entry->count>2)
(*IFD_Value_Size)+=(2*Exif_entry->count);
(*IFD_entry_count)++;
break;
case EXIF_LONG:
(*IFD_Entry_Size)+=12;
if(Exif_entry->count>1)
(*IFD_Value_Size)+=(4*Exif_entry->count);
(*IFD_entry_count)++;
break;
case EXIF_UNDEFINED:
(*IFD_Entry_Size)+=12;
if(Exif_entry->count>4)
{
(*IFD_Value_Size)+=Exif_entry->count;
if(Exif_entry->count & 1 !=0)/*Force to half-word aligned*/
(*IFD_Value_Size)++;
}
(*IFD_entry_count)++;
break;
default:
ASSERT(0);
//return KAL_FALSE;
}
return KAL_TRUE;
}
kal_uint16 exif_Accumulate_ASCII(char* str,kal_uint16* IFD_Value_Size)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -