Is there a simple way to compare BufferedImage instances?

I changed function that equals by pixels in Groovy, may be helpful:

boolean imagesAreEqual(BufferedImage image1, BufferedImage image2) {
    if (image1.width != image2.width || image1.height != image2.height) {
         return false
    }
    for (int x = 1; x < image2.width; x++) {
        for (int y = 1; y < image2.height; y++) {
             if (image1.getRGB(x, y) != image2.getRGB(x, y)) {
                 return false
             }
        }
    }
    return true
}

If speed is an issue, and both BufferedImages are of the same bit-depth, arrangement, etc. (which seems like it must be true here) you can do this:

DataBuffer dbActual = myBufferedImage.getRaster().getDataBuffer();
DataBuffer dbExpected = bufferImageReadFromAFile.getRaster().getDataBuffer();

figure out which type it is, e.g. a DataBufferInt

DataBufferInt actualDBAsDBInt = (DataBufferInt) dbActual ;
DataBufferInt expectedDBAsDBInt = (DataBufferInt) dbExpected ;

do a few "sanity checks" for equals on the sizes and banks of the DataBuffers, then loop

for (int bank = 0; bank < actualDBAsDBInt.getNumBanks(); bank++) {
   int[] actual = actualDBAsDBInt.getData(bank);
   int[] expected = expectedDBAsDBInt.getData(bank);

   // this line may vary depending on your test framework
   assertTrue(Arrays.equals(actual, expected));
}

This is close to as fast as you can get cause you are grabbing a chunk of the data at a time, not one at a time.


This is the best approach. No need to keep a variable to tell whether the image is still equal. Simply return false immediately when the condition if false. Short-circuit evaluation helps save time looping over pixels after the comparison fails as is the case in trumpetlick's answer.

/**
 * Compares two images pixel by pixel.
 *
 * @param imgA the first image.
 * @param imgB the second image.
 * @return whether the images are both the same or not.
 */
public static boolean compareImages(BufferedImage imgA, BufferedImage imgB) {
  // The images must be the same size.
  if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) {
    return false;
  }

  int width  = imgA.getWidth();
  int height = imgA.getHeight();

  // Loop over every pixel.
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      // Compare the pixels for equality.
      if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) {
        return false;
      }
    }
  }

  return true;
}

You could write your own routine for comparison!

int width;
int height;
boolean imagesEqual = true;

if( image1.getWidth()  == ( width  = image2.getWidth() ) && 
    image1.getHeight() == ( height = image2.getHeight() ) ){

    for(int x = 0;imagesEqual == true && x < width; x++){
        for(int y = 0;imagesEqual == true && y < height; y++){
            if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                imagesEqual = false;
            }
        }
    }
}else{
    imagesEqual = false;
}

This would be one way!!!

Tags:

Java

Awt