前言
以前一直很好奇,验证码是怎么做出来的,我会PS的时候,一致认为是PS画的,最近在玩Web,然后发现too young了,原来是代码生成的。
实现参考的博客作者:
永恒の_☆
博客地址:
http://blog.csdn.net/chenghui0317/article/details/12526439
成果
实现参考
关键词参考:
BufferedImage
Graphics2D
ImageIO
利用Graphics2D的drawString方法可以很方便的绘制字符。
主要是如何让字符不粘在一起,只要设置一个偏移量,每次循环就增加一倍偏移量。
另外一个就是添加干扰线,一定程度上可以防止自动登录。。然而除非把验证码弄得面目全非,否则还是很容易被识别的。
另外我尝试了进行扭曲,然后扭曲失败了,效果惨不忍睹,人眼都看不出来- -
网上搜到的感觉略高端,又不是研究这方面的,就没继续深入了解。
(逃
代码实现
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;
public class GetPic {
public static void main(String[] args) {
int codeCount = 4;
String suffix = "png";
String picName = "chapter";
//picName = null;
String chapter = generateImg(codeCount, picName, suffix);
System.out.println(chapter);
}
/**
* 生成验证码图片,并返回验证码的值
* @param codeCount 验证码个数
* @param picName 图片文件名
* @param suffix 图片文件格式(png/jpeg)
* @return 验证码的值
*/
public static String generateImg(int codeCount, String picName, String suffix) {
//图片的宽和高
int imgWidth = codeCount * 20;
int imgHeight = 30;
BufferedImage buffImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_BGR);
String chapter = drawImg(buffImg, codeCount, imgWidth, imgHeight);
//如果图片文件名为空,那么使用验证码的值作为图片文件名
picName = picName == null ? chapter : picName;
outputPic(buffImg, picName, suffix);
return chapter;
}
/**
* 根据宽度、高度、和验证码的个数绘制验证码图片,并返回验证码的值
* @param buffImg BufferedImage对象
* @param codeCount 验证码个数
* @param imgWidth 图片宽度
* @param imgHeight 图片高度
* @return 验证码的值
*/
private static String drawImg(BufferedImage buffImg, int codeCount, int imgWidth, int imgHeight) {
Random rand = new Random();
Graphics2D gd = buffImg.createGraphics();
//填充矩形
gd.setColor(Color.WHITE);
gd.fillRect(0, 0, imgWidth, imgHeight);
//设置字体
Font font = new Font("微软雅黑", Font.PLAIN, imgHeight - 5);
gd.setFont(font);
//绘制边框
gd.setColor(Color.BLACK);
gd.drawRect(0, 0, imgWidth - 1, imgHeight - 1);
//绘制灰色干扰线
gd.setColor(Color.GRAY);
for (int i = 0, x, y, x1, y1; i < 30; i++) {
x = rand.nextInt(imgWidth);
y = rand.nextInt(imgHeight);
x1 = rand.nextInt(12);
y1 = rand.nextInt(12);
gd.drawLine(x, y, x + x1, y + y1);
}
//int codeCount = 4,
int codeX = 15, codeY = 25;
//记录验证码
StringBuffer chapter = new StringBuffer();
//临时变量
String strRand;
char[] codeSequence = { '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
for (int i = 0, red, green, blue; i < codeCount; i++) {
//随机获取字符
strRand = String.valueOf(codeSequence[rand.nextInt(codeSequence.length)]);
//随机选择字符颜色
red = rand.nextInt(255);
green = rand.nextInt(255);
blue = rand.nextInt(255);
gd.setColor(new Color(red, green, blue));
//绘制字符
gd.drawString(strRand, (i + 1) * codeX, codeY);
//记录字符
chapter.append(strRand);
}
return chapter.toString();
}
/**
* 将绘制完毕的图片输出成文件
* @param buffImg 绘制完毕的验证码图片
* @param fileName 文件名
* @param suffix 后缀(png/jpeg)
*/
public static void outputPic(BufferedImage buffImg, String fileName, String suffix) {
try {
int index = 1;
File file = new File(fileName + "." + suffix);
while (file.exists()) {
file = new File(fileName + "(" + (index++) + ")." + suffix);
}
FileOutputStream fos = new FileOutputStream(file);
ImageIO.write(buffImg, suffix, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 显示字体列表
*/
public static void showFontList() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fonts = ge.getAvailableFontFamilyNames();
for (String font : fonts) {
System.out.println(font);
}
}
//试图扭曲图片,失败了
/*
public static void getImgArr(BufferedImage buffImg) {
int offX = 20;
int offY = 20;
int height = buffImg.getHeight();
int width = buffImg.getWidth();
System.out.println("width:" + width + " height:" + height);
int[][] rgbs = new int[width][height];
for (int i = buffImg.getMinY(); i < width; i++) {
for (int j = buffImg.getMinX(); j < height; j++) {
if (i - offX < width && i - offX >= 0) {
buffImg.setRGB(i - offX, j, buffImg.getRGB(i, j));
}
//if (j - offY < height && j - offY >= 0) {
//buffImg.setRGB(i, j - offY, buffImg.getRGB(i, j));
//}
}
//offY -= 2;
offX--;
}
}
*/
}