java do-it-yourself graphics verification code

Recently, on the project, I encountered a problem. It was very simple to make a verification code. It was enough to use the kaptcha plugin to generate it. As a result, I don't know the strange reason, and the root cause of the problem has not yet been found. There is really no other way but to write a verification code myself.
Not much to say, here are the dry goods:


package com.hzseek.web.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * @author dingjunjie
 * @date 2018-02-07 21:14:34
 * @desc 图片验证码工具类
 */
public class GenerateCaptcha {

    // 图片宽度
    private int width = 160;
    // 图片高度
    private int height = 40;
    // 验证码字符个数
    private int codeCount = 5;
    // 字体数组
    private String[] fontTypes = { "黑体", "微软雅黑"};
//  private String[] fontTypes = { "Arial", "Courier"};
    // 验证码干扰线数
    private int lineCount = 2;
    // 验证码
    private String captchaCode = null;
    // 验证码图片Buffer
    private BufferedImage buffImg = null;
    // 验证码范围,去掉0(数字)和O(拼音)容易混淆的(小写的1和L也可以去掉,大写不用了)
    private String codeStr = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
    // 获得随机数
    private Random random = new Random();

    /**
     * 获取随机的颜色
     * 
     * @return
     */
    private Color randomColor() {
        int r = this.random.nextInt(100); // 这里为什么是150,因为当r,g,b都为255时,即为白色,为了好辨认,需要颜色深一点。
        int g = this.random.nextInt(100);
        int b = this.random.nextInt(100);
        return new Color(r, g, b); // 返回一个随机颜色
    }

    /**
     * 获得随机字体
     * 
     * @return
     */
    private Font randomFont() {
        int index = random.nextInt(fontTypes.length); // 获取随机的字体
        String fontName = fontTypes[index];
        int style = random.nextInt(4); // 随机获取字体的样式,0是无样式,1是加粗,2是斜体,3是加粗加斜体
        int size = random.nextInt(5) + 24; // 随机获取字体的大小
        return new Font(fontName, style, size); // 返回一个随机的字体
    }

    /**
     * 获得随机字符
     * 
     * @return
     */
    private char randomChar() {
        int index = random.nextInt(codeStr.length());
        return codeStr.charAt(index);
    }

    /**
     * 画干扰线,验证码干扰线用来防止计算机解析图片
     * 
     * @param image
     * @param lineCount
     *            干扰线的数量
     */
    private void drawLine(BufferedImage image, int lineCount) {
        Graphics2D g = (Graphics2D) image.getGraphics();
        for (int i = 0; i < lineCount; i++) {
            int x1 = random.nextInt(width);
            int y1 = random.nextInt(height);
            int x2 = random.nextInt(width);
            int y2 = random.nextInt(height);
            g.setStroke( new BasicStroke( 2.5f ) );
            g.setColor(randomColor());
//          g.drawLine(x1, y1, x2, y2);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            QuadCurve2D a = new QuadCurve2D.Double(5, y1, 80, random.nextInt(20) + 10, 155, y2);
            g.draw(a);
        }
    }

    /**
     * 创建图片的方法
     * 
     * @return
     */
    private BufferedImage createImage() {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 创建图片缓冲区
        Graphics2D g = (Graphics2D) image.getGraphics(); // 获取画笔
        g.setColor(Color.LIGHT_GRAY); // 设置背景色
        g.fillRect(0, 0, width, height);
         // 随机产生10个干扰点
//      Random rand = new Random();
//      for (int i = 0; i < 10; i++) {
//          int x = rand.nextInt(width);
//          int y = rand.nextInt(height);
//          g.setColor(randomColor());
//          g.drawOval(x, y, 1, 1);
//      }
        return image; // 返回一个图片
    }

    /**
     * 获取验证码图片
     * 
     * @return
     */
    public BufferedImage getImage() {
        BufferedImage image = createImage();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < codeCount; i++) // 显示字符数
        {
            Graphics2D g = (Graphics2D) image.getGraphics(); // 获取画笔
            String s = randomChar() + ""; // 随机生成字符,因为只有画字符串的方法,没有画字符的方法,所以需要将字符变成字符串再画
            sb.append(s); // 添加到StringBuilder里面
            float x = width / (codeCount + 2); // 每个字符的宽度,左右各空出一个字符的位置
            g.setFont(randomFont()); // 设置字体,随机
            g.setColor(Color.BLACK); // 设置颜色,为了区分度高,设为黑色
            g.rotate(-5* Math.PI / 180);
            g.drawString(s, x * (i + 1 + random.nextFloat()/2), height - 5);
        }
        this.captchaCode = sb.toString();
        drawLine(image, lineCount);
        return image;
    }

    /**
     * 获取验证码的文本
     * 
     * @return
     */
    public String getCaptchaCode() {
        return captchaCode;
    }

    /**
     * 将验证码图片写出的方法
     * 
     * @param image
     * @param out
     * @throws IOException
     */
    public void output(BufferedImage image, OutputStream out) throws IOException {
        ImageIO.write(image, "JPEG", out);
    }
}

As for the call, I won't say much, just call the output to generate the verification code.
The effect is as shown in the figure:write picture description here

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326414510&siteId=291194637