使用Java的ImageIO将像素数组转换为Image对象?

我目前正在使用以下代码将像素值数组(最初使用java.awt.image.PixelGrabber对象创建)转换为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类应该总是可用,这就是为什么我有兴趣改变我的方法。

您可以在不使用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的handlepixel方法中有一个这样的例子。 完成后,请确保BufferedImage构造函数中的图像类型为BufferedImage.TYPE_INT_ARGB

使用栅格我得到了一个ArrayIndexOutOfBoundsException即使我用TYPE_INT_ARGB创建了BufferedImage 。 但是,使用BufferedImagesetRGB(...)方法对我BufferedImage

BufferedImage.getData()上的JavaDoc说:“一个Raster,它是图像数据的副本 。”

这段代码对我有用,但我怀疑它的效率:

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

我使用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); 

由于这是在SO上用ImageIO标记的最高投票问题之一,我认为即使问题很老,仍然有更好的解决方案。 🙂

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

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

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

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

作为副作用,保留原始图像的颜色模型和像素布局,而不是使用默认颜色模型转换为int ARGB。 这可能会节省额外的内存。

(PS:如果有人感兴趣,工厂还支持子采样,感兴趣区域和进步听众。:-)

我有同样的问题,其他人试图应用这个问题的正确答案,我的int数组实际上得到一个OutOfboundException,我修复它添加一个索引,因为数组的长度必须是widht * height * 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; } 

如果你在像这样的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