由于安全问题,需要在后台生成图片和随机位移量,所以在java端用BufferedImage实现图片处理。(本篇只提供部分核心功能)
一、生成随机坐标
x、y是全局变量
java
/**
* 生成随机坐标
*/
private void generateCutoutCoordinates(){
Random random=new Random();
int widthDifference=oriWidth-width;
int heightDifference=oriHeight-height;
x=widthDifference<=0?RANGE:random.nextInt(oriWidth-width)+RANGE;
y=heightDifference<=0?RANGE:random.nextInt(oriHeight-height)+RANGE;
}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
二、获取图片信息
width、height、oriWidth、oriHeight为全局变量 Data为自己封装的图片信息类,用于将图片数据流和位移量 x 返回给前台
java
public Data create(InputStream templateFile,InputStream targetFile,String templateType,String targetType)throws IOException{
Assert.hasText(templateType,"file type is empty");
Assert.hasText(targetType,"file type is empty");
// 模板图
BufferedImage tempImage=ImageIO.read(templateFile);
width=tempImage.getWidth();
height=tempImage.getHeight();
// 底图
BufferedImage oriImage=ImageIO.read(targetFile);
oriWidth=oriImage.getWidth();
oriHeight=oriImage.getHeight();
// data.set...
return data;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
三、图片处理核心方法
1、生成一支持alpha通道的图像对象; 2、将原图底图复制到该对象上; 3、循环模版图的像素矩阵,将黑色部分替换为原图的图片; 4、将原图对应模版图的地方设置为透明;
以下代码核心部分用到了位运算,如何运用位运算获取RGB色值?
java
/**
* 抠图后原图生成
*
* @param oriImage 底图
* @param templateImage 模板图
* @return
* @throws IOException 异常
*/
private Data dealOriPictureByTemplate(BufferedImage oriImage, BufferedImage templateImage) throws IOException {
// 源文件备份图像矩阵 支持alpha通道的rgb图像
BufferedImage oriCopyImage = new BufferedImage(oriImage.getWidth(), oriImage.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
// copy 源图
Graphics2D g2d = oriCopyImage.createGraphics();
// 绘制
g2d.drawImage(oriImage, 0, 0, null);
g2d.dispose();
// 模板图像矩阵
int[][] templateImageData = getData(templateImage);
// 模板图像宽度,减去随机生成的位移X后多余的5像素
int widthLen = templateImageData.length - RANGE;
// 模板图片高度,减去随机生成的位移Y后多余的5像素
int heightLen = templateImageData[0].length - RANGE;
for (int i = 0; i < widthLen; i++) {
for (int j = 0; j < heightLen; j++) {
int rgb = templateImageData[i][j];
// BLACK是Color.BLACK.getRGB()
if (rgb == BLACK) {
int rgbOri = oriCopyImage.getRGB(x + i, y + j);
// 模板图片替换像素为原图
templateImage.setRGB(i, j, rgbOri);
int r = (0xff & (rgbOri >> 16));
int g = (0xff & (rgbOri >> 8));
int b = (0xff & rgbOri);
int rgba = (r << 16) + (g << 8) + b + (100 << 24);
// 对源文件备份图像(x+i,y+j)坐标点进行透明处理
oriCopyImage.setRGB(x + i, y + j, rgba);
} else {
// 其他颜色处理
}
}
}
Data data = new Data();
ByteArrayOutputStream os = new ByteArrayOutputStream();
// 最终底图
ImageIO.write(oriCopyImage, "png", os);
data.setTargetImage(os.toByteArray());
os.reset();
// 最终模板图
ImageIO.write(templateImage, "png", os);
data.setTemplateImage(os.toByteArray());
return data;
}
/**
* 生成图像矩阵
*
* @param bimg 目标图像
* @return 图像矩阵
* @throws Exception 异常
*/
private int[][] getData(BufferedImage bimg) {
int[][] data = new int[bimg.getWidth()][bimg.getHeight()];
for (int i = 0; i < bimg.getWidth(); i++) {
for (int j = 0; j < bimg.getHeight(); j++) {
data[i][j] = bimg.getRGB(i, j);
}
}
return data;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
四、将位移量x存到session中
java
xxx.getRequest().getSession().setAttribute("VINSEA_CAPTCHA", x);1