8

获取 a 的每个像素的 RGB 值的最快方法是BufferedImage什么?

现在我正在使用两个for循环获取 RGB 值,如下面的代码所示,但是由于嵌套循环对我的图像总共运行了 479999 次,因此获取这些值花费了太长时间。如果我使用 16 位图像,这个数字会更高!

我需要一种更快的方法来获取像素值。

这是我目前正在尝试使用的代码:

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg"));

int countloop=0;  

for (int x = 0; x <bi.getWidth(); x++) {
    for (int y = 0; y < bi.getHeight(); y++) {
        Color c = new Color(bi.getRGB(x, y));
        System.out.println("red=="+c.getRed()+" green=="+c.getGreen()+"    blue=="+c.getBlue()+"  countloop="+countloop++);                                                                                                                                                  
    }
}
4

5 回答 5

15

我不知道这是否有帮助,我还没有测试过,但你可以通过这种方式获取 rgb 值:

BufferedImage bi=ImageIO.read(new File("C:\\images\\Sunset.jpg"));
int[] pixel;

for (int y = 0; y < bi.getHeight(); y++) {
    for (int x = 0; x < bi.getWidth(); x++) {
        pixel = bi.getRaster().getPixel(x, y, new int[3]);
        System.out.println(pixel[0] + " - " + pixel[1] + " - " + pixel[2] + " - " + (bi.getWidth() * y + x));
    }
}

如您所见,您不必在循环内初始化新颜色。我还按照 onemasse 的建议反转了宽度/高度循环,以从我已有的数据中检索计数器。

于 2012-04-10T12:42:54.623 回答
7

通过从一堆单独的 getRGB 更改为一个大的 getRGB 以将整个图像复制到一个数组中,执行时间从 33,000 毫秒下降了一个数量级到 3,200 毫秒,而创建数组的时间仅为 31 毫秒。

毫无疑问,对数组的一次大读取和对数组的直接索引比许多单独的读取要快得多。

性能差异似乎与在类末尾使用断点语句有关。虽然断点在循环之外,但类中的每一行代码似乎都经过了断点测试。更改为个人获取不会提高速度。

由于代码仍然正确,答案的其余部分可能仍然有用。

旧读声明

colorRed=new Color(bi.getRGB(x,y)).getRed();

读取语句将位图复制到数组中

int[] rgbData = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), 
                null, 0,bi.getWidth());        

数组中的 getRGB 将所有 3 个颜色值放入单个数组元素中,因此必须通过旋转和“与”来提取单个颜色。y 坐标必须乘以图像的宽度。

从数组中读取单个颜色的代码

colorRed=(rgbData[(y*bi.getWidth())+x] >> 16) & 0xFF; 

colorGreen=(rgbData[(y*bi.getWidth())+x] >> 8) & 0xFF; 

colorBlue=(rgbData[(y*bi.getWidth())+x]) & 0xFF; 
于 2012-11-28T04:23:10.617 回答
2

您是否尝试过 BufferedImage.getRGB(int, int ,int ,int, int[] , int , int)

就像是:

int[] rgb = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth() * bi.getHeight(), bi.getWidth()])

没有尝试,所以不确定它是否更快。

编辑 看过@代码,它可能不是,但值得一试。

于 2012-04-10T12:20:21.900 回答
2

您应该循环外部循环中的行和内部循环中的列。这样您就可以避免缓存未命中。

于 2012-04-10T12:25:11.997 回答
0

我在这里找到了解决方案 https://alvinalexander.com/blog/post/java/getting-rgb-values-for-each-pixel-in-image-using-java-bufferedi

BufferedImage bi = ImageIO.read(new File("C:\\images\\Sunset.jpg"));

for (int x = 0; x < bi.getWidth(); x++) {
    for (int y = 0; y < bi.getHeight(); y++) {
        int pixel = bi.getRGB(x, y);
        int red = (pixel >> 16) & 0xff;
        int green = (pixel >> 8) & 0xff;
        int blue = (pixel) & 0xff;
        System.out.println("red: " + red + ", green: " + green + ", blue: " + blue);                                                                                                                                                  
    }
}
于 2018-01-08T14:03:21.550 回答