新スキル「Java描画2Dグラフィック検証コード方式」をアンロック

依存する SDK コンポーネント
<dependency>
  <groupId>io.github.mingyang66</groupId>
  <artifactId>oceansky-captcha</artifactId>
  <version>4.3.2</version>
</dependency>
1. 次の 3 つの一般的なグラフィック検証コードがあります。
  • 混合英数字 (ノイズライン)。
  • 純粋な数値(干渉線)。
  • プレーンレター(ノイズライン)。
2. サンプル図は次のとおりです。

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

ここに画像の説明を挿入

3. ケースコード

質問 1: 描画された検証コードの (x, y) 座標に対する点はどこですか?

答え:左上隅

質問 2: グラフィック検証コードを描画するための X 座標の開始位置を計算するにはどうすればよいですか?

答え: (アートボードの幅 - 確認コード文字のテキスト幅) /2

質問 3: 各文字が 1 つずつ描画される x 座標の位置を計算するにはどうすればよいですか?

答え: 開始 x 座標 + (検証コードの幅/検証コードの文字数) * n-1 番目の文字

質問 4: 検証コードが上下の中心に来るようにするための Y 軸座標を計算するにはどうすればよいですか?

回答案:(高さ - (fm.getAscent() + fm.getDescent())) / 2 + fm.getAscent();

上記の式を理解する前に、まずベースライン、上昇、降下、およびリードとは何かを理解する必要があります。

