使用 Java 以编程方式确定 2 个图像是否看起来相同 [关闭]

2023-11-25

在JAVA中,我试图以编程方式判断两个图像在屏幕上显示时是否相等(又名相同的图像,即使它们具有不同的值)色彩空间。是否有一段代码在呈现 2 个图像时会返回布尔值?

我的示例之一是将 RGB PNG 转换为灰度 PNG。两张图片看起来都一样,我想以编程方式证明这一点。另一个示例是两个图像,它们在屏幕上显示完全相同的颜色像素,但 100% 透明像素使用的颜色已更改。


我查看了所有解决方案,并确定它们可以告诉您图像的不同程度或对于某些类型的图像的工作效果,但不是全部。这是我想出的解决方案......

package image.utils;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility methods used to interact with images.
 */
public class ImageUtils {

    private final static Logger logger = LoggerFactory.getLogger(ImageUtils.class);

    private static final boolean equals(final int[] data1, final int[] data2) {
        final int length = data1.length;
        if (length != data2.length) {
            logger.debug("File lengths are different.");
            return false;
        }
        for(int i = 0; i < length; i++) {
            if(data1[i] != data2[i]) {

                //If the alpha is 0 for both that means that the pixels are 100%
                //transparent and the color does not matter. Return false if 
                //only 1 is 100% transparent.
                if((((data1[i] >> 24) & 0xff) == 0) && (((data2[i] >> 24) & 0xff) == 0)) {
                    logger.debug("Both pixles at spot {} are different but 100% transparent.", Integer.valueOf(i));
                } else {
                    logger.debug("The pixel {} is different.", Integer.valueOf(i));
                    return false;
                }
            }
        }
        logger.debug("Both groups of pixels are the same.");
        return true;
    }

    private static final int[] getPixels(final BufferedImage img, final File file) {

        final int width = img.getWidth();
        final int height = img.getHeight();
        int[] pixelData = new int[width * height];

        final Image pixelImg; 
        if (img.getColorModel().getColorSpace() == ColorSpace.getInstance(ColorSpace.CS_sRGB)) {
            pixelImg = img;
        } else {
            pixelImg = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(img, null);
        }

        final PixelGrabber pg = new PixelGrabber(pixelImg, 0, 0, width, height, pixelData, 0, width);

        try {
            if(!pg.grabPixels()) {
                throw new RuntimeException();
            }
        } catch (final InterruptedException ie) {
            throw new RuntimeException(file.getPath(), ie);
        }

        return pixelData;
    }

    /**
     * Gets the {@link BufferedImage} from the passed in {@link File}.
     * 
     * @param file The <code>File</code> to use.
     * @return The resulting <code>BufferedImage</code>
     */
    @SuppressWarnings("unused")
    final static BufferedImage getBufferedImage(final File file) {
        Image image;

        try (final FileInputStream inputStream = new FileInputStream(file)) {
            // ImageIO.read(file) is broken for some images so I went this 
            // route
            image = Toolkit.getDefaultToolkit().createImage(file.getCanonicalPath());

            //forces the image to be rendered
            new ImageIcon(image);
        } catch(final Exception e2) {
            throw new RuntimeException(file.getPath(), e2);
        }

        final BufferedImage converted = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        final Graphics2D g2d = converted.createGraphics();
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return converted;
    }

    /**
     * Compares file1 to file2 to see if they are the same based on a visual 
     * pixel by pixel comparison. This has issues with marking images different
     * when they are not. Works perfectly for all images.
     * 
     * @param file1 First file to compare
     * @param file2 Second image to compare
     * @return <code>true</code> if they are equal, otherwise 
     *         <code>false</code>.
     */
    private final static boolean visuallyCompareJava(final File file1, final File file2) {
        return equals(getPixels(getBufferedImage(file1), file1), getPixels(getBufferedImage(file2), file2));
    }

