Fastest way to compare pixel values ​​between two BufferedImages?

I have a BufferedImage of type TYPE_INT_BGR. I need to do a phased comparison with another BufferedImage in order to calculate the “distance” between two images. I have something that works, but slow. I get a pixel from a “reference” image, split it into RGB bytes with:

int pixel = referenceImage.getRGB(col, row); int red = (pixel >> 16) & 0xff; int green = (pixel >> 8) & 0xff; int blue = (pixel) & 0xff; 

I compare the r / g / b values ​​with the corresponding pixel of the candidate image and summarize the difference squares.

Is there a faster way to make such a comparison? Looking at the source of the JRE, I see that BufferedImage.getRGB () is actually ORing the RGB values ​​from the raster together, which is useless for my purposes, since I just split it into bytes again.

I will try to do this directly, but I wonder if there is a better way to do this, either using the Java API or a third-party API that I could skip.

+6
java rgb bufferedimage java-2d
source share
4 answers

Reading data from VolatileImage will not be faster. What makes VolatileImages “faster” is that they use accelerated (VRAM) memory instead of system (RAM) memory to draw images. However, reading may require access to memory via a different bus and slower than system memory for these operations.

The fastest way to compare BufferedImages is to use integer comparisons as you discuss in your post, but as you say you cannot use getRGB for performance reasons. You can get a batch of pixels into an array, but in general you should probably just look into Raster and DataBuffer for better performance.

+3
source share

If both images use the same color model and selection, you can perform your comparison in the DataBuffer raster, which will be a little faster.

+2
source share

Have you considered using Java2D to create a new image that is the difference between your two images, and then analyze the difference image instead?

My initial approach would be to take a negative image A and add image B.

+2
source share

If there is a problem with byte splitting + loading additional classes, try the following:

Getting BufferedImage value from RGB pixel value

 img = 65536*R + 256*G + B - 16777216; 

Getting RGB value from BufferedImage img value

 R= Math.round((((371*img)+24576000000) / 96000000) G= Math.round((65536 + 0.003906*img - 256*R)); B= Math.round((65536*R + 256*G -img - 16777216)); 

I'm not sure if this is the best / fastest way to do this, but this is another alternative method that does not use extra classes and is a direct mathematical process (or hacking) ... This may become useful in some cases (please double check, so as this is my own method, which I did not have enough time to play).

I don’t know what kind of comparison you need between the pixel values, so this is how far this post goes ... I hope someone really finds this useful!

+1
source share

All Articles