一、效果展示
实现原理:
- 背景图片是一张目标图片target,图片类型是jpg(在这里称之为target图片)。target图片透明部分是通过java代码实现的,并记录起想x,y 的坐标(目标位置)。
- 被抠出的图片是模板图片(templates图片),它的背景是透明的,只能看到抠图部分,图片类型是png。
- templates图片滑动的时候会随时产生相应的偏移量offsetHorizontal,当最终偏移量与目标位置x坐标相等时(可以设置一定的偏差),验证成功!
二、demo示例
背景: 新建springboot的demo
demo文件目录展示
1.后端
- VerifyImageUtil工具类
该类编写主要是为了实现图片的抠图,坐标位置等对图片处理的功能,是实现图片滚动验证码的核心代码。
代码解析:
pictureTemplatesCut()方法是VerifyImageUtil类的入口函数,主要是初始化参数,首次加载滑块的两张图片,便是调用改方法(在controller层的创建滑块图片:createImgValidate()方法实现加载)。返回的pictureMap 集合是两张 效果处理的图片(背景图片:jpg 和 抠图模板: png)
package com.example.demo.util;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
/**
* 滑块验证工具类
* VerifyImageUtil
*/
public class VerifyImageUtil {
/** 源文件宽度 */
private static final int ORI_WIDTH = 600;
/** 源文件高度 */
private static final int ORI_HEIGHT = 300;
/** 抠图坐标x */
private static int X;
/** 抠图坐标y */
private static int Y;
/** 模板图宽度 */
private static int WIDTH;
/** 模板图高度 */
private static int HEIGHT;
public static int getX() {
return X;
}
public static int getY() {
return Y;
}
/**
* 根据模板切图
* @param templateFile 模板文件
* @param targetFile 目标文件
* @param templateType 模板文件类型
* @param targetType 目标文件类型
* @return 切图map集合
* @throws Exception 异常
*/
public static Map<String, byte[]> pictureTemplatesCut(File templateFile, File targetFile, String templateType, String targetType) throws Exception {
Map<String, byte[]> pictureMap = new HashMap<>(2);
InputStream targetIs = new FileInputStream(targetFile);
// 模板图
BufferedImage imageTemplate = ImageIO.read(templateFile);
WIDTH = imageTemplate.getWidth();
HEIGHT = imageTemplate.getHeight();
// 随机生成抠图坐标
generateCutoutCoordinates();
// 最终图像
BufferedImage newImage = new BufferedImage(WIDTH, HEIGHT, imageTemplate.getType());
Graphics2D graphics = newImage.createGraphics();
graphics.setBackground(Color.white);
int bold = 5;
// 获取感兴趣的目标区域
BufferedImage targetImageNoDeal = getTargetArea(X, Y, WIDTH, HEIGHT, targetIs, targetType);
// 根据模板图片抠图
newImage = dealCutPictureByTemplate(targetImageNoDeal, imageTemplate, newImage);
// 设置“抗锯齿”的属性
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setStroke(new BasicStroke(bold, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
graphics.drawImage(newImage, 0, 0, null);
graphics.dispose();
//模板图像矩阵 加阴影边框
//boundaryShadow(newImage);
//新建流。
ByteArrayOutputStream os = new ByteArrayOutputStream();
//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
ImageIO.write(newImage, "png", os);
byte[] newImages = os.toByteArray();
pictureMap.put("newImage", newImages);
// 源图生成遮罩
BufferedImage oriImage = ImageIO.read(targetFile);
byte[] oriCopyImages = dealOriPictureByTemplate(oriImage, imageTemplate, X, Y);
pictureMap.put("oriCopyImage", oriCopyImages);
System.out.println("X="+X+";y="+Y);
return pictureMap;
}
/**
* 抠图后原图生成
* @param oriImage 原始图片
* @param templateImage 模板图片
* @param x 坐标X
* @param y 坐标Y
* @return 添加遮罩层后的原始图片
* @throws Exception 异常
*/
private static byte[] dealOriPictureByTemplate(BufferedImage