首页/新闻资讯/正文详情

在jpg图片添加Exif信息的C程序实现:TaoToken统一Key接入与config.toml配置骨架

发布时间:2026/9/27 17:30:45 来源:云帆数科 栏目:资讯中心
在jpg图片添加Exif信息的C程序实现:TaoToken统一Key接入与config.toml配置骨架
1. 为什么要在 C 程序里给 jpg 图片写 Exif 信息如果你在做嵌入式相机、图像采集盒、工业视觉设备或者只是想让自己的 C 程序输出的 jpg 图片带上拍摄时间、设备型号、GPS 坐标这些元数据那你迟早会碰到 Exif 写入这件事。Exif 全称 Exchangeable Image File Format是 jpg 文件里一段结构化的二进制数据块通常挂在 APP1 标记0xFFE1下面。它能让 Windows 资源管理器、手机相册、Lightroom 这些工具直接读出「这张图是谁拍的、什么时候拍的、用什么参数拍的」。问题在于很多 C 语言项目里没有现成的 Exif 库或者嵌入式环境根本不允许你引入 libexif 这种依赖。这时候就得自己按 JPEG 的段结构把 Exif 数据块拼出来再插到 SOI0xFFD8之后、原始图像数据之前。我试过在 Fedora 和 Windows 双环境下用纯 C 做这件事核心难点不在写代码而在于字节序、偏移量计算、APP1 长度字段、以及写入后如何验证字段真的被解析出来了。这篇内容面向的是嵌入式或图像处理场景的 C 开发者目标很明确给你一份可复制的 config.toml 配置骨架用 TaoToken 统一 Key 接入的方式管理你的模型调用凭证比如让模型帮你生成或校验 Exif 字段然后给出完整的编译运行步骤最后用读取 Exif 字段的动作来验证写入是否可复现。你不需要先成为 JPEG 格式专家跟着步骤走就能跑通。2. TaoToken 前置统一 Key 接入与 config.toml 配置骨架在开始写 C 代码之前先把凭证管理这件事理清楚。很多开发者的做法是把 API Key 硬编码在源码里或者散落在各个 shell 脚本中一旦要换环境就得全局搜索替换。TaoToken 提供的是统一 Key 接入方式你可以在一个 config.toml 里集中管理模型对话、coding plan、console 等不同用途的凭证C 程序通过读取这个配置文件来获取需要的 Key。先到官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册并登录然后在控制台里创建你的 API Key。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 进去之后找到 API Keys 页面新建一个 Key 并复制保存。如果你后续要做长期编码或 Agent 类任务可以顺带看一下 Coding Plan 页面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 那里有适合持续调用的套餐说明。拿到 Key 之后在你的项目根目录建一个 config.toml内容骨架如下。这个文件的作用是让 C 程序通过一个统一的入口读取配置而不是把敏感信息写死在代码里。# config.toml - TaoToken 统一 Key 接入配置骨架 # 适用于 C 程序读取 Exif 生成/校验所需的模型凭证 [taotoken] # 基础 API 地址不带 UTM 参数 api_base https://taotoken.net/api # 你的统一 Key从 console 的 API Keys 页面获取 api_key sk-你的实际Key粘贴在这里 # 默认使用的模型标识按你控制台里可用的填写 default_model claude-sonnet # 请求超时单位秒 timeout_sec 30 [taotoken.endpoints] # 模型对话入口用于让模型生成 Exif 字段建议值 chat /v1/chat/completions # 接入文档地址排障时查阅 doc https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite [exif] # Exif 写入相关参数供 C 程序读取 app1_marker 0xFFE1 max_exif_size 28800 thumbnail_width 320 thumbnail_height 240 # 默认写入的设备信息 default_make PSY default_model_name CSDN default_copyright Psy665All Rights Reserved这个骨架里[taotoken]段是核心C 程序启动时先解析它拿到 api_base 和 api_key。[exif]段则是把 Exif 写入时用到的常量集中管理避免在 makeExif.c 里到处写魔法数字。你可以在 C 代码里用一个简单的 ini/toml 解析函数读取这些值或者先用环境变量过渡但最终建议统一到 config.toml。注意config.toml 不要提交到公开仓库建议加入 .gitignore。生产环境可以用环境变量覆盖 api_key 字段。3. 可复制配置JPEG 段结构与 Exif 写入的 C 实现要点JPEG 文件的结构其实不复杂。它以 0xFFD8SOIStart of Image开头后面跟着若干段每段以 0xFF 加一个标记字节开始紧接着是两个字节的长度字段大端序包含长度字段本身但不包含标记。APP1 段的标记是 0xFFE1Exif 数据就放在这个段里。写入 Exif 的本质就是在 SOI 之后插入一个完整的 APP1 段然后把原始图像数据原样接在后面。下面这段 C 代码展示了核心的插入逻辑。它先打开源 jpg校验开头是不是 0xFFD8然后定位到 SOI 之后的位置把构造好的 Exif 缓冲区写进去再把原始数据追加上去。#include stdio.h #include stdlib.h #include string.h #include fcntl.h #include unistd.h #include sys/stat.h #define EXIF_FILE_SIZE 28800 // 将 Exif 缓冲区插入到 jpg 的 SOI 之后 int insert_exif_to_jpg(const char *src_path, const char *dst_path, unsigned char *exif_buf, int exif_len) { int src_fd open(src_path, O_RDONLY); if (src_fd 0) { perror(open src); return -1; } struct stat st; fstat(src_fd, st); int src_size st.st_size; unsigned char *src_data malloc(src_size); read(src_fd, src_data, src_size); close(src_fd); // 校验 SOI if (src_data[0] ! 0xFF || src_data[1] ! 0xD8) { printf(not a valid jpg: missing SOI\n); free(src_data); return -1; } int dst_fd open(dst_path, O_RDWR | O_CREAT | O_TRUNC, 0644); if (dst_fd 0) { perror(open dst); free(src_data); return -1; } // 写 SOI write(dst_fd, src_data, 2); // 写 Exif APP1 段 write(dst_fd, exif_buf, exif_len); // 写原始图像剩余数据 write(dst_fd, src_data 2, src_size - 2); printf(exif written: %d bytes, src: %d bytes, total: %d bytes\n, exif_len, src_size, exif_len src_size); close(dst_fd); free(src_data); return 0; }构造 Exif 缓冲区的部分需要按 TIFF 头 IFD0 Exif SubIFD 的顺序拼。TIFF 头固定 8 字节49 49 2A 00 08 00 00 00表示小端序、魔数 42、第一个 IFD 偏移为 8。IFD0 里放 Make、Model、Orientation、DateTime 这些基础字段每个条目 12 字节2 字节 tag、2 字节格式、4 字节组件数、4 字节值或偏移。如果值不超过 4 字节就直接内联否则写到数据区并在条目里填偏移。// 写入一个 IFD 条目的辅助函数 static void write_ifd_entry(unsigned char *buf, int *pos, unsigned short tag, unsigned short fmt, unsigned int count, unsigned int value) { buf[(*pos)] tag 0xFF; buf[(*pos)] (tag 8) 0xFF; buf[(*pos)] fmt 0xFF; buf[(*pos)] (fmt 8) 0xFF; buf[(*pos)] count 0xFF; buf[(*pos)] (count 8) 0xFF; buf[(*pos)] (count 16) 0xFF; buf[(*pos)] (count 24) 0xFF; buf[(*pos)] value 0xFF; buf[(*pos)] (value 8) 0xFF; buf[(*pos)] (value 16) 0xFF; buf[(*pos)] (value 24) 0xFF; }APP1 段的长度字段要算准它等于 Exif 数据总长度加 2长度字段自身。比如你构造的 Exif 数据是 1162 字节0x48A那么长度字段写 0x048C。写入后整个文件大小 原始大小 2APP1 标记 2长度字段 Exif 数据长度。这个计算在验证阶段会用到。4. 验证请求编译运行后读取 Exif 字段代码写完之后编译和运行是验证的第一步。在 Linux 下用 gcc 直接编译gcc -o make_exif makeExif.c -lm ./make_exif程序会读取 config.toml 里的路径参数把 in.jpg 处理后输出 out.jpg。运行成功后终端会打印类似exif written: 1162 bytes, src: 217437 bytes, total: 218599 bytes的信息。这时候你需要验证 Exif 字段是否真的被写进去了。最直接的方法是用 exiftool 读取exiftool out.jpg | grep -E Make|Model|DateTime|Copyright如果输出里能看到Make: PSY、Model: CSDN、Copyright: Psy665All Rights Reserved说明写入成功。另一个方法是写一个小的 C 读取程序定位到 APP1 段后解析 IFD0 条目// 简化的 Exif 读取验证定位 APP1 并打印 Make 字段 void verify_exif(const char *path) { FILE *fp fopen(path, rb); unsigned char hdr[4]; fread(hdr, 1, 4, fp); if (hdr[0] ! 0xFF || hdr[1] ! 0xE1) { printf(no APP1 at expected position\n); fclose(fp); return; } int app1_len (hdr[2] 8) | hdr[3]; printf(APP1 length field: %d (0x%X)\n, app1_len, app1_len); // 跳过 Exif\0\0 和 TIFF 头读取 IFD0 条目数 unsigned char tiff[8]; fseek(fp, 10, SEEK_SET); fread(tiff, 1, 8, fp); printf(TIFF header: %02X %02X %02X %02X\n, tiff[0], tiff[1], tiff[2], tiff[3]); fclose(fp); }运行这个验证函数如果 APP1 长度字段和 TIFF 头都符合预期就说明 Exif 块的结构是正确的。你还可以用 Windows 资源管理器右键查看图片属性在「详细信息」标签页里应该能看到相机型号和版权信息。如果这些字段显示出来了整条链路就打通了。提示验证时优先用 exiftool它比手写解析更可靠。手写解析主要用于嵌入式环境没有 exiftool 的场景。5. 本篇常见错排查写入 Exif 后图片打不开是最常见的报错。原因通常是 APP1 长度字段算错了。长度字段是 2 字节大端序值等于 Exif 数据长度加 2。如果你把长度写成了 Exif 数据长度本身解析器就会多读或少读字节导致后续段错位。排查方法用十六进制编辑器打开 out.jpg看第 5、6 个字节从 0 开始数是不是你预期的长度值。第二个坑是字节序。TIFF 头里的49 49表示小端序4D 4D表示大端序。如果你在 x86 机器上直接 memcpy 一个 unsigned int 到缓冲区得到的是小端序和49 49匹配。但如果你手动按大端写 tag 和长度就会和 TIFF 头声明的小端序冲突解析器读出来的字段全是乱的。统一用小端序或者统一用大端序不要混。第三个常见问题是偏移量基准。IFD 条目里的偏移是相对于 TIFF 头起始位置的不是相对于文件开头。很多人算偏移时从文件开头算结果数据区定位错了。记住TIFF 头从 APP1 段的第 6 个字节开始跳过 0xFFE1、长度、Exif\0\0所有偏移都从这个位置起算。第四个坑是 config.toml 读取失败。C 程序如果没有正确处理文件路径或权限会拿到空的 api_key 或默认值。排查时先在程序里打印读到的配置值确认 api_base 和 api_key 不是空字符串。如果用的是相对路径注意工作目录是否正确。如果遇到模型调用返回 401 或 403先检查 API Keys 页面里的 Key 是否还有效以及 config.toml 里的 api_base 是否写成了https://taotoken.net/api不要带 UTM 参数。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 可以查到完整的错误码说明。6. 接入与排障入口如果你在 Exif 写入过程中遇到编译错误或字段解析异常优先去 API Keys 页面确认凭证状态然后对照接入文档检查 config.toml 的字段拼写。API Keys 入口https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。接入文档入口https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。需要让模型帮你生成 Exif 字段的默认值或校验字节序时用模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。如果你打算把 Exif 写入做成长期运行的图像处理服务或者用 Agent 自动批量处理图片元数据可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。最后说一个实操细节写入 Exif 后原始图像数据一个字节都不能动。我见过有人在插入 APP1 时顺手重新编码了后面的数据结果图片能打开但画质变了。正确做法是只做插入原始数据原样拷贝。验证时除了看 Exif 字段也对比一下 out.jpg 去掉 APP1 段后和 in.jpg 是否完全一致用cmp或md5sum都能查。

