将BufferedImage像素数据转换为可读输出?

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

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."); } } 

我现在要做的是分析一个数组中每个tile(一个BufferedImage)的原始数据,并确定它是否与来自另一个数组的任何已保存的BufferedImage tile相同。 我环顾四周寻找答案,并尝试了getRGB()方法和getData()栅格方法:

  img[a].getRGB(0,0,16,16,rawImgData[a],0,0); rawImgData[a] = ((DataBufferByte) img[a].getRaster().getDataBuffer()).getData(); 

问题是:从我所看到的,从这些方法返回的byte []和int []数据对于任何两个完全相同的图片是不一样的。 我需要一种方法将图像数据转换为原始int []或byte []数据,可用于比较两个完全相同的图片。 (IE;如果两张图片都只是一个16×16的黑色像素arrays,它们应该输出相同的getRGB()或getData()值。)是否有一种方法可以将这些BufferedImages转换为原始图像数据容易相互比较?

任何建议都将非常感谢,谢谢。

首先:JPG格式不是无损压缩。 这意味着对于像这样的序列

 BufferedImage imageA = loadImage("image.jpg"); saveAs("saved.jpg"); BufferedImage imageB = loadImage("saved.jpg"); somehowCompare(imageA, imageB); 

somehowCompare方法很可能会发现图像相等,因为JPG压缩引入了工件。

有疑问,你应该将图像存储为PNG,因为它是无损的,对于如上所述的序列,图像将被视为“相等” – 意味着它们具有完全相同的RGB像素值。

但这是你的实际问题:如何比较这些图像?

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

解决此问题的一个选择是将每个新加载的图像绘制成一个您知道它包含DataBufferInt 。 这意味着你可以使用像这样的方法

 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[]数组获取。 在最好的情况下,您可以简单地比较两个这样的图像的数组

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

另一种方法是简单地从图像中获取单个像素:

 // Assuming equal-sized images: for (int y=0; y 

后一种方法的优点可能是,当它们具有“非常相似”(但不完全相等)的像素值时,可以通过适当调整if-语句来将图像视为“相等”。

首先想到的是JPG是一种有损格式,不应该用于精确像素图形,特别是在16×16分辨率下。 当您阅读它时,您不应期望获得最初写入JPG的完全相同的RGB值。

我在unit testing中成功地将PNG用于参考图像,以与生成的BufferedImage进行比较。