C#如何向JPEG文件写入字符串类型EXIF元数据?
解决EXIF字符串类型元数据(如拍摄时间)写入问题
你遇到的问题核心在于EXIF字符串字段有严格的格式和编码要求,尤其是像拍摄时间这类日期时间字段,必须完全符合EXIF规范才能成功写入,而非简单传递任意字符串。以下是具体解决步骤和代码示例:
关键注意事项
- EXIF日期时间格式:必须严格遵循
yyyy:MM:dd HH:mm:ss格式,分隔符用冒号(不能用斜杠或其他符号),例如2024:05:20 14:30:00。 - 正确的查询路径:不同EXIF字符串字段对应不同查询路径,比如拍摄时间(DateTimeOriginal)的路径是
/app1/{ushort=0}/{ushort=36867}(标签值0x9003)。 - 编码要求:EXIF字符串字段默认使用ASCII编码,避免包含非ASCII字符,否则可能写入失败。
完整读写示例(拍摄时间)
读取拍摄时间
string imagePath = @"C:\Users\xxxx\Desktop\xxxx.JPG"; string dateQuery = "/app1/{ushort=0}/{ushort=36867}"; // DateTimeOriginal标签 // 读取逻辑 using (FileStream stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read)) { BitmapFrame bitmapFrame = BitmapFrame.Create(stream); BitmapMetadata metadata = (BitmapMetadata)bitmapFrame.Metadata; if (metadata.ContainsQuery(dateQuery)) { string originalDate = metadata.GetQuery(dateQuery) as string; Console.WriteLine($"原拍摄时间:{originalDate}"); } }
写入新的拍摄时间
string newDate = "2024:05:20 14:30:00"; // 严格符合EXIF格式 using (FileStream stream = new FileStream(imagePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { BitmapFrame bitmapFrame = BitmapFrame.Create(stream); InPlaceBitmapMetadataWriter metadataWriter = bitmapFrame.CreateInPlaceBitmapMetadataWriter(); // 先确认支持原地写入 if (!metadataWriter.TrySave()) { throw new IOException("图片不支持原地修改元数据"); } // 设置新的拍摄时间 metadataWriter.SetQuery(dateQuery, newDate); if (!metadataWriter.TrySave()) { throw new IOException("写入拍摄时间失败"); } }
常见问题排查
- 写入失败但无报错:检查字符串格式是否完全符合
yyyy:MM:dd HH:mm:ss,比如是否用了斜杠代替冒号,或者日期时间值非法(如月份超过12)。 - 仅能写入短字符串:大概率是编码或格式问题,确保字符串是纯ASCII字符,且符合对应EXIF字段的格式要求(比如作者字段可使用任意ASCII字符串,但日期时间必须严格遵循格式)。
- 原地写入失败:部分图片(如经过编辑压缩的JPEG)可能不支持原地修改元数据,此时需要将图片复制到新流中,写入元数据后保存为新文件:
// 非原地写入示例 using (FileStream inputStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read)) using (FileStream outputStream = new FileStream(imagePath + "_new.jpg", FileMode.Create, FileAccess.Write)) { BitmapFrame bitmapFrame = BitmapFrame.Create(inputStream); BitmapMetadata metadata = (BitmapMetadata)bitmapFrame.Metadata.Clone(); metadata.SetQuery(dateQuery, newDate); BitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmapFrame, bitmapFrame.Thumbnail, metadata, bitmapFrame.ColorContexts)); encoder.Save(outputStream); }
内容的提问来源于stack exchange,提问作者Daniel Müller
相关产品推荐
相关产品推荐

