Цвет 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]()
Ответы
Ответ 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 умерла в огне.
Ответ 2
кажется проблемой цветового пространства, imageIO пытается сделать некоторую кодировку/декодирование изображения, но, похоже, не работает. Посмотрите здесь:
Невозможно прочитать изображение JPEG с помощью ImageIO.read(файл файла)