Читать изображение, изменять метаданные и перезаписывать изображение на чистом Java - PullRequest
1 голос
/ 08 марта 2019

Мне нужно иметь возможность обновлять метаданные изображения (а именно, теги, создатель, описание, комментарии) и делать это в обычных Exif и XMP.Скорее всего, я буду читать Exif и писать XMP.

После долгих поисков библиотеки, которая работает ТАКЖЕ для записи, я натолкнулся на двенадцать обезьян.

https://github.com/haraldk/TwelveMonkeys

Это казалось многообещающим.И действительно, без особых усилий я уже смог прочитать Exif, содержащий описание в одном из моих изображений.Заметьте, не со стандартным API-интерфейсом javax, а с API-интерфейсом с двенадцатью обезьянами.Я не против.Что бы ни работало!

В этот момент я был рад избегать стандартного API в максимально возможной степени, поскольку он казался ужасно запутанным и неэффективным.Я начал с чтения в моем Exif и написания кода для моей проверки концепции.Идея заключалась в том, что наиболее эффективным способом достижения того, чего я хочу (быстрое и безопасное изменение метаданных в файлах JPEG), было выполнение следующих шагов:

  • Считывание всех сегментов в список
  • Найти сегмент, который нужно изменить
  • Сделать это изменение
  • Записать все сегменты последовательно во временный файл
  • Если все идет хорошо, переименуйте оригинал в более позднее безопасное имяудалите, переименуйте копию в исходное имя и, наконец, удалите оригинальный файл.

Однако я был немного встревожен, когда обнаружил, что, похоже, нет реализации

com.twelvemonkeys.imageio.metadata.Directory

, который реализует методы

add(Entry)

и

remove(Object)

с чем-либо, кроме

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

Если это не способ эффективно (и безопасно) достичь того, что я хочу сделать ... У кого-нибудь есть предложение о том, как на чистой Java я могу это сделать?

1 Ответ

0 голосов
/ 11 марта 2019

Отказ от ответственности: я разработал и написал различные устройства чтения / записи метаданных, в основном для внутреннего использования в моей библиотеке ImageIO, и не рассматривал возможность их использования третьими лицами.По этой причине API не может быть «идеальным» в этом смысле.Но то, что вы хотите сделать, должно быть вполне выполнимо.: -)


Хотя конкретные реализации Directory действительно доступны только для чтения, вы можете легко создать свой собственный подкласс AbstractDirectory, который будет изменяемым.Или просто используйте любой Collection<? extends Entry>, который вам нравится, и оберните его в TIFFDirectory или 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++) {
    List<Entry> entries = new ArrayList<>();

    for (Entry entry : exif.getDirectory(i)) {
        entries.add(entry);
    }

    // TODO: Do stuff with entries, remove, add, change, etc...

    ifds.add(new IFD(entries));
}

// Write Exif
new TIFFWriter().write(new TIFFDirectory(ifds), output);

Вы также можете создать свой собственный изменяемый Directory:

public final class MutableDirectory extends AbstractDirectory {
    public MutableDirectory (final Collection<? extends Entry> entries) {
        super(entries);
    }

    public boolean isReadOnly() {
        return false;
    }

    // NOTE: While the above is all you need to make it *mutable*, 
    // TIFF/Exif does not allow entries with duplicate IDs, 
    // you need to handle this somehow. The below code is untested...
    @Override
    public boolean add(Entry entry) {
        Entry existing = getEntryById(entry.getIdentifier());

        if (existing != null) {
            remove(existing);
        }

        super.add(entry);
    }
}

Причина, по которой не реализуются изменяемые каталоги, в точностичто семантика того, как обрабатываются записи, может отличаться от формата к формату.

...