From ba2a8156d50e0e9426fb9a2205863850f92c5c3a Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 1 Dec 2020 18:10:43 +0800 Subject: [PATCH] add GifCaptcha --- CHANGELOG.md | 1 + .../java/cn/hutool/captcha/CaptchaUtil.java | 167 ++++---- .../java/cn/hutool/captcha/GifCaptcha.java | 383 +++++++++--------- .../java/cn/hutool/captcha/CaptchaTest.java | 164 ++++---- 4 files changed, 364 insertions(+), 351 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 798ea2de3..5be8fc61a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ * 【all 】 增加Hutool.getAllUtils和printAllUtils方法 * 【core 】 增加PunyCode(issue#1268@Gitee) * 【core 】 ArrayUtil增加isSorted方法(pr#1271@Github) +* 【captcha】 增加GifCaptcha(pr#1273@Github) ### Bug修复 * 【cron 】 修复CronTimer可能死循环的问题(issue#1224@Github) diff --git a/hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java b/hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java index 7c814e490..54ef806b9 100644 --- a/hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java +++ b/hutool-captcha/src/main/java/cn/hutool/captcha/CaptchaUtil.java @@ -8,87 +8,102 @@ package cn.hutool.captcha; */ public class CaptchaUtil { - /** - * 创建线干扰的验证码,默认5位验证码,150条干扰线 - * - * @param width 图片宽 - * @param height 图片高 - * @return {@link LineCaptcha} - */ - public static LineCaptcha createLineCaptcha(int width, int height) { - return new LineCaptcha(width, height); - } + /** + * 创建线干扰的验证码,默认5位验证码,150条干扰线 + * + * @param width 图片宽 + * @param height 图片高 + * @return {@link LineCaptcha} + */ + public static LineCaptcha createLineCaptcha(int width, int height) { + return new LineCaptcha(width, height); + } - /** - * 创建线干扰的验证码 - * - * @param width 图片宽 - * @param height 图片高 - * @param codeCount 字符个数 - * @param lineCount 干扰线条数 - * @return {@link LineCaptcha} - */ - public static LineCaptcha createLineCaptcha(int width, int height, int codeCount, int lineCount) { - return new LineCaptcha(width, height, codeCount, lineCount); - } + /** + * 创建线干扰的验证码 + * + * @param width 图片宽 + * @param height 图片高 + * @param codeCount 字符个数 + * @param lineCount 干扰线条数 + * @return {@link LineCaptcha} + */ + public static LineCaptcha createLineCaptcha(int width, int height, int codeCount, int lineCount) { + return new LineCaptcha(width, height, codeCount, lineCount); + } - /** - * 创建圆圈干扰的验证码,默认5位验证码,15个干扰圈 - * - * @param width 图片宽 - * @param height 图片高 - * @return {@link CircleCaptcha} - * @since 3.2.3 - */ - public static CircleCaptcha createCircleCaptcha(int width, int height) { - return new CircleCaptcha(width, height); - } + /** + * 创建圆圈干扰的验证码,默认5位验证码,15个干扰圈 + * + * @param width 图片宽 + * @param height 图片高 + * @return {@link CircleCaptcha} + * @since 3.2.3 + */ + public static CircleCaptcha createCircleCaptcha(int width, int height) { + return new CircleCaptcha(width, height); + } - /** - * 创建圆圈干扰的验证码 - * - * @param width 图片宽 - * @param height 图片高 - * @param codeCount 字符个数 - * @param circleCount 干扰圆圈条数 - * @return {@link CircleCaptcha} - * @since 3.2.3 - */ - public static CircleCaptcha createCircleCaptcha(int width, int height, int codeCount, int circleCount) { - return new CircleCaptcha(width, height, codeCount, circleCount); - } + /** + * 创建圆圈干扰的验证码 + * + * @param width 图片宽 + * @param height 图片高 + * @param codeCount 字符个数 + * @param circleCount 干扰圆圈条数 + * @return {@link CircleCaptcha} + * @since 3.2.3 + */ + public static CircleCaptcha createCircleCaptcha(int width, int height, int codeCount, int circleCount) { + return new CircleCaptcha(width, height, codeCount, circleCount); + } - /** - * 创建扭曲干扰的验证码,默认5位验证码 - * - * @param width 图片宽 - * @param height 图片高 - * @return {@link ShearCaptcha} - * @since 3.2.3 - */ - public static ShearCaptcha createShearCaptcha(int width, int height) { - return new ShearCaptcha(width, height); - } + /** + * 创建扭曲干扰的验证码,默认5位验证码 + * + * @param width 图片宽 + * @param height 图片高 + * @return {@link ShearCaptcha} + * @since 3.2.3 + */ + public static ShearCaptcha createShearCaptcha(int width, int height) { + return new ShearCaptcha(width, height); + } - /** - * 创建扭曲干扰的验证码,默认5位验证码 - * - * @param width 图片宽 - * @param height 图片高 - * @param codeCount 字符个数 - * @param thickness 干扰线宽度 - * @return {@link ShearCaptcha} - * @since 3.3.0 - */ - public static ShearCaptcha createShearCaptcha(int width, int height, int codeCount, int thickness) { - return new ShearCaptcha(width, height, codeCount, thickness); - } + /** + * 创建扭曲干扰的验证码,默认5位验证码 + * + * @param width 图片宽 + * @param height 图片高 + * @param codeCount 字符个数 + * @param thickness 干扰线宽度 + * @return {@link ShearCaptcha} + * @since 3.3.0 + */ + public static ShearCaptcha createShearCaptcha(int width, int height, int codeCount, int thickness) { + return new ShearCaptcha(width, height, codeCount, thickness); + } - public static GifCaptcha createGifCaptcha(int width, int height) { - return new GifCaptcha(width, height); - } + /** + * 创建GIF验证码 + * + * @param width 宽 + * @param height 高 + * @return {@link GifCaptcha} + */ + public static GifCaptcha createGifCaptcha(int width, int height) { + return new GifCaptcha(width, height); + } - public static GifCaptcha createGifCaptcha(int width, int height, int delay) { - return new GifCaptcha(width, height, delay); - } + /** + * 创建GIF验证码 + * + * @param width 宽 + * @param height 高 + * @param codeCount 字符个数 + * @return {@link GifCaptcha} + */ + public static GifCaptcha createGifCaptcha(int width, int height, int codeCount) { + return new GifCaptcha(width, height, codeCount); + } } diff --git a/hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java b/hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java index 1112105c9..9c03f6fa6 100644 --- a/hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java +++ b/hutool-captcha/src/main/java/cn/hutool/captcha/GifCaptcha.java @@ -3,219 +3,216 @@ package cn.hutool.captcha; import cn.hutool.core.img.gif.AnimatedGifEncoder; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RandomUtil; -import java.awt.*; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; -import java.util.Random; /** * Gif验证码类 + * + * @author hsoftxl + * @since 5.5.2 */ public class GifCaptcha extends AbstractCaptcha { - private static final long serialVersionUID = 7091627304326538464L; + private static final long serialVersionUID = 7091627304326538464L; - private final Random RANDOM = new Random(); - // 帧延迟 (默认100) - private int delay = 100; - //量化器取样间隔 - 默认是10ms - private int quality = 10; - // 帧循环次数 - private int repeat = 0; - //设置随机颜色时,最小的取色范围 - private int minColor = 0; - //设置随机颜色时,最大的取色范围 - private int maxColor = 255; + //量化器取样间隔 - 默认是10ms + private int quality = 10; + // 帧循环次数 + private int repeat = 0; + //设置随机颜色时,最小的取色范围 + private int minColor = 0; + //设置随机颜色时,最大的取色范围 + private int maxColor = 255; - /** - * 可以设置验证码宽度,高度的构造函数 - * - * @param width -验证码宽度 - * @param height -验证码高度 - */ - public GifCaptcha(int width, int height) { - this(width, height, 100); - } + /** + * 可以设置验证码宽度,高度的构造函数 + * + * @param width 验证码宽度 + * @param height 验证码高度 + */ + public GifCaptcha(int width, int height) { + this(width, height, 100); + } - /** - * @param width -验证码宽度 - * @param height -验证码高度 - * @param codeCount -验证码个数 - */ - public GifCaptcha(int width, int height, int codeCount) { - super(width, height, codeCount, 10); - } + /** + * @param width 验证码宽度 + * @param height 验证码高度 + * @param codeCount 验证码个数 + */ + public GifCaptcha(int width, int height, int codeCount) { + super(width, height, codeCount, 10); + } - /** - * 设置图像的颜色量化(转换质量 由GIF规范允许的最大256种颜色)。 - * 低的值(最小值= 1)产生更好的颜色,但处理显著缓慢。 - * 10是默认,并产生良好的颜色而且有以合理的速度。 - * 值更大(大于20)不产生显著的改善速度 - * - * @param quality 大于1 - */ - public void setQuality(int quality) { - if (quality < 1) { - quality = 1; - } - this.quality = quality; - } + /** + * 设置图像的颜色量化(转换质量 由GIF规范允许的最大256种颜色)。 + * 低的值(最小值= 1)产生更好的颜色,但处理显著缓慢。 + * 10是默认,并产生良好的颜色而且有以合理的速度。 + * 值更大(大于20)不产生显著的改善速度 + * + * @param quality 大于1 + * @return this + */ + public GifCaptcha setQuality(int quality) { + if (quality < 1) { + quality = 1; + } + this.quality = quality; + return this; + } - /** - * 设置GIF帧应该播放的次数。 - * 默认是 0; 0意味着无限循环。 - * 必须在添加的第一个图像之前被调用。 - * - * @param repeat 必须大于等于0 - */ - public void setRepeat(int repeat) { - if (repeat >= 0) { - this.repeat = repeat; - } - } + /** + * 设置GIF帧应该播放的次数。 + * 默认是 0; 0意味着无限循环。 + * 必须在添加的第一个图像之前被调用。 + * + * @param repeat 必须大于等于0 + * @return this + */ + public GifCaptcha setRepeat(int repeat) { + if (repeat >= 0) { + this.repeat = repeat; + } + return this; + } - /** - * 设置验证码字符颜色 - * - * @param maxColor 颜色 - */ - public void setMaxColor(int maxColor) { - this.maxColor = maxColor; - } + /** + * 设置验证码字符颜色 + * + * @param maxColor 颜色 + * @return this + */ + public GifCaptcha setMaxColor(int maxColor) { + this.maxColor = maxColor; + return this; + } - /** - * 设置验证码字符颜色 - * - * @param minColor 颜色 - */ - public void setMinColor(int minColor) { - this.minColor = minColor; - } + /** + * 设置验证码字符颜色 + * + * @param minColor 颜色 + * @return this + */ + public GifCaptcha setMinColor(int minColor) { + this.minColor = minColor; + return this; + } - @Override - public void createCode() { - generateCode(); - final ByteArrayOutputStream out = new ByteArrayOutputStream(); + @Override + public void createCode() { + generateCode(); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); - AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder();// gif编码类 - //生成字符 - gifEncoder.start(out); - gifEncoder.setQuality(quality);//设置量化器取样间隔 - gifEncoder.setDelay(delay);//设置帧延迟 - gifEncoder.setRepeat(repeat);//帧循环次数 - BufferedImage frame; - char[] chars = code.toCharArray(); - Color[] fontColor = new Color[chars.length]; - for (int i = 0; i < chars.length; i++) { - fontColor[i] = getRandomColor(minColor, maxColor); - frame = graphicsImage(chars, fontColor, chars, i); - gifEncoder.addFrame(frame); - frame.flush(); - } - gifEncoder.finish(); - this.imageBytes = out.toByteArray(); - } + AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder();// gif编码类 + //生成字符 + gifEncoder.start(out); + gifEncoder.setQuality(quality);//设置量化器取样间隔 + // 帧延迟 (默认100) + int delay = 100; + gifEncoder.setDelay(delay);//设置帧延迟 + gifEncoder.setRepeat(repeat);//帧循环次数 + BufferedImage frame; + char[] chars = code.toCharArray(); + Color[] fontColor = new Color[chars.length]; + for (int i = 0; i < chars.length; i++) { + fontColor[i] = getRandomColor(minColor, maxColor); + frame = graphicsImage(chars, fontColor, chars, i); + gifEncoder.addFrame(frame); + frame.flush(); + } + gifEncoder.finish(); + this.imageBytes = out.toByteArray(); + } - @Override - protected Image createImage(String code) { - return null; - } + @Override + protected Image createImage(String code) { + return null; + } - /** - * 画随机码图 - * - * @param fontColor 随机字体颜色 - * @param words 字符数组 - * @param flag 透明度使用 - * @return BufferedImage - */ - private BufferedImage graphicsImage(char[] chars, Color[] fontColor, char[] words, int flag) { - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - //或得图形上下文 - Graphics2D g2d = image.createGraphics(); - //利用指定颜色填充背景 - g2d.setColor(ObjectUtil.defaultIfNull(this.background, Color.WHITE)); - g2d.fillRect(0, 0, width, height); - AlphaComposite ac; - // 字符的y坐标 - float y = (height >> 1) + (font.getSize() >> 1); - float m = 1.0f * (width - (chars.length * font.getSize())) / chars.length; - //字符的x坐标 - float x = Math.max(m / 2.0f, 2); - g2d.setFont(font); - // 指定透明度 - if (null != this.textAlpha) { - g2d.setComposite(this.textAlpha); - } - for (int i = 0; i < chars.length; i++) { - ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getPellucidity(chars.length, flag, i)); - g2d.setComposite(ac); - g2d.setColor(fontColor[i]); - g2d.drawOval(num(width), num(height), num(5, 30), 5 + num(5, 30));//绘制椭圆边框 - g2d.drawString(words[i] + "", x + (font.getSize() + m) * i, y); - } - g2d.dispose(); - return image; - } + /** + * 画随机码图 + * + * @param fontColor 随机字体颜色 + * @param words 字符数组 + * @param flag 透明度使用 + * @return BufferedImage + */ + private BufferedImage graphicsImage(char[] chars, Color[] fontColor, char[] words, int flag) { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + //或得图形上下文 + Graphics2D g2d = image.createGraphics(); + //利用指定颜色填充背景 + g2d.setColor(ObjectUtil.defaultIfNull(this.background, Color.WHITE)); + g2d.fillRect(0, 0, width, height); + AlphaComposite ac; + // 字符的y坐标 + float y = (height >> 1) + (font.getSize() >> 1); + float m = 1.0f * (width - (chars.length * font.getSize())) / chars.length; + //字符的x坐标 + float x = Math.max(m / 2.0f, 2); + g2d.setFont(font); + // 指定透明度 + if (null != this.textAlpha) { + g2d.setComposite(this.textAlpha); + } + for (int i = 0; i < chars.length; i++) { + ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(chars.length, flag, i)); + g2d.setComposite(ac); + g2d.setColor(fontColor[i]); + g2d.drawOval( + RandomUtil.randomInt(width), + RandomUtil.randomInt(height), + RandomUtil.randomInt(5, 30), 5 + RandomUtil.randomInt(5, 30) + );//绘制椭圆边框 + g2d.drawString(words[i] + "", x + (font.getSize() + m) * i, y); + } + g2d.dispose(); + return image; + } - /** - * 获取透明度,从0到1,自动计算步长 - * - * @return float 透明度 - */ - private float getPellucidity(int v, int i, int j) { - int num = i + j; - float r = (float) 1 / v; - float s = (v + 1) * r; - return num > v ? (num * r - s) : num * r; - } - - /** - * 通过给定范围获得随机的颜色 - * - * @return Color 获得随机的颜色 - */ - private Color getRandomColor(int min, int max) { - if (min > 255) { - min = 255; - } - if (max > 255) { - max = 255; - } - if (min < 0) { - min = 0; - } - if (max < 0) { - max = 0; - } - if (min > max) { - min = 0; - max = 255; - } - return new Color(min + num(max - min), min + num(max - min), min + num(max - min)); - } - - - /** - * 产生两个数之间的随机数 - * - * @param min 小数 - * @param max 比min大的数 - * @return int 随机数字 - */ - private int num(int min, int max) { - return min + RANDOM.nextInt(max - min); - } - - /** - * 产生0--num的随机数,不包括num - * - * @param num 数字 - * @return int 随机数字 - */ - private int num(int num) { - return RANDOM.nextInt(num); - } + /** + * 获取透明度,从0到1,自动计算步长 + * + * @return float 透明度 + */ + private float getAlpha(int v, int i, int j) { + int num = i + j; + float r = (float) 1 / v; + float s = (v + 1) * r; + return num > v ? (num * r - s) : num * r; + } + /** + * 通过给定范围获得随机的颜色 + * + * @return Color 获得随机的颜色 + */ + private Color getRandomColor(int min, int max) { + if (min > 255) { + min = 255; + } + if (max > 255) { + max = 255; + } + if (min < 0) { + min = 0; + } + if (max < 0) { + max = 0; + } + if (min > max) { + min = 0; + max = 255; + } + return new Color( + RandomUtil.randomInt(min, max), + RandomUtil.randomInt(min, max), + RandomUtil.randomInt(min, max)); + } } diff --git a/hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java b/hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java index d6708e66a..95f5a7260 100644 --- a/hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java +++ b/hutool-captcha/src/test/java/cn/hutool/captcha/CaptchaTest.java @@ -15,97 +15,97 @@ import java.awt.*; */ public class CaptchaTest { - @Test - public void lineCaptchaTest1() { - // 定义图形验证码的长和宽 - LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100); - Assert.assertNotNull(lineCaptcha.getCode()); - Assert.assertTrue(lineCaptcha.verify(lineCaptcha.getCode())); - } + @Test + public void lineCaptchaTest1() { + // 定义图形验证码的长和宽 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100); + Assert.assertNotNull(lineCaptcha.getCode()); + Assert.assertTrue(lineCaptcha.verify(lineCaptcha.getCode())); + } - @Test - @Ignore - public void lineCaptchaTest3() { - // 定义图形验证码的长和宽 - LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 70, 4, 15); - lineCaptcha.setBackground(Color.yellow); - lineCaptcha.write("f:/test/captcha/tellow.png"); - } + @Test + @Ignore + public void lineCaptchaTest3() { + // 定义图形验证码的长和宽 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 70, 4, 15); + lineCaptcha.setBackground(Color.yellow); + lineCaptcha.write("f:/test/captcha/tellow.png"); + } - @Test - @Ignore - public void lineCaptchaWithMathTest() { - // 定义图形验证码的长和宽 - LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 80); - lineCaptcha.setGenerator(new MathGenerator()); - lineCaptcha.setTextAlpha(0.8f); - lineCaptcha.write("f:/captcha/math.png"); - } + @Test + @Ignore + public void lineCaptchaWithMathTest() { + // 定义图形验证码的长和宽 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 80); + lineCaptcha.setGenerator(new MathGenerator()); + lineCaptcha.setTextAlpha(0.8f); + lineCaptcha.write("f:/captcha/math.png"); + } - @Test - @Ignore - public void lineCaptchaTest2() { + @Test + @Ignore + public void lineCaptchaTest2() { - // 定义图形验证码的长和宽 - LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100); - // LineCaptcha lineCaptcha = new LineCaptcha(200, 100, 4, 150); - // 图形验证码写出,可以写出到文件,也可以写出到流 - lineCaptcha.write("f:/captcha/line.png"); - Console.log(lineCaptcha.getCode()); - // 验证图形验证码的有效性,返回boolean值 - lineCaptcha.verify("1234"); + // 定义图形验证码的长和宽 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100); + // LineCaptcha lineCaptcha = new LineCaptcha(200, 100, 4, 150); + // 图形验证码写出,可以写出到文件,也可以写出到流 + lineCaptcha.write("f:/captcha/line.png"); + Console.log(lineCaptcha.getCode()); + // 验证图形验证码的有效性,返回boolean值 + lineCaptcha.verify("1234"); - lineCaptcha.createCode(); - lineCaptcha.write("f:/captcha/line2.png"); - Console.log(lineCaptcha.getCode()); - // 验证图形验证码的有效性,返回boolean值 - lineCaptcha.verify("1234"); - } + lineCaptcha.createCode(); + lineCaptcha.write("f:/captcha/line2.png"); + Console.log(lineCaptcha.getCode()); + // 验证图形验证码的有效性,返回boolean值 + lineCaptcha.verify("1234"); + } - @Test - @Ignore - public void circleCaptchaTest() { + @Test + @Ignore + public void circleCaptchaTest() { - // 定义图形验证码的长和宽 - CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20); - // CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20); - // 图形验证码写出,可以写出到文件,也可以写出到流 - captcha.write("f:/captcha/circle.png"); - // 验证图形验证码的有效性,返回boolean值 - captcha.verify("1234"); - } + // 定义图形验证码的长和宽 + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 20); + // CircleCaptcha captcha = new CircleCaptcha(200, 100, 4, 20); + // 图形验证码写出,可以写出到文件,也可以写出到流 + captcha.write("f:/captcha/circle.png"); + // 验证图形验证码的有效性,返回boolean值 + captcha.verify("1234"); + } - @Test - @Ignore - public void ShearCaptchaTest() { + @Test + @Ignore + public void ShearCaptchaTest() { - // 定义图形验证码的长和宽 - ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(203, 100, 4, 4); - // ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4); - // 图形验证码写出,可以写出到文件,也可以写出到流 - captcha.write("f:/captcha/shear.png"); - // 验证图形验证码的有效性,返回boolean值 - captcha.verify("1234"); - } + // 定义图形验证码的长和宽 + ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(203, 100, 4, 4); + // ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4); + // 图形验证码写出,可以写出到文件,也可以写出到流 + captcha.write("f:/captcha/shear.png"); + // 验证图形验证码的有效性,返回boolean值 + captcha.verify("1234"); + } - @Test - @Ignore - public void ShearCaptchaWithMathTest() { - // 定义图形验证码的长和宽 - ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 4); - captcha.setGenerator(new MathGenerator()); - // ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4); - // 图形验证码写出,可以写出到文件,也可以写出到流 - captcha.write("f:/captcha/shear_math.png"); - // 验证图形验证码的有效性,返回boolean值 - captcha.verify("1234"); - } + @Test + @Ignore + public void ShearCaptchaWithMathTest() { + // 定义图形验证码的长和宽 + ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(200, 45, 4, 4); + captcha.setGenerator(new MathGenerator()); + // ShearCaptcha captcha = new ShearCaptcha(200, 100, 4, 4); + // 图形验证码写出,可以写出到文件,也可以写出到流 + captcha.write("f:/captcha/shear_math.png"); + // 验证图形验证码的有效性,返回boolean值 + captcha.verify("1234"); + } - @Test - @Ignore - public void GifCaptchaTest() { - GifCaptcha captcha = CaptchaUtil.createGifCaptcha(200, 100, 4); - captcha.write("f:/gif_captcha.gif"); - assert captcha.verify(captcha.getCode()); - } + @Test + @Ignore + public void GifCaptchaTest() { + GifCaptcha captcha = CaptchaUtil.createGifCaptcha(200, 100, 4); + captcha.write("d:/test/gif_captcha.gif"); + assert captcha.verify(captcha.getCode()); + } }