将BufferedImage像素数据转换为可读输出? [英] Converting BufferedImage pixel data into a readable output?

查看:84
本文介绍了将BufferedImage像素数据转换为可读输出?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个程序,将旧GBA游戏的地图划分为16x16的图块,保存每个图块,然后将每个抓取的图块的原始图像数据与另一个保存的图块列表进行比较,并自动确定是否相同的图像.到目前为止,我已经设法将地图划分为16x16的图块,自动将每个16x16的图块保存到一个新的图像文件中,然后将所有这些图像文件作为BufferedImages加载到一个数组中.

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 of saved tiles and automatically determine if it's the same image. So far I've managed to divide the map into 16x16 tiles, automatically save each 16x16 tile into a new image file, and then load all of these image files as BufferedImages into an array.

 public TileSorter()
 {
   for (int a = 0; a < 1269; a++)
   {
     try {
       img[a] = ImageIO.read(new File("img" + a + ".jpg"));
     } catch (IOException e) {}
     System.out.println("img" + a + ".jpg loaded into Array.");
   }
 }

我现在要做的是分析一个数组中每个图块(一个BufferedImage)的原始数据,并确定它是否与另一个数组中保存的BufferedImage图块相同. 我一直在寻找答案,并尝试了getRGB()方法和getData()栅格方法:

What I want to do now, is analyze the raw data of each tile (a BufferedImage) in one array and determine if it's the same as any of the saved BufferedImage tiles from another array. I've looked around for answers and attempted both the getRGB() method and the getData() raster method:

    img[a].getRGB(0,0,16,16,rawImgData[a],0,0);

    rawImgData[a] = ((DataBufferByte) img[a].getRaster().getDataBuffer()).getData();

问题是:据我所知,对于任何两个完全相同的图片,从这些方法返回的byte []和int []数据都不相同.我需要一种将图像数据转换为原始int []或byte []数据的方法,可用于比较两个完全相同的图片. (即,如果两张图片都只是一个16x16黑色像素阵列,则它们应该输出相同的getRGB()或getData()值.) 是否可以使用一种方法将这些BufferedImages转换为可以轻松进行比较的原始图像数据?

The problem is: from what I can see, the byte[] and int[] data that's returned from these methods is not the same for any two exact same pictures. I need a way to convert image data into raw int[] or byte[] data that can be used to compare two exact same pictures. (IE; if two pictures are both just a 16x16 array of black pixels, they should output the same getRGB() or getData() values.) Is there a method that I can use to convert these BufferedImages into primitive image data that can be easily compared to one another?

任何建议,将不胜感激,谢谢.

Any suggestions would be much appreciated, thanks.

推荐答案

首先:JPG格式是无损压缩.这意味着对于类似

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);

somehowCompare方法很可能会发现图像不相同,因为JPG压缩引入了伪像.

the somehowCompare method would most likely find the images to be not equal, because the JPG compression introduced artifacts.

毫无疑问,您应该将图像存储为PNG,因为它是无损的,并且对于如上所述的序列,图像将被视为相等",这意味着它们具有完全相同的RGB像素值.

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?

获得数据缓冲区的方法将是最有效的一种.但是仍然有一些警告:图像是否包含DataBufferIntDataBufferByte取决于细微的细节.它可能取决于文件类型(JPG,GIF或PNG),图像是否包含透明度(如果是PNG或GIF)或压缩方法.

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.

解决此问题的一种方法是将每个新加载的图像绘制到一个您知道包含一个DataBufferInt的图像中.这意味着您可以使用类似

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;
}

然后使用

img[a] = convertToARGB(ImageIO.read(new File("img" + a + ".png")));

生成的图像将带有DataBufferInt.从此缓冲区,您可以将数据获取为int[]数组.最好的情况是,您可以使用

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!
        }
    }
}

后一种方法的优点是,可以通过适当调整if语句,将图像具有非常相似"(但不完全相等)的像素值视为相等".

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.

这篇关于将BufferedImage像素数据转换为可读输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