相关推荐

爽!IDEA官宣接入Codex,TaoToken统一Key配置实战
爽!IDEA官宣接入Codex,TaoToken统一Key配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 17:30:39

从 0 到 1 构建营销 AI Agent Harness Engineering:TaoToken 统一 Key 接入内容生成、投放优化与效果分析实战
从 0 到 1 构建营销 AI Agent Harness Engineering:TaoToken 统一 Key 接入内容生成、投放优化与效果分析实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 17:30:39

CSS-鼠标属性篇:用 cursor 与 TaoToken 统一配置 AI 工具交互体验
CSS-鼠标属性篇:用 cursor 与 TaoToken 统一配置 AI 工具交互体验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 17:30:33

天津业之峰装饰公司官网改版避坑:最佳实践与SEO实战
天津业之峰装饰公司官网改版避坑:最佳实践与SEO实战

天津业之峰装饰公司官网改版避坑:最佳实践与SEO实战 模板网站太丑不够用,这是很多装修公司老板的痛点。看着同行那个页面流畅、加载飞快,自己手里拿到的却是千篇一律的模板,改个颜色都费劲,更别提SEO排名了。其实,想让【天津业之峰装饰公司官网】… · 2026/9/27 18:09:47

Hermes-Agent 开源自主智能体实战:用 TaoToken 统一 Key 打通多模型配置
Hermes-Agent 开源自主智能体实战:用 TaoToken 统一 Key 打通多模型配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 18:09:47

