package com.whyc.util;
|
|
import javax.imageio.ImageIO;
|
import javax.xml.bind.DatatypeConverter;
|
import java.awt.*;
|
import java.awt.image.BufferedImage;
|
import java.io.ByteArrayOutputStream;
|
import java.io.File;
|
import java.io.FileInputStream;
|
import java.io.IOException;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
|
public class ImageDiff {
|
|
//不同的像素标记为红色
|
|
public static final int RGB_RED = 16711680;
|
//public static final int RGB2 = 02550;
|
|
//允许的Red,Green,Blue单个维度的像素差值
|
|
public static final int DIFF_ALLOW_RANGE = 0;
|
//public static final int DIFF_ALLOW_RANGE = 125;
|
|
//不同像素点统计值
|
|
public static int diffPointCount = 0;
|
|
//从rgb值中抽取red
|
|
public static int getRed(int rgbValue) {
|
|
return rgbValue & 0xff0000 >> 16;
|
|
}
|
|
//从rgb值中抽取green
|
|
public static int getGreen(int rgbValue) {
|
|
return rgbValue & 0xff00 >> 8;
|
|
}
|
|
//从rgb值中抽取blue
|
|
public static int getBlue(int rgbValue) {
|
|
return rgbValue & 0xff;
|
|
}
|
|
/**
|
* 修改BufferedImage中的图片尺寸,以便和源图片进行比较
|
*
|
* @param image
|
* @param newHeight
|
* @param newWidth
|
* @return
|
*/
|
|
public static BufferedImage changeImageSize(BufferedImage image, int newHeight, int newWidth) {
|
|
Image img = image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
|
|
int width = img.getWidth(null);
|
|
int height = img.getHeight(null);
|
|
//获取新图片的BufferedImage实例
|
|
BufferedImage newBufferedImage = new BufferedImage(width, height,
|
|
BufferedImage.TYPE_INT_ARGB);
|
|
Graphics g = newBufferedImage.getGraphics();
|
|
g.drawImage(img, 0, 0, null);
|
|
g.dispose();
|
|
return newBufferedImage;
|
|
}
|
|
/**
|
* 比较两图片,并用红色标出不同的像素点,然后保存差异图片到本地,打印匹配率
|
*
|
* @param srcImgPath
|
* @param targetImgPath
|
*/
|
|
public static ByteArrayOutputStream compareImages(String srcImgPath, String targetImgPath) throws IOException {
|
|
try {
|
|
BufferedImage srcImg = ImageIO.read(new File(srcImgPath));
|
|
BufferedImage targetImg = ImageIO.read(new File(targetImgPath));
|
|
diffPointCount = 0;
|
|
BufferedImage diffImg = srcImg;
|
|
int srcHeight = srcImg.getHeight();
|
|
int srcWidth = srcImg.getWidth();
|
|
//修改待比较图片的尺寸以适应源图片的尺寸
|
targetImg = changeImageSize(targetImg, srcHeight, srcWidth);
|
|
/*int w2 = 554;
|
int h2 = 487;
|
int srcRgb2;
|
|
int targetRgb2;
|
|
srcRgb2 = srcImg.getRGB(w2, h2);
|
|
targetRgb2 = targetImg.getRGB(w2, h2);
|
int red = getRed(srcRgb2);
|
int red1 = getRed(targetRgb2);
|
int green = getGreen(srcRgb2);
|
int green1 = getGreen(targetRgb2);
|
int blue = getBlue(srcRgb2);
|
int blue1 = getBlue(targetRgb2);
|
|
if (Math.abs(red - red1) > DIFF_ALLOW_RANGE ||
|
|
Math.abs(green - green1) > DIFF_ALLOW_RANGE ||
|
|
Math.abs(blue - blue1) > DIFF_ALLOW_RANGE) {
|
diffImg.setRGB(w2, h2, RGB_RED);
|
}*/
|
int srcRgb;
|
int targetRgb;
|
for (int h = 0; h < srcHeight; h++) {
|
for (int w = 0; w < srcWidth; w++) {
|
srcRgb = srcImg.getRGB(w, h);
|
targetRgb = targetImg.getRGB(w, h);
|
/*if (Math.abs(getRed(srcRgb) - getRed(targetRgb)) > DIFF_ALLOW_RANGE ||
|
Math.abs(getGreen(srcRgb) - getGreen(targetRgb)) > DIFF_ALLOW_RANGE ||
|
Math.abs(getBlue(srcRgb) - getBlue(targetRgb)) > DIFF_ALLOW_RANGE) {
|
diffImg.setRGB(w, h, RGB_RED);
|
diffPointCount++;
|
}
|
}*/
|
if (Math.abs(targetRgb - srcRgb) > DIFF_ALLOW_RANGE) {
|
diffImg.setRGB(w, h, RGB_RED);
|
}
|
diffPointCount++;
|
}
|
}
|
//保存差异图片
|
ByteArrayOutputStream bs = new ByteArrayOutputStream();
|
//ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
|
//ImageIO.write(diffImg, "png", new File("diffImg.png"));
|
ImageIO.write(diffImg,"png",bs);
|
|
/*//计算相似度(保留小数点后四位)
|
int totalPixel = srcHeight * srcWidth;
|
DecimalFormat decimalFormat = new DecimalFormat("#.####");
|
double matchRate = (totalPixel - diffPointCount) / (totalPixel * 1.0);
|
System.out.println("图片相似度为: " + decimalFormat.format(matchRate) + "%");*/
|
return bs;
|
|
} catch(Exception ex){
|
ex.printStackTrace();
|
return null;
|
}
|
|
}
|
public static boolean compareImagesCheck(String srcImgPath, String targetImgPath) {
|
String hash1 = calculateMD5(srcImgPath);
|
String hash2 = calculateMD5(targetImgPath);
|
// 比较两个哈希值是否相同
|
return hash1 != null && hash2 != null && hash1.equals(hash2);
|
/*boolean sameImage = true;
|
try {
|
|
|
|
BufferedImage srcImg = ImageIO.read(new File(srcImgPath));
|
BufferedImage targetImg = ImageIO.read(new File(targetImgPath));
|
|
int srcHeight = srcImg.getHeight();
|
int srcWidth = srcImg.getWidth();
|
|
//修改待比较图片的尺寸以适应源图片的尺寸
|
targetImg = changeImageSize(targetImg, srcHeight, srcWidth);
|
|
|
int srcRgb;
|
int targetRgb;
|
for (int h = 0; h < srcHeight; h++) {
|
for (int w = 0; w < srcWidth; w++) {
|
srcRgb = srcImg.getRGB(w, h);
|
targetRgb = targetImg.getRGB(w, h);
|
*//*if (Math.abs(getRed(srcRgb) - getRed(targetRgb)) > DIFF_ALLOW_RANGE ||
|
Math.abs(getGreen(srcRgb) - getGreen(targetRgb)) > DIFF_ALLOW_RANGE ||
|
Math.abs(getBlue(srcRgb) - getBlue(targetRgb)) > DIFF_ALLOW_RANGE) {
|
diffImg.setRGB(w, h, RGB_RED);
|
diffPointCount++;
|
}
|
}*//*
|
if (Math.abs(targetRgb - srcRgb) > DIFF_ALLOW_RANGE) { //像素点不同,判断为不同图片
|
return false;
|
}
|
}
|
}
|
|
|
}catch (Exception ex){
|
ex.printStackTrace();
|
}
|
return sameImage;*/
|
}
|
public static String calculateMD5(String filePath) {
|
try (FileInputStream fis = new FileInputStream(filePath)) {
|
// 获取MD5摘要算法的 MessageDigest 实例
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
// 读取文件内容并更新摘要
|
byte[] buffer = new byte[1024];
|
int bytesRead;
|
while ((bytesRead = fis.read(buffer)) != -1) {
|
md.update(buffer, 0, bytesRead);
|
}
|
|
// 计算哈希值并转换为十六进制字符串
|
byte[] digest = md.digest();
|
return DatatypeConverter.printHexBinary(digest).toUpperCase();
|
} catch (NoSuchAlgorithmException | IOException e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
public static void main(String[] args) throws IOException {
|
|
compareImages("C:\\\\Users\\\\29550\\\\Desktop\\\\当前项目\\\\202207图纸管理\\\\图纸升级\\\\fbo-60010nt-t-j-002_a11-dwg.png",
|
"C:\\\\Users\\\\29550\\\\Desktop\\\\当前项目\\\\202207图纸管理\\\\图纸升级\\\\fbo-60010nt-t-j-002_a12-dwg.png");
|
}
|
|
}
|