diff --git a/pom.xml b/pom.xml index 1e40aad..4206d22 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.whvcse EasyCaptcha - 1.4.0-RELEASE + 1.5.0-RELEASE jar EasyCaptcha diff --git a/src/main/java/com/wf/captcha/Captcha.java b/src/main/java/com/wf/captcha/Captcha.java index 9b1089a..2fbb633 100644 --- a/src/main/java/com/wf/captcha/Captcha.java +++ b/src/main/java/com/wf/captcha/Captcha.java @@ -1,7 +1,6 @@ package com.wf.captcha; -import java.awt.Color; -import java.awt.Font; +import java.awt.*; import java.io.OutputStream; /** @@ -9,8 +8,8 @@ import java.io.OutputStream; * Created by 王帆 on 2018-07-27 上午 10:08. */ public abstract class Captcha extends Randoms { - protected Font font = new Font("Arial", Font.PLAIN, 32); // 字体Verdana - protected int len = 5; // 验证码随机字符长度 + protected Font font = new Font("Arial", Font.BOLD, 32); // 字体Verdana + protected int len = 4; // 验证码随机字符长度 protected int width = 130; // 验证码显示宽度 protected int height = 48; // 验证码显示高度 protected String chars = null; // 当前验证码 @@ -18,6 +17,9 @@ public abstract class Captcha extends Randoms { public static final int TYPE_DEFAULT = 1; // 字母数字混合 public static final int TYPE_ONLY_NUMBER = 2; // 纯数字 public static final int TYPE_ONLY_CHAR = 3; // 纯字母 + public static final int TYPE_ONLY_UPPER = 4; // 纯大写字母 + public static final int TYPE_ONLY_LOWER = 5; // 纯小写字母 + public static final int TYPE_NUM_AND_UPPER = 6; // 数字大写字母 // 常用颜色 public static final int[][] COLOR = {{0, 135, 255}, {51, 153, 51}, {255, 102, 102}, {255, 153, 0}, {153, 102, 0}, {153, 102, 153}, {51, 153, 153}, {102, 102, 255}, {0, 102, 204}, {204, 51, 51}, {0, 153, 204}, {0, 51, 102}}; @@ -36,6 +38,15 @@ public abstract class Captcha extends Randoms { case 3: cs[i] = alpha(charMinIndex, charMaxIndex); break; + case 4: + cs[i] = alpha(upperMinIndex, upperMaxIndex); + break; + case 5: + cs[i] = alpha(lowerMinIndex, lowerMaxIndex); + break; + case 6: + cs[i] = alpha(upperMaxIndex); + break; default: cs[i] = alpha(); } @@ -109,6 +120,61 @@ public abstract class Captcha extends Randoms { } } + /** + * 随机画干扰线 + * + * @param num 数量 + * @param g Graphics2D + */ + public void drawLine(int num, Graphics2D g) { + drawLine(num, null, g); + } + + /** + * 随机画干扰线 + * + * @param num 数量 + * @param color 颜色 + * @param g Graphics2D + */ + public void drawLine(int num, Color color, Graphics2D g) { + for (int i = 0; i < num; i++) { + g.setColor(color == null ? color(150, 250) : color); + int x1 = num(-10, width - 10); + int y1 = num(5, height - 5); + int x2 = num(10, width + 10); + int y2 = num(2, height - 2); + g.drawLine(x1, y1, x2, y2); + } + } + + /** + * 随机画干扰圆 + * + * @param num 数量 + * @param g Graphics2D + */ + public void drawOval(int num, Graphics2D g) { + for (int i = 0; i < num; i++) { + g.setColor(color(100, 250)); + g.drawOval(num(width), num(height), 10 + num(20), 10 + num(20)); + } + } + + /** + * 随机画干扰圆 + * + * @param num 数量 + * @param color 颜色 + * @param g Graphics2D + */ + public void drawOval(int num, Color color, Graphics2D g) { + for (int i = 0; i < num; i++) { + g.setColor(color == null ? color(100, 250) : color); + g.drawOval(num(width), num(height), 10 + num(20), 10 + num(20)); + } + } + public Font getFont() { return font; } diff --git a/src/main/java/com/wf/captcha/ChineseCaptcha.java b/src/main/java/com/wf/captcha/ChineseCaptcha.java index 6af6d84..6d524a3 100644 --- a/src/main/java/com/wf/captcha/ChineseCaptcha.java +++ b/src/main/java/com/wf/captcha/ChineseCaptcha.java @@ -58,7 +58,6 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract { g.fillRect(0, 0, width, height); // 抗锯齿 g.setColor(color()); - g.setFont(font); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int hp = (height - font.getSize()) >> 1; int h = height - hp; @@ -69,8 +68,8 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract { // 计算坐标 int x = i * w + sp + num(-5, 5); int y = h + num(-5, 5); - if (x < 0) { - x = 0; + if (x < 5) { + x = 5; } if (x + font.getSize() > width) { x = width - font.getSize(); @@ -81,21 +80,16 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract { if (y - font.getSize() < 0) { y = font.getSize(); } + g.setFont(font.deriveFont(num(2) == 0 ? Font.PLAIN : Font.ITALIC)); g.drawString(String.valueOf(strs[i]), x, y); } // 随机画干扰线 g.setStroke(new BasicStroke(1.25f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - for (int i = 0; i < 6; i++) { - ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f); // 指定透明度 - g.setComposite(ac3); - int x1 = num(-10, width - 10); - int y1 = num(5, height - 5); - int x2 = num(10, width + 10); - int y2 = num(2, height - 2); - g.drawLine(x1, y1, x2, y2); - // 画干扰圆圈 - g.drawOval(num(width), num(height), 5 + num(25), 5 + num(25)); - } + ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); // 指定透明度 + g.setComposite(ac3); + drawLine(2, g.getColor(), g); + // 画干扰圆圈 + drawOval(5, g.getColor(), g); ImageIO.write(bi, "png", out); out.flush(); ok = true; diff --git a/src/main/java/com/wf/captcha/ChineseCaptchaAbstract.java b/src/main/java/com/wf/captcha/ChineseCaptchaAbstract.java index e64e0ff..edc0e2d 100644 --- a/src/main/java/com/wf/captcha/ChineseCaptchaAbstract.java +++ b/src/main/java/com/wf/captcha/ChineseCaptchaAbstract.java @@ -35,4 +35,16 @@ public abstract class ChineseCaptchaAbstract extends Captcha { return DELTA.charAt(num(DELTA.length())); } + + @Override + public void drawLine(int num, Color color, Graphics2D g) { + for (int i = 0; i < num; i++) { + g.setColor(color == null ? color(150, 250) : color); + int x1 = num(-10, width / 3); + int y1 = num(5, height - 5); + int x2 = num(width / 3 * 2, width + 10); + int y2 = num(2, height - 2); + g.drawLine(x1, y1, x2, y2); + } + } } diff --git a/src/main/java/com/wf/captcha/ChineseGifCaptcha.java b/src/main/java/com/wf/captcha/ChineseGifCaptcha.java index 38c44af..dc6e12c 100644 --- a/src/main/java/com/wf/captcha/ChineseGifCaptcha.java +++ b/src/main/java/com/wf/captcha/ChineseGifCaptcha.java @@ -28,7 +28,7 @@ public class ChineseGifCaptcha extends ChineseCaptchaAbstract { @Override public boolean out(OutputStream os) { checkAlpha(); - boolean ok = false; + boolean ok; try { char[] rands = textChar(); // 获取验证码数组 GifEncoder gifEncoder = new GifEncoder(); @@ -71,7 +71,6 @@ public class ChineseGifCaptcha extends ChineseCaptchaAbstract { // 抗锯齿 AlphaComposite ac3; g2d.setColor(fontcolor); - g2d.setFont(font); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 画验证码 int hp = (height - font.getSize()) >> 1; @@ -96,23 +95,16 @@ public class ChineseGifCaptcha extends ChineseCaptchaAbstract { if (y - font.getSize() < 0) { y = font.getSize(); } + g2d.setFont(font.deriveFont(num(2) == 0 ? Font.PLAIN : Font.ITALIC)); g2d.drawString(String.valueOf(strs[i]), x, y); } // 随机画干扰线 g2d.setStroke(new BasicStroke(1.25f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.45f); g2d.setComposite(ac3); - for (int i = 0; i < 4; i++) { - int x1 = num(-10, width - 10); - int y1 = num(5, height - 5); - int x2 = num(10, width + 10); - int y2 = num(2, height - 2); - g2d.drawLine(x1, y1, x2, y2); - } + drawLine(1, g2d.getColor(), g2d); // 画干扰圆圈 - for (int i = 0; i < 8; i++) { - g2d.drawOval(num(width), num(height), 5 + num(50), 5 + num(50)); - } + drawOval(3, g2d.getColor(), g2d); g2d.dispose(); return image; } diff --git a/src/main/java/com/wf/captcha/GifCaptcha.java b/src/main/java/com/wf/captcha/GifCaptcha.java index a88adf6..e4f870d 100644 --- a/src/main/java/com/wf/captcha/GifCaptcha.java +++ b/src/main/java/com/wf/captcha/GifCaptcha.java @@ -32,7 +32,7 @@ public class GifCaptcha extends Captcha { @Override public boolean out(OutputStream os) { checkAlpha(); - boolean ok = false; + boolean ok; try { char[] rands = textChar(); // 获取验证码数组 GifEncoder gifEncoder = new GifEncoder(); @@ -77,35 +77,27 @@ public class GifCaptcha extends Captcha { g2d.setColor(Color.WHITE); g2d.fillRect(0, 0, width, height); // 抗锯齿 - g2d.setFont(font); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); + // 画干扰圆圈 + drawOval(4, g2d); // 随机画干扰线 - for (int i = 0; i < num(5, 12); i++) { - g2d.setStroke(new BasicStroke(1.1f + RANDOM.nextFloat() / 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - g2d.setColor(color(150, 250)); - int x1 = num(-10, width - 10); - int y1 = num(5, height - 5); - int x2 = num(10, width + 10); - int y2 = num(2, height - 2); - g2d.drawLine(x1, y1, x2, y2); - // 画干扰圆圈 - g2d.setColor(color(100, 250)); - g2d.drawOval(num(width), num(height), 5 + num(25), 5 + num(25)); - } + drawLine(2, g2d); // 画验证码 int hp = (height - font.getSize()) >> 1; int h = height - hp; int w = width / strs.length; - //int sp = (w - font.getSize()) / 2; + int sp = (w - font.getSize()) / 2; for (int i = 0; i < strs.length; i++) { AlphaComposite ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(flag, i)); g2d.setComposite(ac3); g2d.setColor(fontcolor[i]); // 计算坐标 - int x = i * w + num(6); - int y = h - num(2, 8); - if (x < 0) { - x = 0; + int x = i * w + sp + num(3); + int y = h - num(3, 6); + // 调整溢出的字 + if (x < 8) { + x = 8; } if (x + font.getSize() > width) { x = width - font.getSize(); @@ -116,6 +108,7 @@ public class GifCaptcha extends Captcha { if (y - font.getSize() < 0) { y = font.getSize(); } + g2d.setFont(font.deriveFont(num(2) == 0 ? Font.PLAIN : Font.ITALIC)); g2d.drawString(String.valueOf(strs[i]), x, y); } g2d.dispose(); diff --git a/src/main/java/com/wf/captcha/Randoms.java b/src/main/java/com/wf/captcha/Randoms.java index 06a62c4..1771a48 100644 --- a/src/main/java/com/wf/captcha/Randoms.java +++ b/src/main/java/com/wf/captcha/Randoms.java @@ -15,6 +15,10 @@ public class Randoms { protected static final int numMaxIndex = 8; // 数字的最大索引,不包括最大值 protected static final int charMinIndex = numMaxIndex; // 字符的最小索引,包括最小值 protected static final int charMaxIndex = ALPHA.length; // 字符的最大索引,不包括最大值 + protected static final int upperMinIndex = charMinIndex; // 大写字符最小索引 + protected static final int upperMaxIndex = upperMinIndex + 23; // 大写字符最大索引 + protected static final int lowerMinIndex = upperMaxIndex; // 小写字母最小索引 + protected static final int lowerMaxIndex = charMaxIndex; // 小写字母最大索引 /** * 产生两个数之间的随机数 diff --git a/src/main/java/com/wf/captcha/SpecCaptcha.java b/src/main/java/com/wf/captcha/SpecCaptcha.java index 92d98b1..9a78684 100644 --- a/src/main/java/com/wf/captcha/SpecCaptcha.java +++ b/src/main/java/com/wf/captcha/SpecCaptcha.java @@ -14,7 +14,6 @@ import javax.imageio.ImageIO; public class SpecCaptcha extends Captcha { public SpecCaptcha() { - setFont(new Font(font.getFontName(), Font.ITALIC, font.getSize())); } public SpecCaptcha(int width, int height) { @@ -60,35 +59,26 @@ public class SpecCaptcha extends Captcha { g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); // 抗锯齿 - g.setFont(font); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setStroke(new BasicStroke(1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); // 随机画干扰线 - for (int i = 0; i < 12; i++) { - g.setColor(color(150, 250)); - g.setStroke(new BasicStroke(1.1f + RANDOM.nextFloat() / 2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - int x1 = num(-10, width - 10); - int y1 = num(5, height - 5); - int x2 = num(10, width + 10); - int y2 = num(2, height - 2); - g.drawLine(x1, y1, x2, y2); - // 画干扰圆圈 - g.setColor(color(100, 250)); - g.drawOval(num(width), num(height), 5 + num(25), 5 + num(25)); - } + drawLine(3, g); + // 随机画干扰圆 + drawOval(8, g); // 画字符串 - AlphaComposite ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f);// 指定透明度 + AlphaComposite ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);// 指定透明度 g.setComposite(ac3); int hp = (height - font.getSize()) >> 1; int h = height - hp; int w = width / strs.length; - //int sp = (w - font.getSize()) / 2; + int sp = (w - font.getSize()) / 2; for (int i = 0; i < strs.length; i++) { g.setColor(new Color(20 + num(110), 20 + num(110), 20 + num(110))); // 计算坐标 - int x = i * w + num(10); - int y = h - num(9); - if (x < 0) { - x = 0; + int x = i * w + sp + num(3); + int y = h - num(3, 6); + if (x < 8) { + x = 8; } if (x + font.getSize() > width) { x = width - font.getSize(); @@ -99,6 +89,7 @@ public class SpecCaptcha extends Captcha { if (y - font.getSize() < 0) { y = font.getSize(); } + g.setFont(font.deriveFont(num(2) == 0 ? Font.PLAIN : Font.ITALIC)); g.drawString(String.valueOf(strs[i]), x, y); } ImageIO.write(bi, "png", out); diff --git a/src/test/java/com/wf/captcha/CaptchaTest.java b/src/test/java/com/wf/captcha/CaptchaTest.java index e75818d..3900b1f 100644 --- a/src/test/java/com/wf/captcha/CaptchaTest.java +++ b/src/test/java/com/wf/captcha/CaptchaTest.java @@ -13,37 +13,39 @@ public class CaptchaTest { @Test public void test() throws Exception { - for (int i = 0; i < 5; i++) { + /*for (int i = 0; i < 5; i++) { SpecCaptcha specCaptcha = new SpecCaptcha(); - //specCaptcha.setCharType(Captcha.TYPE_ONLY_NUMBER); + specCaptcha.setCharType(Captcha.TYPE_ONLY_UPPER); System.out.println(specCaptcha.text()); - //specCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".png"))); - } + specCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".png"))); + }*/ } @Test public void testGIf() throws Exception { - for (int i = 0; i < 5; i++) { + /*for (int i = 0; i < 5; i++) { GifCaptcha gifCaptcha = new GifCaptcha(); System.out.println(gifCaptcha.text()); - //gifCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".gif"))); - } + gifCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".gif"))); + }*/ } @Test public void testHan() throws Exception { - // ChineseCaptcha chineseCaptcha = new ChineseCaptcha(); - //chineseCaptcha.setFont(new Font("微软雅黑", Font.PLAIN, 25)); - // System.out.println(chineseCaptcha.text()); - //chineseCaptcha.out(new FileOutputStream(new File("D:/Java/aa.png"))); + /*for (int i = 0; i < 5; i++) { + ChineseCaptcha chineseCaptcha = new ChineseCaptcha(); + System.out.println(chineseCaptcha.text()); + chineseCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".png"))); + }*/ } @Test public void testGifHan() throws Exception { - // ChineseGifCaptcha chineseGifCaptcha = new ChineseGifCaptcha(); - //chineseGifCaptcha.setFont(new Font("微软雅黑", Font.PLAIN, 30)); - // System.out.println(chineseGifCaptcha.text()); - //chineseGifCaptcha.out(new FileOutputStream(new File("D:/Java/aa.gif"))); + /*for (int i = 0; i < 5; i++) { + ChineseGifCaptcha chineseGifCaptcha = new ChineseGifCaptcha(); + System.out.println(chineseGifCaptcha.text()); + chineseGifCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".gif"))); + }*/ } }