Pregunta

Actualmente estoy convirtiendo una matriz de valores de píxeles (creada originalmente con un objeto java.awt.image.PixelGrabber) en un objeto Imagen usando el siguiente código:

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

¿Es posible lograr el mismo resultado usando clases de los paquetes ImageIO para no tener que usar el kit de herramientas AWT?

Toolkit.getDefaultToolkit() no parece ser 100% confiable y a veces arroja un AWTError, mientras que las clases ImageIO siempre deberían estar disponibles, razón por la cual estoy interesado en cambiar mi método.

¿Fue útil?

Solución

Puede crear la imagen sin utilizar ImageIO.Simplemente cree una Imagen Buffered usando un tipo de imagen que coincida con el contenido de la matriz de píxeles.

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

Cuando trabaje con PixelGrabber, no olvide extraer la información RGBA de la matriz de píxeles antes de llamar. getImageFromArray.Hay un ejemplo de esto en el manejarmétodo de píxeles en el javadoc PixelGrabber.Una vez hecho esto, asegúrese de que el tipo de imagen en el constructor BufferedImage sea BufferedImage.TYPE_INT_ARGB.

Otros consejos

Usando el ráster obtuve un ArrayIndexOutOfBoundsException incluso cuando creé el BufferedImage con TYPE_INT_ARGB.Sin embargo, utilizando el setRGB(...) método de BufferedImage trabajó para mi.

JavaDoc en BufferedImage.getData() dice:"un ráster que es un Copiar de los datos de la imagen."

Este código me funciona pero dudo de su eficiencia:

        // Получаем картинку из массива.
        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);

He tenido mucho éxito al usar java.awt.Robot para tomar una captura de pantalla (o un segmento de la pantalla), pero para trabajar con ImageIO, necesitarás almacenarla en una BufferedImage en lugar de la fuente de la imagen de la memoria.Luego puede llamar a un método estático de ImageIO y guardar el archivo.Pruebe algo como:

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

Como esta es una de las preguntas más votadas etiquetadas con ImageIO en SO, creo que todavía hay espacio para una mejor solución, incluso si la pregunta es antigua.:-)

Echa un vistazo a BufferedImageFactory.java clase de mi proyecto imageio de código abierto en GitHub.

Con él, simplemente puedes escribir:

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

La otra cosa buena es que este enfoque, en el peor de los casos, tiene aproximadamente el mismo rendimiento (tiempo) que el PixelGrabber-ejemplos basados ​​​​ya en este hilo.En la mayoría de los casos comunes (normalmente JPEG), es aproximadamente el doble de rápido.En cualquier caso, utiliza menos memoria.

Como beneficio adicional, el modelo de color y el diseño de píxeles de la imagen original se mantienen, en lugar de traducirse a int ARGB con el modelo de color predeterminado.Esto podría ahorrar memoria adicional.

(PD:La fábrica también admite escuchas de submuestreo, regiones de interés y progreso si alguien está interesado.:-)

Tuve el mismo problema con todos los demás que intentaban aplicar la respuesta correcta a esta pregunta, mi matriz int en realidad obtuvo una excepción OutOfboundException donde la arreglé agregando un índice más porque la longitud de la matriz debe ser ancho*alto*3 después de esto. No pude obtener la imagen, así que la arreglé configurando el ráster de la imagen.

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);
        image.setData(raster); 
        return image;
    }

Y puedes ver la imagen si la muestras en una etiqueta en un jframe como este.

    JFrame frame = new JFrame();
    frame.getContentPane().setLayout(new FlowLayout());
    frame.getContentPane().add(new JLabel(new ImageIcon(image)));
    frame.pack();
    frame.setVisible(true);

configurando la imagen en imageIcon().El último consejo es que puedes intentar cambiar Bufferedimage.TYPE_INT_ARGB por otra cosa que coincida con la imagen que obtuviste. La matriz de este tipo es muy importante. Tenía una matriz de 0 y -1, así que usé este tipo BufferedImage.TYPE_3BYTE_BGR.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top