Как записать измененное изображение с теми же настройками сжатия, что и исходное изображение

Вариант использования, который я исследую, - прочитать входное изображение (tif), изменить его и записать в выходное изображение (tif).

Я ищу удобный способ убедиться, что писатель использует те же настройки сжатия и т. д., что и исходное изображение. Я не нашел удобного способа добиться этого с помощью ImageIO (с плагином JAI). Я попытался исследовать imageReader.getDefaultReadParam(), но он не содержит ничего примечательного. imageReader.getImageMetadata(...) содержит информацию глубоко внутри, но организация структуры данных безнадежна.

Мой запасной подход в настоящее время заключается в использовании Apache Commons для обнаружения сжатия (например, Imaging.getImageInfo(inputFile).getCompressionAlgorithm()) и логической установке параметра сжатия записи в ImageIO.

Есть ли более элегантный способ сделать это без необходимости прыгать через этот обруч?

Кроме того, я не могу использовать Apache Commons Imaging исключительно для нашей задачи обработки изображений, потому что он еще не полностью поддерживает некоторые другие форматы, которые мне нужны, например. надпись jpg

Спасибо


person Vinay B    schedule 11.10.2014    source источник


Ответы (1)


Похоже, что метод, который вы ищете, это:

ImageIO.getImageWriter( Средство чтения изображений)

Из документа API:

Этот механизм можно использовать для получения ImageWriter, который будет понимать внутреннюю структуру непиксельных метаданных (закодированных объектами IIOMetadata), сгенерированных ImageReader. Получив эти данные из ImageReader и передав их ImageWriter, полученному с помощью этого метода, программа-клиент может прочитать изображение, каким-то образом изменить его и записать обратно, сохраняя все метаданные, без необходимости что-либо понимать в структуре. метаданных или даже о формате изображения.

Из документации кажется, что вам все еще нужно передавать метаданные от читателя к писателю, но, по крайней мере, вам не нужно заботиться о получении настроек сжатия (или других) из метаданных.

Самый простой способ добиться этого, вероятно, сделать что-то вроде:

ImageReader reader;
reader.setInput(input);

IIOImage image = reader.readAll(0, null); // Read image and metadata in one go

doStuffWithImage(image.getRenderedImage()); // Most likely safe to cast to BufferedImage

ImageWriter writer = ImageIO.getImageWriter(reader);
writer.setOutput(output);

ImageWriteParam param = writer.getDefaultWriteParam();

// According to the API doc, the default compressionMode is
// MODE_COPY_FROM_METADATA which is what we want :-)

writer.write(null, image, param); // Don't need stream metadata for TIFF
person Harald K    schedule 12.10.2014
comment
Спасибо @haraldK, я попробовал ваше предложение, но проблема осталась. Вот простой пример кода, который иллюстрирует мою точку зрения (обратите внимание на несоответствие в настройках компенсации): balamuru/2053a86da79e9fb3711d Вывод: ` #### сжатие входных данных: CCITT Group 3 1-Dimensional Modified Huffman кодирование длин серий. #### в формате: TIFF Настройки вывода должны совпадать с настройками ввода #### сжатие вывода: Нет #### формат вывода: TIFF ` - person Vinay B; 12.10.2014
comment
См. мой (обновленный) последний абзац. Вам нужно передать метаданные от читателя к писателю (ваша суть передает null как метаданные). Проще всего использовать reader.readAll(0, param). Получение писателя таким образом гарантирует, что писатель поймет метаданные от читателя. Поскольку оба могут использоваться повторно, вам необходимо каждый раз передавать метаданные. - person Harald K; 12.10.2014
comment
Кроме того, @haraldK, ваш порт ImageIO для двенадцати обезьян выполняет мои желаемые операции быстрее / эффективнее, чем официальный пакет: github. com/haraldk/TwelveMonkeys . Мои требования: изменение размера и добавление в документ простых фигур (обычно называемых аннотациями к документу). - person Vinay B; 12.10.2014
comment
Нет простите. По крайней мере, не сейчас. Я стараюсь, чтобы мой код был максимально эффективным. Но мой читатель TIFF не полностью поддерживает метаданные, а мой писатель TIFF еще не очень сложен (работа в процессе...). Для записи в формате TIFF вам, вероятно, пока лучше использовать JAI. ПС; Это не порт, это полностью чистая реализация, чтобы избежать всех проблем с лицензией, связанных с JAI. :-) - person Harald K; 12.10.2014
comment
Спасибо. Это сработало, я добавил обновленную суть по адресу gist.github.com/balamuru/432f59facb5f3947902d. (с методом, который модифицирует изображение). Один побочный эффект заключается в том, что размер измененного файла (out.tif) меньше, чем размер input.tif (независимо от того, изменено изображение или нет). Я проверил с помощью программы идентификации Linux, что метаданные для ввода и вывода идентичны, за исключением порядка следования байтов (возможно, программа просто скопировала входные метаданные в вывод, перезаписав его реальные свойства). Мысли ? - person Vinay B; 12.10.2014
comment
Изображения выглядят одинаково? Многие алгоритмы сжатия предоставляют разработчикам некоторую гибкость, это означает, что вполне возможно, что идентичные данные будут сжиматься лучше при использовании одной библиотеки, чем другой. Кроме того, вы читаете только изображение (страницу) 0. Вы уверены, что в исходном TIFF больше нет страниц? - person Harald K; 13.10.2014
comment
Решил мой последний вопрос. Разница в размере, вероятно, связана с небольшими различиями в программе, используемой для создания исходного tif и сгенерированного tif. Чтобы проверить, я использовал сгенерированный tif в качестве входных данных для своей программы, и сгенерированный им вывод был идентичен по размеру входным данным. Спасибо еще раз! - person Vinay B; 13.10.2014