2008-09-24 51 views
24

我使用以下代码当前转动的像素值(最初是用java.awt.image.PixelGrabber中对象创建)的阵列为图像对象:使用Java的ImageIO将像素数组转换为Image对象?

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

是否有可能实现相同的结果使用ImageIO包中的类,所以我不必使用AWT Toolkit?

Toolkit.getDefaultToolkit()似乎不是100%可靠的,有时会抛出一个AWTError,而ImageIO类应该始终可用,这就是为什么我有兴趣改变我的方法。

回答

23

您可以在不使用ImageIO的情况下创建图像。只需使用匹配像素数组内容的图像类型创建一个BufferedImage。

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

当使用PixelGrabber都会工作,不要忘记调用getImageFromArray之前提取来自像素阵列的RGBA信息。在PixelGrabber javadoc的handlepixelmethod中有一个例子。一旦你这样做了,确保BufferedImage构造函数中的图像类型为BufferedImage.TYPE_INT_ARGB

+1

谢谢bcash,但是当我尝试这个代码时,我得到了一个java.lang.ArrayIndexOutOfBoundsException异常。有任何想法吗? – 2008-09-24 02:53:40

+0

我认为这很接近,我们可能需要克里斯的更多细节与细节?这看起来应该起作用......你的整数是什么?他们是RGB? ARGB?某种打包格式? – 2008-09-24 04:37:39

+0

像素来自PixelGrabber,因此: int [] pixels = new int [width * height]; PixelGrabber pg = new PixelGrabber(img,0,0,width,height,pixels,0,width); pg.grabPixels(); – 2008-09-24 05:17:13

1

我已经使用java.awt.Robot抓取屏幕截图(或屏幕的一部分)取得了很好的成功,但要使用ImageIO,您需要将其存储在BufferedImage而不是内存中图像源。然后你可以调用ImageIO的一个静态方法并保存文件。尝试类似:

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

使用光栅即使我创建了BufferedImageTYPE_INT_ARGB,我也得到了ArrayIndexOutOfBoundsException。但是,使用setRGB(...)方法BufferedImage为我工作。

3

BufferedImage.getData()上的JavaDoc表示:“一个栅格是拷贝的图像数据。”

此代码对我的作品,但我怀疑它的效率:

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

由于这是对SO标记ImageIO的最高投票的问题之一,我认为还是有空间,更好的解决方案,即使这个问题很古老。 :-)

看看我在GitHub的开源imageio项目中的BufferedImageFactory.java类。

有了它,你可以简单的写:

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

另一个好处是,这种方法,因为最坏的情况下,具有相同的性能(时间)作为PixelGrabber基的例子已经在这个线。对于大多数常见情况(通常为JPEG),速度大约快两倍。无论如何,它使用较少的内存。

作为一项附加功能,保留原始图像的颜色模型和像素布局,而不是使用默认颜色模型转换为int ARGB。这可能会节省更多的内存。

(PS:如果任何人有兴趣,工厂还支持子采样,感兴趣区域和进度监听器。:-)

0

我有同样的问题,其他人试图应用这个问题的正确答案,我的int数组实际上得到一个OutOfboundException,我修复它添加一个索引,因为数组的长度必须是widht *高* 3在这之后我无法得到的图像,所以我固定它的栅格设置到图像

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

而且你可以看到图像,如果u显示它的标签上JFrame上这样

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

在imageIcon()上设置图像。 最后的建议,您可以尝试将Bufferedimage.TYPE_INT_ARGB更改为与您从此类型中获得数组的图像相匹配的其他内容,这非常重要,因为我有一个0和-1的数组,因此我使用了此类型BufferedImage.TYPE_3BYTE_BGR