web-dev-qa-db-fra.com

Problème avec le fichier jpg ImageIO.write: fond rose

J'utilise le code suivant pour écrire un fichier jpg:

String url="http://img01.taobaocdn.com/imgextra/i1/449400070/T2hbVwXj0XXXXXXXXX_!!449400070.jpg";
String to="D:/temp/result.jpg";
ImageIO.write(ImageIO.read(new URL(url)),"jpg", new File(to));

Mais je reçois le result.jpg est une image d'arrière-plan rose:

alt text

47
Koerr

Vous pouvez contourner ce problème en utilisant Toolkit.createImage(url) au lieu de ImageIO.read(url) qui utilise une implémentation différente de l'algorithme de décodage.

Si vous utilisez l'encodeur JPEG fourni avec le Sun JDK, vous devez également vous assurer de lui transmettre une image sans canal alpha.

Exemple:

private static final int[] RGB_MASKS = {0xFF0000, 0xFF00, 0xFF};
private static final ColorModel RGB_OPAQUE =
    new DirectColorModel(32, RGB_MASKS[0], RGB_MASKS[1], RGB_MASKS[2]);

    // ...

String sUrl="http://img01.taobaocdn.com/imgextra/i1/449400070/T2hbVwXj0XXXXXXXXX_!!449400070.jpg";
URL url = new URL(sUrl);
Image img = Toolkit.getDefaultToolkit().createImage(url);

PixelGrabber pg = new PixelGrabber(img, 0, 0, -1, -1, true);
pg.grabPixels();
int width = pg.getWidth(), height = pg.getHeight();

DataBuffer buffer = new DataBufferInt((int[]) pg.getPixels(), pg.getWidth() * pg.getHeight());
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, RGB_MASKS, null);
BufferedImage bi = new BufferedImage(RGB_OPAQUE, raster, false, null);

String to = "D:/temp/result.jpg";
ImageIO.write(bi, "jpg", new File(to));

Remarque: Je suppose que le profil de couleur est corrompu et Toolkit.createImage() ignore tous les profils de couleur. Si c'est le cas, cela réduira la qualité des fichiers JPEG qui ont un profil de couleur correct.

38
finnw

J'ai eu des problèmes similaires. Mais je l'ai résolu en utilisant celui-ci

   BufferedImage image = new BufferedImage(width, height,
            BufferedImage.TYPE_INT_RGB); 

   //do something to populate the image
   //such as
   image.setRGB( x, y, pixelValue); //set your own pixels color



   ImageIO.write(image, "jpg", new File("D:\\test.jpg"));

Notez que j'utilise Java version 1.6.0_25-b06 et ça fonctionne très bien.

Vous pouvez peut-être vérifier la version Java.

19
Wen

Cela fonctionne pour moi:

int w = originalImage.getWidth();
int h = originalImage.getHeight();
BufferedImage newImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
int[] rgb = originalImage.getRGB(0, 0, w, h, null, 0, w);
newImage.setRGB(0, 0, w, h, rgb, 0, w);
12
Claudio Rossetto
  • pour moi le problème n'était pas la lecture mais l'écriture
  • ImageIO sera heureux d'écrire des fichiers JPG depuis ARGB BufferedImages
  • Les navigateurs/autres programmes interprètent ensuite ce fichier 4 canaux comme une couleur CMJN ou quelque chose comme cela, résultant en l'effet décrit dans cette question
  • solution pour moi: assurez-vous que la BufferedImage transmise à ImageIO.write est de type RGB (pas ARGB)
  • cela explique également pourquoi le problème n'apparaît que lors de l'enregistrement en jpeg, mais pas lors de l'enregistrement en png
  • cela m'a pris beaucoup de temps à comprendre car mes propres outils d'image se convertissent toujours en ARGB à la volée, donc je passais toujours une image ARGB à ImageIO.write, sans m'en rendre compte
1
Reto Höhener

J'ai rencontré le même problème lors de la lecture et de l'écriture d'images à l'aide de ImageIO. Après avoir lu les réponses ici, j'ai changé mon JRE - de openjdk version "1.8.0_91" à HotSpot Java version "1.8.0_102". L'astuce n'était pas évidente dans la réponse de finnw mais ça vaut le coup d'essayer ;-)

Et ainsi le problème a été résolu! Donc, si vous utilisez OpenJDK JRE et libre de changer votre JRE, changez-le HotSpot et vous n'aurez pas besoin de changer votre code.

1
Bazi
BufferedImage originalImage = ImageIO.read(getContent());
BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);

    for (int x = 0; x < originalImage.getWidth(); x++) {
        for (int y = 0; y < originalImage.getHeight(); y++) {
            newImage.setRGB(x, y, originalImage.getRGB(x, y));
        }
    }

cela a fait l'affaire pour moi

1
hans moleman