Java 有没有比较BuffereImage实例的简单方法?

Java 有没有比较BuffereImage实例的简单方法?,java,awt,Java,Awt,我正在开发一个Java应用程序的一部分,该应用程序将图像作为字节数组,将其读入Java.awt.image.buffereImage实例,并将其传递给第三方库进行处理 对于单元测试,我希望获取一个映像(来自磁盘上的文件),并断言它与代码处理过的相同映像相同 使用ImageIO.read(URL)从磁盘上的PNG文件读取我的预期的buffereImage 我的test代码将同一文件读入buffereImage并将其作为PNG写入字节数组,以提供给被测系统 当被测系统将字节数组写入一个新的buf

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

对于单元测试,我希望获取一个映像(来自磁盘上的文件),并断言它与代码处理过的相同映像相同

  • 使用
    ImageIO.read(URL)
    从磁盘上的PNG文件读取我的预期的
    buffereImage
  • 我的test代码将同一文件读入
    buffereImage
    并将其作为PNG写入字节数组,以提供给被测系统
当被测系统将字节数组写入一个新的
buffereImage
时,我想断言这两个映像在某种意义上是相等的。使用
equals()
(从
对象继承而来)当然不起作用。比较
buffereImage.toString()
值也不起作用,因为输出字符串包含对象引用信息


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

您可以编写自己的例程进行比较

int width;
int height;
boolean imagesEqual = true;

