Почему загрузка этого jpg с помощью JavaIO дает CMMException?

ImageIO.read(imagePath) с этим файлом дает CMMException, почему Java не может справиться с этим, казалось бы, допустимым файлом http://www.jthink.net/jaikoz/scratch/front.jpg

java.awt.color.CMMException: Invalid image format
    at sun.awt.color.CMM.checkStatus(Unknown Source)
    at sun.awt.color.ICC_Transform.<init>(Unknown Source)
    at java.awt.image.ColorConvertOp.filter(Unknown Source)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(Unknown Source)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(Unknown Source)
    at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)
    at javax.imageio.ImageIO.read(Unknown Source)

person Paul Taylor    schedule 17.12.2010    source источник
comment
Какую версию Java вы используете?? он работает для jdk 1.5 и 1.6.   -  person Favonius    schedule 17.12.2010
comment
Эх, я использую 1.6.22 на WIndows 7   -  person Paul Taylor    schedule 17.12.2010
comment
Я добавил трассировку стека, может быть, это прольет свет на это   -  person Paul Taylor    schedule 17.12.2010


Ответы (3)


Кажется, я разобрался с вашей проблемой. Я проверил изображение, на которое вы ссылаетесь ( http://www.jthink.net/jaikoz/scratch/front.jpg). Это связано со стандартами Exif и JFIF.

когда вы делаете что-то вроде ImageIO.read('some file'), он вызывает реализацию sun jpeg по умолчанию com.sun.imageio.plugins.jpeg.JPEGImageReader. У которого раньше были проблемы с загрузкой файлов JFIF BUG 6488904 (см. комментарий к конец).

Согласно спецификации, как Exif, так и JFIF требуют, чтобы их соответствующий сегмент маркера приложения был первым сразу после SOI (APP1 и APP0), поэтому на самом деле согласно спецификации файл JPEG не может быть совместимым. с обоими стандартами.

Хотя об этом сообщалось давно

Обходной путь — использовать библиотеку JAI (https://jai.dev.java.net/binary-builds.html#Release_builds). Я использую версию Java (без собственного ускорения).

SeekableStream seekableStream =  new FileSeekableStream(new File("front.jpg"));
ParameterBlock pb = new ParameterBlock();
pb.add(seekableStream);

BufferedImage image = JAI.create("jpeg", pb).getAsBufferedImage();

надеюсь, это поможет.

person Favonius    schedule 17.12.2010
comment
@ user294896: добро пожаловать. Если ответ решил вашу проблему, отметьте его как принятый. таким образом, он будет вне списка неотвеченных. Благодарю. - person Favonius; 20.12.2010
comment
да, это работает, мне просто интересно, есть ли способ сделать это, используя общедоступный API, а не базовые классы Sun (такие как SeekableStream) - person Paul Taylor; 05.01.2011

Кстати, эта проблема исправлена ​​в JDK8 (обратите внимание на фиксацию внизу http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7064516). Я подтвердил, что предварительная сборка JDK8 правильно загружает образы, с которыми JDK7 не работает, как описано над.

person cemerick    schedule 09.10.2013

Старый пост, но на будущее:

Вдохновленный этим вопросом и ссылками, найденными здесь, я написал плагин JPEGImageReader для ImageIO, который поддерживает изображения JPEG с такими «плохими» цветовыми профилями ICC («проблема» заключается в том, что цель рендеринга в профиле ICC несовместима с ColorConvertOp Java). ). Это простая Java и не требует JAI. Исходный код находится в свободном доступе по адресу:

https://github.com/haraldk/TwelveMonkeys/tree/master/imageio/imageio-jpeg

person Harald K    schedule 22.04.2013
comment
Можете ли вы предоставить небольшое объяснение и пример в вашем GitHub README о том, как интегрировать и использовать ваш плагин? Это было бы прекрасно. - person Jack; 30.06.2013
comment
@Джек, я так и сделаю. Кроме того, не стесняйтесь сообщать о проблемах с отсутствующими документами на GitHub, если есть что-то конкретное, что вам нравится документировать. Но все, что вам нужно сделать, это собрать проект с помощью Maven и поместить JAR-файлы в путь к классам. Вы будете использовать его так же, как стандартный плагин JPEG (т.е. ImageIO.read(...) или ImageIO.getImageReaders(...)). - person Harald K; 30.06.2013