Pregunta

Estamos utilizando Java2d para cambiar el tamaño de las fotos cargadas en nuestro sitio web, pero nos encontramos con un problema (uno aparentemente antiguo, cf.: http://forums.sun.com/thread.jspa?threadid=5425569) - Algunos jpegs particulares elevan un CMMException Cuando intentamos ImageIO.read() Un InputStream que contiene sus datos binarios:

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)
    ...

(recortó el resto del rastro de la pila, que es nuestro ImageIO.read() llamar, código de servlet y tal)

Lo reducimos a las fotos tomadas en cámaras específicas, y seleccioné una foto que desencadena este error: http://img214.imageshack.us/img214/5121/estacaosp.jpg. Notamos que esto solo sucede con JVM de Sun (en Linux y Mac, solo lo probó en 1.6.0_20): una máquina de prueba con OpenJDK lee las mismas fotos sin problemas, posiblemente debido a una implementación diferente del lector JPEG.

Desafortunadamente, no podemos cambiar JVM en producción, ni usar soluciones dependientes de nativas como ImageMagick ( http://www.imagemagick.org/ ).

Teniendo en cuenta eso, mi pregunta es: ¿Existe un reemplazo para el lector de Imageios JPEG que puede manejar fotos como la vinculada? Si no, ¿hay otra solución de cambio de tamaño de foto Java 100% pura que podemos usar?

¡Gracias!

¿Fue útil?

Solución

Una biblioteca posiblemente útil para usted podría ser la biblioteca de imágenes avanzadas de Java (Jai)

El uso de esta biblioteca puede ser un poco más complicado que usar ImageIO, pero en una prueba rápida, acabo de ejecutarlo, abrió y mostró el archivo de imagen del problema que vinculó.

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);
    }

Después de ejecutar este código, la imagen parece cargarse bien. Luego se cambia el tamaño por un 50% usando el paramaterblock

Y finalmente, si desea guardar el archivo, puede llamar:

String filename2 = new String ("tofile.jpg");
  String format = new String ("JPEG");
  RenderedOp op = JAI.create ("filestore", image, filename2, format);

Espero que esto te ayude. La mejor de las suertes.

Otros consejos

Publicación antigua, pero para referencia futura:

Inspirado en esta pregunta y enlaces que se encuentran aquí, he escrito un complemento JPEGIMAGERAREADER para ImageIO que admite imágenes JPEG con este tipo de perfiles de color ICC "malos" (el "problema" es la intención de representación en el perfil de ICC es incompatible con el ColorConvertop de Java ). Es Java simple y no requiere Jai.

El código fuente y las compilaciones binarias vinculadas están disponibles gratuitamente en el Proyecto de TwelVemonkeys en Github.

Me enfrenté al mismo problema. Era reacio a usar Jai, ya que está desactualizado, pero parece que es la solución más corta.

Este código convierte una entrada de entrada en una BufferedImage, utilizando Sun's Imageio (rápido) o en los pocos casos en los que ocurre este problema, usando 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();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top