使用Java的ImageIO将像素数组转换为Image对象?
我使用以下代码当前转动的像素值(最初是用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类应该始终可用,这就是为什么我有兴趣改变我的方法。
您可以在不使用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
。
我已经使用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);
使用光栅即使我创建了BufferedImage
和TYPE_INT_ARGB
,我也得到了ArrayIndexOutOfBoundsException
。但是,使用setRGB(...)
方法BufferedImage
为我工作。
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);
由于这是对SO标记ImageIO的最高投票的问题之一,我认为还是有空间,更好的解决方案,即使这个问题很古老。 :-)
看看我在GitHub的开源imageio项目中的BufferedImageFactory.java类。
有了它,你可以简单的写:
BufferedImage image = new BufferedImageFactory(image).getBufferedImage();
另一个好处是,这种方法,因为最坏的情况下,具有相同的性能(时间)作为PixelGrabber
基的例子已经在这个线。对于大多数常见情况(通常为JPEG),速度大约快两倍。无论如何,它使用较少的内存。
作为一项附加功能,保留原始图像的颜色模型和像素布局,而不是使用默认颜色模型转换为int ARGB。这可能会节省更多的内存。
(PS:如果任何人有兴趣,工厂还支持子采样,感兴趣区域和进度监听器。:-)
我有同样的问题,其他人试图应用这个问题的正确答案,我的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
谢谢bcash,但是当我尝试这个代码时,我得到了一个java.lang.ArrayIndexOutOfBoundsException异常。有任何想法吗? – 2008-09-24 02:53:40
我认为这很接近,我们可能需要克里斯的更多细节与细节?这看起来应该起作用......你的整数是什么?他们是RGB? ARGB?某种打包格式? – 2008-09-24 04:37:39
像素来自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