验证码生成

一个简单的验证码生成过程:

  1 import javax.imageio.ImageIO;
  2 import java.awt.*;
  3 import java.awt.geom.AffineTransform;
  4 import java.awt.image.BufferedImage;
  5 import java.io.File;
  6 import java.io.FileOutputStream;
  7 import java.io.IOException;
  8 import java.io.OutputStream;
  9 import java.util.Arrays;
 10 import java.util.Random;
 11 
 12 
 13 public class VerifyCodeUtils {
 14 
 15     //使用到Algerian字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,i,o几个容易混淆的字符
 16     public static final String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
 17     private static Random random = new Random();
 18 
 19 
 20     /**
 21      * 使用系统默认字符源生成验证码
 22      *
 23      * @param verifySize 验证码长度
 24      * @return
 25      */
 26     public static String generateVerifyCode(int verifySize) {
 27         return generateVerifyCode(verifySize, VERIFY_CODES);
 28     }
 29 
 30     /**
 31      * 使用指定源生成验证码
 32      *
 33      * @param verifySize 验证码长度
 34      * @param sources    验证码字符源
 35      * @return
 36      */
 37     public static String generateVerifyCode(int verifySize, String sources) {
 38         if (sources == null || sources.length() == 0) {
 39             sources = VERIFY_CODES;
 40         }
 41         int codesLen = sources.length();
 42         Random rand = new Random(System.currentTimeMillis());
 43         StringBuilder verifyCode = new StringBuilder(verifySize);
 44         for (int i = 0; i < verifySize; i++) {
 45             verifyCode.append(sources.charAt(rand.nextInt(codesLen - 1)));
 46         }
 47         return verifyCode.toString();
 48     }
 49 
 50     /**
 51      * 生成随机验证码文件,并返回验证码值
 52      *
 53      * @param w
 54      * @param h
 55      * @param outputFile
 56      * @param verifySize
 57      * @return
 58      * @throws IOException
 59      */
 60     public static String outputVerifyImage(int w, int h, File outputFile, int verifySize) throws IOException {
 61         String verifyCode = generateVerifyCode(verifySize);
 62         outputImage(w, h, outputFile, verifyCode);
 63         return verifyCode;
 64     }
 65 
 66     /**
 67      * 输出随机验证码图片流,并返回验证码值
 68      *
 69      * @param w
 70      * @param h
 71      * @param os
 72      * @param verifySize
 73      * @return
 74      * @throws IOException
 75      */
 76     public static String outputVerifyImage(int w, int h, OutputStream os, int verifySize) throws IOException {
 77         String verifyCode = generateVerifyCode(verifySize);
 78         outputImage(w, h, os, verifyCode);
 79         return verifyCode;
 80     }
 81 
 82     /**
 83      * 生成指定验证码图像文件
 84      *
 85      * @param w
 86      * @param h
 87      * @param outputFile
 88      * @param code
 89      * @throws IOException
 90      */
 91     public static void outputImage(int w, int h, File outputFile, String code) throws IOException {
 92         if (outputFile == null) {
 93             return;
 94         }
 95         File dir = outputFile.getParentFile();
 96         if (!dir.exists()) {
 97             dir.mkdirs();
 98         }
 99         try {
100             outputFile.createNewFile();
101             FileOutputStream fos = new FileOutputStream(outputFile);
102             outputImage(w, h, fos, code);
103             fos.close();
104         } catch (IOException e) {
105             throw e;
106         }
107     }
108 
109     /**
110      * 输出指定验证码图片流
111      *
112      * @param w
113      * @param h
114      * @param os
115      * @param code
116      * @throws IOException
117      */
118     public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {
119         int verifySize = code.length();
120         BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
121         Random rand = new Random();
122         Graphics2D g2 = image.createGraphics();
123         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
124         Color[] colors = new Color[5];
125         Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN,
126                 Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,
127                 Color.PINK, Color.YELLOW};
128         float[] fractions = new float[colors.length];
129         for (int i = 0; i < colors.length; i++) {
130             colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];
131             fractions[i] = rand.nextFloat();
132         }
133         Arrays.sort(fractions);
134 
135         g2.setColor(Color.GRAY);// 设置边框色
136         g2.fillRect(0, 0, w, h);
137 
138         Color c = getRandColor(200, 250);
139         g2.setColor(c);// 设置背景色
140         g2.fillRect(0, 2, w, h - 4);
141 
142         //绘制干扰线
143         Random random = new Random();
144         g2.setColor(getRandColor(160, 200));// 设置线条的颜色
145         for (int i = 0; i < 20; i++) {
146             int x = random.nextInt(w - 1);
147             int y = random.nextInt(h - 1);
148             int xl = random.nextInt(6) + 1;
149             int yl = random.nextInt(12) + 1;
150             g2.drawLine(x, y, x + xl + 40, y + yl + 20);
151         }
152 
153         // 添加噪点
154         float yawpRate = 0.05f;// 噪声率
155         int area = (int) (yawpRate * w * h);
156         for (int i = 0; i < area; i++) {
157             int x = random.nextInt(w);
158             int y = random.nextInt(h);
159             int rgb = getRandomIntColor();
160             image.setRGB(x, y, rgb);
161         }
162 
163         shear(g2, w, h, c);// 使图片扭曲
164 
165         g2.setColor(getRandColor(100, 160));
166         int fontSize = h - 4;
167         Font font = new Font("Algerian", Font.ITALIC, fontSize);
168         g2.setFont(font);
169         char[] chars = code.toCharArray();
170         for (int i = 0; i < verifySize; i++) {
171             AffineTransform affine = new AffineTransform();
172             affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize / 2, h / 2);
173             g2.setTransform(affine);
174             g2.drawChars(chars, i, 1, ((w - 10) / verifySize) * i + 5, h / 2 + fontSize / 2 - 10);
175         }
176 
177         g2.dispose();
178         ImageIO.write(image, "jpg", os);
179     }
180 
181     private static Color getRandColor(int fc, int bc) {
182         if (fc > 255)
183             fc = 255;
184         if (bc > 255)
185             bc = 255;
186         int r = fc + random.nextInt(bc - fc);
187         int g = fc + random.nextInt(bc - fc);
188         int b = fc + random.nextInt(bc - fc);
189         return new Color(r, g, b);
190     }
191 
192     private static int getRandomIntColor() {
193         int[] rgb = getRandomRgb();
194         int color = 0;
195         for (int c : rgb) {
196             color = color << 8;
197             color = color | c;
198         }
199         return color;
200     }
201 
202     private static int[] getRandomRgb() {
203         int[] rgb = new int[3];
204         for (int i = 0; i < 3; i++) {
205             rgb[i] = random.nextInt(255);
206         }
207         return rgb;
208     }
209 
210     private static void shear(Graphics g, int w1, int h1, Color color) {
211         shearX(g, w1, h1, color);
212         shearY(g, w1, h1, color);
213     }
214 
215     private static void shearX(Graphics g, int w1, int h1, Color color) {
216 
217         int period = random.nextInt(2);
218 
219         boolean borderGap = true;
220         int frames = 1;
221         int phase = random.nextInt(2);
222 
223         for (int i = 0; i < h1; i++) {
224             double d = (double) (period >> 1)
225                     * Math.sin((double) i / (double) period
226                     + (6.2831853071795862D * (double) phase)
227                     / (double) frames);
228             g.copyArea(0, i, w1, 1, (int) d, 0);
229             if (borderGap) {
230                 g.setColor(color);
231                 g.drawLine((int) d, i, 0, i);
232                 g.drawLine((int) d + w1, i, w1, i);
233             }
234         }
235 
236     }
237 
238     private static void shearY(Graphics g, int w1, int h1, Color color) {
239 
240         int period = random.nextInt(40) + 10; // 50;
241 
242         boolean borderGap = true;
243         int frames = 20;
244         int phase = 7;
245         for (int i = 0; i < w1; i++) {
246             double d = (double) (period >> 1)
247                     * Math.sin((double) i / (double) period
248                     + (6.2831853071795862D * (double) phase)
249                     / (double) frames);
250             g.copyArea(i, 0, 1, h1, 0, (int) d);
251             if (borderGap) {
252                 g.setColor(color);
253                 g.drawLine(i, (int) d, i, 0);
254                 g.drawLine(i, (int) d + h1, i, h1);
255             }
256 
257         }
258 
259     }
260 
261     public static void main(String[] args) throws IOException {
262         File dir = new File("F:/verifies");
263         int w = 200, h = 80;
264         for (int i = 0; i < 50; i++) {
265             String verifyCode = generateVerifyCode(4);
266             File file = new File(dir, verifyCode + ".jpg");
267             outputImage(w, h, file, verifyCode);
268         }
269     }
270 }

 

posted @ 2018-08-21 10:07  ƃuədnxıəʍ  阅读(249)  评论(0编辑  收藏  举报