Java的生成图片验证码(有点仿QQ验证码的意思)http://www.bieryun.com/806.html
看了挺多图片验证码的代码,感觉没什么长的好看点的,就自己动手写了个,写完发现跟QQ的有几分相似,比较满意。
功能包括:自定义图片尺寸和字符长度,随机背景颜色和字符颜色,随机字符偏移角度,字符平滑边缘,干扰线,噪点,背景扭曲。
本来想做字符扭曲的,不知道怎的先生成文字再扭曲就报错了,先就这样吧,希望有高手能帮助修正一下。
需要说明的是之所以有几分像QQ的验证码感觉是因为这个阿尔及利亚的字体,如果系统没有的话需要自行安装,百度搜字体名能下载到,丢系统字体文件夹就行。
JAVA文件和字体打了个包发资里里,http://download.csdn.net/detail/ruixue0117/7138469。
效果图:
AuthImage类:
- 包 hh.com.util;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- 公共类 AuthImage 扩展 javax.servlet.http.HttpServlet 实现 javax.servlet.Servlet {
- static final long serialVersionUID = 1L;
- 公共无效 服务(HttpServletRequest请求,HttpServletResponse响应) 抛出 ServletException,IOException {
- response.setHeader(“Pragma” , “No-cache” );
- response.setHeader(“Cache-Control” , “no-cache” );
- response.setDateHeader(“Expires” , 0 );
- response.setContentType(“image / jpeg” );
- //生成随机字串
- 字符串verifyCode = VerifyCodeUtils.generateVerifyCode(4 );
- //存入会话的会话
- HttpSession session = request.getSession(true );
- session.setAttribute(“rand” ,verifyCode.toLowerCase());
- //生成图片
- int w = 200 ,h = 80 ;
- VerifyCodeUtils.outputImage(w,h,response.getOutputStream(),verifyCode);
- }
- }
VerifyCodeUtils类,生成图片流,然后不同框架下的输出可以参考上面的代码或者自行百度,无非就是获取的OutputStream和ContentType的的区别,主要的方法可直接执行:
(PS:不想下载的话复制这个类就行了)
- 包 hh.com.util;
- import java.awt.Color;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Graphics2D;
- import java.awt.LinearGradientPaint;
- import java.awt.Paint;
- import java.awt.RenderingHints;
- import java.awt.geom.AffineTransform;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.util.Arrays;
- import java.util.Random;
- import javax.imageio.ImageIO;
- 公共类 VerifyCodeUtils {
- //使用到阿尔及利亚字体,系统里没有的话需要安装字体,字体只显示大写,去掉了1,0,I,O几个容易混淆的字符
- public static final String VERIFY_CODES = “ 23456789ABCDEFGHJKLMNPQRSTUVWXYZ ” ;
- private static Random = new Random();
- / **
- *使用系统默认字符源生成验证码
- * @param verifySize验证码长度
- * @返回
- * /
- public static String generateVerifyCode(int verifySize){
- 返回 generateVerifyCode(verifySize,VERIFY_CODES);
- }
- / **
- *使用指定源生成验证码
- * @param verifySize验证码长度
- * @param来源验证码字符源
- * @返回
- * /
- 公共静态 字符串generateVerifyCode(诠释 verifySize,字符串来源){
- if (sources == null || sources.length()== 0 ){
- 来源= VERIFY_CODES;
- }
- int codesLen = sources.length();
- 随机rand = 新 随机(System.currentTimeMillis());
- StringBuilder verifyCode = new StringBuilder(verifySize);
- for (int i = 0 ; i <verifySize; i ++){
- verifyCode.append(sources.charAt(rand.nextInt(codesLen- 1 )));
- }
- 返回 verifyCode.toString();
- }
- / **
- *生成随机验证码文件,并返回验证码值
- * @param w
- * @参数h
- * @param outputFile
- * @param verifySize
- * @返回
- * @抛出IOException
- * /
- public static String outputVerifyImage(int w, int h,File outputFile, int verifySize) throws IOException {
- String verifyCode = generateVerifyCode(verifySize);
- outputImage(w,h,outputFile,verifyCode);
- 返回 verifyCode;
- }
- / **
- *输出随机验证码图片流,并返回验证码值
- * @param w
- * @参数h
- * @参数操作系统
- * @param verifySize
- * @返回
- * @抛出IOException
- * /
- public static String outputVerifyImage(int w, int h,OutputStream os, int verifySize) throws IOException {
- String verifyCode = generateVerifyCode(verifySize);
- outputImage(w,h,os,verifyCode);
- 返回 verifyCode;
- }
- / **
- *生成指定验证码图像文件
- * @param w
- * @参数h
- * @param outputFile
- * @参数代码
- * @抛出IOException
- * /
- public static void outputImage(int w, int h,File outputFile,String code) throws IOException {
- if (outputFile == null ){
- 返回;
- }
- 文件dir = outputFile.getParentFile();
- if (!dir.exists()){
- dir.mkdirs();
- }
- 尝试{
- outputFile.createNewFile();
- FileOutputStream fos = new FileOutputStream(outputFile);
- outputImage(w,h,fos,code);
- fos.close();
- } 捕捉(IOException的发送){
- 扔 e;
- }
- }
- / **
- *输出指定验证码图片流
- * @param w
- * @参数h
- * @参数操作系统
- * @参数代码
- * @抛出IOException
- * /
- public static void outputImage(int w, int h,OutputStream os,String code) throws IOException {
- int verifySize = code.length();
- BufferedImage image = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);
- 随机rand = 新 随机();
- Graphics2D g2 = image.createGraphics();
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
- 颜色[]颜色= 新 颜色[ 5 ];
- 颜色[] colorSpaces = 新 颜色[] {Color.WHITE,Color.CYAN,
- Color.GRAY,Color.LIGHT_GRAY,Color.MAGENTA,Color.ORANGE,
- Color.PINK,Color.YELLOW};
- float [] fractions = new float [colors.length];
- for (int i = 0 ; i <colors.length; i ++){
- colors [i] = colorSpaces [rand.nextInt(colorSpaces.length)];
- 分数[i] = rand.nextFloat();
- }
- Arrays.sort(级分);
- g2.setColor(Color.GRAY); //设置边框色
- g2.fillRect(0 , 0 ,W,H);
- 颜色C = getRandColor(200 , 250 );
- g2.setColor(C); //设置背景色
- g2.fillRect(0 , 2 ,W,H- 4 );
- //绘制干扰线
- 随机随机= 新 随机();
- g2.setColor(getRandColor(160 , 200 )); //设置线条的颜色
- for (int i = 0 ; i < 20 ; i ++){
- int x = random.nextInt(w - 1 );
- int y = random.nextInt(h - 1 );
- int xl = random.nextInt(6 )+ 1 ;
- int yl = random.nextInt(12 )+ 1 ;
- g2.drawLine(x,y,x + xl + 40 ,y + yl + 20 );
- }
- //添加噪点
- float yawpRate = 0 .05f; //噪声率
- int area =(int )(yawpRate * w * h);
- for (int i = 0 ; i <area; i ++){
- int x = random.nextInt(w);
- int y = random.nextInt(h);
- int rgb = getRandomIntColor();
- image.setRGB(x,y,rgb);
- }
- 剪切(g2,w,h,c); //使图片扭曲
- g2.setColor(getRandColor(100 , 160 ));
- int fontSize = h- 4 ;
- Font font = new Font(“Algerian” ,Font.ITALIC,fontSize);
- g2.setFont(字体);
- char [] chars = code.toCharArray();
- for (int i = 0 ; i <verifySize; i ++){
- AffineTransform affine = new AffineTransform();
- affine.setToRotation(Math.PI / 4 * rand.nextDouble()*(rand.nextBoolean()? 1 :-1 ),(w / verifySize)* i + fontSize / 2 ,h / 2 );
- g2.setTransform(仿射);
- g2.drawChars(字符,I, 1 ,((W- 10 )/ verifySize)* I + 5 ,H / 2 + fontSize的/ 2 - 10 );
- }
- g2.dispose();
- ImageIO.write(image, “jpg” ,os);
- }
- private static Color getRandColor(int fc, int bc){
- 如果 (fc> 255 )
- fc = 255 ;
- 如果 (bc> 255 )
- bc = 255 ;
- int r = fc + random.nextInt(bc - fc);
- int g = fc + random.nextInt(bc - fc);
- int b = fc + random.nextInt(bc - fc);
- 返回新的 颜色(r,g,b);
- }
- private static int getRandomIntColor(){
- int [] rgb = getRandomRgb();
- int color = 0 ;
- for (int c:rgb){
- 颜色=颜色<< 8 ;
- color = color | C;
- }
- 返回 颜色;
- }
- private static int [] getRandomRgb(){
- int [] rgb = new int [ 3 ];
- for (int i = 0 ; i < 3 ; i ++){
- rgb [i] = random.nextInt(255 );
- }
- 返回 rgb;
- }
- private static void shear(Graphics g, int w1, int h1,Color color){
- 剪切X(g,w1,h1,颜色);
- 剪切Y(g,w1,h1,颜色);
- }
- private static void shearX(Graphics g, int w1, int h1,Color color){
- int period = random.nextInt(2 );
- boolean borderGap = true ;
- int frames = 1 ;
- int phase = random.nextInt(2 );
- for (int i = 0 ; i <h1; i ++){
- 双 d =(双)(期间>> 1 )
- * Math.sin((双)我/(双)期间
- +(6 .2831853071795862D *(双)相)
- /(双)帧);
- g.copyArea(0 ,I,W1, 1 ,(INT )d, 0 );
- if (borderGap){
- g.setColor(颜色);
- g.drawLine((int )d,i, 0 ,i);
- g.drawLine((int )d + w1,i,w1,i);
- }
- }
- }
- private static void shearY(Graphics g, int w1, int h1,Color color){
- int period = random.nextInt(40 )+ 10 ; // 50;
- boolean borderGap = true ;
- int frames = 20 ;
- int phase = 7 ;
- for (int i = 0 ; i <w1; i ++){
- 双 d =(双)(期间>> 1 )
- * Math.sin((双)我/(双)期间
- +(6 .2831853071795862D *(双)相)
- /(双)帧);
- g.copyArea(I, 0 , 1 ,H1, 0 ,(INT )d);
- if (borderGap){
- g.setColor(颜色);
- g.drawLine(i,(int )d,i, 0 );
- g.drawLine(i,(int )d + h1,i,h1);
- }
- }
- }
- public static void main(String [] args) throws IOException {
- 文件dir = 新 文件(“F:/ verifies” );
- int w = 200 ,h = 80 ;
- for (int i = 0 ; i < 50 ; i ++){
- String verifyCode = generateVerifyCode(4 );
- File file = new File(dir,verifyCode + “.jpg” );
- outputImage(w,h,file,verifyCode);
- }
- }
- }
web.xml中配置:
- < servlet >
- < servlet-name > AuthImage </ servlet-name >
- < servlet-class > hh.com.util.AuthImage </ servlet-class >
- </ servlet >
- < servlet-mapping >
- < servlet-name > AuthImage </ servlet-name >
- < url-pattern > / authImage </ url-pattern >
- </ servlet-mapping >