package cn.lili.modules.verification; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; /** * ImageUtil * * @author Chopper * @version v1.0 * 2020-11-17 14:50 */ public class ImageUtil { /** * 添加水印 * * @param oriImage 原图 * @param text 文字 * @throws IOException 流操作异常 */ public static void addWatermark(BufferedImage oriImage, String text) { Graphics2D graphics2D = oriImage.createGraphics(); //设置水印文字颜色 graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); //设置水印文字Font graphics2D.setColor(Color.black); //设置水印文字透明度 graphics2D.setFont(new Font("宋体", Font.BOLD, 30)); //第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4f)); graphics2D.drawString(text, 10, 40); graphics2D.dispose(); } /** * 干扰图 * * @param oriImage 原图 * @param templateImage 模板图 * @param x 随机扣取坐标X * @param y 随机扣取坐标y */ public static void interfereTemplate(BufferedImage oriImage, BufferedImage templateImage, int x, int y) { //临时数组遍历用于高斯模糊存周边像素值 int[][] matrix = new int[3][3]; int[] values = new int[9]; int xLength = templateImage.getWidth(); int yLength = templateImage.getHeight(); //模板图像宽度 for (int i = 0; i < xLength; i++) { //模板图片高度 for (int j = 0; j < yLength; j++) { //如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中 int rgb = templateImage.getRGB(i, j); if (rgb < 0) { //抠图区域高斯模糊 readPixel(oriImage, x + i, y + j, values); fillMatrix(matrix, values); oriImage.setRGB(x + i, y + j, avgMatrix(matrix)); } //防止数组越界判断 if (i == (xLength - 1) || j == (yLength - 1)) { continue; } int rightRgb = templateImage.getRGB(i + 1, j); int downRgb = templateImage.getRGB(i, j + 1); //描边处理,,取带像素和无像素的界点,判断该点是不是临界轮廓点,如果是设置该坐标像素是白色 boolean rgbImage = ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0) || (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0)); } } } /** * @param oriImage 原图 * @param templateImage 模板图 * @param newImage 新抠出的小图 * @param x 随机扣取坐标X * @param y 随机扣取坐标y */ public static void cutByTemplate(BufferedImage oriImage, BufferedImage templateImage, BufferedImage newImage, int x, int y) { //临时数组遍历用于高斯模糊存周边像素值 int[][] matrix = new int[3][3]; int[] values = new int[9]; int xLength = templateImage.getWidth(); int yLength = templateImage.getHeight(); //模板图像宽度 for (int i = 0; i < xLength; i++) { //模板图片高度 for (int j = 0; j < yLength; j++) { //如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中 int rgb = templateImage.getRGB(i, j); if (rgb < 0) { newImage.setRGB(i, j, oriImage.getRGB(x + i, y + j)); //抠图区域高斯模糊 readPixel(oriImage, x + i, y + j, values); fillMatrix(matrix, values); oriImage.setRGB(x + i, y + j, avgMatrix(matrix)); } //防止数组越界判断 if (i == (xLength - 1) || j == (yLength - 1)) { continue; } int rightRgb = templateImage.getRGB(i + 1, j); int downRgb = templateImage.getRGB(i, j + 1); //描边处理,,取带像素和无像素的界点,判断该点是不是临界轮廓点,如果是设置该坐标像素是白色 boolean rgbImage = ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0) || (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0)); if (rgbImage) { newImage.setRGB(i, j, Color.GRAY.getRGB()); } } } } public static void readPixel(BufferedImage img, int x, int y, int[] pixels) { int xStart = x - 1; int yStart = y - 1; int current = 0; for (int i = xStart; i < 3 + xStart; i++) { for (int j = yStart; j < 3 + yStart; j++) { int tx = i; if (tx < 0) { tx = -tx; } else if (tx >= img.getWidth()) { tx = x; } int ty = j; if (ty < 0) { ty = -ty; } else if (ty >= img.getHeight()) { ty = y; } pixels[current++] = img.getRGB(tx, ty); } } } public static void fillMatrix(int[][] matrix, int[] values) { int filled = 0; for (int[] x : matrix) { for (int j = 0; j < x.length; j++) { x[j] = values[filled++]; } } } public static int avgMatrix(int[][] matrix) { int r = 0; int g = 0; int b = 0; for (int[] x : matrix) { for (int j = 0; j < x.length; j++) { if (j == 1) { continue; } Color c = new Color(x[j]); r += c.getRed(); g += c.getGreen(); b += c.getBlue(); } } return new Color(r / 8, g / 8, b / 8).getRGB(); } }