Existe-t-il une alternative 100% Java à ImageIO pour lire des fichiers JPEG?

nous utilisons Java2D pour redimensionner les photos téléchargées sur notre site Web, mais nous rencontrons un problème (apparemment ancien, cf.: http://forums.sun.com/thread.jspa?threadID=5425569) - quelques JPEGs particuliers soulèvent un CMMException quand nous essayons de nous ImageIO.read() un flux entrant contenant leurs données binaires:

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

(ciselée le reste de la trace de la pile, qui est notre ImageIO.read() appel, servlet code)

nous l'avons réduit à des photos prises sur des caméras spécifiques, et j'ai choisi une photo qui déclenche cette erreur: http://img214.imageshack.us/img214/5121/estacaosp.jpg. Nous avons remarqué que cela ne se produit qu'avec la JVM de Sun (sur Linux et Mac, juste testé sur 1.6.0_20) - une machine de test avec OpenJDK lit les mêmes photos sans problème, probablement en raison d'une implémentation différente du lecteur JPEG.

<!-Malheureusement, nous ne sommes pas en mesure de changer de JVM en production, ni d'utiliser des solutions natives comme ImageMagick ( http://www.imagemagick.org/).

compte tenu de cela, ma question Est: Existe-t-il un remplacement pour ImageIOs JPEG reader qui peut gérer des photos comme celle liée? Dans le cas contraire, y a-t-il une autre solution de redimensionnement 100% Java pur que nous pouvons utiliser?

Merci!

20
demandé sur chesterbr 2010-06-08 21:02:12

3 réponses

une bibliothèque peut-être utile pour vous pourrait être la Java Advanced Imaging Library ( JAI)

l'Utilisation de cette bibliothèque peut être un peu plus compliqué que d'utiliser ImageIO mais dans un test rapide j'ai juste couru qu'il n'a ouvrir et afficher l'image de problème fichier lié.

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

après l'exécution de ce code, l'image semble se charger correctement. Il est ensuite redimensionné de 50% en utilisant le ParamaterBlock

Et enfin, si vous souhaitez enregistrer le fichier, vous pouvez simplement appeler :

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

j'espère que cela vous aide. Le meilleur de la chance.

12
répondu gruntled 2010-06-09 00:40:17

Vieux post, mais pour l'avenir de référence:

inspiré par cette question et les liens trouvés ici, j'ai écrit un plugin JPEGImageReader pour ImageIO qui supporte les images JPEG avec ce genre de "mauvais" profils de couleurs ICC (le "problème" est l'intention de rendu dans le profil ICC est incompatible avec le ColorConvertOp de Java). C'est du Java pur et ne nécessite pas de JAI.

le code source et les constructions binaires liées sont librement disponibles sur TwelveMonkeys le projet sur GitHub.

10
répondu haraldK 2014-08-07 20:14:31

j'ai fait face à la même question. J'étais réticent à utiliser JAI car il est désuet mais il semble que ce soit la solution la plus courte.

ce code convertit un InputStream en BufferedImage, en utilisant L'ImageIO de sun (fast) ou dans les quelques cas où ce problème se produit, en utilisant 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();
    }
}
7
répondu Florent 2012-10-11 16:35:19