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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/124630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:35:23  来源:igfitidea点击:

Turn an array of pixels into an Image object with Java's ImageIO?

javaimageawttoolkitjavax.imageio

提问by Chris Carruthers

I'm currently turning an array of pixel values (originally created with a java.awt.image.PixelGrabber object) into an Image object using the following code:

我目前正在使用以下代码将像素值数组(最初使用 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);
}

Is it possible to achieve the same result using classes from the ImageIO package(s) so I don't have to use the AWT Toolkit?

是否可以使用 ImageIO 包中的类实现相同的结果,因此我不必使用 AWT 工具包?

Toolkit.getDefaultToolkit() does not seem to be 100% reliable and will sometimes throw an AWTError, whereas the ImageIO classes should always be available, which is why I'm interested in changing my method.

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

采纳答案by Brendan Cashman

You can create the image without using ImageIO. Just create a BufferedImage using an image type matching the contents of the pixel array.

您可以在不使用 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;
        }

When working with the PixelGrabber, don't forget to extract the RGBA info from the pixel array before calling getImageFromArray. There's an example of this in the handlepixelmethodin the PixelGrabber javadoc. Once you do that, make sure the image type in the BufferedImage constructor to BufferedImage.TYPE_INT_ARGB.

使用 PixelGrabber 时,不要忘记在调用getImageFromArray. 在 PixelGrabber javadoc的handlepixelmethod中有一个这样的例子。完成此操作后,请确保 BufferedImage 构造函数中的图像类型为BufferedImage.TYPE_INT_ARGB.

回答by Steve Moyer

I've had good success using java.awt.Robot to grab a screen shot (or a segment of the screen), but to work with ImageIO, you'll need to store it in a BufferedImage instead of the memory image source. Then you can call one static method of ImageIO and save the file. Try something like:

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

回答by mdm

Using the raster I got an ArrayIndexOutOfBoundsExceptioneven when I created the BufferedImagewith TYPE_INT_ARGB. However, using the setRGB(...)method of BufferedImageworked for me.

使用我的光栅ArrayIndexOutOfBoundsException,当我创建的,甚至BufferedImageTYPE_INT_ARGB。但是,使用对我有用的setRGB(...)方法BufferedImage

回答by beemaster

JavaDoc on BufferedImage.getData() says: "a Raster that is a copyof the image data."

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

This code works for me but I doubt in it's efficiency:

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

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

回答by haraldK

As this is one of the highest voted question tagged with ImageIO on SO, I think there's still room for a better solution, even if the question is old. :-)

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

Have a look at the BufferedImageFactory.javaclass from my open source imageio project at GitHub.

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

With it, you can simply write:

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

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

The other good thing is that this approach, as a worst case, has about the same performance (time) as the PixelGrabber-based examples already in this thread. For most of the common cases (typically JPEG), it's about twice as fast. In any case, it uses less memory.

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

As a side bonus, the color model and pixel layout of the original image is kept, instead of translated to int ARGB with default color model. This might save additional memory.

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

(PS: The factory also supports subsampling, region-of-interest and progress listeners if anyone's interested. :-)

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

回答by Raul H

I had the same problem of everyone else trying to apply the correct answer of this question, my int array actually get an OutOfboundException where i fixed it adding one more index because the length of the array has to be widht*height*3 after this i could not get the image so i fixed it setting the raster to the image

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

And you can see the image if u show it on a label on a jframe like this

如果你像这样在 jframe 上的标签上显示它,你可以看到图像

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

setting the image on the imageIcon(). Last advice you can try to change the Bufferedimage.TYPE_INT_ARGB to something else that matches the image you got the array from this type is very important i had an array of 0 and -1 so I used this type BufferedImage.TYPE_3BYTE_BGR

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