Java 使用 BufferedImages 获取图像每个像素的颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22391353/
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-13 15:29:37  来源:igfitidea点击:

Get color of each pixel of an image using BufferedImages

javaimagecolorspixel

提问by user2410644

I am trying to get every single color of every single pixel of an image. My idea was following:

我正在尝试获取图像每个像素的每种颜色。我的想法如下:

int[] pixels;
BufferedImage image;

image = ImageIO.read(this.getClass.getResources("image.png");
int[] pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

Is that right? I can't even check what the "pixels" array contains, because i get following error:

那正确吗?我什至无法检查“像素”数组包含什么,因为我收到以下错误:

java.awt.image.DataBufferByte cannot be cast to java.awt.image.DataBufferInt

I just would like to receive the color of every pixel in an array, how do i achieve that?

我只想接收数组中每个像素的颜色,我该如何实现?

回答by Black Shadow

byte[] pixels

not

不是

int[] pixels

try this : Java - get pixel array from image

试试这个:Java - 从图像中获取像素数组

回答by Black Shadow

import java.io.*;
import java.awt.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

public class GetPixelColor {
    public static void main(String args[]) throws IOException {
        File file = new File("your_file.jpg");
        BufferedImage image = ImageIO.read(file);
        // Getting pixel color by position x and y 
        int clr = image.getRGB(x, y);
        int red =   (clr & 0x00ff0000) >> 16;
        int green = (clr & 0x0000ff00) >> 8;
        int blue =   clr & 0x000000ff;
        System.out.println("Red Color value = " + red);
        System.out.println("Green Color value = " + green);
        System.out.println("Blue Color value = " + blue);
    }
}

of course you have to add a for loop for all pixels

当然你必须为所有像素添加一个 for 循环

回答by Marco13

The problem (also with the answer that was linked from the first answer) is that you hardly ever know what exact type your buffered image will be after reading it with ImageIO. It could contain a DataBufferByteor a DataBufferInt. You may deduce it in some cases via BufferedImage#getType(), but in the worst case, it has type TYPE_CUSTOM, and then you can only fall back to some instanceoftests.

问题(也与第一个答案中链接的答案有关)是,在使用 ImageIO 读取缓冲图像后,您几乎不知道缓冲图像的确切类型。它可以包含一个DataBufferByte或一个DataBufferInt。在某些情况下BufferedImage#getType(),您可以通过 推断出它,但在最坏的情况下,它具有 type TYPE_CUSTOM,然后您只能退回到某些instanceof测试。

However, you can convert your image into a BufferedImage that is guaranteed to have a DataBufferIntwith ARGB values - namely with something like

但是,您可以将图像转换为保证DataBufferInt具有 ARGB 值的 BufferedImage - 即具有类似

public static BufferedImage convertToARGB(BufferedImage image)
{
    BufferedImage newImage = new BufferedImage(
        image.getWidth(), image.getHeight(),
        BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = newImage.createGraphics();
    g.drawImage(image, 0, 0, null);
    g.dispose();
    return newImage;
}

Otherwise, you can call image.getRGB(x,y), which may perform the required conversions on the fly.

否则,您可以调用image.getRGB(x,y),它可以即时执行所需的转换。

BTW: Note that obtaining the data buffer of a BufferedImage may degrade painting performance, because the image can no longer be "managed" and kept in VRAM internally.

顺便说一句:请注意,获取 BufferedImage 的数据缓冲区可能会降低绘画性能,因为图像无法再在内部“管理”并保存在 VRAM 中。

回答by Daniel

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageUtil {

    public static Color[][] loadPixelsFromImage(File file) throws IOException {

        BufferedImage image = ImageIO.read(file);
        Color[][] colors = new Color[image.getWidth()][image.getHeight()];

        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                colors[x][y] = new Color(image.getRGB(x, y));
            }
        }

        return colors;
    }

    public static void main(String[] args) throws IOException {
        Color[][] colors = loadPixelsFromImage(new File("image.png"));
        System.out.println("Color[0][0] = " + colors[0][0]);
    }
}

回答by Long Nguyen

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedImage bufferedImage = ImageIO.read(new File("norris.jpg"));
        int height = bufferedImage.getHeight(), width = bufferedImage.getWidth();
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int RGBA = bufferedImage.getRGB(x, y);
                int alpha = (RGBA >> 24) & 255;
                int red = (RGBA >> 16) & 255;
                int green = (RGBA >> 8) & 255;
                int blue = RGBA & 255;
            }
        }
    }
}

Assume the buffered image represents an image with 8-bit RGBA color components packed into integer pixels, I search for "RGBA color space" on wikipedia and found following:

假设缓冲图像表示一个图像,其中 8 位 RGBA 颜色分量打包成整数像素,我在维基百科上搜索“RGBA 颜色空间”,发现以下内容:

In the byte-order scheme, "RGBA" is understood to mean a byte R, followed by a byte G, followed by a byte B, and followed by a byte A. This scheme is commonly used for describing file formats or network protocols, which are both byte-oriented.

在字节序方案中,“RGBA”被理解为表示一个字节R,后跟一个字节G,后跟一个字节B,再后跟一个字节A。这种方案通常用于描述文件格式或网络协议,它们都是面向字节的。

With simple Bitwise and Bitshift you can get the value of each color and the alpha value of the pixel.

通过简单的 Bitwise 和 Bitshift,您可以获得每种颜色的值和像素的 alpha 值。

Very interesting is also the other order scheme of RGBA:

非常有趣的还有RGBA的另一种排序方案:

In the word-order scheme, "RGBA" is understood to represent a complete 32-bit word, where R is more significant than G, which is more significant than B, which is more significant than A. This scheme can be used to describe the memory layout on a particular system. Its meaning varies depending on the endianness of the system.

在字序方案中,“RGBA”理解为表示一个完整的32位字,其中R比G更有效,比B更有效,比A更有效。这个方案可以用来描述特定系统上的内存布局。它的含义取决于系统的字节序。

回答by Robert E Fry

I know this has already been answered, but the answers given are a bit convoluted and could use improvement. The simple idea is to just loop through every (x,y) pixel in the image, and get the color of that pixel.

我知道这已经得到了回答,但给出的答案有点令人费解,可以改进。简单的想法是循环遍历图像中的每个 (x,y) 像素,并获取该像素的颜色。

BufferedImage image = MyImageLoader.getSomeImage();
for ( int x = 0; x < image.getWidth(); x++ ) {
    for( int y = 0; y < image.getHeight(); y++ ) {
        Color pixel = new Color( image.getRGB( x, y ) );
        // Do something with pixel color here :)
    }
}

You could then perhaps wrap this method in a class, and implement Java's Iterable API.

然后,您也许可以将此方法包装在一个类中,并实现 Java 的 Iterable API。

class IterableImage implements Iterable<Color> {

    private BufferedImage image;

    public IterableImage( BufferedImage image ) {
        this.image = image;
    }

    @Override
    public Iterator<Color> iterator() {
        return new Itr();
    }

    private final class Itr implements Iterator<Color> {

        private int x = 0, y = 0;

        @Override
        public boolean hasNext() {
            return x < image.getWidth && y < image.getHeight();
        }

        @Override
        public Color next() {
            x += 1;
            if ( x >= image.getWidth() ) {
                x = 0;
                y += 1;
            }
            return new Color( image.getRGB( x, y ) );
        }

    }

}

The usage of which might look something like the following

which 的用法可能如下所示

BufferedImage image = MyImageLoader.getSomeImage();
for ( Color color : new IterableImage( image ) ) {
    // Do something with color here :)
}