变形 不规则的验证码生成程序



import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import java.util.UUID;
import javax.imageio.ImageIO;

public class VerifyImageUtil {
public static String generate(OutputStream out) {
Random rand = new Random(System.currentTimeMillis());
// 图片宽高
int width = 80 + rand.nextInt(25);
int height = 28 + rand.nextInt(10);
Graphics2D g = null;
String value = null;
try {
BufferedImage bimage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
g = bimage.createGraphics();
// 设置随机背景色
Color color = new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));
// 填充深色背景
g.setColor(color.darker());
g.fillRect(0, 0, width, height);
// 设置字体
g.setFont(new Font("arial", Font.BOLD, 36));
// 随机生成字符,根据截取的位数决定产生的数字
value = UUID.randomUUID().toString().replace("-", "").substring(0,4);
int w = (g.getFontMetrics()).stringWidth(value);
int d = (g.getFontMetrics()).getDescent();
int a = (g.getFontMetrics()).getMaxAscent();
int x = 0, y = 0;
// 设置随机线条,15这个数值越大图片中线条越稀蔬
for (int i = 0; i < height;) {
i += 8 + rand.nextInt(15);
g.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
g.drawLine(x, y + i, width, y + i);
}
// reset x and y
x = 0;
y = 0;
// 设置随机线条,15这个数值越大图片中线条越稀蔬
for (int i = 0; i < height;) {
i += 8 + rand.nextInt(15);
g.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
g.drawLine(x, y + d - i, width + w, height + d - i);
}

// 展示验证码中颜色,随机
g.setColor(new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)).brighter());
// 设置文字出现位置为中央
x = width / 2 - w / 2;
y = height / 2 + a / 2 - 6;
// 文字变形设置
AffineTransform fontAT = new AffineTransform();
int xp = x - 2;
// 每个文字都变形
for (int c = 0; c < value.length(); c++) {
// 产生弧度
int rotate = rand.nextInt(25);
fontAT.rotate(rand.nextBoolean() ? Math.toRadians(rotate):-Math.toRadians(rotate / 2));
Font fx = new Font(new String[] { "Times New Roman", "Verdana","arial" }[rand.nextInt(2)], rand.nextInt(5), 20 + rand.nextInt(16)).deriveFont(fontAT);
g.setFont(fx);
// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
Random random = new Random();
int red = random.nextInt(255);
int green = random.nextInt(255);
int blue = random.nextInt(255);
// 用随机产生的颜色将验证码绘制到图像中。
g.setColor(new Color(red, green, blue));
String ch = String.valueOf(value.charAt(c));
int ht = rand.nextInt(3);
// 打印字并移动位置
g.drawString(ch, xp, y + (rand.nextBoolean() ? -ht : ht));
// 移动指针.
xp += g.getFontMetrics().stringWidth(ch) + 2;
}
// 打印出图片
ImageIO.write(bimage, "png", out);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (g != null)
g.dispose();
if (out != null)
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return value;
}

//for test
public static void main(String args[]) throws FileNotFoundException {
System.out.println(generate(new FileOutputStream("D:/verify.png")));
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值