验证码生成器(java)

本文提供一个验证码生成器,编程使用语言java。

摘要

使用该验证码生成器将会生成特定字符串的验证码图片,需指定图片高度,文字内容自适应。如果没有提供文字则自动返回文字内容及验证码图片,你也可以提供文字生成验证码图片。

代码

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Random;

/**
 * 验证码生成器
 * Created by chunliangh on 14-10-14.
 */
public class VerificationCoder {

    public static final int _30 = 30;
    public static final int _180 = 180;
    public static final int DEFAULT_LINE_COUNT = 5;
    public static final int DEFAULT_FONT_STYLE = Font.BOLD+Font.ITALIC;
    public static final String IMG_TYPE = "jpg";
    //200个常用汉字
    private static final char[] codeArray = new char[]{'的','我','美','张','爱','完','天','地','高','啊',
            '鹅','丽','雨','网','牛','春','秋','刚','成','公','晶','亮','国','路','眼','手','他','你','钱','元',
            '日','风','水','妈','爸','浩','开','米','无','韩','丹','佳','家','云','杨','北','西','东','男','和',
            '亚','放','林','刘','正','指','智','景','黄','在','服','陈','道','味','大','静','为','李','雪','学',
            '虎','图','旁','领','瘦','胖','左','有','游','玉','社','见','步','近','问','同','电','雷','周','宇',
            '高','老','是','冰','泪','用','接','出','会','来','小','打','答','得','等','多','都','平','票','拍',
            '纱','说','上','下','个','给','跟','话','就','叫','那','年','能','买','们','没','量','里','了','均',
            '把','被','表','比','才','从','吃','次','差','想','恶','晚','前','走','最','做','中','这','些','写',
            '热','如','然','要','新','求','修','定','明','毛','世','选','霞','艳','朋','录','敏','民','雅','猫',
            '界','棒','旅','行','程','英','带','达','客','本','望','品','礼','绿','迪','姐','唱','场','还','边',
            '记','评','盼','钟','郭','经','祝','福','龙','孩'};
    /**
     * 生成验证码字符串及对应图片的字节数组(使用自适应的宽度、默认的样式及默认的干扰线数量)
     * @param height 图片高度
     * @param count  验证码字数
     * @return [String:验证码字符串,byte[]:验证码图片字节数组]
     */
    public static Object[] verificationCodeAndImg(int height,int count){
        char[] codes = generateCodes(count);
        return new Object[]{new String(codes),verificationCodeImg(height,codes)};
    }

    /**
     * 生成验证码字符串及对应图片的字节数组
     * @param width 预生成验证码图片宽度
     * @param height 预生成验证码图片高度
     * @param count 给定的验证码字符数
     * @param fontStyle 图片中文字的样式
     * @param lineCount 干扰线的数量
     * @return [String:验证码字符串,byte[]:验证码图片字节数组]
     */
    public static Object[] verificationCodeAndImg(int width,int height,int count,int fontStyle,int lineCount){
        char[] codes = generateCodes(count);
        return new Object[]{new String(codes),verificationCodeImg(width,height,codes,fontStyle,lineCount)};
    }

    /**
     * 生成验证码字符串对应图片的字节数组(使用自适应的宽度、默认的样式及默认的干扰线数量)
     * @param height 图片高度
     * @param codes  验证码字符数组
     * @return byte[]:验证码图片字节数组
     */
    public static byte[] verificationCodeImg(int height,char[] codes){
        return verificationCodeImg(0,height,codes,DEFAULT_FONT_STYLE,DEFAULT_LINE_COUNT);
    }

    /**
     * 生成验证码字符串对应图片的字节数组
     * @param width 预生成验证码图片宽度
     * @param height 预生成验证码图片高度
     * @param codes 给定的验证码字符数组
     * @param fontStyle 图片中文字的样式
     * @param lineCount 干扰线的数量
     * @return byte[]:验证码图片字节数组
     */
    public static byte[] verificationCodeImg(int width,int height,char[] codes,int fontStyle,int lineCount){
        //处理宽度
        int suitWidth = height*codes.length;
        if (width<suitWidth) width = suitWidth;
        BufferedImage bi = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
        Graphics g = bi.getGraphics();
        setBackgroundColor(g,width,height);
        addBackGroundLine(g,width,height,lineCount);
        addCodes(g,height,codes,fontStyle);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            ImageIO.write(bi, IMG_TYPE, bos);
            return bos.toByteArray();
        } catch (IOException e) {}
        return null;
    }

    //设置背景色
    private static void setBackgroundColor(Graphics g,int width,int height){
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);
    }
    //设置边框颜色
    private static void setRectColor(Graphics g,int width,int height){
        g.setColor(Color.BLUE);
        g.drawRect(0, 0, width-1, height-1);
    }
    //画干扰线
    private static void addBackGroundLine(Graphics g,int width,int height,int lineCount){
        for (int i = 0; i < lineCount; i++) {// 设置线条个数并画线
            if (i%2==0){
                g.setColor(Color.BLACK);
            }else{
                g.setColor(Color.RED);
            }
            int x1 = new Random().nextInt(width);
            int y1 = new Random().nextInt(height);
            int x2 = new Random().nextInt(width);
            int y2 = new Random().nextInt(height);
            g.drawLine(x1, y1, x2, y2);
        }
    }
    //填充汉字
    private static void addCodes(Graphics g,int height,char[] codes,int fontStyle){
        //字号:=height*Math.sqrt(3)/(1+Math.sqrt(3))=height*0.634
        int size = (int) (height*0.634);
        int _x = size/2;         //字的横坐标相对圆心横坐标的偏移量
        int y0 = (height+size)/2;//字的纵坐标
        int x = height/2,y = x;  //圆心的横纵坐标
        Graphics2D g2D = (Graphics2D) g;
        g2D.setFont(new Font(null, fontStyle, size));
        for (int i=0,len=codes.length;i<len;i++){
            if (i%2==0){
                g2D.setColor(Color.BLACK);
            }else{
                g2D.setColor(Color.RED);
            }
            int degree = new Random().nextInt() % _30;//随机生成偏转角度
            g2D.rotate(degree * Math.PI/_180, x, y);//正向偏转
            g2D.drawString(codes[i] + "", x-_x, y0);//添加字符
            g2D.rotate(-degree * Math.PI/_180, x, y);//负向偏转
            x += height;
        }
    }
    //给定长度生成随机字符数组
    private static char[] generateCodes(int count) {
        char[] res = new char[count];
        for (int i=0,len=codeArray.length;i<count;i++){
            int j = new Random().nextInt(len);
            res[i] = codeArray[j];
        }
        return res;
    }
    //测试
    public static void main(String[] args){
        Object[] res = verificationCodeAndImg(30,2);
        System.out.println(res[0]);
        try {
            BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream((byte[]) res[1]));
            ImageIO.write(bufferedImage,IMG_TYPE,new File("/Users/daojian/Desktop/ass.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

posted on 2014-10-15 09:16  韩春亮  阅读(458)  评论(0)    收藏  举报

导航