一个生成网页验证码的类 (mycome-validate)

一个小练习

可以通过 BufferedImage next() 返回一个内存图片

也可以通过String void next(OutputStream out) 写到一个输出流中,并返回验证码的值

jar包下载:https://files.cnblogs.com/mycome/mycome-validate.zip

package validate;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;

public class Validate {
    // 支持的验证码干扰效果
    public static final int ROTATE = Integer.parseInt("00000001", 2);// 旋转
    public static final int CIRCLE = Integer.parseInt("00000010", 2);// 干扰圈
    public static final int LINE = Integer.parseInt("00000100", 2);// 干扰线
    public static final int FOG = Integer.parseInt("00001000", 2);// 雾化
    public static final int LIGHTER = Integer.parseInt("00010000", 2);// 颜色变淡

    // 验证码属性
    private int width; // 尺寸
    private int height;
    private int size;// 字符数
    private int fontSize;// 字体大小
    private int interval;// 字符间隔
    private int obstruction;// 干扰效果
    private String value;// 验证码的字符值
    private Graphics2D graphics;// 绘图器
    private BufferedImage validate;// 结果对象
    private String range;// 取字范围

    // 构造方法
    public Validate(int width, int height, int size, int obstruction,
            String rangeSource) {
        // 初始化验证码的尺寸
        this.width = width;
        this.height = height;
        // 初始化验证码的字符数
        this.size = size;
        // 设定验证码的干扰效果
        this.obstruction = obstruction;
        // 设定字体大小和间隔
        calculateSize();
        // 设置验证码范围
        setRange(rangeSource);
    }

    // 生成验证码
    public BufferedImage next() {
        // 生成图片
        validate = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        graphics = (Graphics2D) validate.getGraphics();
        addBackground();
        // 添加文字
        addCharacters();
        // 添加干扰
        addObstruction();

        return validate;
    }

    // 把验证码图片当作流输出
    public String next(OutputStream out) throws IOException {
        next();
        ImageIO.write(validate, "jpg", out);
        return value;
    }

    // 设置背景色
    private void addBackground() {
        // 设置背景色为淡灰色
        graphics.setColor(new Color(0xf8f8f8));
        graphics.fillRect(0, 0, width, height);
    }

    // 添加文字
    private void addCharacters() {
        // 设置字体
        graphics.setFont(new Font("宋体", Font.BOLD, fontSize));
        graphics.setColor(Color.black);
        // 字符位置标记
        int x = 0;
        int y = (height - fontSize) / 2 + fontSize;
        Character c;
        // 取字范围
        int len = range.length();
        // 判断是否需要旋转
        boolean doRotate = (obstruction % 2) != 0 ? true : false;
        double radian = 0;
        // 画出字体
        value = "";
        for (int i = 0; i < size; i++) {
            x += interval;
            // 设定旋转角度
            if (doRotate)
                radian = Math.random() * Math.PI / 3 - Math.PI / 6;
            if (doRotate)
                graphics.rotate(radian, x + fontSize / 2, y - fontSize / 2);
            // 取字,画字
            c = range.charAt((int) (Math.random() * len));
            value += c.toString();
            graphics.drawString(c.toString(), x, y);
            // 恢复旋转角度
            if (doRotate)
                graphics.rotate(-radian, x + fontSize / 2, y - fontSize / 2);
            x += fontSize;
        }
    }

    // 画干扰物
    private void addObstruction() {
        // 定义变量
        boolean needCircle = false;
        boolean needLine = false;
        boolean needFog = false;
        boolean needLighter = false;

        // 为以上变量赋值
        if ((obstruction & CIRCLE) == CIRCLE)
            needCircle = true;
        if ((obstruction & LINE) == LINE)
            needLine = true;
        if ((obstruction & FOG) == FOG)
            needFog = true;
        if ((obstruction & LIGHTER) == LIGHTER)
            needLighter = true;

        // 添加干扰物
        if (needCircle)
            addCircle();
        if (needLine)
            addLine();
        if (needFog)
            addFog();
        if (needLighter)
            addLighter();
    }

    // 增加验证码图片的亮度
    private void addLighter() {
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                // 获得原来的颜色
                int color = validate.getRGB(i, j);
                color += 256 * 256 * 4;
                color += 256 * 4;
                color += 4;
                // 设置更亮的颜色
                validate.setRGB(i, j, color);
            }
        }
    }

    // 添加雾化效果
    private void addFog() {
        // 设置雾化的颜色是灰色
        Color pointColor = Color.DARK_GRAY;
        // 设置雾化的密度是1/4;
        for (int i = 0; i < width; i += 4) {
            for (int j = 0; j < height; j += 4) {
                validate.setRGB(i, j, pointColor.getRGB());
            }
        }
    }

    // 添加干扰线
    private void addLine() {
        // 定义干扰线的起点和终点
        int startX;
        int startY;
        int endX;
        int endY;
        // 设置颜色
        graphics.setColor(Color.GRAY);

        // 画干扰线
        for (int i = 0; i < 5; i++) {
            startX = (int) (Math.random() * width);
            startY = (int) (Math.random() * height);
            endX = (int) (Math.random() * width);
            endY = (int) (Math.random() * height);

            graphics.drawLine(startX, startY, endX, endY);
        }
    }

    // 添加干扰圈
    private void addCircle() {
        int x;
        int y;
        int oval;
        for (int i = 0; i < 5; i++) {
            x = (int) (Math.random() * width);
            y = (int) (Math.random() * height);
            oval = (int) (Math.random() * (height / 2 - 5));
            graphics.drawOval(x, y, oval, oval);
        }
    }

    // 设定字体大小和间隔
    private void calculateSize() {
        int interval;
        int fontSize;
        // 计算合适的字体尺寸
        int accordingToWidth = (width - ((size + 1) * 5)) / size;
        int accordingToHeight = height - 10;
        fontSize = accordingToWidth < accordingToHeight ? accordingToWidth
                : accordingToHeight;
        // 计算合适的间隔尺寸
        interval = (width - (fontSize * size)) / (size + 1);
        // 初始化成员变量
        this.fontSize = fontSize;
        this.interval = interval;
    }

    // 设置验证码的取字范围
    private void setRange(String rangeSource) {
        FileInputStream in = null;
        byte[] buf = new byte[1024];
        int len;
        // 从文件读取数据
        try {
            in = new FileInputStream(rangeSource);
            while ((len = in.read(buf, 0, 1024)) > 0) {
                range += new String(buf, 0, len);
            }
        } catch (FileNotFoundException e) {
            new RuntimeException("读取验证码取字范围失败", e);
        } catch (IOException e) {
            new RuntimeException("读取验证码取字范围失败", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                }
            }

        }
    }
}
posted @ 2014-07-16 21:20  mycome  阅读(347)  评论(0编辑  收藏  举报