我正在尝试制作一个程序,将旧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.");
}
}
我现在要做的是分析一个数组中每个图块(一个BufferedImage)的原始数据,并确定它是否与另一个数组中保存的任何BufferedImage图块相同.
我四处寻找答案,并尝试了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 []数据的方法,可用于比较两个完全相同的图片. (即,如果两张图片都只是一个16×16黑色像素阵列,则它们应该输出相同的getRGB()或getData()值.)
有没有一种方法可以将这些BufferedImages转换为可以轻松进行比较的原始图像数据?
任何建议将不胜感激,谢谢.
解决方法:
首先:JPG格式不是无损压缩.这意味着对于类似
BufferedImage imageA = loadImage("image.jpg");
saveAs("saved.jpg");
BufferedImage imageB = loadImage("saved.jpg");
somehowCompare(imageA, imageB);
somehowCompare方法很可能会发现图像不相等,因为JPG压缩引入了伪像.
毫无疑问,您应该将图像存储为PNG,因为它是无损的,并且对于如上所述的序列,图像将被视为“相等”,这意味着它们具有完全相同的RGB像素值.
但这是您的实际问题:如何比较这些图像?
获得数据缓冲区的方法将是最有效的一种.但是仍然有一些警告:图像是否包含DataBufferInt或DataBufferByte取决于细微的细节.它可能取决于文件类型(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<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语句,在图像具有“非常相似”(但不是完全相等)的像素值时将其视为“相等”.