Converting BufferedImage pixel data into a readable output?

后端 未结 2 1764
萌比男神i
萌比男神i 2021-01-16 19:06

I\'m trying to make a program to divide the map of an old GBA game into 16x16 tiles, save each tile, and then compare the raw image data of each grabbed tile to another list

2条回答
  •  耶瑟儿~
    2021-01-16 19:36

    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

    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.

提交回复
热议问题