
net.ymate.platform.commons.util.ImageUtils Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2007-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.ymate.platform.commons.util;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @author 刘镇 ([email protected]) on 2021/11/21 12:58 下午
* @since 2.1.0
*/
public class ImageUtils {
private static final Log LOG = LogFactory.getLog(ImageUtils.class);
/**
* 替换原图片里面的二维码
*
* @param originImage 原图
* @param qrImage 要替换的二维码
* @param deviate 定位点与起始点的差值
* @return 替换后的图片
* @throws NotFoundException 识别二维码失败
*/
public static BufferedImage replaceQrCode(BufferedImage originImage, BufferedImage qrImage, int deviate) throws NotFoundException {
BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(originImage)));
Map hints = new HashMap<>(1);
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result[] results = new QRCodeMultiReader().decodeMultiple(binaryBitmap, hints);
if (results != null) {
for (Result result : results) {
// 定位点的坐标,按照左下、左上、右上顺序
ResultPoint[] resultPoint = result.getResultPoints();
float x1 = resultPoint[0].getX();
float y1 = resultPoint[0].getY();
float x2 = resultPoint[1].getX();
float y2 = resultPoint[1].getY();
// 定位点与起始点的差值
if (deviate == 0) {
deviate = 36;
}
// 计算二维码图片边长
final int length = (int) Math.sqrt(Math.abs(x1 - x2) * Math.abs(x1 - x2) + Math.abs(y1 - y2) * Math.abs(y1 - y2)) + 2 * deviate;
// 根据二维码定位坐标计算起始坐标
int x = Math.round(x2) - deviate;
int y = Math.round(y2) - deviate;
// 替换二维码图案
Graphics2D graphics = originImage.createGraphics();
//
BufferedImage resizedQrImage = new BufferedImage(length, length, qrImage.getType());
Graphics gc = resizedQrImage.getGraphics();
gc.setColor(Color.WHITE);
gc.drawImage(qrImage.getScaledInstance(length, length, Image.SCALE_SMOOTH), 0, 0, null);
resizedQrImage.flush();
gc.dispose();
//
graphics.drawImage(resizedQrImage, x, y, length, length, null);
originImage.flush();
graphics.dispose();
}
}
return originImage;
}
public static BufferedImage replaceQrCode(BufferedImage originImage, BufferedImage qrImage) throws NotFoundException {
return replaceQrCode(originImage, qrImage, 0);
}
/**
* 计算海明距离(即相似度差异值,一般值小于5为同一张图片)
*
* @param dHash1 dHash值1
* @param dHash2 dHash值2
* @return 返回海明距离值
*/
public static long hammingDistance(String dHash1, String dHash2) {
int distance = 0;
if (dHash1 == null || dHash2 == null || dHash1.length() != dHash2.length()) {
distance = -1;
} else {
for (int i = 0; i < dHash1.length(); i++) {
if (dHash1.charAt(i) != dHash2.charAt(i)) {
distance++;
}
}
}
return distance;
}
/**
* @param srcImage 源图片
* @return 计算图片文件dHash值
*/
public static String dHash(BufferedImage srcImage) {
// 转换为 9*8 像素
BufferedImage buffImg = new BufferedImage(9, 8, BufferedImage.TYPE_INT_RGB);
buffImg.getGraphics().drawImage(srcImage.getScaledInstance(9, 8, Image.SCALE_SMOOTH), 0, 0, null);
int width = buffImg.getWidth();
int height = buffImg.getHeight();
int[][] grayPix = new int[width][height];
StringBuilder figure = new StringBuilder();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// 图片灰度化
int rgb = buffImg.getRGB(x, y);
int r = rgb >> 16 & 0xff;
int g = rgb >> 8 & 0xff;
int b = rgb & 0xff;
int gray = (r * 30 + g * 59 + b * 11) / 100;
grayPix[x][y] = gray;
// 开始计算 dHash
if (x != 0) {
long bit = grayPix[x - 1][y] > grayPix[x][y] ? 1 : 0;
figure.append(bit);
}
}
}
return figure.toString();
}
/**
* 重置图片大小
*
* @param source 源图片
* @param width 宽度
* @param height 高度
* @param quality 质量
* @param format 输出文件格式
* @return 返回Thumbnails.Builder对象实例
*/
public static Thumbnails.Builder resize(BufferedImage source, int width, int height, float quality, String format) {
Thumbnails.Builder thumbBuilder = Thumbnails.of(source);
if (width <= 0 || height <= 0) {
if (width > 0) {
thumbBuilder.width(width);
} else if (height > 0) {
thumbBuilder.height(height);
}
} else {
thumbBuilder.size(width, height).keepAspectRatio(false);
}
if (quality > 0 && quality < 1) {
thumbBuilder.outputQuality(quality);
}
if (StringUtils.isNotBlank(format)) {
thumbBuilder.outputFormat(format);
}
return thumbBuilder;
}
public static Thumbnails.Builder resize(BufferedImage source, int width, int height, float quality) {
return resize(source, width, height, quality, null);
}
/**
* 重置图片大小并将重置后的文件写入目标文件
*
* @param source 源图片
* @param dist 目标文件
* @param width 宽度
* @param height 高度
* @param quality 质量
* @return 返回true表示重置成功
*/
public static boolean resize(BufferedImage source, File dist, int width, int height, float quality) {
try {
resize(source, width, height, quality, null).toFile(dist);
return true;
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn(StringUtils.EMPTY, RuntimeUtils.unwrapThrow(e));
}
}
return false;
}
public static Thumbnails.Builder resize(BufferedImage source, float scale, float quality, String format) {
if (scale <= 0 || scale > 1) {
scale = 1f;
}
Thumbnails.Builder thumbBuilder = Thumbnails.of(source).scale(scale);
if (quality > 0 && quality < 1) {
thumbBuilder.outputQuality(quality);
}
if (StringUtils.isNotBlank(format)) {
thumbBuilder.outputFormat(format);
}
return thumbBuilder;
}
public static Thumbnails.Builder resize(BufferedImage source, float scale, float quality) {
return resize(source, scale, quality, null);
}
public static boolean resize(BufferedImage source, File dist, float scale, float quality) {
try {
resize(source, scale, quality, null).toFile(dist);
return true;
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn(StringUtils.EMPTY, RuntimeUtils.unwrapThrow(e));
}
}
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy