我试图制作一个程序,将一个老的GBA游戏的地图分成16x16个瓷砖,保存每个瓷砖,然后将每个抓取的瓷砖的原始图像数据与另一个保存的瓷砖列表进行比较,并自动确定是否是相同的图像。到目前为止,我已经将地图划分为16x16块,自动将每个16x16块保存到一个新的图像文件中,然后将所有这些图像文件作为BufferedImages加载到一个数组中。
html" target="_blank">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[]或字节[]数据,可以用来比较两个完全相同的图片。(也就是说,如果两张图片都是一个16x16的黑色像素数组,它们应该输出相同的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
-语句,当图像具有“非常相似”(但不完全相等)的像素值时,您可以将图像视为“相等”。
问题内容: 在StackOverflow上已经存在类似此链接的问题,并且可接受的答案是“广播”: 在我的程序中,我尝试: 不幸的是,我得到运行时错误: sun.awt.image.ToolkitImage无法转换为java.awt.image.BufferedImage 显然,投射不起作用。 问题是:将Image转换为BufferedImage的正确方法是(或存在)什么? 问题答案: 从Java游
问题内容: 我这里有点问题。 我有一个applet,用户可以在其中“绘制”它。为此,我使用java.awt.Graphics2D。但是,如何将用户绘图图像保存为JPEG图像,或者至少将其转换为BufferedImage或其他内容?我不知道该怎么做。 谢谢。 问题答案: 我这样做,并且效果很好: 就这些了:)谢谢大家:)
问题内容: 我一直在尝试将a转换为…而且我没有运气。 我有一个预先存在的ImageIcon,对于存在的大量BufferedImage操作,需要将其转换为Buffered Image。 我发现了几种方法,但是所有方法都占用大量CPU。 问题答案: 有什么问题:
我在Java中有一个tiff图像的INT[2048][2048]原始数据数组。我想把那个数组转换回BufferedImage。我该如何进行?
问题内容: 我有一个图像文件的Data-URL,必须将其传递给另一个函数。从Data-URL到BufferedImage的路径必须是一个byteArray。 我的方法如下: 问题是,它总是抛出UnknownImageFormatException异常,这意味着inputImage为null,这意味着ImageIO.read无法识别图像类型。 我使用ImageIO.getReaderFormatNa
问题内容: 我正在使用servlet上传图像。为了执行调整大小的操作,我将InputStream转换为BufferedImage。现在我想将其保存在mongoDB中。因为据我所知,我是mongoDB的新手,所以GridFS采用InputStream。 那么,有什么方法可以将BufferedImage转换为InputStream吗? 问题答案: 您需要使用该类将BufferedImage保存为,然后