Impossible de lire L'image JPEG en utilisant ImageIO.lire(Fichier fichier)

j'ai des problèmes pour lire ce fichier JPEG en utilisant ImageIO.Lire (fichier) - il lance une exception avec le message "Unsupported Image Type".

j'ai essayé d'autres images JPEG, et elles semblent bien fonctionner.

La seule différence que j'ai pu endroit est que ce fichier semble inclure une miniature est connue pour causer des problèmes avec ImageIO.lire()?

Troublesome image

EDIT:

a ajouté l'image résultante:

Strange colors

39
demandé sur Eddie Curtis 2010-03-09 14:27:32

6 réponses

votre image " Modèle Couleur "est CMYK, JPEGImageReader (la classe intérieure qui lit votre fichier) lit seulement Modèle couleur RGB.

si vous insistez pour lire des images CMJN, alors vous aurez besoin de les convertir, essayez ce code.

mise à JOUR

Lire une image CMJN en RVB BufferedImage.

    File f = new File("/path/imagefile.jpg");

    //Find a suitable ImageReader
    Iterator readers = ImageIO.getImageReadersByFormatName("JPEG");
    ImageReader reader = null;
    while(readers.hasNext()) {
        reader = (ImageReader)readers.next();
        if(reader.canReadRaster()) {
            break;
        }
    }

    //Stream the image file (the original CMYK image)
    ImageInputStream input =   ImageIO.createImageInputStream(f); 
    reader.setInput(input); 

    //Read the image raster
    Raster raster = reader.readRaster(0, null); 

    //Create a new RGB image
    BufferedImage bi = new BufferedImage(raster.getWidth(), raster.getHeight(), 
    BufferedImage.TYPE_4BYTE_ABGR); 

    //Fill the new image with the old raster
    bi.getRaster().setRect(raster);

mise à jour-Mars 2015-ajout d'images de simulation

Les images originales de

ont été retirées de la dropbox de L'OP. Donc j'ajoute de nouvelles images (pas les originaux) qui simulent le problème qui se passait avec eux.

première image est à quoi ressemble une image RGB normale.

Image RGB

deuxième image est comment la même image ressemblera dans le modèle couleur CMYK.

vous ne pouvez pas en fait voir comment il regarde sur le web parce qu'il sera converti en RVB par l'hôte. Pour voir exactement de quoi il a l'air, prenez l'image RVB et lancez-la dans un convertisseur RVB vers CMJN.

troisième image est la façon dont l'image CMYK ressemblera lorsqu'elle sera lue puis écrite en utilisant Java ImageIO.

Image CMYK read through Java RGB

le problème qui se produisait avec OP est qu'ils avaient quelque chose comme l'image 2 qui jette un exception lorsque vous essayez de lire.

35
répondu medopal 2015-03-15 07:26:53

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

inspiré par cette question et les liens trouvés ici, j'ai écrit un plugin JPEGImageReader pour ImageIO qui supporte les modèles couleur CMYK (à la fois avec le Modèle Couleur original, ou implicitement converti en RGB sur read). Le lecteur fait aussi la conversion de couleur appropriée, en utilisant le profil ICC intégré dans le flux JPEG, en contraste avec d'autres solutions mentionnées ici.

C'est Java simple et ne nécessite pas JAI. Le le code source et les distributions binaires sont librement disponibles à github.com/haraldk/TwelveMonkeys , et est couvert par une licence de style BSD.

une fois que vous l'avez installé, il vous permet de lire CMYK JPEGs en utilisant ImageIO.read(...) comme ceci:

File cmykJPEGFile = new File(/*path*/);
BufferedImage image = ImageIO.read(cmykJPEGFile);

c'est-à-dire: Dans la plupart des cas, il n'est pas nécessaire de modifier votre code.

44
répondu haraldK 2017-06-13 07:09:31

je suis un peu en retard à la fête. Mais il est probablement encore intéressant que je poste ma réponse comme aucune des réponses résout vraiment le problème.

la solution nécessite Sanselan (ou Apache Commons Imaging comme il est appelé maintenant) et il exige un profil de couleur CMYK raisonnable (.fichier icc). Vous pouvez obtenir la dernière de Adobe ou de eci.org.

le problème de base est que Java - out of the box - ne peut lire les fichiers JPEG qu'en RGB. Si vous avez un CMJN fichier, vous devez distinguer entre CMYK régulier, Adobe CMYK (avec des valeurs inversées, i.e. 255 pour pas d'encre et 0 pour un maximum d'encre) et Adobe CYYK (une variante avec des couleurs inversées ainsi).

public class JpegReader {

    public static final int COLOR_TYPE_RGB = 1;
    public static final int COLOR_TYPE_CMYK = 2;
    public static final int COLOR_TYPE_YCCK = 3;

    private int colorType = COLOR_TYPE_RGB;
    private boolean hasAdobeMarker = false;

