Coding

如何修改图像的 EXIF 头信息?

使用exiv2修改图像的EXIF头信息

JamzumSum · ·updated 2026年6月21日 · 3 min read
Structure
Structure Photo by @estherrj.

笔者编写了一个下载 Bing 必应美图的程序。然而笔者一直想修改一下 这个东西。当时查阅了"详细信息""属性"等相关信息,但未找到可行方法。

某日通过对比试验发现,修改了详细信息的 JPEG 文件会多出一个"头部",经查证此为 EXIF 头信息,于是有了下文。

编译 Exiv2

下文简要介绍通过搜索找到的 Exiv2 库的编译与使用过程。

从 Exiv2 官网下载了 2017msvc64 的 build 包,加载到项目中即出现编译错误。错误信息显示缺少 std::auto_ptr 类型。该类型在 C++11 中已被弃用,C++17 时已移除。由于项目使用 C++17 标准,因此该类型不再可用。笔者倾向于使用较新的语言标准,因此决定自行编译 Exiv2。

git clone

从仓库拉取最新源码(仓库地址可在官网下载页找到)。

用 VS CMake 编译 Exiv2

笔者对 CMake 并不熟悉,但 Visual Studio 提供了对 CMake 的支持。此前编译 tesseract 时已初步接触过 CMake。

在 exiv2 文件夹中通过右键菜单选择"用 Visual Studio 打开",VS 将自动建立 CMake 缓存,可在"输出"选项卡中查看进度。

随后遇到错误提示找不到 EXPAT,通过 vcpkg 安装解决:

vcpkg install expat:x64-windows

注意:笔者使用 x64 平台编译,因此仅安装 64 位版本;若使用 x86 平台,还需安装对应版本。

vcpkg 在日常项目中表现一般,但在 CMake 场景下十分便捷,缺什么包只需一条命令即可安装。

依赖问题解决后,CMake 缓存正常。检查源码发现已不存在 auto_ptr 相关代码,可能是较新版本已修复此问题。

接下来需要指定 C++17 标准。笔者使用以下配置成功编译并通过测试:

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("/std:c++17" _cpp_17_flag_supported)
if (_cpp_17_flag_supported)
    add_compile_options("/std:c++17")
endif()

将上述代码附加到 CMakeLists.txt 末尾,全部生成并安装 Exiv2。

完成 Debug 版本编译后,建议在配置管理器中添加 Release 版本重复编译,以备发布使用。

使用 Exiv2

网上已有的教程多为读取 EXIF 信息,缺少写入的示例。笔者在此补充写入所需的额外步骤。

void BingPicker::addCopyRight(const QString& filepath, const QString& copyright) {
    using namespace Exiv2;
    // 这里已改用 unique_ptr
    Image::UniquePtr image = ImageFactory::open(filepath.toStdString());
    assert(image.get());

    image->readMetadata();
    ExifData ed = image->exifData();
    ed["Exif.Image.Copyright"] = copyright.toStdString();
    image->setExifData(ed);         // 注意此处
    image->writeMetadata();
}

写入的关键在于 setExifDatawriteMetadata 两个调用。笔者此前在网上未找到写入示例,最终在官方文档示例中找到并补全了这两句。

ExifData::operator[] 返回的是一个引用,若键不存在则会直接新建(类似于 mapoperator[]),用法直观,无需担心段错误。

结尾

本文撰写过程中参考了 StackOverflow 上的问题和回答(包括 CMake 切换 C++ 语言标准的代码)以及两篇 Exiv2 读取 EXIF 的教程。感谢所有相关教程的作者们。

源码已上传至 GitHub,同时提供 Release 版本可供下载。

分享
作者
JamzumSum

Open-source developer, major language: Python, C++.

Comments

Hook this up to your favourite commenting platform — Giscus, Disqus, or your own.

Continue reading