夯爆了!AI大模型毕业设计:YOLO+LangChain+LLM多模态电动车头盔载人检测预警系统配置实战
夯爆了!AI大模型毕业设计:YOLO+LangChain+LLM多模态电动车头盔载人检测预警系统配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 18:09:41

备案后修改网站内容完整流程:老手教你避开90%的坑
备案后修改网站内容完整流程:老手教你避开90%的坑

备案后修改网站内容完整流程:老手教你避开90%的坑 网站做好了没人访问,是不是让你心里发虚?别急,很多时候不是内容不够好,而是备案后的修改没搞对,导致搜索引擎抓取失败,或者用户访问时看到“解析错误”。… · 2026/9/27 18:09:41

Agent Skill 火爆全网:用 TaoToken 统一 Key 创建你的第一个渐进式智能体技能
Agent Skill 火爆全网:用 TaoToken 统一 Key 创建你的第一个渐进式智能体技能

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 18:09:41

备忘录:Trae 中带外部库的 Python 文件运行方式与 TaoToken 配置骨架
备忘录:Trae 中带外部库的 Python 文件运行方式与 TaoToken 配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 18:09:41

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现

简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01

汕头网站建设制作厂家避坑指南:5大注意事项救急
汕头网站建设制作厂家避坑指南:5大注意事项救急

汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01

多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习

简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码