Есть ли 100% альтернатива Java для ImageIO для чтения файлов JPEG?
Мы используем Java2D для изменения размера фотографий, загруженных на наш веб-сайт, но мы сталкиваемся с проблемой (казалось бы, старой, cf.: http://forums.sun.com/thread.jspa?threadID=5425569) - несколько конкретных JPEG файлов повышают CMMException
при попытке ImageIO.read()
InputStream, содержащего их двоичные данные:
java.awt.color.CMMException: Invalid image format
at sun.awt.color.CMM.checkStatus(CMM.java:131)
at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89)
at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:516)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1114)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1082)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897)
at javax.imageio.ImageIO.read(ImageIO.java:1422)
at javax.imageio.ImageIO.read(ImageIO.java:1326)
...
(удалил оставшуюся часть трассировки стека, которая является нашим вызовом ImageIO.read()
, сервлет-кодом и т.д.)
Мы сузили его к фотографиям, снятым на определенных камерах, и я выбрал фотографию, которая вызывает эту ошибку: http://img214.imageshack.us/img214/5121/estacaosp.jpg.
Мы заметили, что это происходит только с Sun JVM (на Linux и Mac, просто протестировало его на 1.6.0_20) - тестовая машина с OpenJDK считывает одни и те же фотографии без заминки, возможно, из-за другой реализации программы чтения JPEG.
К сожалению, мы не можем переключать JVM в производстве и не использовать нативные решения, такие как ImageMagick (http://www.imagemagick.org/).
Учитывая этот вопрос, мой вопрос: существует ли замена для читателя ImageIOs JPEG, который может обрабатывать такие фотографии, как связанный? Если нет, существует ли еще 100% чистое решение для изменения размера фотографии Java, которое мы можем использовать?
Спасибо!
Ответы
Ответ 1
Одной из полезных библиотек для вас может быть Java Advanced Imaging Library (JAI)
Использование этой библиотеки может быть довольно сложнее, чем использование ImageIO, но в быстром тесте, который я только что запустил, он открыл и отобразил связанный файл образа проблемы.
public static void main(String[] args) {
RenderedImage image = JAI.create("fileload", "estacaosp.jpg");
float scale=(float) 0.5;
ParameterBlock pb = new ParameterBlock();
pb.addSource(image);
pb.add(scale);
pb.add(scale);
pb.add(1.0F);
pb.add(1.0F);
pb.add(new InterpolationNearest() );// ;InterpolationBilinear());
image = JAI.create("scale", pb);
// Create an instance of DisplayJAI.
DisplayJAI srcdj = new DisplayJAI(image);
JScrollPane srcScrollPaneImage = new JScrollPane(srcdj);
// Use a label to display the image
JFrame frame = new JFrame();
frame.getContentPane().add(srcScrollPaneImage, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
После запуска этого кода изображение, кажется, загружается штрафом. Затем он изменяется на 50% с помощью параметра ParamaterBlock
И, наконец, если вы хотите сохранить файл, вы можете просто позвонить:
String filename2 = new String ("tofile.jpg");
String format = new String ("JPEG");
RenderedOp op = JAI.create ("filestore", image, filename2, format);
Надеюсь, это поможет вам. Удачи.
Ответ 2
Старый пост, но для справок в будущем:
Вдохновленный этим вопросом и ссылками, найденными здесь, я написал плагин JPEGImageReader для ImageIO, который поддерживает изображения JPEG с этими "плохими" цветовыми профилями ICC ( "проблема" - это намерение рендеринга в профиле ICC несовместимо с Java ColorConvertOp). Это простая Java и не требует JAI.
Исходный код и связанные бинарные сборки свободно доступны из проекта TwelveMonkeys на GitHub.
Ответ 3
Я столкнулся с той же проблемой. Я не хотел использовать JAI, поскольку он устарел, но он выглядит как кратчайшее решение.
Этот код преобразует InputStream в BufferedImage, используя sun ImageIO (быстро) или в тех случаях, когда эта проблема возникает, используя JAI:
public static BufferedImage read(InputStream is) throws IOException {
try {
// We try it with ImageIO
return ImageIO.read(ImageIO.createImageInputStream(is));
} catch (CMMException ex) {
// If we failed...
// We reset the inputStream (start from the beginning)
is.reset();
// And use JAI
return JAI.create("stream", SeekableStream.wrapInputStream(is, true)).getAsBufferedImage();
}
}