1 package com.sunll.common.util; 2 3 import javax.imageio.ImageIO; 4 import java.awt.*; 5 import java.awt.image.BufferedImage; 6 import java.io.IOException; 7 import java.io.OutputStream; 8 import java.util.Random; 9 10 /** 11 * 验证码工具类 12 * Created by ZhangShuzheng on 2017/6/28. 13 */ 14 public class CaptchaUtil { 15 // 图片的宽度。 16 private int width = 160; 17 // 图片的高度。 18 private int height = 40; 19 // 验证码字符个数 20 private int codeCount = 4; 21 // 验证码干扰线数 22 private int lineCount = 20; 23 // 验证码 24 private String code = null; 25 // 验证码图片Buffer 26 private BufferedImage buffImg = null; 27 Random random = new Random(); 28 29 public CaptchaUtil() { 30 creatImage(); 31 } 32 33 public CaptchaUtil(int width, int height) { 34 this.width = width; 35 this.height = height; 36 creatImage(); 37 } 38 39 public CaptchaUtil(int width, int height, int codeCount) { 40 this.width = width; 41 this.height = height; 42 this.codeCount = codeCount; 43 creatImage(); 44 } 45 46 public CaptchaUtil(int width, int height, int codeCount, int lineCount) { 47 this.width = width; 48 this.height = height; 49 this.codeCount = codeCount; 50 this.lineCount = lineCount; 51 creatImage(); 52 } 53 54 // 生成图片 55 private void creatImage() { 56 int fontWidth = width / codeCount;// 字体的宽度 57 int fontHeight = height - 5;// 字体的高度 58 int codeY = height - 8; 59 60 // 图像buffer 61 buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 62 Graphics g = buffImg.getGraphics(); 63 //Graphics2D g = buffImg.createGraphics(); 64 // 设置背景色 65 g.setColor(getRandColor(200, 250)); 66 g.fillRect(0, 0, width, height); 67 68 69 // 设置字体 70 //Font font1 = getFont(fontHeight); 71 Font font = new Font("Fixedsys", Font.BOLD, fontHeight); 72 g.setFont(font); 73 74 // 设置干扰线 75 for (int i = 0; i < lineCount; i++) { 76 int xs = random.nextInt(width); 77 int ys = random.nextInt(height); 78 int xe = xs + random.nextInt(width); 79 int ye = ys + random.nextInt(height); 80 g.setColor(getRandColor(1, 255)); 81 g.drawLine(xs, ys, xe, ye); 82 } 83 84 // 添加噪点 85 float yawpRate = 0.01f;// 噪声率 86 int area = (int) (yawpRate * width * height); 87 for (int i = 0; i < area; i++) { 88 int x = random.nextInt(width); 89 int y = random.nextInt(height); 90 91 buffImg.setRGB(x, y, random.nextInt(255)); 92 } 93 94 String str1 = randomStr(codeCount);// 得到随机字符 95 this.code = str1; 96 for (int i = 0; i < codeCount; i++) { 97 String strRand = str1.substring(i, i + 1); 98 g.setColor(getRandColor(1, 255)); 99 // g.drawString(a,x,y); 100 // a为要画出来的东西,x和y表示要画的东西最左侧字符的基线位于此图形上下文坐标系的 (x, y) 位置处 101 102 g.drawString(strRand, i * fontWidth + 3, codeY); 103 } 104 } 105 106 // 得到随机字符 107 private String randomStr(int n) { 108 String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 109 String str2 = ""; 110 int len = str1.length() - 1; 111 double r; 112 for (int i = 0; i < n; i++) { 113 r = (Math.random()) * len; 114 str2 = str2 + str1.charAt((int) r); 115 } 116 return str2; 117 } 118 119 // 得到随机颜色 120 private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色 121 if (fc > 255) 122 fc = 255; 123 if (bc > 255) 124 bc = 255; 125 int r = fc + random.nextInt(bc - fc); 126 int g = fc + random.nextInt(bc - fc); 127 int b = fc + random.nextInt(bc - fc); 128 return new Color(r, g, b); 129 } 130 131 /** 132 * 产生随机字体 133 */ 134 private Font getFont(int size) { 135 Random random = new Random(); 136 Font font[] = new Font[5]; 137 font[0] = new Font("Ravie", Font.PLAIN, size); 138 font[1] = new Font("Antique Olive Compact", Font.PLAIN, size); 139 font[2] = new Font("Fixedsys", Font.PLAIN, size); 140 font[3] = new Font("Wide Latin", Font.PLAIN, size); 141 font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size); 142 return font[random.nextInt(5)]; 143 } 144 145 // 扭曲方法 146 private void shear(Graphics g, int w1, int h1, Color color) { 147 shearX(g, w1, h1, color); 148 shearY(g, w1, h1, color); 149 } 150 151 private void shearX(Graphics g, int w1, int h1, Color color) { 152 153 int period = random.nextInt(2); 154 155 boolean borderGap = true; 156 int frames = 1; 157 int phase = random.nextInt(2); 158 159 for (int i = 0; i < h1; i++) { 160 double d = (double) (period >> 1) 161 * Math.sin((double) i / (double) period 162 + (6.2831853071795862D * (double) phase) 163 / (double) frames); 164 g.copyArea(0, i, w1, 1, (int) d, 0); 165 if (borderGap) { 166 g.setColor(color); 167 g.drawLine((int) d, i, 0, i); 168 g.drawLine((int) d + w1, i, w1, i); 169 } 170 } 171 } 172 173 private void shearY(Graphics g, int w1, int h1, Color color) { 174 175 int period = random.nextInt(40) + 10; // 50; 176 177 boolean borderGap = true; 178 int frames = 20; 179 int phase = 7; 180 for (int i = 0; i < w1; i++) { 181 double d = (double) (period >> 1) 182 * Math.sin((double) i / (double) period 183 + (6.2831853071795862D * (double) phase) 184 / (double) frames); 185 g.copyArea(i, 0, 1, h1, 0, (int) d); 186 if (borderGap) { 187 g.setColor(color); 188 g.drawLine(i, (int) d, i, 0); 189 g.drawLine(i, (int) d + h1, i, h1); 190 } 191 } 192 } 193 194 public void write(OutputStream sos) throws IOException { 195 ImageIO.write(buffImg, "png", sos); 196 sos.close(); 197 } 198 199 public BufferedImage getBuffImg() { 200 return buffImg; 201 } 202 203 public String getCode() { 204 return code.toLowerCase(); 205 } 206 207 // /** 208 // * 验证码 209 // * @param request 210 // * @param response 211 // * @param session 212 // * @throws IOException 213 // */ 214 // @RequestMapping("/code.jpg") 215 // public void getCode3(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException { 216 // int width = NumberUtils.toInt(request.getParameter("width"), 100); 217 // int height = NumberUtils.toInt(request.getParameter("height"), 30); 218 // int codeCount = NumberUtils.toInt(request.getParameter("codeCount"), 4); 219 // int lineCount = NumberUtils.toInt(request.getParameter("lineCount"), 10); 220 // if (width > 1000) width = 100; 221 // if (height > 300) height = 30; 222 // if (codeCount > 10) codeCount = 4; 223 // if (lineCount > 100) lineCount = 10; 224 // // 设置响应的类型格式为图片格式 225 // response.setContentType("image/jpeg"); 226 // // 禁止图像缓存。 227 // response.setHeader("Pragma", "no-cache"); 228 // response.setHeader("Cache-Control", "no-cache"); 229 // response.setDateHeader("Expires", 0); 230 // // 自定义参数 231 // CaptchaUtil code = new CaptchaUtil(width, height, codeCount, lineCount); 232 // String sessionId = session.getId(); 233 // RedisUtil.set("captcha_" + sessionId, code.getCode(), 60 * 30); 234 // code.write(response.getOutputStream()); 235 // } 236 237 }