web-dev-qa-db-fra.com

Transformez un tableau de pixels en objet Image avec le logiciel ImageIO de Java?

Je suis en train de transformer un tableau de valeurs en pixels (créé à l'origine avec un objet Java.awt.image.PixelGrabber) en objet Image à l'aide du code suivant:

public Image getImageFromArray(int[] pixels, int width, int height) {
    MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width);
    Toolkit tk = Toolkit.getDefaultToolkit();
    return tk.createImage(mis);
}

Est-il possible d'obtenir le même résultat en utilisant des classes du (des) package (s) ImageIO, de sorte que je n'ai pas à utiliser AWT Toolkit?

Toolkit.getDefaultToolkit () ne semble pas fiable à 100% et génère parfois une erreur AWTError, alors que les classes ImageIO doivent toujours être disponibles. C'est pourquoi je souhaite modifier ma méthode.

26
Chris Carruthers

Vous pouvez créer l'image sans utiliser ImageIO. Créez simplement une BufferedImage en utilisant un type d'image correspondant au contenu du tableau de pixels.

public static Image getImageFromArray(int[] pixels, int width, int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            WritableRaster raster = (WritableRaster) image.getData();
            raster.setPixels(0,0,width,height,pixels);
            return image;
        }

Lorsque vous travaillez avec PixelGrabber, n'oubliez pas d'extraire les informations RGBA du tableau de pixels avant d'appeler getImageFromArray. Il y a un exemple de ceci dans le handlepixelmethod dans le javadoc PixelGrabber. Une fois que vous avez fait cela, assurez-vous que le type d’image dans le constructeur BufferedImage correspond à BufferedImage.TYPE_INT_ARGB

27
Brendan Cashman

En utilisant le raster, j'ai obtenu une ArrayIndexOutOfBoundsException même lorsque j'ai créé la BufferedImage avec TYPE_INT_ARGB. Cependant, l’utilisation de la méthode setRGB(...) de BufferedImage a fonctionné pour moi.

7
mdm

JavaDoc sur BufferedImage.getData () dit: "Un raster qui est une copie des données d'image."

Ce code fonctionne pour moi mais je doute de son efficacité:

        // Получаем картинку из массива.
        int[] pixels = new int[width*height];
            // Рисуем диагональ.
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
                    if (i == j) {
                        pixels[j*width + i] = Color.RED.getRGB();
                    }
                    else {
                        pixels[j*width + i] = Color.BLUE.getRGB();
                        //pixels[j*width + i] = 0x00000000;
                    }
                }
            }

BufferedImage pixelImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
    pixelImage.setRGB(0, 0, width, height, pixels, 0, width);
3
beemaster

J'ai réussi à utiliser Java.awt.Robot pour capturer une capture d'écran (ou un segment de l'écran), mais pour utiliser ImageIO, vous devez le stocker dans une BufferedImage au lieu de la source d'image mémoire. Ensuite, vous pouvez appeler une méthode statique d'ImageIO et enregistrer le fichier. Essayez quelque chose comme:

// Capture whole screen
Rectangle region = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capturedImage = new Robot().createScreenCapture(region);

// Save as PNG
File imageFile = new File("capturedImage.png");
ImageIO.write(capturedImage, "png", imageFile);
2
Steve Moyer

Comme il s’agit de l’une des questions les plus votées avec ImageIO sur SO, je pense qu’il est encore possible de trouver une meilleure solution, même si la question est ancienne. :-)

Jetez un coup d’œil à la classe BufferedImageFactory.Java de mon projet imageio open source sur GitHub. 

Avec cela, vous pouvez simplement écrire: 

BufferedImage image = new BufferedImageFactory(image).getBufferedImage();

L'autre avantage est que cette approche, dans le pire des cas, a à peu près les mêmes performances (temps) que les exemples basés sur PixelGrabber déjà dans ce fil. Dans la plupart des cas courants (généralement au format JPEG), le délai est environ deux fois plus rapide. Dans tous les cas, il utilise moins de mémoire.

En prime, le modèle de couleur et la disposition en pixels de l'image d'origine sont conservés au lieu d'être traduits en int ARVB avec le modèle de couleur par défaut. Cela pourrait économiser de la mémoire supplémentaire.

(PS: l’usine prend également en charge les écouteurs de sous-échantillonnage, de région d’intérêt et de progression si cela vous intéresse. :-)

0
haraldK