java生成简单验证码图片
概要
最近项目需要用java实现输出随机验证码图片到前台,正好有机会接触下java的绘图类,完成需求后也有时间做个总结,写篇随笔记录下也希望能帮助到有同样需求的人!
需求流程图

1.生成随机数
在java中生成随机数无非就是调用Random的api,但为了后续更好的实用,应该分成多种组合以适应需求的变化,应将生成随机数的个数和类型组合还有排除字符抽取成参数,这个也比较简单,没有什么难度,就直接贴上代码
/**
* 生成随机验证码
* @param type 类型
* @param length 长度
* @param exChars 排除的字符
* @return
*/
public static String getRandomCode(int type,int length,String exChars){
case TYPE_NUM_CHAR://数字+(大小写)字母
while(i<length){
int t=random.nextInt(123);
if((t>=97||(t>=65&&t<=90)||(t>=48&&t<=57))&&(exChars==null||exChars.indexOf((char)t)<0)){
sb.append((char)t);
i++;
}
}
break; }
2.绘制图片
绘制图片是重点也是难点,老实说我之前都没用过BufferedImage、Graphics、Color等对象,都是从度娘处脑补并结合帖子写出来的输出图片
1)创建BufferedImage对象
如果把BufferedImage比作是画板,那么Graphics就是画纸,这样比较好理解,后续的操作都是在这画纸上进行的
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
//随机操作对象
Random r=new Random();
2)绘制背景
Graphics有个setColor()方法,可理解为画笔,在绘制任何东西前要选好画笔,即颜色,然后调用fillRect()进行轮廓的绘制,后续的绘制范围不会超过这个轮廓
g.setColor(backColor==null?getRandomColor():backColor);
g.fillRect(0,0,width,height);
3)绘制干扰线
调用drawLine画直线,绘制不超过interLine条干扰线
if(interLine>0){
int x=r.nextInt(4),y=0;
int x1=width-r.nextInt(4),y1=0;
for(int i=0;i<interLine;i++){
g.setColor(lineColor==null?getRandomColor():lineColor);
y=r.nextInt(height-r.nextInt(4));
y1=r.nextInt(height-r.nextInt(4));
g.drawLine(x,y,x1,y1);
}
}
4)写验证码
写验证码时调用drawString()方法,为了不整整齐齐而且重叠的写,应将每个字符的高度和水平位置随机,重点在于每绘制完一个字符后,需将画笔的水平坐标往右边移动一定的位置,这里我用了依据宽度浮动,可不必照搬这里的,有合适的算法就行
int fsize=(int)(height*0.8);//字体大小为图片高度的80%
int fx=0;
int fy=fsize;
g.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,fsize));
//写字符
for(int i=0;i<textCode.length();i++){
fy=randomLocation?(int)((Math.random()*0.3+0.6)*height):fy;//每个字符高低是否随机
g.setColor(foreColor==null?getRandomColor():foreColor);
g.drawString(textCode.charAt(i)+"",fx,fy);
fx+=(width / textCode.length()) * (Math.random() * 0.3 + 0.8); //依据宽度浮动
}
5)扭曲图片
图片的扭曲就是将图片水平和垂直按不同比例平移,copyArea()方法简单明了,直接是复制区域,也是同个意识
//扭曲图片
shearX(g, width, height, backColor);
shearY(g, width, height, backColor);
private static void shearX(Graphics g, int w1, int h1, Color color) {
Random random=new Random();
int period = 2; boolean borderGap = true;
int frames = 1;
int phase = random.nextInt(2); for (int i = 0; i < h1; i++) {
double d = (double) (period >> 1)* Math.sin((double) i / (double) period
+ (2.2831853071795862D * (double) phase)/ (double) frames);
g.copyArea(0, i, w1, 1, (int) d, 0);
if (borderGap) {
g.setColor(color);
g.drawLine((int) d, i, 0, i);
g.drawLine((int) d + w1, i, w1, i);
}
} } private static void shearY(Graphics g, int w1, int h1, Color color) {
Random random=new Random();
int period = random.nextInt(40) + 10; // 50; boolean borderGap = true;
int frames = 20;
int phase = random.nextInt(2);
for (int i = 0; i < w1; i++) {
double d = (double) (period >> 1)
* Math.sin((double) i / (double) period
+ (2.2831853071795862D * (double) phase)/ (double) frames);
g.copyArea(i, 0, 1, h1, 0, (int) d);
if (borderGap) {
g.setColor(color);
g.drawLine(i, (int) d, i, 0);
g.drawLine(i, (int) d + h1, i, h1);
} } }
6)添加噪点
噪点的添加实质上就是在画纸上没有规律的点点点...,所以用随机颜色随机位置来执行image.setRGB()方法最合适了
float yawpRate = 0.05f;// 噪声率
int area = (int) (yawpRate * width * height);//噪点数量
for (int i = 0; i < area; i++) {
int xxx = r.nextInt(width);
int yyy = r.nextInt(height);
int rgb = getRandomColor().getRGB();
image.setRGB(xxx, yyy, rgb);
}
7)封笔
以上一切画完之后,下一步就是封笔了,思来想去这样表达最合适,绘制完之后就是放好笔,收起画纸,这里就是返回BufferedImage对象
g.dispose();
return image;
输出目标位置
1)输出文件
这里写了一个简单的测试类,将图片输出成文件
public static void main(String[] args) {
String randomCode = CodeUtils.getRandomCode(CodeUtils.TYPE_NUM_CHAR, 4, null);
System.out.println(randomCode);
BufferedImage imageFromCode = ImageUtils.getImageFromCode(randomCode, 100, 50, 3, true, Color.WHITE, Color.BLACK, null);
try {
File file = new File("d:/test01.jpg");
ImageIO.write(imageFromCode,"jpg",file);
System.out.println("成功保存到:"+file.getAbsolutePath());
} catch (IOException e) {
System.out.println("保存失败");
e.printStackTrace();
}
}
效果图:

