2008-09-24 32 views
24

Actualmente estoy girando una matriz de valores de píxel (creados originalmente con un objeto java.awt.image.PixelGrabber) en un objeto de imagen usando el siguiente código:¿Convertir una matriz de píxeles en un objeto de imagen con ImageIO de Java?

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 de utilizar clases de los paquetes de ImageO para que no tenga que usar AWT Toolkit?

Toolkit.getDefaultToolkit() no parece ser 100% confiable y algunas veces lanzará un AWTError, mientras que las clases ImageIO siempre deberían estar disponibles, por lo que estoy interesado en cambiar mi método.

Respuesta

23

Puede crear la imagen sin utilizar ImageIO. Simplemente cree una Imagen Buffered utilizando 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 se trabaja con la PixelGrabber, no se olvide de extraer la información RGBA de la matriz de píxeles antes de llamar getImageFromArray. Hay un ejemplo de esto en el handlepixelmethod en el javadoc de PixelGrabber. Una vez que lo hagas, asegúrate de que el tipo de imagen en el constructor BufferedImage sea BufferedImage.TYPE_INT_ARGB.

+1

Gracias bcash, pero obtengo una java.lang.ArrayIndexOutOfBoundsException cuando pruebo ese código. ¿Algunas ideas? –

+0

Creo que esto está cerca, ¿podríamos necesitar más detalles de Chris con los detalles? esto parece que debería funcionar ... ¿Cuáles son tus datos? ¿son RGB? ARGB? algún tipo de formato empaquetado? –

+0

Los píxeles provienen de un PixelGrabber como tal: int [] pixels = new int [width * height]; PixelGrabber pg = new PixelGrabber (img, 0, 0, ancho, alto, píxeles, 0, ancho); pg.grabPíxeles(); –

1

He tenido mucho éxito usando java.awt.Robot para tomar una captura de pantalla (o un segmento de la pantalla), pero para trabajar con ImageIO, deberá almacenarla en una Imagen Buffered en lugar de la memoria fuente de imagen. 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); 
7

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

+0

Tuve un problema similar, a pesar de que el tamaño de la matriz de la entrada y la salida coinciden. Terminé usando setRGB también. Puede ser trivialmente más lento pero funciona. El no pensaría que Alpha versus no alpha debería cambiar el tamaño de la matriz, ya que es simplemente los 2 bytes más significativos en la int individual. – bobtheowl2

3

JavaDoc en BufferedImage.getData() dice: "un Raster que es un copia de los datos de imagen."

Este código funciona para mí, pero dudo de que es la 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); 
+1

..o use 'getRaster()' en lugar de 'getData()'. – haraldK

0

ya que es uno de los más altos cuestión votado etiquetados con ImageIO en tanto, creo que todavía hay espacio para una mejor solución, incluso si la pregunta es vieja :-)

Eche un vistazo a la clase BufferedImageFactory.java de mi proyecto de creación de imágenes en GitHub.

Con él, simplemente hay que escribir:

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

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

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

(PD: La fábrica también es compatible con submuestreo, región de interés y escuchas de progreso si alguien está interesado.:-)

0

Tuve el mismo problema que todos los demás tratando de aplicar la respuesta correcta a esta pregunta, mi matriz int en realidad obtiene una excepción OutOfboundException donde lo arreglé agregando un índice más porque la longitud de la matriz debe ser widht * altura * 3 después de esto no pude conseguir la imagen, así que fijo que establecer la trama a 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 se puede ver la imagen si u mostrar que en una etiqueta en un JFrame como esto

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 el imageIcon(). Último consejo que puede tratar de cambiar la imagen Buffered.TYPE_INT_ARGB a otra cosa que coincide con la imagen que obtuvo la matriz de este tipo es muy importante que tenía una matriz de 0 y -1, así que usé este tipo BufferedImage.TYPE_3BYTE_BGR

Cuestiones relacionadas