2010-06-08 17 views
20

Estamos utilizando Java2D para cambiar el tamaño de las fotos cargadas en nuestro sitio web, pero nos encontramos con un problema (un antiguo aparentemente, cf .: http://forums.sun.com/thread.jspa?threadID=5425569) - algunos JPEGs particulares plantean un CMMException cuando intentamos ImageIO.read() un InputStream que contiene sus datos binarios :¿Existe una alternativa 100% Java a ImageIO para leer archivos JPEG?

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

(cortó el resto de la traza de la pila, que es nuestro ImageIO.read() llamada, código del servlet y tal)

Hemos reducido a las fotos tomadas con cámaras específicas, y selecciona una foto que los desencadenantes este error: http://img214.imageshack.us/img214/5121/estacaosp.jpg. Notamos que esto solo ocurre con la JVM de Sun (en Linux y Mac, recién probado 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 de JPEG.

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

Teniendo en cuenta que, mi pregunta es: ¿Existe un reemplazo para ImageIOs JPEG reader que puede manejar fotos como el vinculado? Si no, ¿hay otra solución de redimensionamiento de fotos de Java 100% pura que podamos usar?

Gracias!

+0

Por cierto, soy consciente de que ImageIO no procesa imágenes CMYK (según http://stackoverflow.com/questions/2408613/problem-reading-jpeg-image-using-imageio-readfile-file).Pero la muestra es RGB (en lo que respecta a la Vista previa de Mac, estaría contento si alguien pudiera confirmarlo) – chesterbr

+0

Abrí un error en la base de datos Oracle/Sun bug aquí: http://bugs.sun.com/bugdatabase /view_bug.do?bug_id=7064516 ¡Vota por él si aún estás interesado en la solución! –

Respuesta

11

Una biblioteca posiblemente útil para usted podría ser el Java Advanced Imaging Library (JAI)

El uso de esta biblioteca puede ser un poco más complicado que usar ImageIO pero en una prueba rápida que acaba de ejecutar lo hizo abierta y la pantalla el archivo de imagen problemático que ha vinculado.

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 cargar bien. A continuación, se cambia el tamaño en un 50% mediante el ParamaterBlock

Y finalmente, si se desea guardar el archivo sólo puede llamar a:

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

espero que esto te ayuda. La mejor de las suertes.

+0

¡Seguro! Tengo que comprobar qué tan bien funcionará en una configuración "sin cabeza", pero creo que podemos resolverlo. ¡Gracias! – chesterbr

+1

Solo para que lo sepan, nuestros desarrolladores implementaron esta solución y funcionó a las mil maravillas. ¡Una vez más, gracias! – chesterbr

+1

enlace muerto, actualice con http://www.oracle.com/technetwork/java/current-142188.html o lo que sea ahora. – user1133275

7

Tuve el mismo problema. Era reacio a usar JAI porque está desactualizado, pero parece que es la solución más corta.

Este código convierte un InputStream a un BufferedImage, utilizando ImageIO del sol (rápida) o en los pocos casos en que se produce este problema, utilizando 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(); 
    } 
} 
8

Mensaje viejo, pero para referencia futura:

Inspirado por esta pregunta y los enlaces encontrados aquí, escribí un plugin JPEGImageReader para ImageIO que admite imágenes JPEG con este tipo de perfiles de color ICC "incorrectos" (el "problema" es el intento de representación en el perfil ICC incompatible con Java ColorConvertOp). Es Java simple y no requiere JAI.

El código fuente y las construcciones binarias vinculadas están disponibles gratuitamente en TwelveMonkeys project en GitHub.

Cuestiones relacionadas