    /**
     * Compares file1 to file2 to see if they are the same based on a visual 
     * pixel by pixel comparison. This has issues with marking images different
     * when they are not. Works perfectly for all images.
     * 
     * @param file1 Image 1 to compare
     * @param file2 Image 2 to compare
     * @return <code>true</code> if both images are visually the same.
     */
    public final static boolean visuallyCompare(final File file1, final File file2) {

        logger.debug("Start comparing \"{}\" and \"{}\".", file1.getPath(), file2.getPath());

        if(file1 == file2) {
            return true;
        }

        boolean answer = visuallyCompareJava(file1, file2);

        if(!answer) {
            logger.info("The files \"{}\" and \"{}\" are not pixel by pixel the same image. Manual comparison required.", file1.getPath(), file2.getPath());
        }

        logger.debug("Finish comparing \"{}\" and \"{}\".", file1.getPath(), file2.getPath());

        return answer;
    }

    /**
     * @param file The image to check
     * @return <code>true</code> if the image contains one or more pixels with
     *         some percentage of transparency (Alpha)
     */
    public final static boolean containsAlphaTransparency(final File file) {
        logger.debug("Start Alpha pixel check for {}.", file.getPath());

        boolean answer = false;
        for(final int pixel : getPixels(getBufferedImage(file), file)) {
            //If the alpha is 0 for both that means that the pixels are 100%
            //transparent and the color does not matter. Return false if 
            //only 1 is 100% transparent.
            if(((pixel >> 24) & 0xff) != 255) {
                logger.debug("The image contains Aplha Transparency.");
                return true;
            }
        }

        logger.debug("The image does not contain Aplha Transparency.");
        logger.debug("End Alpha pixel check for {}.", file.getPath());

        return answer;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Java 以编程方式确定 2 个图像是否看起来相同 [关闭] 的相关文章

  • 如何将 JSpinner 的值设置为特定日期

    我有一个JSpinner我添加到JPanel我想将其时间设置为 GregorianCalendar calendar JSpinner spinner new JSpinner spinner setModel model pom add
  • GET 请求的 Spring 注解

    这两种spring GET方法有什么区别呢 哪一种是首选方法 Component Scope request Path public class TestComponent GET Path hello public String prin
  • 在 Java 中从 SOAPMessage 获取原始 XML

    我已经在 J AX WS 中设置了 SOAP WebServiceProvider 但我无法弄清楚如何从 SOAPMessage 或任何 Node 对象获取原始 XML 下面是我现在获得的代码示例 以及我试图获取 XML 的位置 WebSe
  • 项目缺少所需的注释处理库

    我的 Eclipse IDE 突然在问题视图中显示 xxxx 项目缺少所需的注释处理库 xxxx M2 REPO 中的一些旧 jar 我用谷歌搜索 没有找到任何答案 为什么我的项目使用旧的 jar 以及错误来自哪里 To remove th
  • JTextField 和 JTextArea

    JTextField 和 JTextArea 有什么不同 是否可以在一个班级中使用这两个班级 总之 JTextField 是单行文本字段 而 JTextArea 可以跨越多行 文档中清楚地解释了这些差异 文本区 http docs orac
  • 具有 CRUD 功能的基于 Spring Web 的管理工具

    在 PHP Symfony 世界里有一个工具叫 Sonata Adminhttps sonata project org https sonata project org 基于 AdminLTE 模板 这是一款一体化管理工具 具有登录 菜单
  • java中的单链表和双向链表?

    在java中 哪个集合接口可以有效地实现单链表和双向链表 请问代码示例吗 毫不奇怪 实现双向链表的正确接口是 LinkedList 看Java文档 http docs oracle com javase 8 docs api java ut
  • Kafka Java Consumer 已关闭

    我刚刚开始使用卡夫卡 我面临着消费者的一个小问题 我用Java写了一个消费者 我收到此异常 IllegalStateException 此消费者已关闭 我在以下行中遇到异常 ConsumerRecords
  • maven 无法下载 jacoco 0.7.10-SNAPSHOT jar

    我对此感到困惑 我的 pom xml 中有这个
  • 将现有 eclipse 项目导出到 war 文件时出现“模块名称无效”

    我正在尝试将现有 Eclipse 项目导出到 war 文件 但无论我在 WAR Export 对话框页面中输入什么 系统总是返回 模块名称无效 我不知道如何解决这个问题 谢谢您的帮助 我有同样的问题 我修复了它 请按照以下步骤操作 您可以创
  • 如何使用 swagger-codegen-plugin (maven) 生成客户端代码?

    我需要使用 swagger codegen plugin for maven 在 eclipse 中生成服务器存根代码 你能帮忙怎么做吗 以及需要什么配置 在 pom xml 中 我找到了这个答案 您只需要像下面这样更改 pom xml 即
  • 从 Android 访问云存储

    我一直无法找到任何有关如何从 Android 应用程序使用云存储的具体文档 我确实遇到过这个客户端库 https cloud google com storage docs reference libraries然而 Google Clou
  • 如何在 Bean Validation 1.0 中构造 ConstraintViolationException?

    我对 javax validation API 感到困惑 我正在编写一个简单的测试来理解它 Sample sample new Sample Set
  • Java String ReplaceAll 方法给出非法重复错误?

    我有一个字符串 当我尝试运行时replaceAll方法 我收到这个奇怪的错误 String str something op str str replaceAll o n it works fine str str replaceAll n
  • 在 Freemarker 模板中检查 Spring 安全角色和记录的用户名

    有谁知道 freemarker 标签来检查 freemarker 文件中的 spring 安全角色和用户名 我从网络上的几个资源中发现以下代码将打印登录的用户名 但它没有打印用户名 而是打印 登录为
  • java中的预增量/后增量

    有人可以帮助我理解为什么 int i 1 int j 1 int k 1 int l 1 System out println i i System out println j j System out println k k System
  • 使用自定义比较器在 Java 中创建 SortedMap

    我想创建一个TreeMap在 Java 中具有自定义排序顺序 排序后的键是字符串 需要根据第二个字符进行排序 这些值也是字符串 示例地图 Za FOO Ab Bar 您可以像这样使用自定义比较器 Comparator
  • 如何使用注释处理 Hibernate 和 Spring 中的连接查询?

    我正在使用 Spring 和 Hibernate 以及 MySQL 开发应用程序 我是 Hibernate 新手 完成了基本任务 现在我需要在选择查询中应用联接以使用注释从多个表中获取数据 我已经搜索过但仍然没有任何想法 这是我的数据库表和
  • Android Google 地图无法在当前主题中找到样式“mapViewStyle”

    添加谷歌地图视图时 我扩展了MapView 使用xml编辑器将其添加到活动中 并将我的谷歌地图api密钥手动添加到布局xml文件中 我的权限在清单文件中允许互联网 我想知道的是 在 xml 编辑器中 我收到错误 无法在当前主题中找到样式 m
  • 你能快速告诉我这个伪代码是否有意义吗?

    我相信我的代码现在是万无一失的 我现在将写出伪代码 但我确实有一个问题 为什么 DRJava 要求我返回 if 语句之外的内容 正如你所看到的 我为 ex 写了 return 1 只是因为它问了 但是它永远不会返回该值 谁可以给我解释一下这

随机推荐

  • celeryd 进程的数量是否取决于 --concurrency 设置?

    我们在 Supervisor 后面运行 Celery 并启动它 celeryd events loglevel INFO concurrency 2 然而 这会创建一个最多三层深并包含最多 7 个 celeryd 进程的流程图 Superv
  • Matplotlib图形facecolor(背景颜色)

    有人可以解释一下为什么下面的代码在设置图形的面部颜色时不起作用吗 import matplotlib pyplot as plt create figure instance fig1 plt figure 1 fig1 set fighe
  • Ansible 循环处理 URI 调用的 JSON 输出

    一段时间以来我一直在尝试让它发挥作用 但我无法做到这一点 我希望这是我所缺少的一些很小的东西 我正在尝试解析使用 with items 的任务的 JSON 输出 我知道最终组件的变量列表将包含在结果数组中 name Get list of
  • Swift:检查字符串是否有数组中的元素

    我想检查一个字符串是否至少包含数组中的一个元素 我试过这个 但我认为它太长了 想象一下 如果我想要 if 语句中的所有字母表 我希望有一个适当的方法来做到这一点 var str Hello playground let typeString
  • 无法将项目导入到android studio

    我正在尝试使用this library 我已经添加 compile net rdrei android dirchooser library 2 0 aar 到依赖项 我的顶级构建文件 Top level build file where
  • 创建一个零填充的二维数组,其位置由向量索引

    我正在尝试向量化以下 MATLAB 操作 给定一个带有索引的列向量 我想要一个带有 相同数量的行和固定数量的列 这 矩阵用零初始化并在位置中包含 1 由索引指定 这是我已经编写的脚本的示例 y 1 3 2 1 3 m size y 1 Fo
  • EditorFor() 和 html 属性

    Asp Net MVC 2 0 预览版提供了类似的帮助器 Html EditorFor c gt c propertyname 如果属性名称是字符串 上面的代码将呈现一个文本框 如果我想将 MaxLength 和 Size 属性传递到文本框
  • 如何获取真实运行的进程名称?

    在 NET core 控制台应用程序中 我想获取正在运行的进程名称 我使用ProcessName正如文档所说 但它总是返回dotnet作为进程名称 而不是正在运行的实际下划线 dll 虽然它是一个 dll 但这是一个控制台应用程序 而不是一
  • 空格导致 PowerShell 路径分割

    在包含空格的路径中调用 exe 时 我遇到了 powershell 问题 PS C Windows Services gt invoke expression C Windows Services MyService exe 术语 C Wi
  • 如何在 Scala/Lift 中惯用地处理 null 检查?

    即使 Box 和 Option monad 很流行 我们仍然必须到处检查空值 到目前为止我想出的最好的方法是使用 Box 方法 Box possiblyNull map toString openOr 有一个更好的方法吗 我尝试使用 Box
  • Eclipse 终止键盘快捷键

    How do I get eclipse to terminate I use the keyboard shortcut Ctrl F11 to run a program and I cannot enable the terminat
  • Expo 构建 EAS - 本地 - 未找到 SDK 位置

    当我使用来自博览会的新构建工具时EAS在本地构建我的 React Native 应用程序 eas build platform android local 我收到一个错误 未找到 SDK 位置 使用 ANDROID SDK ROOT 定义位
  • 给定一组点,如何找到彼此最远的两个点? [复制]

    这个问题在这里已经有答案了 可能的重复 最大线性尺寸二维点集 我可以计算每个点之间的距离并取最大的距离 但是当有大量 gt 1000 点时 这听起来不是一种非常有效的方法 注意 这是针对 iPhone 的 所以我没有太多的处理能力 为什么不
  • 如果没有堆内存,如何释放 std::vector

    我有一个这样的类成员变量 vector
  • 在 Microsoft Outlook 中使用 applescript 创建新的外发邮件

    我正在尝试使用 Microsoft Outlook 2011 for mac 创建新的外发邮件 使用AppleScript 以下示例适用于10 6 8 tell application Microsoft Outlook set newMe
  • 数据库大小计算?

    估计具有以下特征的数据库有多大的最准确方法是什么 MySQL 1 Table with three columns id gt 大整型 字段1 gt varchar 32 字段2 gt 字符 32 field2 上有一个索引 您可以假设 v
  • 在 bash 中创建 RS256 JWT

    我正在尝试仅使用 bash 和 openSSL 构建 RS256 JWT 令牌 我可以使用的开发工具有限 我设计了一个脚本 它从 txt 文件中获取标头和有效负载 去掉换行符等 base 64URL 对它们进行编码并用 将它们连接在一起 分
  • Mongoose .update() 不会触发验证检查

    我可以设置超出枚举数组的值 但我不知道为什么猫鼬不验证该值 我是否以错误的方式更新枚举 my code var OrderSchema new mongoose Schema status type String enum created
  • 如何在Python 3中将具有属性的对象转换为不带“_”的JSON?

    我想将 Python 对象转换为 JSON 格式 类的私有属性User使用属性定义 方法to Json 我已经发现here class User def init self self name None self gender None p
  • 使用 Java 以编程方式确定 2 个图像是否看起来相同 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 在JAVA中 我试图以编程方式判断两个图像在屏幕上显示时是否相等 又名相同的图像 即使它们具有不同的值 色彩空间 是否有一段代码在呈现 2 个图像时会返回布尔值 我的示例之一是将