问题
What is the fastest way to get the RGB value of each pixel of a BufferedImage
?
Right now I am getting the RGB values using two for
loops as shown in the code below, but it took too long to get those values as the nested loop runs a total of 479999 times for my image. If I use a 16-bit image this number would be even higher!
I need a faster way to get the pixel values.
Here is the code I am currently trying to work with:
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++);
}
}
回答1:
I don't know if this might help and I haven't tested it yet but you can get the rgb values this way:
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));
}
}
As you can see you don't have to initialize a new Color inside the loop. I also inverted the width/height loops as suggested by onemasse to retrieve the counter from data I already have.
回答2:
By changing from a bunch of in individual getRGB's to one big getRGB to copy the entire image into an array, the execution time dropped by an order of magnitude from 33,000 milliseconds to 3,200 milliseconds, while the time create the array was only 31 milliseconds.
No doubt about it, one big read into an array and direct indexing of the array is much faster than many individual reads.
Performance difference appears related to the use of a breakpoint statement at the end of the class. While the breakpoint was outside the loop, every line of code within the class appears to be tested for the breakpoint. Changing to individual gets does NOT improve speed.
Since the code is still correct, the remainder of the answer may still be of use.
Old read statement
colorRed=new Color(bi.getRGB(x,y)).getRed();
Read statement to copy an bit image into an array
int[] rgbData = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(),
null, 0,bi.getWidth());
The getRGB into an array puts all 3 color values into a single array element, so individual colors must be extracted by rotating and an "and". The y coordinate must be multiplied by the width of the image.
Code to read individual colors out of the array
colorRed=(rgbData[(y*bi.getWidth())+x] >> 16) & 0xFF;
colorGreen=(rgbData[(y*bi.getWidth())+x] >> 8) & 0xFF;
colorBlue=(rgbData[(y*bi.getWidth())+x]) & 0xFF;
回答3:
You should loop the rows in the outer loop and the columns in the inner. That way you'll avoid cache misses.
回答4:
Did you try BufferedImage.getRGB(int, int ,int ,int, int[] , int , int)?
Something like:
int[] rgb = bi.getRGB(0,0, bi.getWidth(), bi.getHeight(), new int[bi.getWidth() * bi.getHeight(), bi.getWidth()])
Didn't try, so not sure if it's faster.
edit Having looked @ the code, it probably isn't, but worth a shot.
回答5:
I found a solution here 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);
}
}
来源:https://stackoverflow.com/questions/10088465/need-faster-way-to-get-rgb-value-for-each-pixel-of-a-buffered-image