2)输出流
输出到流中也是用到和到文件中的方法,根据业务保存到目标位置即可
public static void outputStream(HttpServletRequest request,HttpServletResponse response){
try {
// 设置浏览器不缓存本页
response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Expires", "0");
// 生成验证码,写入用户session
String verifyCode = CodeUtils.getRandomCode(CodeUtils.TYPE_NUM_CHAR, 4, null);
request.getSession().setAttribute("imageVerify", verifyCode);
// 输出验证码给客户端
response.setContentType("image/jpeg");
BufferedImage bim = ImageUtils
.getImageFromCode(verifyCode, 47, 18, 3, true,
Color.WHITE, Color.BLACK, null);
ImageIO.write(bim, "JPEG", response.getOutputStream());
} catch (Exception e) {
}
return null;
}
总结
也没有比较深入的去分析绘制类,有需求可以通过调整位置参数来实现自己要的效果
java生成简单验证码图片的更多相关文章
- java生成随机验证码图片
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; i ...
- java 生成简单word(利用Itext工具),生成简单Excel,以及下载笔记
1.java 生成简单word(包含图片表格) pom中加入itext 相关依赖 <dependency> <groupId>com.lowagie</groupId&g ...
- struts2生成随机验证码图片
之前想做一个随机验证码的功能,自己也搜索了一下别人写的代码,然后自己重新用struts2实现了一下,现在将我自己实现代码贴出来!大家有什么意见都可以指出来! 首先是生成随机验证码图片的action: ...
- java生成汉字验证码
java实现的汉字输入验证码,主要包含两个类,一个是生成验证码,一个是判断验证码输入是否正确,实现原理非常简单,将汉字和干扰线生成图片并将汉字保存到session,前台获取每次生成验证码图片并用文本框 ...
- Java生成随机验证码
package com.tg.snail.core.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphic ...
- java生成简单Excel工作薄
前言: 代码都是建立在实际需求上的,上周做完一个调外部电影券接口的项目,这周产品又要excel表格,大致内容为:券所属影院.图片URL.等信息制作为excel表格,把每次同步过来的数据给他分析. jx ...
- 如何用java生成随机验证码
1.VerifyCode 类: 1 package com.HRuinger.enity; ImageIO.write(image, " ...
- java生成图形验证码
效果图 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.Buf ...
- Python利用PIL生成随机验证码图片
安装pillow: pip install pillow PIL中的Image等模块提供了创建图片,制作图片的功能,大致的步骤就是我们利用random生成6个随机字符串,然后利用PIL将字符串绘制城图 ...
随机推荐
- 20155219付颖卓《网络攻防》Exp4 恶意代码分析
一.基础问题回答 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操作有哪些,用什么方法来监控. 可以用window7自带的schtasks ...
- 蓝桥每周一题之1. 3n+1 问题
[问题描述] 考虑如下的序列生成算法:从整数 n 开始,如果 n 是偶数,把它除以 2:如果 n 是奇数,把它乘 3 加1.用新得到的值重复上述步骤,直到 n = 1 时停止.例如,n = 22 时该 ...
- 点击按钮下载图片(ie,FF,chrome)
参考网上的一些资料后,总结出来 <!DOCTYPE html><html> <head> <meta content="text/html; cha ...
- 2.4 逻辑运算符 &&(与)、||(或)、非(!)
一.逻辑运算符 &&(与).||(或).非(!) 逻辑运算符两边的表达式一定是布尔值,结果也是布尔值. 1.1.1 逻辑与 && => 表示并且.且的意思: tr ...
- Wpf TemplateBinding
TemplateBinding. ControlTemplate最终会被用到一个控件上,我们称这个控件为模板目标控件或者模板化控件,ControlTemplate里面的控件可以使用TemplateBi ...
- 贴图平移&凹凸贴图偏移
1. 平移(UV坐标动画) UV 坐标动画或 UV 平移的含义是,水平 (U) 和/或垂直 (V) 移动纹理的 UV 坐标,以产生复杂动画的错觉. 在以下示例中,火焰纹理沿着 U(水平)方向平移, ...
- wireshark相关知识
wireshark抓包原理如下 https://www.cnblogs.com/yhcreak/p/5911904.html
- PTA8
这个作业属于哪个课程 C语言程序设计2 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/software-engineering-class2-2018/ ...
- Linux安装JDK.8
E&T: CentOS_7.4 64位; jdk-8u191-linux-x64; Xftp5; Xshell5; P1.下载Linux环境下的jdk1.8 下载链接: https://www ...
- camelcase-hankerrank
int camelcase(string s) { int cnt=0; int a; for(int i=0;i<s.size();i++) { a=s[i]; if(65<=a& ...