Подтвердить что ты не робот

Цвет jpeg-изображения сильно изменяется после просто ImageIO.read() и ImageIO.write()

Я использую методы ImageIO.read() и ImageIO.write() в javax.imageio.ImageIO для чтения и записи изображений, и я обнаружил, что цвет некоторых изображений сильно изменился.

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

Нужно ли добавлять какой-либо другой код до/после методов ImageIO.read/write?

Вот код, который я использовал:

    File f = new File("obw.jpg");
    BufferedImage bi = ImageIO.read(f);
    FileOutputStream fos2 = new FileOutputStream("obw2.jpg");
    ImageIO.write(bi, "JPG", fos2);
    FileOutputStream fos3 = new FileOutputStream("obw3.gif");
    ImageIO.write(bi, "GIF", fos3);
    FileOutputStream fos4 = new FileOutputStream("obw4.png");
    ImageIO.write(bi, "PNG", fos4);

Моя среда:

    java version "1.6.0_35"
    MacOSX 10.8.2

Оригинальное изображение: enter image description here

Одно из изображений после чтения и записи:

enter image description here

4b9b3361

Ответ 1

Ваша проблема в том, что ImageIO неправильно интерпретирует данные YCbCr в вашем JPEG как данные RBG. Соответствующие ошибки Java 4712797 и 4776576, которые Oracle ошибочно утверждает, были исправлены в Java 1.4, но на самом деле все еще затрагивают некоторые Java 5, 6 и 7 JVM.

В проекте, над которым я работаю, мы столкнулись с этой проблемой, загрузив специально сконструированный тестовый JPEG с одним черным пикселем в посмотрите, правильно ли загружает ImageIO. Если пиксель выглядит зеленым, тогда ImageIO неправильно интерпретирует данные изображения, поэтому, когда мы загружаем JPEG позже, и мы обнаруживаем вид JPEG, который вызывает проблему, мы также применяем цветокоррекцию. (Тип JPEG, который вызывает проблему в JVM, которые показывают его, имеет особый вид подвыборки и маркер JFIF.)

Здесь LGPLv2-лицензионный код, который касается проблемы. Необходимость такого кода, чтобы работать вокруг десятков летних ошибок, когда весь остальной мир справляется с загрузкой JPEG файлов, является одной из причин, по которым я хочу, чтобы Java умерла в огне.