增加内置字体、贝塞尔曲线、算术验证码、base64输出
This commit is contained in:
96
src/main/java/com/wf/captcha/ArithmeticCaptcha.java
Normal file
96
src/main/java/com/wf/captcha/ArithmeticCaptcha.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.wf.captcha;
|
||||
|
||||
import com.wf.captcha.base.ArithmeticCaptchaAbstract;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* png格式验证码
|
||||
* Created by 王帆 on 2018-07-27 上午 10:08.
|
||||
*/
|
||||
public class ArithmeticCaptcha extends ArithmeticCaptchaAbstract {
|
||||
|
||||
public ArithmeticCaptcha() {
|
||||
}
|
||||
|
||||
public ArithmeticCaptcha(int width, int height) {
|
||||
this();
|
||||
setWidth(width);
|
||||
setHeight(height);
|
||||
}
|
||||
|
||||
public ArithmeticCaptcha(int width, int height, int len) {
|
||||
this(width, height);
|
||||
setLen(len);
|
||||
}
|
||||
|
||||
public ArithmeticCaptcha(int width, int height, int len, Font font) {
|
||||
this(width, height, len);
|
||||
setFont(font);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*
|
||||
* @param out 输出流
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean out(OutputStream out) {
|
||||
checkAlpha();
|
||||
return graphicsImage(getArithmeticString().toCharArray(), out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBase64() {
|
||||
return toBase64("data:image/png;base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图形
|
||||
*
|
||||
* @param strs 验证码
|
||||
* @param out 输出流
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean graphicsImage(char[] strs, OutputStream out) {
|
||||
try {
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = (Graphics2D) bi.getGraphics();
|
||||
// 填充背景
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 画干扰圆
|
||||
drawOval(2, g2d);
|
||||
// 画字符串
|
||||
g2d.setFont(getFont());
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
int fW = width / strs.length; // 每一个字符所占的宽度
|
||||
int fSp = (fW - (int) fontMetrics.getStringBounds("8", g2d).getWidth()) / 2; // 字符的左右边距
|
||||
for (int i = 0; i < strs.length; i++) {
|
||||
g2d.setColor(color());
|
||||
int fY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight()) >> 1); // 文字的纵坐标
|
||||
g2d.drawString(String.valueOf(strs[i]), i * fW + fSp + 3, fY - 3);
|
||||
}
|
||||
g2d.dispose();
|
||||
ImageIO.write(bi, "png", out);
|
||||
out.flush();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -38,10 +38,14 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract {
|
||||
*/
|
||||
@Override
|
||||
public boolean out(OutputStream out) {
|
||||
checkAlpha();
|
||||
return graphicsImage(textChar(), out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBase64() {
|
||||
return toBase64("data:image/png;base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图形
|
||||
*
|
||||
@@ -50,54 +54,34 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract {
|
||||
* @return boolean
|
||||
*/
|
||||
private boolean graphicsImage(char[] strs, OutputStream out) {
|
||||
boolean ok;
|
||||
try {
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = (Graphics2D) bi.getGraphics();
|
||||
AlphaComposite ac3;
|
||||
int len = strs.length;
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(0, 0, width, height);
|
||||
Graphics2D g2d = (Graphics2D) bi.getGraphics();
|
||||
// 填充背景
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
g.setColor(color());
|
||||
Font font = getFont();
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
int hp = (height - font.getSize()) >> 1;
|
||||
int h = height - hp;
|
||||
int w = width / strs.length;
|
||||
int sp = (w - font.getSize()) / 2;
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 画干扰圆
|
||||
drawOval(3, g2d);
|
||||
// 画干扰线
|
||||
g2d.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
drawBesselLine(1, g2d);
|
||||
// 画字符串
|
||||
for (int i = 0; i < len; i++) {
|
||||
// 计算坐标
|
||||
int x = i * w + sp + num(-5, 5);
|
||||
int y = h + num(-5, 5);
|
||||
if (x < 5) {
|
||||
x = 5;
|
||||
}
|
||||
if (x + font.getSize() > width) {
|
||||
x = width - font.getSize();
|
||||
}
|
||||
if (y > height) {
|
||||
y = height;
|
||||
}
|
||||
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);
|
||||
g2d.setFont(getFont());
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
int fW = width / strs.length; // 每一个字符所占的宽度
|
||||
int fSp = (fW - (int) fontMetrics.getStringBounds("王", g2d).getWidth()) / 2; // 字符的左右边距
|
||||
for (int i = 0; i < strs.length; i++) {
|
||||
g2d.setColor(color());
|
||||
int fY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight()) >> 1); // 文字的纵坐标
|
||||
g2d.drawString(String.valueOf(strs[i]), i * fW + fSp + 3, fY - 3);
|
||||
}
|
||||
// 随机画干扰线
|
||||
g.setStroke(new BasicStroke(1.25f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f); // 指定透明度
|
||||
g.setComposite(ac3);
|
||||
drawLine(2, g.getColor(), g);
|
||||
// 画干扰圆圈
|
||||
drawOval(5, g.getColor(), g);
|
||||
g2d.dispose();
|
||||
ImageIO.write(bi, "png", out);
|
||||
out.flush();
|
||||
ok = true;
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
ok = false;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
@@ -106,6 +90,6 @@ public class ChineseCaptcha extends ChineseCaptchaAbstract {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import com.wf.captcha.base.ChineseCaptchaAbstract;
|
||||
import com.wf.captcha.utils.GifEncoder;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -30,24 +31,39 @@ public class ChineseGifCaptcha extends ChineseCaptchaAbstract {
|
||||
|
||||
@Override
|
||||
public boolean out(OutputStream os) {
|
||||
checkAlpha();
|
||||
boolean ok;
|
||||
try {
|
||||
char[] rands = textChar(); // 获取验证码数组
|
||||
char[] strs = textChar(); // 获取验证码数组
|
||||
// 随机生成每个文字的颜色
|
||||
Color fontColor[] = new Color[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
fontColor[i] = color();
|
||||
}
|
||||
// 随机生成贝塞尔曲线参数
|
||||
int x1 = 5, y1 = num(5, height / 2);
|
||||
int x2 = width - 5, y2 = num(height / 2, height - 5);
|
||||
int ctrlx = num(width / 4, width / 4 * 3), ctrly = num(5, height - 5);
|
||||
if (num(2) == 0) {
|
||||
int ty = y1;
|
||||
y1 = y2;
|
||||
y2 = ty;
|
||||
}
|
||||
int ctrlx1 = num(width / 4, width / 4 * 3), ctrly1 = num(5, height - 5);
|
||||
int[][] besselXY = new int[][]{{x1, y1}, {ctrlx, ctrly}, {ctrlx1, ctrly1}, {x2, y2}};
|
||||
// 开始画gif每一帧
|
||||
GifEncoder gifEncoder = new GifEncoder();
|
||||
gifEncoder.start(os);
|
||||
gifEncoder.setQuality(180);
|
||||
gifEncoder.setDelay(100);
|
||||
gifEncoder.setRepeat(0);
|
||||
BufferedImage frame;
|
||||
Color fontcolor = color();
|
||||
gifEncoder.start(os);
|
||||
for (int i = 0; i < len; i++) {
|
||||
frame = graphicsImage(fontcolor, rands, i);
|
||||
BufferedImage frame = graphicsImage(fontColor, strs, i, besselXY);
|
||||
gifEncoder.addFrame(frame);
|
||||
frame.flush();
|
||||
}
|
||||
gifEncoder.finish();
|
||||
ok = true;
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
@@ -55,60 +71,53 @@ public class ChineseGifCaptcha extends ChineseCaptchaAbstract {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBase64() {
|
||||
return toBase64("data:image/gif;base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
* 画随机码图
|
||||
*
|
||||
* @param fontcolor 随机字体颜色
|
||||
* @param fontColor 随机字体颜色
|
||||
* @param strs 字符数组
|
||||
* @param flag 透明度使用
|
||||
* @param flag 透明度
|
||||
* @param besselXY 干扰线参数
|
||||
* @return BufferedImage
|
||||
*/
|
||||
private BufferedImage graphicsImage(Color fontcolor, char[] strs, int flag) {
|
||||
private BufferedImage graphicsImage(Color[] fontColor, char[] strs, int flag, int[][] besselXY) {
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = (Graphics2D) image.getGraphics();
|
||||
g2d.setColor(Color.WHITE); // 填充背景颜色
|
||||
// 填充背景颜色
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
AlphaComposite ac3;
|
||||
g2d.setColor(fontcolor);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 画验证码
|
||||
Font font = getFont();
|
||||
int hp = (height - font.getSize()) >> 1;
|
||||
int h = height - hp;
|
||||
int w = width / strs.length;
|
||||
int sp = (w - font.getSize()) / 2;
|
||||
for (int i = 0; i < len; i++) {
|
||||
ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(flag, i));
|
||||
g2d.setComposite(ac3);
|
||||
// 计算坐标
|
||||
int x = i * w + sp + num(-3, 3);
|
||||
int y = h + num(-3, 3);
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (x + font.getSize() > width) {
|
||||
x = width - font.getSize();
|
||||
}
|
||||
if (y > height) {
|
||||
y = height;
|
||||
}
|
||||
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);
|
||||
drawLine(1, g2d.getColor(), g2d);
|
||||
// 画干扰圆圈
|
||||
drawOval(3, g2d.getColor(), g2d);
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f * num(10))); // 设置透明度
|
||||
drawOval(2, g2d);
|
||||
// 画干扰线
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); // 设置透明度
|
||||
g2d.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
g2d.setColor(fontColor[0]);
|
||||
CubicCurve2D shape = new CubicCurve2D.Double(besselXY[0][0], besselXY[0][1], besselXY[1][0], besselXY[1][1], besselXY[2][0], besselXY[2][1], besselXY[3][0], besselXY[3][1]);
|
||||
g2d.draw(shape);
|
||||
// 画验证码
|
||||
g2d.setFont(getFont());
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
int fW = width / strs.length; // 每一个字符所占的宽度
|
||||
int fSp = (fW - (int) fontMetrics.getStringBounds("W", g2d).getWidth()) / 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 fY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight()) >> 1); // 文字的纵坐标
|
||||
g2d.drawString(String.valueOf(strs[i]), i * fW + fSp - 3, fY - 3);
|
||||
}
|
||||
g2d.dispose();
|
||||
return image;
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ import com.wf.captcha.base.Captcha;
|
||||
import com.wf.captcha.utils.GifEncoder;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -34,27 +37,39 @@ public class GifCaptcha extends Captcha {
|
||||
|
||||
@Override
|
||||
public boolean out(OutputStream os) {
|
||||
checkAlpha();
|
||||
boolean ok;
|
||||
try {
|
||||
char[] rands = textChar(); // 获取验证码数组
|
||||
char[] strs = textChar(); // 获取验证码数组
|
||||
// 随机生成每个文字的颜色
|
||||
Color fontColor[] = new Color[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
fontColor[i] = color();
|
||||
}
|
||||
// 随机生成贝塞尔曲线参数
|
||||
int x1 = 5, y1 = num(5, height / 2);
|
||||
int x2 = width - 5, y2 = num(height / 2, height - 5);
|
||||
int ctrlx = num(width / 4, width / 4 * 3), ctrly = num(5, height - 5);
|
||||
if (num(2) == 0) {
|
||||
int ty = y1;
|
||||
y1 = y2;
|
||||
y2 = ty;
|
||||
}
|
||||
int ctrlx1 = num(width / 4, width / 4 * 3), ctrly1 = num(5, height - 5);
|
||||
int[][] besselXY = new int[][]{{x1, y1}, {ctrlx, ctrly}, {ctrlx1, ctrly1}, {x2, y2}};
|
||||
// 开始画gif每一帧
|
||||
GifEncoder gifEncoder = new GifEncoder();
|
||||
gifEncoder.start(os);
|
||||
gifEncoder.setQuality(180);
|
||||
gifEncoder.setDelay(100);
|
||||
gifEncoder.setRepeat(0);
|
||||
BufferedImage frame;
|
||||
Color fontcolor[] = new Color[len];
|
||||
gifEncoder.start(os);
|
||||
for (int i = 0; i < len; i++) {
|
||||
fontcolor[i] = new Color(20 + num(110), 20 + num(110), 20 + num(110));
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
frame = graphicsImage(fontcolor, rands, i);
|
||||
BufferedImage frame = graphicsImage(fontColor, strs, i, besselXY);
|
||||
gifEncoder.addFrame(frame);
|
||||
frame.flush();
|
||||
}
|
||||
gifEncoder.finish();
|
||||
ok = true;
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
@@ -62,18 +77,24 @@ public class GifCaptcha extends Captcha {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBase64() {
|
||||
return toBase64("data:image/gif;base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
* 画随机码图
|
||||
*
|
||||
* @param fontcolor 随机字体颜色
|
||||
* @param fontColor 随机字体颜色
|
||||
* @param strs 字符数组
|
||||
* @param flag 透明度使用
|
||||
* @param flag 透明度
|
||||
* @param besselXY 干扰线参数
|
||||
* @return BufferedImage
|
||||
*/
|
||||
private BufferedImage graphicsImage(Color[] fontcolor, char[] strs, int flag) {
|
||||
private BufferedImage graphicsImage(Color[] fontColor, char[] strs, int flag, int[][] besselXY) {
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g2d = (Graphics2D) image.getGraphics();
|
||||
// 填充背景颜色
|
||||
@@ -81,39 +102,27 @@ public class GifCaptcha extends Captcha {
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setStroke(new BasicStroke(1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
// 画干扰圆圈
|
||||
drawOval(4, g2d);
|
||||
// 随机画干扰线
|
||||
drawLine(2, g2d);
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f * num(10))); // 设置透明度
|
||||
drawOval(2, g2d);
|
||||
// 画干扰线
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f)); // 设置透明度
|
||||
g2d.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
g2d.setColor(fontColor[0]);
|
||||
CubicCurve2D shape = new CubicCurve2D.Double(besselXY[0][0], besselXY[0][1], besselXY[1][0], besselXY[1][1], besselXY[2][0], besselXY[2][1], besselXY[3][0], besselXY[3][1]);
|
||||
g2d.draw(shape);
|
||||
// 画验证码
|
||||
Font font = getFont();
|
||||
int hp = (height - font.getSize()) >> 1;
|
||||
int h = height - hp;
|
||||
int w = width / strs.length;
|
||||
int sp = (w - font.getSize()) / 2;
|
||||
g2d.setFont(getFont());
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
int fW = width / strs.length; // 每一个字符所占的宽度
|
||||
int fSp = (fW - (int) fontMetrics.getStringBounds("W", g2d).getWidth()) / 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 + sp + num(3);
|
||||
int y = h - num(3, 6);
|
||||
// 调整溢出的字
|
||||
if (x < 8) {
|
||||
x = 8;
|
||||
}
|
||||
if (x + font.getSize() > width) {
|
||||
x = width - font.getSize();
|
||||
}
|
||||
if (y > height) {
|
||||
y = height;
|
||||
}
|
||||
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.setColor(fontColor[i]);
|
||||
int fY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight()) >> 1); // 文字的纵坐标
|
||||
g2d.drawString(String.valueOf(strs[i]), i * fW + fSp + 3, fY - 3);
|
||||
}
|
||||
g2d.dispose();
|
||||
return image;
|
||||
|
@@ -45,6 +45,11 @@ public class SpecCaptcha extends Captcha {
|
||||
return graphicsImage(textChar(), out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toBase64() {
|
||||
return toBase64("data:image/png;base64,");
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成验证码图形
|
||||
*
|
||||
@@ -55,45 +60,28 @@ public class SpecCaptcha extends Captcha {
|
||||
private boolean graphicsImage(char[] strs, OutputStream out) {
|
||||
try {
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = (Graphics2D) bi.getGraphics();
|
||||
Graphics2D g2d = (Graphics2D) bi.getGraphics();
|
||||
// 填充背景
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(0, 0, width, height);
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setStroke(new BasicStroke(1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
// 随机画干扰线
|
||||
// drawLine(3, g);
|
||||
// 随机画干扰圆
|
||||
// drawOval(8, g);
|
||||
drawBesselLine(2, g);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
// 画干扰圆
|
||||
drawOval(2, g2d);
|
||||
// 画干扰线
|
||||
g2d.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
drawBesselLine(1, g2d);
|
||||
// 画字符串
|
||||
// AlphaComposite ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);// 指定透明度
|
||||
// g.setComposite(ac3);
|
||||
g.setFont(getFont());
|
||||
int fontSize = getFont().getSize();
|
||||
int fY = height - ((height - fontSize) >> 1); // 文字的纵坐标
|
||||
g2d.setFont(getFont());
|
||||
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||
int fW = width / strs.length; // 每一个字符所占的宽度
|
||||
int fSp = (fW - fontSize) / 2; // 字符的左右边距
|
||||
int fSp = (fW - (int) fontMetrics.getStringBounds("W", g2d).getWidth()) / 2; // 字符的左右边距
|
||||
for (int i = 0; i < strs.length; i++) {
|
||||
g.setColor(color());
|
||||
// 计算坐标
|
||||
int x = i * fW + fSp;
|
||||
int y = fY/* - num(3, 6)*/;
|
||||
/*if (x < 8) {
|
||||
x = 8;
|
||||
}
|
||||
if (x + fontSize > width) {
|
||||
x = width - fontSize;
|
||||
}*/
|
||||
/*if (y > height) {
|
||||
y = height;
|
||||
}
|
||||
if (y - fontSize < 0) {
|
||||
y = fontSize;
|
||||
}*/
|
||||
g.drawString(String.valueOf(strs[i]), x, y);
|
||||
g2d.setColor(color());
|
||||
int fY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), g2d).getHeight()) >> 1); // 文字的纵坐标
|
||||
g2d.drawString(String.valueOf(strs[i]), i * fW + fSp + 3, fY - 3);
|
||||
}
|
||||
g2d.dispose();
|
||||
ImageIO.write(bi, "png", out);
|
||||
out.flush();
|
||||
return true;
|
||||
|
@@ -0,0 +1,55 @@
|
||||
package com.wf.captcha.base;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
|
||||
public abstract class ArithmeticCaptchaAbstract extends Captcha {
|
||||
private String arithmeticString; // 计算公式
|
||||
|
||||
public ArithmeticCaptchaAbstract() {
|
||||
setLen(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机验证码
|
||||
*
|
||||
* @return 验证码字符数组
|
||||
*/
|
||||
@Override
|
||||
protected char[] alphas() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(num(10));
|
||||
if (i < len - 1) {
|
||||
int type = num(1, 4);
|
||||
if (type == 1) {
|
||||
sb.append("+");
|
||||
} else if (type == 2) {
|
||||
sb.append("-");
|
||||
} else if (type == 3) {
|
||||
sb.append("x");
|
||||
}
|
||||
}
|
||||
}
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("javascript");
|
||||
try {
|
||||
chars = String.valueOf(engine.eval(sb.toString().replaceAll("x", "*")));
|
||||
} catch (ScriptException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
sb.append("=?");
|
||||
arithmeticString = sb.toString();
|
||||
return chars.toCharArray();
|
||||
}
|
||||
|
||||
public String getArithmeticString() {
|
||||
checkAlpha();
|
||||
return arithmeticString;
|
||||
}
|
||||
|
||||
public void setArithmeticString(String arithmeticString) {
|
||||
this.arithmeticString = arithmeticString;
|
||||
}
|
||||
}
|
@@ -1,8 +1,11 @@
|
||||
package com.wf.captcha.base;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -108,6 +111,20 @@ public abstract class Captcha extends Randoms {
|
||||
*/
|
||||
public abstract boolean out(OutputStream os);
|
||||
|
||||
public abstract String toBase64();
|
||||
|
||||
/**
|
||||
* 输出base64编码
|
||||
*
|
||||
* @param type 编码头
|
||||
* @return
|
||||
*/
|
||||
public String toBase64(String type) {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
out(outputStream);
|
||||
return type + new BASE64Encoder().encode(outputStream.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的验证码
|
||||
*
|
||||
@@ -156,7 +173,7 @@ public abstract class Captcha extends Randoms {
|
||||
*/
|
||||
public void drawLine(int num, Color color, Graphics2D g) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
g.setColor(color == null ? color(150, 250) : color);
|
||||
g.setColor(color == null ? color() : color);
|
||||
int x1 = num(-10, width - 10);
|
||||
int y1 = num(5, height - 5);
|
||||
int x2 = num(10, width + 10);
|
||||
@@ -172,10 +189,7 @@ public abstract class Captcha extends Randoms {
|
||||
* @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));
|
||||
}
|
||||
drawOval(num, null, g);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,8 +201,9 @@ public abstract class Captcha extends Randoms {
|
||||
*/
|
||||
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));
|
||||
g.setColor(color == null ? color() : color);
|
||||
int w = 5 + num(10);
|
||||
g.drawOval(num(width - 25), num(height - 15), w, w);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,19 +227,20 @@ public abstract class Captcha extends Randoms {
|
||||
public void drawBesselLine(int num, Color color, Graphics2D g) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
g.setColor(color == null ? color() : color);
|
||||
int x1 = 5;
|
||||
int y1 = num(5, height - 5);
|
||||
int x2 = width - 5;
|
||||
int y2 = num(5, height - 5);
|
||||
int ctrlx = num(5, width - 5);
|
||||
int ctrly = num(5, height - 5);
|
||||
int x1 = 5, y1 = num(5, height / 2);
|
||||
int x2 = width - 5, y2 = num(height / 2, height - 5);
|
||||
int ctrlx = num(width / 4, width / 4 * 3), ctrly = num(5, height - 5);
|
||||
if (num(2) == 0) {
|
||||
int ty = y1;
|
||||
y1 = y2;
|
||||
y2 = ty;
|
||||
}
|
||||
if (num(2) == 0) { // 二阶贝塞尔曲线
|
||||
QuadCurve2D shape = new QuadCurve2D.Double();
|
||||
shape.setCurve(x1, y1, ctrlx, ctrly, x2, y2);
|
||||
g.draw(shape);
|
||||
} else { // 三阶贝塞尔曲线
|
||||
int ctrlx1 = num(5, width - 5);
|
||||
int ctrly1 = num(5, height - 5);
|
||||
int ctrlx1 = num(width / 4, width / 4 * 3), ctrly1 = num(5, height - 5);
|
||||
CubicCurve2D shape = new CubicCurve2D.Double(x1, y1, ctrlx, ctrly, ctrlx1, ctrly1, x2, y2);
|
||||
g.draw(shape);
|
||||
}
|
||||
@@ -247,7 +263,11 @@ public abstract class Captcha extends Randoms {
|
||||
}
|
||||
|
||||
public void setFont(int font) throws IOException, FontFormatException {
|
||||
setFont(font, Font.BOLD, 32f);
|
||||
setFont(font, 32f);
|
||||
}
|
||||
|
||||
public void setFont(int font, float size) throws IOException, FontFormatException {
|
||||
setFont(font, Font.BOLD, size);
|
||||
}
|
||||
|
||||
public void setFont(int font, int style, float size) throws IOException, FontFormatException {
|
||||
|
@@ -1,7 +1,5 @@
|
||||
package com.wf.captcha.base;
|
||||
|
||||
import com.wf.captcha.base.Captcha;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class ChineseCaptchaAbstract extends Captcha {
|
||||
@@ -37,16 +35,4 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import com.wf.captcha.GifCaptcha;
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
|
||||
/**
|
||||
@@ -16,21 +15,9 @@ import com.wf.captcha.SpecCaptcha;
|
||||
*/
|
||||
public class CaptchaUtil {
|
||||
private static final String SESSION_KEY = "captcha";
|
||||
|
||||
/**
|
||||
* 验证验证码
|
||||
*
|
||||
* @param code 用户输入的验证码
|
||||
* @param request HttpServletRequest
|
||||
* @return 是否正确
|
||||
*/
|
||||
public static boolean ver(String code, HttpServletRequest request) {
|
||||
if (code != null && !code.trim().isEmpty()) {
|
||||
String captcha = (String) request.getSession().getAttribute(SESSION_KEY);
|
||||
return code.trim().toLowerCase().equals(captcha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static final int DEFAULT_LEN = 4; // 默认长度
|
||||
private static final int DEFAULT_WIDTH = 130; // 默认宽度
|
||||
private static final int DEFAULT_HEIGHT = 48; // 默认高度
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
@@ -41,7 +28,7 @@ public class CaptchaUtil {
|
||||
*/
|
||||
public static void out(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
out(5, request, response);
|
||||
out(DEFAULT_LEN, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,21 +41,7 @@ public class CaptchaUtil {
|
||||
*/
|
||||
public static void out(int len, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
out(130, 48, len, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param len 长度
|
||||
* @param font 字体
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void out(int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
out(130, 48, len, font, request, response);
|
||||
out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,42 +62,14 @@ public class CaptchaUtil {
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param len 长度
|
||||
* @param font 字体
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void out(int width, int height, int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
public static void out(Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outCaptcha(width, height, len, font, 1, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void outPng(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outPng(5, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param len 长度
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void outPng(int len, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outPng(130, 48, len, request, response);
|
||||
out(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_LEN, font, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,24 +81,9 @@ public class CaptchaUtil {
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void outPng(int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
public static void out(int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outPng(130, 48, len, font, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param len 长度
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void outPng(int width, int height, int len, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outPng(width, height, len, null, request, response);
|
||||
out(DEFAULT_WIDTH, DEFAULT_HEIGHT, len, font, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,39 +97,46 @@ public class CaptchaUtil {
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void outPng(int width, int height, int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
public static void out(int width, int height, int len, Font font, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
outCaptcha(width, height, len, font, 0, request, response);
|
||||
SpecCaptcha specCaptcha = new SpecCaptcha(width, height, len);
|
||||
if (font != null) {
|
||||
specCaptcha.setFont(font);
|
||||
}
|
||||
out(specCaptcha, request, response);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 输出验证码
|
||||
*
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param len 长度
|
||||
* @param font 字体
|
||||
* @param cType 类型
|
||||
* @param captcha Captcha
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private static void outCaptcha(int width, int height, int len, Font font, int cType, HttpServletRequest request, HttpServletResponse response)
|
||||
private static void out(Captcha captcha, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
setHeader(response);
|
||||
Captcha captcha = null;
|
||||
if (cType == 0) {
|
||||
captcha = new SpecCaptcha(width, height, len);
|
||||
} else if (cType == 1) {
|
||||
captcha = new GifCaptcha(width, height, len);
|
||||
}
|
||||
if (font != null) {
|
||||
captcha.setFont(font);
|
||||
}
|
||||
request.getSession().setAttribute(SESSION_KEY, captcha.text().toLowerCase());
|
||||
captcha.out(response.getOutputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证验证码
|
||||
*
|
||||
* @param code 用户输入的验证码
|
||||
* @param request HttpServletRequest
|
||||
* @return 是否正确
|
||||
*/
|
||||
public static boolean ver(String code, HttpServletRequest request) {
|
||||
if (code != null) {
|
||||
String captcha = (String) request.getSession().getAttribute(SESSION_KEY);
|
||||
return code.trim().toLowerCase().equals(captcha);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除session中的验证码
|
||||
*
|
||||
|
@@ -1,15 +1,9 @@
|
||||
package com.wf.captcha;
|
||||
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 测试类
|
||||
@@ -19,98 +13,59 @@ public class CaptchaTest {
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
/*for (int i = 0; i < 10; i++) {
|
||||
SpecCaptcha specCaptcha = new SpecCaptcha();
|
||||
// specCaptcha.setCharType(Captcha.TYPE_ONLY_UPPER);
|
||||
specCaptcha.setLen(4);
|
||||
specCaptcha.setFont(i, 32f);
|
||||
System.out.println(specCaptcha.text());
|
||||
// specCaptcha.setFont(Font.createFont(Font.TRUETYPE_FONT, new File(getClass().getResource("/actionj.ttf").getFile())).deriveFont(Font.BOLD, 32));
|
||||
specCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".png")));
|
||||
}
|
||||
specCaptcha.out(new FileOutputStream(new File("C:/Java/aa" + i + ".png")));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGIf() throws Exception {
|
||||
/*for (int i = 0; i < 5; i++) {
|
||||
/*for (int i = 0; i < 10; i++) {
|
||||
GifCaptcha gifCaptcha = new GifCaptcha();
|
||||
gifCaptcha.setLen(5);
|
||||
gifCaptcha.setFont(i, 32f);
|
||||
System.out.println(gifCaptcha.text());
|
||||
gifCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".gif")));
|
||||
gifCaptcha.out(new FileOutputStream(new File("C:/Java/aa" + i + ".gif")));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHan() throws Exception {
|
||||
/*for (int i = 0; i < 5; i++) {
|
||||
/*for (int i = 0; i < 10; i++) {
|
||||
ChineseCaptcha chineseCaptcha = new ChineseCaptcha();
|
||||
System.out.println(chineseCaptcha.text());
|
||||
chineseCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".png")));
|
||||
chineseCaptcha.out(new FileOutputStream(new File("C:/Java/aa" + i + ".png")));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGifHan() throws Exception {
|
||||
/*for (int i = 0; i < 5; i++) {
|
||||
/*for (int i = 0; i < 10; i++) {
|
||||
ChineseGifCaptcha chineseGifCaptcha = new ChineseGifCaptcha();
|
||||
System.out.println(chineseGifCaptcha.text());
|
||||
chineseGifCaptcha.out(new FileOutputStream(new File("D:/Java/aa" + i + ".gif")));
|
||||
chineseGifCaptcha.out(new FileOutputStream(new File("C:/Java/aa" + i + ".gif")));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() throws Exception {
|
||||
String[] colors = new String[]{"#8cc540", "#009f5d", "#019fa0", "#019fde", "#007cdc", "#887ddd", "#cd7bdd", "#ff5675", "#ff1244", "#ff8345", "#f8bd0b", "#d1d2d4"};
|
||||
String[] fonts = new String[]{"actionj.ttf", "epilog.ttf", "fresnel.ttf", "headache.ttf", "lexo.ttf", "prefix.ttf", "progbot.ttf", "ransom.ttf", "robot.ttf", "scandal.ttf"};
|
||||
int i = 0;
|
||||
for (String f : fonts) {
|
||||
i++;
|
||||
FileOutputStream out = new FileOutputStream(new File("D:/Java/aa" + i + ".png"));
|
||||
try {
|
||||
int width = 130, height = 48;
|
||||
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D g = (Graphics2D) bi.getGraphics();
|
||||
g.setColor(Color.WHITE);
|
||||
g.fillRect(0, 0, width, height);
|
||||
// 抗锯齿
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setStroke(new BasicStroke(1.3f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
// 画字符串
|
||||
float fontSize = 32f;
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, new File(getClass().getResource("/" + f).getFile())).deriveFont(Font.BOLD, fontSize);
|
||||
g.setFont(font);
|
||||
char[] chars = "N4WbS".toCharArray();
|
||||
float sp = (width / chars.length - fontSize) / 2;
|
||||
int j = 0;
|
||||
for (char c : chars) {
|
||||
j++;
|
||||
g.setColor(Color.getColor(colors[j]));
|
||||
float x = sp * j + fontSize * (j - 1);
|
||||
float y = (height - fontSize) / 2 + fontSize;
|
||||
System.out.println(x + "-" + y);
|
||||
g.drawString(String.valueOf(c), x, y);
|
||||
}
|
||||
g.drawString("Hello", 8, 37);
|
||||
//
|
||||
QuadCurve2D shape = new QuadCurve2D.Double();
|
||||
shape.setCurve(8, 38, 38, 10, 120, 40);
|
||||
g.draw(shape);
|
||||
ImageIO.write(bi, "png", out);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void testArit() throws Exception {
|
||||
/*for (int i = 0; i < 10; i++) {
|
||||
ArithmeticCaptcha specCaptcha = new ArithmeticCaptcha();
|
||||
specCaptcha.setLen(3);
|
||||
specCaptcha.setFont(i, 28f);
|
||||
System.out.println(specCaptcha.getArithmeticString() + " " + specCaptcha.text());
|
||||
specCaptcha.out(new FileOutputStream(new File("C:/Java/aa" + i + ".png")));
|
||||
}*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() throws Exception {
|
||||
String filePath = getClass().getResource("/actionj.ttf").getFile();
|
||||
System.out.println(filePath);
|
||||
public void testBase64() throws Exception {
|
||||
/*GifCaptcha specCaptcha = new GifCaptcha();
|
||||
System.out.println(specCaptcha.toBase64(""));*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user