有没有一种比较BufferedImage实例的简单方法?

pha*_*cle 17 java awt

我正在研究Java应用程序的一部分,该应用程序将图像作为字节数组,将其读入java.awt.image.BufferedImage实例并将其传递给第三方库进行处理.

对于单元测试,我想拍摄一张图像(来自磁盘上的文件)并声明它等于代码处理过的相同图像.

  • 期望的 BufferedImage是从磁盘上的PNG文件中读取ImageIO.read(URL).
  • 我的测试代码将相同的文件读入a BufferedImage并将其作为PNG写入字节数组,以提供给被测系统.

当被测系统将字节数组写入新的时,BufferedImage我想断言两个图像以有意义的方式相等.使用equals()(继承自Object)不起作用(当然).比较BufferedImage.toString()值也不起作用,因为输出字符串包括对象引用信息.

有人知道任何捷径吗?我不想在大型应用程序的一小部分中引入第三方库进行单个单元测试.

Mr.*_*irl 16

这是最好的方法.无需保留变量来判断图像是否仍然相等.如果条件为false,则立即返回false.短路评估有助于在比较失败后节省像素循环时间,就像trumpetlick的回答一样.

/**
 * Compares two images pixel by pixel.
 *
 * @param imgA the first image.
 * @param imgB the second image.
 * @return whether the images are both the same or not.
 */
public static boolean compareImages(BufferedImage imgA, BufferedImage imgB) {
  // The images must be the same size.
  if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) {
    return false;
  }

  int width  = imgA.getWidth();
  int height = imgA.getHeight();

  // Loop over every pixel.
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      // Compare the pixels for equality.
      if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) {
        return false;
      }
    }
  }

  return true;
}
Run Code Online (Sandbox Code Playgroud)


use*_*300 5

如果速度是一个问题,并且两者BufferedImages都具有相同的位深度,排列等(这似乎必须在这里),你可以这样做:

DataBuffer dbActual = myBufferedImage.getRaster().getDataBuffer();
DataBuffer dbExpected = bufferImageReadFromAFile.getRaster().getDataBuffer();
Run Code Online (Sandbox Code Playgroud)

弄清楚它是哪种类型,例如a DataBufferInt

DataBufferInt actualDBAsDBInt = (DataBufferInt) dbActual ;
DataBufferInt expectedDBAsDBInt = (DataBufferInt) dbExpected ;
Run Code Online (Sandbox Code Playgroud)

对DataBuffers的大小和库进行一些"完整性检查",然后循环

for (int bank = 0; bank < actualDBAsDBInt.getNumBanks(); bank++) {
   int[] actual = actualDBAsDBInt.getData(bank);
   int[] expected = expectedDBAsDBInt.getData(bank);

   // this line may vary depending on your test framework
   assertTrue(Arrays.equals(actual, expected));
}
Run Code Online (Sandbox Code Playgroud)

由于您一次抓取一大块数据,而不是一次抓取一大块数据,因此速度接近最快.

  • 相同的位深度、排列等……是相当大的。昨天刚刚回答了一个人的问题,他基本上是在对图像进行比较,他发现一个是 ARGB_8888,另一个是 RGB_565。这些都是很大的假设。你确实是对的,如果这些参数是真的,这将是最快的方法:-) (2认同)