Android P 分析 HAL3 图片信息 exif

3 篇文章 0 订阅

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 information
    mDbgInfo.clear();
    mMapModuleID.clear();
    //
    // Exif Utilitis
    mpBaseExif = 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 ; // sRGB
    mICCIdx = ::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 width
    MUINT32     u4ImageHeight;      // Image height
    //
    MUINT32     u4FNumber;          // Format: F2.8 = 28
    MUINT32     u4FocalLength;      // Format: FL 3.5 = 350
    MUINT32     u4FocalLength35mm;  // Format: FL35mm 28 = 28
    MUINT32     u4AWBMode;          // White balance mode
    MUINT32     u4LightSource;      // Light Source mode
    MUINT32     u4ExpProgram;       // Exposure Program
    MUINT32     u4SceneCapType;     // Scene Capture Type
    MUINT32     u4FlashLightTimeus; // Strobe on/off
    MUINT32     u4AEMeterMode;      // Exposure metering mode
    MINT32      i4AEExpBias;        // Exposure index*10
    MUINT32     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, 270
    MUINT32     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 front
    MUINT32     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 return
    rOutputExifSize = 0;
    MY_LOGI("out buffer(%#" PRIxPTR ")", getBufAddr());

    unsigned int u4OutputExifSize = 0;
    exifAPP1Info_s exifApp1Info;
    exifImageInfo_s exifImgInfo;

    //  (1) Fill exifApp1Info
    updateStdExif(&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 App2
    int 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);
    }
    else
        MY_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 exif
    if ( isEnableDbgExif() )
    {
        updateDbgExif();
    }

    return (status_t)ret;
}

 

上述代码简要概述了相机拍照时 JpegNode 调用 StdExif 生成照片详细信息的流程。

如果需要加入自定义的照片信息,修改 StudExif.cpp 即可。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值