jpeg Exif file format Marker APP1 简介
jpeg Exif file format Marker APP1 分析
Android P 分析 HAL3 JpegNode 生成图片流程
我的设备 MTK cpu , Android P
在相册中查看手机拍摄的照片详情, 图片的相关信息: 制造商、日期、曝光时间、焦距、光圈值、GPS等信息。
那么拍摄照片的过程中是如何生成照片详情信息的呢?
照片中的信息保存的格式是 EXIF 。关于 Jpeg EIXF 的知识参考 jpeg Exif file format Marker APP1 简介 。
在分析 JpegNode 拍照pipeline 时,找到了 Jpeg EXIF 的代码。在这里简要分析。
代码位置:
vendor\mediatek\proprietary\hardware\mtkcam\utils\exif\v3\StdExif.cpp
vendor\mediatek\proprietary\hardware\mtkcam\include\mtkcam\utils\exif\IBaseCamExif.h -> ExifParams
初始化函数如下:
初始化 ExifParams 的值。
MBOOL
StdExif::
init(ExifParams const& rExifParams,MBOOL const enableDbgExif
)
{mExifParam = rExifParams;MY_LOGI("mpExifParam(%p) ImageSize(%dx%d) FNumber(%d/10) FocalLegth(%d/1000) AWBMode(%d) Strobe(%d) AEMeterMode(%d) AEExpBias(%d)",&mExifParam, mExifParam.u4ImageWidth, mExifParam.u4ImageHeight, mExifParam.u4FNumber, mExifParam.u4FocalLength,mExifParam.u4AWBMode, mExifParam.u4FlashLightTimeus, mExifParam.u4AEMeterMode, mExifParam.i4AEExpBias);MY_LOGI("CapExposureTime(%d) AEISOSpeed(%d) LightSource(%d) ExpProgram(%d) SceneCapType(%d) Orientation(%d) ZoomRatio(%d) Facing(%d) ICC(%d)",mExifParam.u4CapExposureTime, mExifParam.u4AEISOSpeed, mExifParam.u4LightSource, mExifParam.u4ExpProgram,mExifParam.u4SceneCapType, mExifParam.u4Orientation, mExifParam.u4ZoomRatio, mExifParam.u4Facing, mExifParam.u4ICCIdx);MY_LOGI("GPS(%d), Altitude(%d), Latitude(%s), Longitude(%s), TimeStamp(%s), ProcessingMethod(%s)",mExifParam.u4GpsIsOn, mExifParam.u4GPSAltitude, mExifParam.uGPSLatitude,mExifParam.uGPSLongitude, mExifParam.uGPSTimeStamp, mExifParam.uGPSProcessingMethod);// DebugExif: reset debug informationmDbgInfo.clear();mMapModuleID.clear();//// Exif UtilitismpBaseExif = new ExifUtils();if ( !(mpBaseExif->init(mExifParam.u4GpsIsOn)) ){MY_LOGE("mpBaseExif->init() fail");return MFALSE;}//mpDebugIdMap = new ExifIdMap();//mbEnableDbgExif = enableDbgExif;mApp1Size = mpBaseExif->exifApp1SizeGet();mDbgAppnSize = isEnableDbgExif() ? (APPN_SIZE*APPN_COUNT) : 0;mICCIdx = mExifParam.u4ICCIdx ; // sRGBmICCIdx = ::property_get_int32("jpeg.exif.icc.profile", mExifParam.u4ICCIdx);mICCSize = mICCIdx==EXIF_ICC_PROFILE_SRGB ? sizeof(icc_profile_srgb)/sizeof(int8_t) :(mICCIdx==EXIF_ICC_PROFILE_DCI_P3 ? sizeof(icc_profile_display_p3)/sizeof(int8_t) : 0) ;MY_LOGD_IF(mLogLevel, "ICCIdx %d ICCSize %zu", mICCIdx, mICCSize);//if ( ! getDebugExif() ) {MY_LOGE("bad getDebugExif()");return MFALSE;}//if ( ! getBufInfo_cam() ) {MY_LOGE("bad getBufInfo_cam()");return MFALSE;}//return MTRUE;
}
ExifParams 结构体
struct ExifParams {MUINT32 u4ImageWidth; // Image widthMUINT32 u4ImageHeight; // Image height//MUINT32 u4FNumber; // Format: F2.8 = 28MUINT32 u4FocalLength; // Format: FL 3.5 = 350MUINT32 u4FocalLength35mm; // Format: FL35mm 28 = 28MUINT32 u4AWBMode; // White balance modeMUINT32 u4LightSource; // Light Source modeMUINT32 u4ExpProgram; // Exposure ProgramMUINT32 u4SceneCapType; // Scene Capture TypeMUINT32 u4FlashLightTimeus; // Strobe on/offMUINT32 u4AEMeterMode; // Exposure metering modeMINT32 i4AEExpBias; // Exposure index*10MUINT32 u4CapExposureTime; //MUINT32 u4AEISOSpeed; // AE ISO value//MUINT32 u4GpsIsOn;MUINT32 u4GPSAltitude;MUINT8 uGPSLatitude[32];MUINT8 uGPSLongitude[32];MUINT8 uGPSTimeStamp[32];MUINT8 uGPSProcessingMethod[64]; //(values of "GPS", "CELLID", "WLAN" or "MANUAL" by the EXIF spec.)//MUINT32 u4Orientation; // 0, 90, 180, 270MUINT32 u4ZoomRatio; // Digital zoom ratio (x100) For example, 100, 114, and 132 refer to 1.00, 1.14, and 1.32 respectively.//MUINT32 u4Facing; // 1: front camera, 0: not frontMUINT32 u4ICCIdx;//
public: Operations.ExifParams() { ::memset(this, 0, sizeof(ExifParams)); }};
生成 EXIF 格式流
void
StdExif::
updateStdExif(exifAPP1Info_s* exifApp1Info)
{/*********************************************************************************GPS**********************************************************************************/
.../*********************************************************************************common**********************************************************************************/
.../*********************************************************************************3A**********************************************************************************/
.../*********************************************************************************update customized exif**********************************************************************************/
.../*********************************************************************************MISC**********************************************************************************/// [flashPixVer]memcpy(exifApp1Info->strFlashPixVer, "0100 ", 5);// [exposure mode]exifApp1Info->exposureMode = 0; // 0 means Auto exposure}
JPEGNode 调用 StdExif 的 make 方法
如下代码,第一步调用 updateStdExif(&exifApp1Info); 生成 EXIF APP1
status_t
StdExif::
make(MUINTPTR const outputExifBuf,size_t& rOutputExifSize
)
{int ret = 0;mpOutputExifBuf = outputExifBuf;// set 0 first for error returnrOutputExifSize = 0;MY_LOGI("out buffer(%#" PRIxPTR ")", getBufAddr());unsigned int u4OutputExifSize = 0;exifAPP1Info_s exifApp1Info;exifImageInfo_s exifImgInfo;// (1) Fill exifApp1InfoupdateStdExif(&exifApp1Info);// (2) Fill exifImgInfo::memset(&exifImgInfo, 0, sizeof(exifImageInfo_t));exifImgInfo.bufAddr = getBufAddr();exifImgInfo.mainWidth = mExifParam.u4ImageWidth;exifImgInfo.mainHeight = mExifParam.u4ImageHeight;exifImgInfo.thumbSize = getThumbnailSize();ret = mpBaseExif->exifApp1Make(&exifImgInfo, &exifApp1Info, &u4OutputExifSize);rOutputExifSize = (size_t)u4OutputExifSize;// (4) Append App2int app2 = 2;unsigned int app2ReturnSize = 0;int size = mICCSize; // Data(n bytes)unsigned char *pAddr = (unsigned char*)getBufAddr()+ getStdExifSize() + getThumbnailSize();MY_LOGD_IF(mLogLevel,"offset %zu buf %p ", getBufAddr(), getStdExifSize() + getThumbnailSize() , pAddr);if(mICCIdx == EXIF_ICC_PROFILE_SRGB) {ret = mpBaseExif->exifAppnMake(app2, pAddr, (unsigned char*)&icc_profile_srgb, size, &app2ReturnSize, 0);}else if(mICCIdx == EXIF_ICC_PROFILE_DCI_P3) {ret = mpBaseExif->exifAppnMake(app2, pAddr, (unsigned char*)&icc_profile_display_p3, size, &app2ReturnSize, 0);}elseMY_LOGE("not support ICC profile %d", mICCIdx);// return app2ReturnSize is mICCSize + 2 +2 (Data(n bytes) + Data size(2 bytes) + Data tag(2 bytes))// (3) Append debug exifif ( isEnableDbgExif() ){updateDbgExif();}return (status_t)ret;
}
上述代码简要概述了相机拍照时 JpegNode 调用 StdExif 生成照片详细信息的流程。
如果需要加入自定义的照片信息,修改 StudExif.cpp 即可。