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

Есть ли 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, которое мы можем использовать?

Спасибо!

4b9b3361

Ответ 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();
    }
}