    public BufferedImage readImage(File file) throws IOException, ImageReadException {
        colorType = COLOR_TYPE_RGB;
        hasAdobeMarker = false;

        ImageInputStream stream = ImageIO.createImageInputStream(file);
        Iterator<ImageReader> iter = ImageIO.getImageReaders(stream);
        while (iter.hasNext()) {
            ImageReader reader = iter.next();
            reader.setInput(stream);

            BufferedImage image;
            ICC_Profile profile = null;
            try {
                image = reader.read(0);
            } catch (IIOException e) {
                colorType = COLOR_TYPE_CMYK;
                checkAdobeMarker(file);
                profile = Sanselan.getICCProfile(file);
                WritableRaster raster = (WritableRaster) reader.readRaster(0, null);
                if (colorType == COLOR_TYPE_YCCK)
                    convertYcckToCmyk(raster);
                if (hasAdobeMarker)
                    convertInvertedColors(raster);
                image = convertCmykToRgb(raster, profile);
            }

            return image;
        }

        return null;
    }

    public void checkAdobeMarker(File file) throws IOException, ImageReadException {
        JpegImageParser parser = new JpegImageParser();
        ByteSource byteSource = new ByteSourceFile(file);
        @SuppressWarnings("rawtypes")
        ArrayList segments = parser.readSegments(byteSource, new int[] { 0xffee }, true);
        if (segments != null && segments.size() >= 1) {
            UnknownSegment app14Segment = (UnknownSegment) segments.get(0);
            byte[] data = app14Segment.bytes;
            if (data.length >= 12 && data[0] == 'A' && data[1] == 'd' && data[2] == 'o' && data[3] == 'b' && data[4] == 'e')
            {
                hasAdobeMarker = true;
                int transform = app14Segment.bytes[11] & 0xff;
                if (transform == 2)
                    colorType = COLOR_TYPE_YCCK;
            }
        }
    }

    public static void convertYcckToCmyk(WritableRaster raster) {
        int height = raster.getHeight();
        int width = raster.getWidth();
        int stride = width * 4;
        int[] pixelRow = new int[stride];
        for (int h = 0; h < height; h++) {
            raster.getPixels(0, h, width, 1, pixelRow);

            for (int x = 0; x < stride; x += 4) {
                int y = pixelRow[x];
                int cb = pixelRow[x + 1];
                int cr = pixelRow[x + 2];

                int c = (int) (y + 1.402 * cr - 178.956);
                int m = (int) (y - 0.34414 * cb - 0.71414 * cr + 135.95984);
                y = (int) (y + 1.772 * cb - 226.316);

                if (c < 0) c = 0; else if (c > 255) c = 255;
                if (m < 0) m = 0; else if (m > 255) m = 255;
                if (y < 0) y = 0; else if (y > 255) y = 255;

                pixelRow[x] = 255 - c;
                pixelRow[x + 1] = 255 - m;
                pixelRow[x + 2] = 255 - y;
            }

            raster.setPixels(0, h, width, 1, pixelRow);
        }
    }

    public static void convertInvertedColors(WritableRaster raster) {
        int height = raster.getHeight();
        int width = raster.getWidth();
        int stride = width * 4;
        int[] pixelRow = new int[stride];
        for (int h = 0; h < height; h++) {
            raster.getPixels(0, h, width, 1, pixelRow);
            for (int x = 0; x < stride; x++)
                pixelRow[x] = 255 - pixelRow[x];
            raster.setPixels(0, h, width, 1, pixelRow);
        }
    }

    public static BufferedImage convertCmykToRgb(Raster cmykRaster, ICC_Profile cmykProfile) throws IOException {
        if (cmykProfile == null)
            cmykProfile = ICC_Profile.getInstance(JpegReader.class.getResourceAsStream("/ISOcoated_v2_300_eci.icc"));
        ICC_ColorSpace cmykCS = new ICC_ColorSpace(cmykProfile);
        BufferedImage rgbImage = new BufferedImage(cmykRaster.getWidth(), cmykRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
        WritableRaster rgbRaster = rgbImage.getRaster();
        ColorSpace rgbCS = rgbImage.getColorModel().getColorSpace();
        ColorConvertOp cmykToRgb = new ColorConvertOp(cmykCS, rgbCS, null);
        cmykToRgb.filter(cmykRaster, rgbRaster);
        return rgbImage;
    }
}

le code essaie d'abord de lire le fichier en utilisant la méthode régulière, qui fonctionne pour les fichiers RGB. S'il échoue, il lit les détails du modèle Couleur (profil, Adobe marker, variante Adobe). Puis il lit les données brutes de pixel (raster) et fait toute la conversion nécessaire (YCCK à CMYK, couleurs inversées, CMYK À RVB).

Je ne suis pas très satisfait de ma solution. Alors que les couleurs sont généralement bonnes, les zones sombres sont légèrement trop claires, en particulier le noir n'est pas entièrement noir. Si quelqu'un sait ce que je pourrais améliorer, je serais heureux de l'entendre.

18
répondu Codo 2012-08-26 18:31:33

ImageIO.read() ->

File filePath = new File("C:\Users\chang\Desktop\05036877.jpg");
com.sun.image.codec.jpeg.JPEGImageDecoder jpegDecoder =  JPEGCodec.createJPEGDecoder (new FileInputStream(filePath));

BufferedImage image = jpegDecoder.decodeAsBufferedImage();
6
répondu Peter 2012-08-02 10:30:20

je le fixe par ceci. seulement besoin d'ajouter cette dépendance. je peux lire L'image CMJN par ImageIO. TwelveMonkeys

ImageIO.read(new URL("http://img3.tianyancha.com/api/9b80a61183787909e719c77fd0f78103.png"))
0
répondu yaoning 2017-11-30 07:20:56