因对系统安全性的要求,需要实现后台生成 图片滑动验证码的需求。
最开始接到这个需求,脑子里一片雾水,流程均清楚,可切图对我这个普通的小码农来说太难了,于是便上网查询资料,结果惊喜的发现了一位博主的文章(链接地址:https://blog.csdn.net/qq_36892341/article/details/86644580),具体步骤该文章中均有列出,就不缀述了~
在充分参考该博主的文章后,发现实际结果不是很理想:
如上图,切出来的小图几乎和大图背景融为一体,扣掉的那块儿因为要保证在每张图上都很明显,就改了个固定色,但比起之前纯前端画的图,简直是天差地别
于是在原来代码的基础上,参考前端切图的样式,计划给抠下来的小图加上白色边框,并将大图上被抠掉部分的底色换成白色!于是经过一波对博主代码的分析及精密计算(实际上就运用了个勾股定理,哈哈),最终做出了下图的效果:
下面就要贴出干货了——我修改后的代码:
/**
*
* @Createdate: 2019年1月24日上午10:52:42
* @Title: getBlockData
* @Description: 生成小图轮廓
* @author mzl
* @return int[][]
* @throws
*/
private int[][] getBlockData() {
int[][] data = new int[targetLength][targetWidth];
double x2 = targetLength-circleR;
//随机生成圆的位置
// double h1 = circleR + Math.random() * (targetWidth-3*circleR-r1);
double h1 = 20.678101695669376;
double po = circleR*circleR;
double xbegin = targetLength-circleR-r1;
double ybegin = targetWidth-circleR-r1;
for (int i = 0; i < targetLength; i++) {
for (int j = 0; j < targetWidth; j++) {
double d3 = Math.pow(i - x2,2) + Math.pow(j - h1,2);
double d2 = Math.pow(j-2,2) + Math.pow(i - h1,2);
if ((j < ybegin && d2 < po)||(i > xbegin && d3 > po)) {
data[i][j] = 0;
} else {
data[i][j] = 1;
// || i == targetLength-2 || i == targetLength-1
// 边框部分置为2(取两个宽度)
if (i == 0 || i==1 || i == targetLength-1 || j == 0 || j == 1 || j == targetWidth-2 || j == targetWidth-1){
data[i][j] = 2;
}
if ((j <= ybegin && Math.abs(Math.sqrt(d2)-circleR) < 2)||(i >= xbegin-1 && Math.abs(Math.sqrt(d3)-circleR) < 2)) {
data[i][j] = 2;
}
if ((i == xbegin || i == xbegin-1) && (j <= Math.sqrt(po-Math.pow(r1,2)) || j >= ybegin)){
data[i][j] = 2;
}
}
}
}
return data;
}
/**
*
* @Createdate: 2019年1月24日上午10:51:30
* @Title: cutByTemplate
* @Description: 生成小图片、给大图片添加阴影
* @author mzl
* @param oriImage
* @param targetImage
* @param templateImage
* @param x
* @param y void
* @throws
*/
private void cutByTemplate(BufferedImage oriImage, BufferedImage targetImage, int[][] templateImage, int x, int y){
for (int i = 0; i < targetLength; i++) {
for (int j = 0; j < targetWidth; j++) {
int rgb = templateImage[i][j];
// 原图中对应位置变色处理
int count = 0;
do {
try {
int rgb_ori = oriImage.getRGB(x + i, y + j);
if (rgb == 1) {
//抠图上复制对应颜色值
targetImage.setRGB(i, j, rgb_ori);
//原图对应位置颜色变化
// oriImage.setRGB(x + i, y + j, rgb_ori & 0x363636 );
oriImage.setRGB(x + i, y + j, 0x88F5F5F5);
}else if (rgb == 2){
// targetImage.setRGB(i, j, rgb_ori & 0xff000000);
// oriImage.setRGB(x + i, y + j, rgb_ori & 0xff000000);
// 边框设为白色
targetImage.setRGB(i, j, 0xffffffff);
oriImage.setRGB(x + i, y + j, 0xffffffff);
}else if (rgb == 0){
//这里把背景设为透明
targetImage.setRGB(i, j, rgb_ori & 0x00ffffff);
}
} catch (Exception e) {
count++;
}
} while (count > 0 && count < 5);
}
}
}
虽然这样做出来的图还是很丑,但起码看着效果好了很多~
目前很遗憾的一点就是自己实在能力有限,不会如前端切图那样,给大图被抠掉部分加上透明罩层,如有大神莅临,请多多指教~