【问题标题】:Get color of each pixel of an image using BufferedImages使用 BufferedImages 获取图像每个像素的颜色
【发布时间】:2014-04-18 22:31:48
【问题描述】:

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

int[] pixels;
BufferedImage image;

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

对吗?我什至无法检查“像素”数组包含的内容,因为我收到以下错误:

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

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

【问题讨论】:

    标签: java image colors pixel


    【解决方案1】:
    byte[] pixels
    

    不是

    int[] pixels
    

    试试这个:Java - get pixel array from image

    【讨论】:

    • 会尝试的。但是这个数组包含什么?十六进制颜色? argb 颜色?
    • 我更喜欢getRGB(),很好用,试试吧,getRGB(x,y)返回(x,y)位置的像素颜色,如果你要我发个代码
    • 我在红色图像上尝试了这个,输出如下 int: -60160 这个数字是什么意思?是 rgb 颜色吗?
    【解决方案2】:
    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);
        }
    }
    

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

    【讨论】:

    • 对不起,我对此完全陌生:我以前见过,但是“>> 16”或“>> 8”是什么意思?你能解释一下:int red = (clr & 0x00ff0000) >> 16;谢谢!
    • @user2410644 像素/颜色作为打包的int 返回,这意味着RGBA 值形成int 的各个字节。基本上 BlackShadow 使用位移来提取单个像素。您可以使用Color color = new Color(clr, true) 做同样的事情并使用Color API 来提取组件,恕我直言,这更容易、更安全;)
    • 谢谢大家,我总是看到人们使用这些转换方法进行编码,但我一直不太明白他们到底在做什么
    • >>8 :右移8位,假设red = 00000000 00001111 ,red>>16表示11111111 00000000 ,(00001111消失)
    • @SriP 如果您仍然想知道,您可以创建两个嵌套的 for 循环(一个用于 x,一个用于 y),其中 x 从 0 到图像的宽度,y 从 0 到图像的高度,然后在 Black Shadow 的代码中将其插入 x 和 y。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:
      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]);
          }
      }
      

      【讨论】:

        【解决方案5】:
        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;
                    }
                }
            }
        }
        

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

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

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

        RGBA的另一种排序方案也很有意思:

        在字序方案中,“RGBA”被理解为代表一个完整的 32 位字,其中 R 比 G 更重要,G 更重要 比 B 显着,比 A 更显着。这种方案可以 用于描述特定系统上的内存布局。它的 含义因系统的字节顺序而异。

        【讨论】:

          【解决方案6】:

          我知道这已经得到解答,但给出的答案有点复杂,可以改进。 简单的想法是遍历图像中的每个 (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 :)
              }
          }
          

          然后您或许可以将此方法包装在一个类中,并实现 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 ) );
                  }
          
              }
          
          }
          

          其中的用法可能如下所示

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-21
            • 2019-07-27
            • 1970-01-01
            • 2012-05-07
            • 1970-01-01
            • 2015-01-19
            相关资源
            最近更新 更多