package angkor;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
public class VerificationCode {
private final int WIDTH = 100; //定义图像宽度
private final int HEIGHT = 40;//定义图像高度
private final int POINT_NUMBERS = 6; //定义干扰线的端点数
private final int CHARACTER_NUMBERS = 4;//定义验证码图片中字符的个数
private final int CHARACTER_SIZE = 30;//定义验证码图片中字符的大小
private final Color BACKGROUD_COLOR = Color.WHITE; //定义背景颜色
private final String PATH = "h:/2.jpg";
private String verificationCode; //定义存储生成的验证码的字符串,这个字符串将放到session中
private BufferedImage image;
private Graphics2D graphics2d;
//定义生成验证码所需要的字符0~9,a~z,A~Z
private String characters[] =
{
"0","1","2","3","4","5","6","7","8","9",
"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",
"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"
};
//定义验证码字符的字体
private int fonts[] = {Font.ITALIC,Font.BOLD,Font.PLAIN};
//定义Font的字体名称
private String fontNames[] =
{"Default","Serif","Dialog","DialogInput","SansSerif","Monospaced"};
//定义字体的颜色
private Color colors[] =
{
Color.BLACK,Color.BLUE,Color.CYAN,Color.DARK_GRAY,
Color.GRAY,Color.GREEN,Color.LIGHT_GRAY,Color.MAGENTA,
Color.ORANGE,Color.PINK,Color.RED,Color.YELLOW
};
/**
* 获得image对象的get方法
* @author angkor
*/
public BufferedImage getImage(){
createBufferedImage();
generateCharacters();
addInterferingLine();
drawImage();
disposeGraphics2D();
return image;
}
/**
* 获得验证码的get方法
* @author angkor
*/
public String getVerificationCode(){
return verificationCode;
}
/**
* 此方法生成一个BufferedImage对象,并将图像的背景设置为指定颜色
* @author angkor
*/
private void createBufferedImage(){
image = new BufferedImage(WIDTH,HEIGHT, BufferedImage.TYPE_3BYTE_BGR);
/*WritableRaster raster = image.getRaster();
ColorModel model = image.getColorModel();
int rgb = BACKGROUD_COLOR.getRGB();
Object bgColorData = model.getDataElements(rgb, null);
//将背景颜色设为指定颜色
for(int i=0;i<WIDTH;i++){
for(int j=0;j<HEIGHT;j++){
raster.setDataElements(i, j, bgColorData);
}
}*/
graphics2d = image.createGraphics();
graphics2d.setColor(BACKGROUD_COLOR);
graphics2d.fillRect(0, 0, WIDTH, HEIGHT);
}
/**
* 此方法用于生成验证码的字符,并将其写入BufferedImage对象中。
* 形如fontNames[getRandomNumber(fontNames.length)]的说明:根据数组fontNames的length获得一个随机数,
* 再根据这个随机数在fontNames数组中取得对应的值,并将这个值作为参数传入相应的方法,如new Font()中。
* @author angkor
*/
private void generateCharacters(){
//graphics2d = image.createGraphics();
verificationCode = "";
int baseHorizontalPixel = 10; //定义第一个字符的横向起始像素
int increasementPixel = 20;//定义两个字符之间的间隔像素
int minVerticalRange = 20;//定义字符纵向的最低像素
int maxVerticalRange = 30;//定义字符纵向的最高像素
String tempCode = "";//定义存储生成的临时的验证码字符
Font font;
for(int i=0;i<CHARACTER_NUMBERS;i++){
font = new Font(fontNames[getRandomNumber(fontNames.length)],fonts[getRandomNumber(fonts.length)],CHARACTER_SIZE);
graphics2d.setFont(font); //设置字体
graphics2d.setColor(colors[getRandomNumber(colors.length)]);//设置字体颜色
//随机选择characters数组中的字符,并将字符写入相应的位置
tempCode = characters[getRandomNumber(characters.length)];
graphics2d.drawString(tempCode, baseHorizontalPixel, getRandomNumber(minVerticalRange, maxVerticalRange));
verificationCode += tempCode;
baseHorizontalPixel += increasementPixel;
}
}
/**
* 此方法用于在图像中加入干扰线
* @author angkor
*/
private void addInterferingLine(){
int[] xPoints = new int[POINT_NUMBERS];
int[] yPoints = new int[POINT_NUMBERS];
for(int i=0;i<POINT_NUMBERS;i++){
xPoints[i] = getRandomNumber(WIDTH);
yPoints[i] = getRandomNumber(HEIGHT);
}
graphics2d.setColor(colors[getRandomNumber(colors.length)]);//设置干扰线颜色
graphics2d.drawPolyline(xPoints, yPoints, POINT_NUMBERS);
}
/**
* 将生成的图像写入指定的地方
* @author angkor
*/
private void drawImage(){
try {
ImageIO.write(image, "JPEG", new File(PATH));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 释放此图形的上下文以及它使用的所有系统资源。
* 调用 dispose 之后,就不能再使用 Graphics 对象。
* Java 程序运行时,可以在一个短时间帧内创建大量的 Graphics 对象。
* 尽管垃圾回收器的终止进程也能够进行相同的系统资源释放,
* 但是最好通过调用此方法来手工释放相关资源,而不是依靠终止进程,
* 因为终止进程需要很长时间才能结束运行。
*/
private void disposeGraphics2D(){
graphics2d.dispose();
}
/**
* 在0到指定的范围中生成随机数
* @param range 随机数的最大范围
* @return int型的随机数
* @author angkor
*/
private int getRandomNumber(int range){
Random random = new Random();
int num = random.nextInt(range);
return num;
}
/**
* 在指定的最小和最大范围内生成随机数
* @param minRange 随机数的最小范围
* @param maxRange 随机数的最大范围
* @return int型的随机数
* @author angkor
*/
private int getRandomNumber(int minRange,int maxRange){
Random random = new Random((long)minRange);
int num = random.nextInt(maxRange);
return num;
}
}