1
2
3
4
5
6
7 package com.octo.captcha.component.image.deformation;
8
9 import com.jhlabs.image.RotateFilter;
10 import com.octo.captcha.component.image.utils.ToolkitFactory;
11
12 import java.awt.*;
13 import java.awt.image.BufferedImage;
14 import java.awt.image.FilteredImageSource;
15 import java.awt.image.ImageFilter;
16 import java.security.SecureRandom;
17 import java.util.Random;
18
19 /***
20 * Deformation where the image is divided in little squares, moved individualty in a random position. Each move is
21 * really light, in order to let the captcha readble.
22 *
23 * @author Benoit Doumas
24 */
25 public class PuzzleImageDeformation implements ImageDeformation {
26
27 /***
28 * Number of colums to divide the image, max number if rows and colums are managed randomly
29 */
30 private int colNum = 6;
31
32 /***
33 * Number of rows to divide the image, max number if rows and colums are managed randomly
34 */
35 private int rowNum = 4;
36
37 /***
38 * Maximal angle of rotation for each square.
39 */
40 private double maxAngleRotation = 0.3;
41
42 private Random random = new SecureRandom();
43
44 /***
45 * Conststruct a PuzzleImageDeformation, with the numbers of colums and rows. If manageRowAndColRandomly is set to
46 * true, the numbers of rows and colums are choosed between 1 and colNum/rowNum
47 *
48 * @param colNum Number of colums to divide the image, max number if rows and colums are managed
49 * randomly
50 * @param rowNum Number of rows to divide the image, max number if rows and colums are managed
51 * randomly
52 * @param maxAngleRotation Maximal angle of rotation for each square.
53 */
54 public PuzzleImageDeformation(int colNum, int rowNum, double maxAngleRotation) {
55 super();
56 this.colNum = colNum;
57 this.rowNum = rowNum;
58 this.maxAngleRotation = maxAngleRotation;
59 }
60
61
62
63
64 public BufferedImage deformImage(BufferedImage image) {
65
66 int height = image.getHeight();
67 int width = image.getWidth();
68
69 int xd = width / colNum;
70 int yd = height / rowNum;
71
72 BufferedImage backround = new BufferedImage(width, height, image.getType());
73 Graphics2D pie = (Graphics2D) backround.getGraphics();
74
75 pie.setColor(Color.white);
76 pie.setBackground(Color.white);
77 pie.fillRect(0, 0, width, height);
78 pie.dispose();
79
80 Graphics2D g = (Graphics2D) image.getGraphics();
81 g.setBackground(Color.white);
82
83 BufferedImage smallPart = new BufferedImage(xd, yd, image.getType());
84 Graphics2D gSmall = smallPart.createGraphics();
85 FilteredImageSource filtered;
86
87 for (int i = 0; i < colNum; i++) {
88 for (int j = 0; j < rowNum; j++) {
89 gSmall.drawImage(image, 0, 0, xd, yd, xd * i, yd * j, xd * i + xd, yd * j + yd,
90 null);
91
92 RotateFilter filter = new RotateFilter((float)maxAngleRotation * random.nextFloat()
93 * (random.nextBoolean() ? -1 : 1));
94
95
96
97
98
99 smallPart.getGraphics().dispose();
100
101 g.drawImage(smallPart, xd * i, yd * j, null, null);
102 }
103 }
104
105 return image;
106 }
107
108 }