public class CaptchaUtils {
    
    
    /**
     * 数字
     */
    private static final String[] DIGIT = {
    
    "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
    /**
     * 字母
     */
    private static final String[] LETTER = {
    
    
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
    /**
     * 字母数字
     */
    private static final String[] ALPHANUMERIC = {
    
    
            "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
            "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
    /**
     * 图片格式
     */
    public static final String FORMAT_NAME = "JPEG";

    /**
     * @param width    画板宽度
     * @param height   画板高度
     * @param count    验证码个数
     * @param fontSize 字体大小
     * @return
     * @Description: 绘制数字图形验证码,不带干扰线
     */
    public static Captcha createDigit(int width, int height, int count, int fontSize) throws IOException {
    
    
        return createDigit(width, height, count, fontSize, false, null);
    }

    /**
     * @param width     画板宽度
     * @param height    画板高度
     * @param count     验证码个数
     * @param fontSize  字体大小
     * @param line      是否画干扰线
     * @param lineCount 干扰线数量
     * @return
     * @Description: 绘制数字图形验证码
     */
    public static Captcha createDigit(int width, int height, int count, int fontSize, boolean line, Integer lineCount) throws IOException {
    
    
        /**
         * 字体名又分为两大类:中文字体名:宋体,楷体,黑体等;
         *           英文字体名:Arial,Times New Roman等;
         */
        Font font = new Font("Times New Roman", Font.ITALIC, fontSize);
        // 绘制的字符串
        String[] code = getDrawCode(CaptchaType.DIGIT, count);
        return create2D(width, height, code, font, line, lineCount);
    }

    /**
     * @param width    画板宽度
     * @param height   画板高度
     * @param count    验证码个数
     * @param fontSize 字体大小
     * @return
     * @throws IOException
     * @Description: 绘制字母图形验证码
     */
    public static Captcha createLetter(int width, int height, int count, int fontSize) throws IOException {
    
    
        return createLetter(width, height, count, fontSize, false, null);
    }

    /**
     * @param width     画板宽度
     * @param height    画板高度
     * @param count     验证码个数
     * @param fontSize  字体大小
     * @param line      是否画干扰线
     * @param lineCount 干扰线数量
     * @return
     * @throws IOException
     * @Description: 绘制字母图形验证码
     */
    public static Captcha createLetter(int width, int height, int count, int fontSize, boolean line, Integer lineCount) throws IOException {
    
    
        /**
         * 字体名又分为两大类:中文字体名:宋体,楷体,黑体等;
         *           英文字体名:Arial,Times New Roman等;
         */
        Font font = new Font("Times New Roman", Font.ITALIC, fontSize);
        // 绘制的字符串
        String[] code = getDrawCode(CaptchaType.LETTER, count);
        return create2D(width, height, code, font, line, lineCount);
    }

    /**
     * @param width    画板宽度
     * @param height   画板高度
     * @param count    验证码个数
     * @param fontSize 字体大小
     * @return
     * @throws IOException
     * @Description: 绘制数字字母图形验证码
     */
    public static Captcha createAlphanumeric(int width, int height, int count, int fontSize) throws IOException {
    
    
        return createAlphanumeric(width, height, count, fontSize, false, null);
    }

    /**
     * @param width     画板宽度
     * @param height    画板高度
     * @param count     验证码个数
     * @param fontSize  字体大小
     * @param line      是否画干扰线
     * @param lineCount 干扰线数量
     * @return
     * @throws IOException
     * @Description: 绘制数字字母图形验证码
     */
    public static Captcha createAlphanumeric(int width, int height, int count, int fontSize, boolean line, Integer lineCount) throws IOException {
    
    
        /**
         * 字体名又分为两大类:中文字体名:宋体,楷体,黑体等;
         *           英文字体名:Arial,Times New Roman等;
         */
        Font font = new Font("Times New Roman", Font.ITALIC, fontSize);
        // 绘制的字符串
        String[] code = getDrawCode(CaptchaType.ALPHANUMERIC, count);
        return create2D(width, height, code, font, line, lineCount);
    }

    /**
     * @param width     画板宽度
     * @param height    画板高度
     * @param code      验证码
     * @param font      字体
     * @param line      是否绘制干扰线
     * @param lineCount 干扰线条数
     * @return 生成的图形验证码对象
     * @throws IOException
     * @Description: 生成图形验证码
     */
    public static Captcha create2D(int width, int height, String[] code, Font font, boolean line, Integer lineCount) throws IOException {
    
    
        // 创建空白图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取图片画笔
        Graphics graphic = image.getGraphics();
        // 绘制矩形背景(实心矩形)
        graphic.fillRect(0, 0, width, height);
        /**
         * Font.PLAIN(普通)
         * Font.BOLD(加粗)
         * Font.ITALIC(斜体)
         * Font.BOLD+ Font.ITALIC(粗斜体)
         */
        graphic.setFont(font);
        // 画图形验证码
        drawCode(graphic, width, height, code);
        // 画干扰线
        if (line) {
    
    
            drawLine(graphic, width, height, lineCount);
        }
        ByteArrayOutputStream bas = new ByteArrayOutputStream();
        ImageIO.write(image, FORMAT_NAME, bas);
        return new CaptchaBuilder().code(StringUtils.join(code)).image(bas.toByteArray()).build();

    }

    /**
     * @param graphic 画板对象
     * @param width   画板宽度
     * @param height  画板高度
     * @param code    图形验证码字符串
     * @Description 画图形验证码
     */
    protected static void drawCode(Graphics graphic, int width, int height, String[] code) {
    
    
        // 计算文字长度,计算居中的x点坐标,即字符串左边位置
        FontMetrics fm = graphic.getFontMetrics(graphic.getFont());
        // 字符串宽度
        int textWidth = fm.stringWidth(StringUtils.join(code));
        // 字符串左侧x坐标
        int x = (width - textWidth) / 2;
        int y = (height - (fm.getAscent() + fm.getDescent())) / 2 + fm.getAscent();
        for (int i = 0; i < code.length; i++) {
    
    
            // 设置随机颜色
            graphic.setColor(new Color(RandomUtils.nextInt(0, 255), RandomUtils.nextInt(0, 255), RandomUtils.nextInt(0, 255)));
            // 绘制字符串
            graphic.drawString(code[i], x + (textWidth / code.length) * i, y);
        }
    }

    /**
     * 获取绘制的验证码
     *
     * @param type  字符串类型
     * @param count 字符个数
     * @return 字符串数组
     */
    protected static String[] getDrawCode(CaptchaType type, int count) {
    
    
        String[] code = new String[count];
        Random ran = new Random();
        for (int i = 0; i < count; i++) {
    
    
            switch (type) {
    
    
                case DIGIT:
                    code[i] = DIGIT[ran.nextInt(DIGIT.length)];
                    break;
                case LETTER:
                    code[i] = LETTER[ran.nextInt(LETTER.length)];
                    break;
                default:
                    code[i] = ALPHANUMERIC[ran.nextInt(ALPHANUMERIC.length)];
                    break;

            }
        }
        return code;
    }

    /**
     * @param graphic   画板对象
     * @param width     画板宽度
     * @param height    画板高度
     * @param lineCount 干扰线条数
     * @Description 绘制干扰线
     */
    protected static void drawLine(Graphics graphic, int width, int height, Integer lineCount) {
    
    
        // 画干扰线
        for (int i = 0; i < lineCount; i++) {
    
    
            // 设置随机颜色
            graphic.setColor(new Color(RandomUtils.nextInt(0, 255), RandomUtils.nextInt(0, 255), RandomUtils.nextInt(0, 255)));
            // 随机画线
            graphic.drawLine(RandomUtils.nextInt(0, width), RandomUtils.nextInt(0, height), RandomUtils.nextInt(0, width), RandomUtils.nextInt(0, height));
        }
    }
}

このケースの完全なコードについては、https: //github.com/mingyang66/spring-parentを参照してください。

おすすめ

転載: blog.csdn.net/yaomingyang/article/details/130487227
おすすめ