使用Image\_NativeModule读取和编辑图片Exif信息
==================================

Image Kit提供图片Exif信息的读取与编辑能力。

Exif（Exchangeable image file format）是专门为数码相机的照片设定的文件格式，可以记录数码照片的属性信息和拍摄数据。需要图片包含Exif信息。

在图库、相机、图片编辑等应用中，开发者可以读取图片的拍摄时间、方向、焦距、地理位置等Exif信息，也可以在需要时修改部分Exif信息。例如，当摄像机的手动镜头参数无法自动写入Exif信息，或者因相机断电导致拍摄时间错误时，可手动修正对应的Exif数据。

系统目前仅支持读取和修改部分Exif信息，具体支持范围请参见[变量](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-image-common-h#变量)里的OHOS\_IMAGE\_PROPERTY\_XXX类型。不同图片格式对Exif信息的读写支持情况如下。

| 图片格式 | 读取Exif信息 | 修改Exif信息 |
| :-- | :-- | :-- |
| JPG/JPEG | 支持 | 支持 |
| PNG | 支持 | 支持 |
| HEIF | 支持 | 支持 |
| WebP23+ | 支持 | 支持 |
| DNG23+ | 支持 | 不支持 |

#### 接口说明

Exif信息的读取与编辑相关C API如下，详细介绍请参考[image\_source\_native.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-image-source-native-h)。

| 接口 | 说明 |
| :-- | :-- |
| [OH\_ImageSourceNative\_GetImageProperty()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-image-source-native-h#oh_imagesourcenative_getimageproperty) | 获取指定属性键的Exif信息。 |
| [OH\_ImageSourceNative\_ModifyImageProperty()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-image-source-native-h#oh_imagesourcenative_modifyimageproperty) | 修改指定属性键的Exif信息。 |

#### 注意事项

*   需要先创建OH\_ImageSourceNative对象，再读取或编辑Exif信息。
*   读取图片Exif信息前，需要确保应用对目标图片具有读取权限；修改图片Exif信息前，需要确保应用对目标图片具有写入权限。
*   在部分图片来源或访问场景下，即使应用具有图片读取权限，系统也可能对GPS等隐私信息进行去隐私化处理，此时无法获取对应的Exif信息。
*   图片文件需要包含Exif信息。对于没有Exif信息或不包含目标属性键的图片，读取结果可能为空或返回错误码。
*   修改Exif信息前，需要确认图片格式和目标属性键支持写入。
*   图片元数据可能包含拍摄位置等隐私信息，应用展示、上传或共享前应结合业务场景做好用户授权和隐私保护。

#### 开发步骤

#### \[h2\]添加链接库

在进行应用开发之前，开发者需要打开Native工程的src/main/cpp/CMakeLists.txt，在target\_link\_libraries依赖中添加libimage\_source.so以及日志依赖libhilog\_ndk.z.so。

target\_link\_libraries(entry PUBLIC libhilog\_ndk.z.so libimage\_source.so)

#### \[h2\]Native接口调用

在DevEco Studio中新建Native C++应用，默认生成的项目中包含index.ets文件，在entry/src/main/cpp目录下会自动生成一个cpp文件（hello.cpp或napi\_init.cpp，本示例以hello.cpp文件名为例）。在hello.cpp中实现C API接口调用逻辑，示例代码如下：

**读取和编辑图片Exif信息接口使用示例**

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/0/v3/iRAzIX-IRriUhrtlpcIXnQ/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073520Z&HW-CC-Expire=86400&HW-CC-Sign=679881F11830E8323C5FCBD6C8BC058C4E126C305B5556920F00D69301882C45)

部分接口从API version 20开始支持，需要开发者在进行开发时选择合适的API版本。

1.  导入相关头文件。
    
    #include <string>
    #include <hilog/log.h>
    #include <multimedia/image\_framework/image/image\_source\_native.h>
    #include "napi/native\_api.h"
    
2.  日志宏定义可参考下述代码按实际需求自行修改。
    
    #undef LOG\_DOMAIN
    #undef LOG\_TAG
    #define LOG\_DOMAIN 0x3200
    #define LOG\_TAG "IMAGE\_SAMPLE"
    
3.  定义ImageSourceNative类。
    
    class ImageSourceNative {
    public:
        OH\_ImageSource\_Info \*imageInfo;
        OH\_ImageSourceNative \*source = nullptr;
        OH\_PixelmapNative \*resPixMap = nullptr;
        OH\_Pixelmap\_ImageInfo \*pixelmapImageInfo = nullptr;
        uint32\_t frameCnt = 0;
        ImageSourceNative() {}
        ~ImageSourceNative() {}
    };
    
4.  创建ImageSourceNative的一个实例。
    
    static ImageSourceNative \*g\_thisImageSource = new ImageSourceNative();
    
5.  创建GetJsResult函数处理napi返回值。
    
    // 处理napi返回值。
    napi\_value GetJsResult(napi\_env env, int result)
    {
        napi\_value resultNapi = nullptr;
        napi\_create\_int32(env, result, &resultNapi);
        return resultNapi;
    }
    
6.  在成功创建ImageSource对象后，读取、编辑Exif信息。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c8/v3/CDq4azWASWKN7bv9B994WQ/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073520Z&HW-CC-Expire=86400&HW-CC-Sign=61D81E1007111A3BCDC4DE69A12CA6075AF38B3D7ECE27F9FF8A9F87C6C73BBF)
    
    创建ImageSource对象可参考[图片解码](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/image-source-c)。
    
    // 获取指定property的value值。
    napi\_value GetImageProperty(napi\_env env, napi\_callback\_info info)
    {
        napi\_value argValue\[1\] = {nullptr};
        size\_t argCount = 1;
        if (napi\_get\_cb\_info(env, info, &argCount, argValue, nullptr, nullptr) != napi\_ok || argCount < 1 ||
            argValue\[0\] == nullptr) {
            OH\_LOG\_ERROR(LOG\_APP, "GetImageProperty napi\_get\_cb\_info failed!");
            return GetJsResult(env, IMAGE\_BAD\_PARAMETER);
        }
        // 修改指定属性键的值。
        char key\[MAX\_STRING\_LENGTH\];
        size\_t keySize = MAX\_STRING\_LENGTH;
        napi\_get\_value\_string\_utf8(env, argValue\[0\], (char \*)key, sizeof(key), &keySize);
        Image\_String getKey;
        getKey.data = key;
        getKey.size = keySize;
        Image\_String getValue = {nullptr, 0};
        OH\_LOG\_INFO(LOG\_APP, "OH\_ImageSourceNative\_GetImageProperty key: %{public}s.", getKey.data);
        Image\_ErrorCode errCode = OH\_ImageSourceNative\_GetImagePropertyWithNull(g\_thisImageSource->source,
                                                                                &getKey, &getValue);
        if (errCode != IMAGE\_SUCCESS) {
            OH\_LOG\_ERROR(LOG\_APP, "OH\_ImageSourceNative\_GetImageProperty failed, errCode: %{public}d.", errCode);
            if (getValue.data != nullptr) {
                free(getValue.data);
                getValue.data = nullptr;
            }
            return GetJsResult(env, errCode);
        }
        napi\_value resultNapi = nullptr;
        napi\_create\_string\_utf8(env, getValue.data, getValue.size, &resultNapi);
        free(getValue.data);
        getValue.data = nullptr;
        return resultNapi;
    }
    
    // 修改指定property的value值。
    napi\_value ModifyImageProperty(napi\_env env, napi\_callback\_info info)
    {
        napi\_value argValue\[2\] = {nullptr};
        size\_t argCount = 2;
        const size\_t minCount = 2;
        if (napi\_get\_cb\_info(env, info, &argCount, argValue, nullptr, nullptr) != napi\_ok || argCount < minCount ||
            argValue\[0\] == nullptr || argValue\[1\] == nullptr) {
            OH\_LOG\_ERROR(LOG\_APP, "ModifyImageProperty napi\_get\_cb\_info failed!");
            return GetJsResult(env, IMAGE\_BAD\_PARAMETER);
        }
    
        // 获取要修改的key值。
        char key\[MAX\_STRING\_LENGTH\];
        size\_t keySize = MAX\_STRING\_LENGTH;
        napi\_get\_value\_string\_utf8(env, argValue\[0\], (char \*)key, sizeof(key), &keySize);
        Image\_String setKey;
        setKey.data = key;
        setKey.size = keySize;
        OH\_LOG\_INFO(LOG\_APP, "ModifyImageProperty key: %{public}s.", setKey.data);
        
        // 获取要修改的value值。
        char value\[MAX\_STRING\_LENGTH\];
        size\_t valueSize;
        napi\_get\_value\_string\_utf8(env, argValue\[1\], (char \*)value, MAX\_STRING\_LENGTH, &valueSize);
        Image\_String setValue;
        setValue.data = value;
        setValue.size = valueSize;
        OH\_LOG\_INFO(LOG\_APP, "ModifyImageProperty value: %{public}s.", setValue.data);
    
        Image\_ErrorCode errCode = OH\_ImageSourceNative\_ModifyImageProperty(g\_thisImageSource->source, &setKey, &setValue);
        return GetJsResult(env, errCode);
    }