if( image1.getWidth()  == ( width  = image2.getWidth() ) && 
    image1.getHeight() == ( height = image2.getHeight() ) ){

    for(int x = 0;imagesEqual == true && x < width; x++){
        for(int y = 0;imagesEqual == true && y < height; y++){
            if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                imagesEqual = false;
            }
        }
    }
}else{
    imagesEqual = false;
}
int宽度;
内部高度;
布尔值imagesEqual=true;
如果(image1.getWidth()=(width=image2.getWidth())&&
image1.getHeight()==(height=image2.getHeight()){
对于(int x=0;imagesEqual==true&&x

这将是一种方式

除了蛮力“做循环”之外,我想不出什么了:

buffereImage bi1、bi2。。。
...
光栅r1=bi1.getData();
DataBuffer db1=r1.getDataBuffer();
if(db1.getSize()!=db2.getSize())
...
对于(inti=0;i
如果速度是一个问题,并且两个
缓冲区图像具有相同的位深度、排列方式等(此处似乎必须是正确的),则可以执行以下操作:

DataBuffer dbActual = myBufferedImage.getRaster().getDataBuffer();
DataBuffer dbExpected = bufferImageReadFromAFile.getRaster().getDataBuffer();
找出它是哪种类型,例如
DataBufferInt

DataBufferInt actualDBAsDBInt = (DataBufferInt) dbActual ;
DataBufferInt expectedDBAsDBInt = (DataBufferInt) dbExpected ;
对数据缓冲区的大小和组进行一些“合理性检查”,然后循环

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));
}
for(int bank=0;bank

这是最快的,因为您一次捕获一块数据,而不是一次捕获一块。

您可以通过
图像IO
通过
输出流将图像写入
字节[]
。 在我的代码中,大致如下所示:

byte[] encodeJpegLossless(BufferedImage img){...using imageio...}
...
Assert.assertTrue(Arrays.equals(encodeJpegLossless(img1)
                               ,encodeJpegLossless(img2)
                               )
                 );
我在Groovy中进行了更改,可能会有所帮助:

boolean ImagesReequal(BuffereImage image1,BuffereImage image2){
if(image1.width!=image2.width | | image1.height!=image2.height){
返回错误
}
对于(int x=1;x
这是最好的方法。不需要保留变量来判断图像是否仍然相等。如果条件为false,只需立即返回false。短路评估有助于在比较失败后节省在像素上循环的时间,就像特朗普利克的情况一样

/**
*逐像素比较两个图像。
*
*@param imgA第一张图片。
*@param imgB是第二个图像。
*@return无论图像是否相同。
*/
公共静态布尔比较图像(BuffereImage imgA、BuffereImage imgB){
//图像的大小必须相同。
如果(imgA.getWidth()!=imgB.getWidth()| | imgA.getHeight()!=imgB.getHeight()){
返回false;
}
int width=imgA.getWidth();
int height=imgA.getHeight();
//在每个像素上循环。
对于(int y=0;y
工作正常但效率不高

public static boolean compareImage(File fileA, File fileB) {        
    try {
        // take buffer data from botm image files //
        BufferedImage biA = ImageIO.read(fileA);
        DataBuffer dbA = biA.getData().getDataBuffer();
        int sizeA = dbA.getSize();                      
        BufferedImage biB = ImageIO.read(fileB);
        DataBuffer dbB = biB.getData().getDataBuffer();
        int sizeB = dbB.getSize();
        // compare data-buffer objects //
        if(sizeA == sizeB) {
            for(int i=0; i<sizeA; i++) { 
                if(dbA.getElem(i) != dbB.getElem(i)) {
                    return false;
                }
            }
            return true;
        }
        else {
            return false;
        }
    } 
    catch (Exception e) { 
        e.printStackTrace();
        return  false;
    }
}
公共静态布尔比较图像(文件fileA,文件fileB){
试一试{
//从botm图像文件中获取缓冲区数据//
BuffereImage biA=ImageIO.read(文件A);
DataBuffer dbA=biA.getData().getDataBuffer();
int sizeA=dbA.getSize();
BuffereImage biB=ImageIO.read(文件B);
DataBuffer dbB=biB.getData().getDataBuffer();
int sizeB=dbB.getSize();
//比较数据缓冲区对象//
if(sizeA==sizeB){
对于(inti=0;i如果您想使用,那么您可以编写一个匹配器


你能解释一下为什么
.equals()
不起作用吗?@JakeKing:如果它是从Object继承的,它就不起作用,因为那只是对象标识。你不能只比较字节数组(包含PNG)吗?@JakeKing
buffereImage
不会覆盖
Object#equals()
。有几件事我不太清楚。也许我可以通过检查来简化问20个问题。1)假设您加载了
BuffereImage
实例,最快的图像比较检查能否回答您的问题?2)内存是个大问题吗?(它们是4000x300px图像吗?)当大小不匹配时,也需要为false。仅在
if
块内部将布尔值设置为true。@trumpetlicks另外,
break
语句不会起多大作用,您已经为嵌套了

/**
 * 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;
}
public static boolean compareImage(File fileA, File fileB) {        
    try {
        // take buffer data from botm image files //
        BufferedImage biA = ImageIO.read(fileA);
        DataBuffer dbA = biA.getData().getDataBuffer();
        int sizeA = dbA.getSize();                      
        BufferedImage biB = ImageIO.read(fileB);
        DataBuffer dbB = biB.getData().getDataBuffer();
        int sizeB = dbB.getSize();
        // compare data-buffer objects //
        if(sizeA == sizeB) {
            for(int i=0; i<sizeA; i++) { 
                if(dbA.getElem(i) != dbB.getElem(i)) {
                    return false;
                }
            }
            return true;
        }
        else {
            return false;
        }
    } 
    catch (Exception e) { 
        e.printStackTrace();
        return  false;
    }
}
import org.mockito.ArgumentMatcher;

public class BufferedImageMatcher extends ArgumentMatcher<BufferedImage> {

  private final BufferedImage expected;

  public BufferedImageMatcher(BufferedImage expected) {
    this.expected = expected;
  }

  @Override
  public boolean matches(Object argument) {
    BufferedImage actual = (BufferedImage) argument;

    assertEquals(expected.getWidth(), actual.getWidth());
    assertEquals(expected.getHeight(), actual.getHeight());

    for (int x = 0; x < actual.getWidth(); x++) {
      for (int y = 0; y < actual.getHeight(); y++) {
        assertEquals(expected.getRGB(x, y), actual.getRGB(x, y));
      }
    }

    return true;
  }
}
assertThat(actual, new BufferedImageMatcher(expected));