First of all: The JPG format is NOT a lossless compression. That means that for a sequence like
BufferedImage imageA = loadImage("image.jpg");
saveAs("saved.jpg");
BufferedImage imageB = loadImage("saved.jpg");
somehowCompare(imageA, imageB);
the somehowCompare
method would most likely find the images to be not equal, because the JPG compression introduced artifacts.
In doubt, you should store the images as PNG, because it is lossless, and for a sequence as the one described above, the images would be considered as "equal" - meaning that they have exactly the same RGB pixel values.
But this is your actual question: How to compare these images?
The approach of obtaining the data buffer would be the most efficient one. But there are still some caveats: Whether or not the image contains a DataBufferInt
or a DataBufferByte
depends on subtle details. It may depend on the file type (JPG, GIF or PNG), or whether the image contains transparency (if it is a PNG or GIF), or on the compression method.
One option to solve this would be to paint each newly loaded image into one where you know that it contains a DataBufferInt
. That means you could use a method like
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;
}
and then load your images with
img[a] = convertToARGB(ImageIO.read(new File("img" + a + ".png")));
The resulting images will have a DataBufferInt
. From this buffer, you may obtain the data as an int[]
array. And in the best case, you can simply compare the arrays of two such images using
DataBufferInt bufferA = (DataBufferInt)imageA.getRaster().getDataBuffer();
DataBufferInt bufferB = (DataBufferInt)imageB.getRaster().getDataBuffer();
int arrayA[] = bufferA.getData();
int arrayB[] = bufferB.getData();
if (Arrays.equal(arrayA, arrayB))
{
// Images are equal!
}
The alternative would be to simply obtain individual pixels from the images:
// Assuming equal-sized images:
for (int y=0; y<imageA.getHeight(); y++)
{
for (int x=0; x<imageA.getWidth(); x++)
{
int rgbA = imageA.getRGB(x,y);
int rgbB = imageB.getRGB(x,y);
if (rgbA != rgbB)
{
// Images are NOT equal!
}
}
}
The advantage with the latter approach could be that you may consider images as "equal" when they have "very similar" (but not perfectly equal) pixel values, by adjusting the if
-statement appropriately.