001package io.jboot.web.render;
002
003import com.jfinal.captcha.CaptchaRender;
004import com.jfinal.kit.StrKit;
005
006import java.awt.*;
007import java.awt.geom.QuadCurve2D;
008import java.awt.image.BufferedImage;
009import java.util.concurrent.ThreadLocalRandom;
010
011public class JbootCaptchaRender extends CaptchaRender {
012
013    // 验证码随机字符数组
014    protected static char[] charArray = "1234567890ABCDEFGHJKMNPQRSTUVWXY".toCharArray();
015
016
017    /**
018     * @param randomArrayString
019     */
020    public static void setRandomArrayString(String randomArrayString) {
021        if (StrKit.isBlank(randomArrayString)) {
022            throw new IllegalArgumentException("randomArrayString can not be blank.");
023        }
024        charArray = randomArrayString.toCharArray();
025    }
026
027
028    @Override
029    protected String getRandomString() {
030        char[] randomChars = new char[4];
031        for (int i = 0; i < randomChars.length; i++) {
032            randomChars[i] = charArray[ThreadLocalRandom.current().nextInt(charArray.length)];
033        }
034        return String.valueOf(randomChars);
035    }
036
037
038    @Override
039    protected void drawGraphic(String randomString, BufferedImage image) {
040        // 获取图形上下文
041        Graphics2D g = image.createGraphics();
042
043        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
044        // 图形抗锯齿
045        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
046        // 字体抗锯齿
047        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
048
049        ThreadLocalRandom random = ThreadLocalRandom.current();
050
051        // 设定背景色
052        g.setColor(getRandomColor(210, 250, random));
053        g.fillRect(0, 0, WIDTH, HEIGHT);
054
055        //绘制小字符背景
056        Color color = null;
057        for (int i = 0; i < 20; i++) {
058            color = getRandomColor(120, 200, random);
059            g.setColor(color);
060            String rand = String.valueOf(charArray[random.nextInt(charArray.length)]);
061            g.drawString(rand, random.nextInt(WIDTH), random.nextInt(HEIGHT));
062            color = null;
063        }
064
065        //设定字体
066        g.setFont(RANDOM_FONT[random.nextInt(RANDOM_FONT.length)]);
067        // 绘制验证码
068        for (int i = 0; i < randomString.length(); i++) {
069            //旋转度数 最好小于45度
070            int degree = random.nextInt(28);
071            if (i % 2 == 0) {
072                degree = degree * (-1);
073            }
074            //定义坐标
075            int x = 22 * i, y = 21;
076            //旋转区域
077            g.rotate(Math.toRadians(degree), x, y);
078            //设定字体颜色
079            color = getRandomColor(20, 130, random);
080            g.setColor(color);
081            //将认证码显示到图象中
082            g.drawString(String.valueOf(randomString.charAt(i)), x + 8, y + 10);
083            //旋转之后,必须旋转回来
084            g.rotate(-Math.toRadians(degree), x, y);
085        }
086        //图片中间曲线,使用上面缓存的color
087        g.setColor(color);
088        //width是线宽,float型
089        BasicStroke bs = new BasicStroke(3);
090        g.setStroke(bs);
091        //画出曲线
092        QuadCurve2D.Double curve = new QuadCurve2D.Double(0d, random.nextInt(HEIGHT - 8) + 4, WIDTH / 2, HEIGHT / 2, WIDTH, random.nextInt(HEIGHT - 8) + 4);
093        g.draw(curve);
094        // 销毁图像
095        g.dispose();
096    }
097
098
099}