在纯 Java 中读取图像、修改元数据和重写图像

我需要能够更新图像元数据(即标签、创建者、描述、评论)并在常规 Exif 和 XMP 中进行。最有可能的是,我将阅读 Exif,并编写 XMP。

在搜索了一个也可以用于写作的图书馆之后,我遇到了十二只猴子。

https://github.com/haraldk/TwelveMonkeys

这似乎很有希望。事实上,我不费吹灰之力就已经能够阅读我的一张图片中包含描述的 Exif。请注意,不是使用标准的 javax API,而是使用十二猴 API。这对我来说没问题。什么都行!

在这一点上,我很高兴尽可能地避免使用标准 API,因为它看起来非常复杂且效率低下。我开始阅读我的 Exif,并为我的概念验证编写修改代码。这个想法是,实现我想要的最有效的方法(快速和安全地修改 JPEG 文件中的元数据)是执行以下步骤:

  • 将所有段读入列表

  • 找到需要修改的段

  • 做那个修改

  • 将所有段按顺序写入临时文件

  • 如果一切顺利,将原始文件重命名为以后安全删除,将副本重命名为原始名称,最后删除原始文件。

但是,当我发现似乎没有实现的时候,我有点沮丧

com.twelvemonkeys.imageio.metadata.Directory

它实现了方法

add(Entry)

remove(Object)

除了 a

throw new UnsupportedOperationException("Directory is read-only");

如果这不是有效(和安全)实现我想要做的事情的方法......有没有人有关于如何在纯Java中做到这一点的建议?


白猪掌柜的
浏览 208回答 1
1回答

宝慕林4294392

免责声明:我设计和编写的各种元数据读取器/写入器主要供图书馆内部使用ImageIO,并没有仔细考虑第三方使用。因此,从这个意义上说,API 可能并不“完美”。但是你想做的应该是完全可行的。:-)虽然具体的Directory实现确实是只读的,但您可以轻松地创建自己的AbstractDirectory可变子类。或者只是使用任何Collection<? extends Entry>你喜欢的东西并将其包装在 aTIFFDirectory或IFD写作之前。我更喜欢后者,所以我先展示一下。请注意,典型的 JPEG Exif 片段包含两个 IFD,IFD0 用于主 JPEG 图像,IFD1 用于缩略图。因此,您需要将其视为CompoundDirectory:CompoundDirectory exif = (CompoundDirectory) new TIFFReader().read(input);List<Directory> ifds = new ArrayList<>;for (int i = 0; i < exif.directoryCount(); i++) {&nbsp; &nbsp; List<Entry> entries = new ArrayList<>();&nbsp; &nbsp; for (Entry entry : exif.getDirectory(i)) {&nbsp; &nbsp; &nbsp; &nbsp; entries.add(entry);&nbsp; &nbsp; }&nbsp; &nbsp; // TODO: Do stuff with entries, remove, add, change, etc...&nbsp; &nbsp; ifds.add(new IFD(entries));}// Write Exifnew TIFFWriter().write(new TIFFDirectory(ifds), output);您还可以创建自己的 mutable Directory:public final class MutableDirectory extends AbstractDirectory {&nbsp; &nbsp; public MutableDirectory (final Collection<? extends Entry> entries) {&nbsp; &nbsp; &nbsp; &nbsp; super(entries);&nbsp; &nbsp; }&nbsp; &nbsp; public boolean isReadOnly() {&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; // NOTE: While the above is all you need to make it *mutable*,&nbsp;&nbsp; &nbsp; // TIFF/Exif does not allow entries with duplicate IDs,&nbsp;&nbsp; &nbsp; // you need to handle this somehow. The below code is untested...&nbsp; &nbsp; @Override&nbsp; &nbsp; public boolean add(Entry entry) {&nbsp; &nbsp; &nbsp; &nbsp; Entry existing = getEntryById(entry.getIdentifier());&nbsp; &nbsp; &nbsp; &nbsp; if (existing != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; remove(existing);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; super.add(entry);&nbsp; &nbsp; }}不实现可变目录的原因正是因为处理条目的语义可能因格式而异。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java