1.程序的思路
要想获得随机的验证码图片,可以分以下几步来实现:
- 首先生成一张图片,设置图片的大小以及图片的背景色。
- 然后在得到的图片中写下指定数目的随机字符,需要注意的是字符的颜色、字体、字体风格、字号以及字符选取的范围都是随机的(可以通过指定数组随机选择)。
- 因为要产生验证码图片的真实效果,还可以为图片随机添加几条干扰线,这里就需要设置干扰线的起点坐标和终点坐标,也可以通过随机函数产生,干扰线的宽度也可以通过属性指定。
- 最后就是将图片保存下来,这里就直接将图片保存到指定磁盘位置(如”D:/b.jpg”)了。可以在先前的程序中将随机产生的字符串记录下来,然后用以和生成的图片进行对比,其实在网站中进行验证码校验的时候,也是在程序中先将生成的随机字符串保存下来的。
2.程序代码
1. 首先看如何生成一张图片,以及设置图片的大小和图片的背景色。
先放上程序代码
// 生成一张内存中的图片
BufferedImage img = new BufferedImage(70, 35, BufferedImage.TYPE_INT_BGR);
// 设置画笔颜色
img.getGraphics().setColor(bgColor);
// 填充一个与图片一样大小的白色矩形,相当于设置图片背景色为白色
img.getGraphics().fillRect(0, 0, w, h);
- 首先生成一张宽为70,高为35的图片,然后因为要为图片绘制背景色,这里选择的方法就是画一个与图片大小一样的白色矩形覆盖到图片上去,于是通过
img.getGraphics()
方法获得画笔,然后通过setColor(bgColor)
方法设置画笔的颜色,其中的bgColor
是一个颜色参数,可以在程序开始通过new Color(240, 240, 240) //白色
获得,最后一步便是用这支白色画笔画一个图片大小一致的白色矩形覆盖到图片上去,也相当于设置了白色的背景色。
2. 接下来就是生成图片上面的随机字符了
字体的颜色,还是采用RGB的方式产生
// 生成随机颜色 private Color randomColor(){ int r = random.nextInt(256); int g = random.nextInt(256); int b = random.nextInt(256); return new Color(r, g, b); }
现在就是确定选用什么字体,而字体由名称、风格以及字体大小组成
/* * 生成随机字体 * 字体名,样式,字号 */ private String[] fontName = {"宋体","华文行楷","黑体","华文新魏","华文隶书","微软雅黑","楷体_GB2312"}; // private int[] fontStyles = {0, 1, 2, 3}; private int[] fontSize = {24, 25, 26, 27, 28}; private Font randomFont(){ int index = random.nextInt(fontName.length); String name = fontName[index]; int style = random.nextInt(4); // 0,1,2,3 index = random.nextInt(fontSize.length); int size = fontSize[index]; return new Font(name, style, size); }
现在就是随机的字符获取
//生成随机字符 private String codes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private String randomChar(){ int index = random.nextInt(codes.length()); return codes.charAt(index) + ""; }
最后就是用上面设置好的字体去将字符写到图片上了
Graphics g = img.getGraphics(); // 画东西 for(int i = 0; i<4; i++){ String ch = randomChar(); // 获取随机字符 g.setColor(randomColor()); // 随机颜色 g.setFont(randomFont()); // 随机字体 g.drawString(ch, w/4*i, h-5); }
这里最后一句程序 g.drawString(ch, w/4*i, h-5);
其中的第二个参数要写成 w/4*i
是因为后面的两个参数分别代表着x坐标和y坐标,即画笔从哪里开始写字符,如果第二个字符设为一样的话,所有的字符就会叠加在一起。
3. 现在就是在图片上面加上几条干扰线
代码如下:
//画图片上的干扰线
private void drawLine(BufferedImage img){
Graphics2D g = (Graphics2D) img.getGraphics();
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(1.5F));
for(int i=0; i<5;i++){
int x1 = random.nextInt(w);
int y1 = random.nextInt(h);
int x2 = random.nextInt(w);
int y2 = random.nextInt(h);
g.drawLine(x1, y1, x2, y2);
}
}
其中每条线的起始坐标和终点坐标都是随机产生的,因此每条干扰线也是随机的。
4. 最后将生成的图片保存到指定的目录下
// 保存图片的方法
public static void saveImage(BufferedImage img, OutputStream out) throws IOException{
ImageIO.write(img, "JPEG", out);
}
//实际调用方法
ImageImpl.saveImage(img, new FileOutputStream("D:/b.jpg"));
3. 完整的代码如下,直接可以运行
package image;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
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 javax.imageio.ImageIO;
public class ImageImpl {
private int w = 70; // 宽
private int h = 35; // 高
private Color bgColor = new Color(240, 240, 240);
private Random random = new Random();
public BufferedImage createImage(){
/*
* 创建图片
* 设置背景色
*/
// 创建图片
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// 设置画笔颜色
img.getGraphics().setColor(bgColor);
// 填充一个与图片一样大小的白色矩形,相当于设置图片背景色为白色
img.getGraphics().fillRect(0, 0, w, h);
return img;
}
// 生成随机颜色
private Color randomColor(){
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r, g, b);
}
/*
* 生成随机字体
* 字体名,样式,字号
*/
private String[] fontName = {"宋体","华文行楷","黑体","华文新魏","华文隶书","微软雅黑","楷体_GB2312"};
// private int[] fontStyles = {0, 1, 2, 3};
private int[] fontSize = {24, 25, 26, 27, 28};
private Font randomFont(){
int index = random.nextInt(fontName.length);
String name = fontName[index];
int style = random.nextInt(4); // 0,1,2,3
index = random.nextInt(fontSize.length);
int size = fontSize[index];
return new Font(name, style, size);
}
/*
* 生成随机字符
*/
private String codes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private String randomChar(){
int index = random.nextInt(codes.length());
return codes.charAt(index) + "";
}
private String chars=""; // 用于存储随机产生的四个字符
// 用户调用这个方法获取图片
public BufferedImage getImage(){
/*
* 字符:随机,0-9a-zA-Z
* 字体:
* 字符颜色:
*/
BufferedImage img = createImage();
Graphics g = img.getGraphics();
// 画东西
for(int i = 0; i<4; i++){
String ch = randomChar(); // 获取随机字符
chars += ch; // 将随机产生的字符添加到字符串中
g.setColor(randomColor()); // 随机颜色
g.setFont(randomFont()); // 随机字体
g.drawString(ch, w/4*i, h-5);
}
return img;
}
// 保存图片
public static void saveImage(BufferedImage img, OutputStream out) throws IOException{
ImageIO.write(img, "JPEG", out);
}
//画图片上的干扰线
private void drawLine(BufferedImage img){
Graphics2D g = (Graphics2D) img.getGraphics();
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(1.5F));
for(int i=0; i<5;i++){
int x1 = random.nextInt(w);
int y1 = random.nextInt(h);
int x2 = random.nextInt(w);
int y2 = random.nextInt(h);
g.drawLine(x1, y1, x2, y2);
}
}
public static void main(String[] args) throws FileNotFoundException, IOException {
ImageImpl imageImpl = new ImageImpl();
BufferedImage img = imageImpl.getImage();
imageImpl.drawLine(img);
ImageImpl.saveImage(img, new FileOutputStream("D:/b.jpg"));
System.out.println(imageImpl.chars);
}
}