2010-06-08 8 views
20

Utilizziamo Java2D per ridimensionare le foto caricate sul nostro sito Web, ma ci imbattiamo in un problema (apparentemente vecchio, cf .: http://forums.sun.com/thread.jspa?threadID=5425569) - alcuni file JPEG specifici sollevano uno CMMException quando proviamo a ImageIO.read() un InputStream contenente i loro dati binari :Esiste un'alternativa Java al 100% a ImageIO per la lettura di file 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) 
    ... 

(stato tagliato il resto della traccia dello stack, che è il nostro ImageIO.read() chiamata, il codice del servlet e simili)

Abbiamo ristretto verso il basso per le foto scattate con fotocamere specifici, e ho scelto una foto che trigger questo errore: http://img214.imageshack.us/img214/5121/estacaosp.jpg. Abbiamo notato che questo succede solo con JVM di Sun (su Linux e Mac, appena testato su 1.6.0_20) - una macchina di prova con OpenJDK legge le stesse foto senza intoppi, probabilmente a causa di una diversa implementazione del lettore JPEG.

Purtroppo, non siamo in grado di passare JVM in produzione, né di utilizzare soluzioni native-native come ImageMagick (http://www.imagemagick.org/).

Considerando ciò, la mia domanda è: esiste una sostituzione per il lettore JPEG di ImageIO in grado di gestire foto come quella collegata? In caso contrario, esiste un'altra soluzione di ridimensionamento delle foto Java al 100% che possiamo utilizzare?

Grazie!

+0

A proposito, sono consapevole che ImageIO non elabora le immagini CMYK (come per http://stackoverflow.com/questions/2408613/problem-reading-jpeg-image-using-imageio-readfile-file).Ma quello campione è RGB (per quanto riguarda l'anteprima di Mac, sarebbe contento se qualcuno potrebbe confermarlo) – chesterbr

+0

Ho aperto un bug nel database degli errori Oracle/Sun qui: http://bugs.sun.com/bugdatabase /view_bug.do?bug_id=7064516 Vota per questo se sei ancora interessato alla correzione! –

risposta

11

Una biblioteca possibilmente utile per voi potrebbe essere il Java Advanced Imaging Library (JAI)

Usando questa libreria può essere un po 'più complicato di utilizzare ImageIO ma in un test rapido Ho appena eseguito lo ha fatto aprire e visualizzare il file immagine del problema che hai collegato.

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

Dopo aver eseguito questo codice, l'immagine sembra caricata correttamente. E 'poi ridimensionato del 50% utilizzando il ParamaterBlock

E, infine, se si desidera salvare il file si può chiamare:

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

Spero che questo ti aiuta. Buona fortuna.

+0

Lo fa sicuramente! Devo controllare quanto funzionerà su un setup "senza testa", ma credo che possiamo risolverlo. Grazie! – chesterbr

+1

Solo per farvi sapere, i nostri sviluppatori hanno implementato questa soluzione, e ha funzionato come un fascino. Grazie ancora! – chesterbr

+1

collegamento guasto, si prega di aggiornare con http://www.oracle.com/technetwork/java/current-142188.html o qualunque cosa sia ora. – user1133275

7

Ho affrontato lo stesso problema. Ero riluttante a usare JAI perché è obsoleto, ma sembra che sia la soluzione più corta.

Questo codice converte un InputStream ad un BufferedImage, utilizzando ImageIO del sole (veloce) o nei pochi casi in cui si verificano questo problema, utilizzando 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

Vecchio post, ma per riferimento futuro:

Ispirato da questa domanda e dai collegamenti trovati qui, ho scritto un plug-in JPEGImageReader per ImageIO che supporta immagini JPEG con questo tipo di profili di colore ICC "cattivi" (il "problema" è l'intento di rendering nel profilo ICC è incompatibile con Java ColorConvertOp). È semplice Java e non richiede JAI.

Il codice sorgente e le build binarie collegate sono disponibili gratuitamente su TwelveMonkeys project su GitHub.