`
拓子轩
  • 浏览: 210638 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JAVA中图片验证码的生成

    博客分类:
  • java
阅读更多
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * 图片验证码生成工具类
 * 
 * @author tuozixuan
 */
public class ImageCodeHandler
{
    // 图片宽度默认值
    private int imageWidth = 100;

    // 图片高度默认值
    private int imageHeight = 50;

    // 图片验证码长度
    private int codeLength = 4;

    // 噪点率(噪点分布的疏密)
    private float yawpRate = 0.012f;

    // 字体大小
    private int fontSize = 28;

    // 图片是否需要扭曲变形
    private boolean isDistortion = true;
    
    // 图片验证码
    private String imageCode = "";

    // 输出的图片格式
    private static final String imageFormat = "jpg";

    // 0,1,2易和字母的o,l,z易混淆,不生成,可以生成汉字
    private static char[] captchars = new char[] { '2', '3', '4', '5', '6', '7', '8', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
            'p', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U',
            'V', 'W', 'X', 'Y' };

    /**
     * 把生成的验证码图片写到指定目录文件中
     * 
     * @param filePath 目录文件
     * @throws IOException
     */
    public void createImageFile(String filePath) throws IOException
    {
        OutputStream fos = new FileOutputStream(new File(filePath));
        BufferedImage bufferedImage = createImage(getImageWidth(), getImageHeight());
        ImageIO.write(bufferedImage, imageFormat, fos);
    }

    /**
     * 把创建好的图片验证码放入输出流中
     * 
     * @param os 输出流
     * @throws IOException
     */
    public String createImage(OutputStream os) throws IOException
    {
        BufferedImage bufferedImage = createImage(getImageWidth(), getImageHeight());
        ImageIO.write(bufferedImage, imageFormat, os);
        return this.imageCode;
    }

    /**
     * 创建指定宽高的验证码图片对象
     * 
     * @param imageWidth 图片宽度
     * @param imageHeight 图片高度
     * @return BufferedImage 图片对象
     */
    public BufferedImage createImage(int imageWidth, int imageHeight)
    {
        // 创建一个指定宽高并带索引的字节图像对象
        BufferedImage bufferedImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_BYTE_INDEXED);

        // 创建一个二维图形对象以进行更复杂的图像绘制
        Graphics2D graphics2D = bufferedImage.createGraphics();

        // 设置背景色
        Color color = getRandomColor(200, 250);
        graphics2D.setColor(color);

        // 填充指定宽高的矩形,其中x,y坐标为0
        graphics2D.fillRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());

        // 加字符
        graphics2D.setColor(getRandomColor());
        drawString(graphics2D, getCodeLength());
        //drawCnString(graphics2D, getCodeLength());

        // 加一道线
        drawThickLine(graphics2D, 0, imageWidth / (2) + 1, imageWidth, imageHeight / (3) + 1, 4, getRandomColor(100, 200));

        // 加干扰短线
        setLTAttachLine(graphics2D, imageWidth, imageHeight);
        setRBAttachLine(graphics2D, imageWidth, imageHeight);

        // 使图片扭曲
        if (isDistortion)
        {
            shear(graphics2D, bufferedImage.getWidth(), bufferedImage.getHeight(), color);
        }

        // 设置噪点
        setYawp(bufferedImage, getYawpRate());

        return bufferedImage;
    }

    /**
     * 在图片上画上字符
     * 
     * @param graphics2D 图形对象
     * @param length 字符长度
     */
    private void drawString(Graphics2D graphics2D, int length)
    {
        int car = captchars.length - 1;
        Random random = new Random();

        // 随机写字母或汉字
        String text = "";
        for (int i = 0; i < length; i++)
        {
            // 1.随机得到num个字母或数字
            text += captchars[random.nextInt(car) + 1];
        }
        this.imageCode = text;

        int xOffset = 1 + new Random().nextInt(40);
        int yOffset = 30;

        char[] charArray = text.toCharArray();
        for (int i = 0; i < charArray.length; i++)
        {
            graphics2D.setFont(getRandomFont());
            graphics2D.drawString(String.valueOf(charArray[i]), xOffset, yOffset);
            xOffset = xOffset + 14 + new Random().nextInt(5);
        }
    }

    private void drawCnString(Graphics2D graphics2D, int length)
    {

        int xOffset = 1 + new Random().nextInt(40);
        int yOffset = 30;
        for (int i = 0; i < length; i++)
        {
            graphics2D.setFont(getRandomCnFont());
            graphics2D.drawString(String.valueOf(getRandomCnChar()), xOffset, yOffset);
            xOffset = xOffset + 20 + new Random().nextInt(5);
        }
    }

    /**
     * 从左上到右下加上多道干扰线
     */
    private static void setLTAttachLine(Graphics2D graphics2D, int imageWidth, int imageHeight)
    {
        int lineLeft = 7;// 从左上到右下的线条个数
        Random random = new Random();
        for (int i = 0; i < lineLeft; i++)
        {
            int x = random.nextInt(imageWidth - 1);
            int y = random.nextInt(imageHeight - 1);
            int xl = random.nextInt(6) + 1;
            int yl = random.nextInt(12) + 1;
            graphics2D.drawLine(x, y, x + xl + 40, y + yl + 20);
        }
    }

    /**
     * 从右上到左下加多道干扰线
     */
    private static void setRBAttachLine(Graphics2D graphics2D, int imageWidth, int imageHeight)
    {

        int lineRight = 8;// 从右上到左下的线条个数
        Random random = new Random();
        for (int i = 0; i < lineRight; i++)
        {
            int x = random.nextInt(imageWidth - 1);
            int y = random.nextInt(imageHeight - 1);
            int xl = random.nextInt(12) + 1;
            int yl = random.nextInt(6) + 1;
            graphics2D.drawLine(x, y, x - xl + 40, y - yl);
        }
    }

    /**
     * 设置噪点
     * 
     * @param bufferedImage 图片对象
     * @param yawpRate 噪声率
     */
    private static void setYawp(BufferedImage bufferedImage, float yawpRate)
    {
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();

        int area = (int) (yawpRate * width * height);
        Random random = new Random();
        for (int i = 0; i < area; i++)
        {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int rgb = getRandomIntColor();
            bufferedImage.setRGB(x, y, rgb);
        }
    }

    private static int getRandomIntColor()
    {
        int[] rgb = getRandomRgb();
        int color = 0;
        for (int c : rgb)
        {
            color = color << 8;
            color = color | c;
        }
        return color;
    }

    private static int[] getRandomRgb()
    {
        int[] rgb = new int[3];
        Random random = new Random();
        for (int i = 0; i < 3; i++)
        {
            rgb[i] = random.nextInt(255);
        }
        return rgb;
    }

    /**
     * 随机得到一个汉字的方法
     * 
     * @return char
     */
    protected char getRandomCnChar()
    {
        final int minFirstByte = 176;
        final int maxFirstByte = 215;
        final int minSecondByte = 161;
        final int maxSecondByte = 249;

        byte[] b = new byte[2];
        b[0] = (byte) (getRandomIntBetween(minFirstByte, maxFirstByte));
        b[1] = (byte) (getRandomIntBetween(minSecondByte, maxSecondByte));
        try
        {
            String s = new String(b, "gb2312");
            System.out.println(s);
            assert s.length() == 1;
            return s.toCharArray()[0];
        }
        catch (UnsupportedEncodingException uee)
        {
            // 重试
            return getRandomCnChar();
        }
    }

    /**
     * 获取两个整数之间的某个随机数,包含较小的整数,不包含较大的整数
     * 
     * @param first 第一个整数
     * @param second 第二个整数
     * @return
     */
    private static int getRandomIntBetween(int first, int second)
    {
        Random random = new Random();
        if (second < first)
        {
            int tmp = first;
            first = second;
            second = tmp;
        }
        return random.nextInt(second - first) + first;
    }

    /**
     * 产生随机字体
     */
    private Font getRandomFont()
    {
        Random random = new Random();
        Font font[] = new Font[5];
        int fontSize = getFontSize();
        font[0] = new Font("Algerian", Font.PLAIN, fontSize);
        font[1] = new Font("Antique Olive Compact", Font.PLAIN, fontSize);
        font[2] = new Font("Fixedsys", Font.PLAIN, fontSize);
        font[3] = new Font("Algerian", Font.PLAIN, fontSize);
        font[4] = new Font("Arial", Font.PLAIN, fontSize);
        return font[random.nextInt(5)];
    }

    /**
     * 产生随机中文字体
     */
    private Font getRandomCnFont()
    {
        Random random = new Random();
        Font font[] = new Font[5];
        int fontSize = getFontSize();
        font[0] = new Font("微软雅黑", Font.PLAIN, fontSize);
        font[1] = new Font("宋体", Font.PLAIN, fontSize);
        font[2] = new Font("新宋体", Font.PLAIN, fontSize);
        font[3] = new Font("楷体", Font.PLAIN, fontSize);
        font[4] = new Font("幼圆", Font.PLAIN, fontSize);
        return font[random.nextInt(5)];
    }

    /**
     * 给定范围获得随机颜色
     * 
     * @param fc 颜色范围-小
     * @param bc 颜色范围-大
     * @return Color 随机颜色
     */
    private static Color getRandomColor(int fc, int bc)
    {
        if (fc > 255)
        {
            fc = 255;
        }
        if (bc > 255)
        {
            bc = 255;
        }
        Random random = new Random();
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }

    private static Color getRandomColor()
    {
        Random random = new Random();
        Color color[] = new Color[10];
        color[0] = new Color(32, 158, 25);
        color[1] = new Color(218, 42, 19);
        color[2] = new Color(31, 75, 208);
        return color[random.nextInt(3)];
    }

    // 画一道粗线的方法
    private static void drawThickLine(Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c)
    {

        // The thick line is in fact a filled polygon
        g.setColor(c);
        int dX = x2 - x1;
        int dY = y2 - y1;
        // line length
        double lineLength = Math.sqrt(dX * dX + dY * dY);

        double scale = (double) (thickness) / (2 * lineLength);

        // The x and y increments from an endpoint needed to create a
        // rectangle...
        double ddx = -scale * (double) dY;
        double ddy = scale * (double) dX;
        ddx += (ddx > 0) ? 0.5 : -0.5;
        ddy += (ddy > 0) ? 0.5 : -0.5;
        int dx = (int) ddx;
        int dy = (int) ddy;

        // Now we can compute the corner points...
        int xPoints[] = new int[4];
        int yPoints[] = new int[4];

        xPoints[0] = x1 + dx;
        yPoints[0] = y1 + dy;
        xPoints[1] = x1 - dx;
        yPoints[1] = y1 - dy;
        xPoints[2] = x2 - dx;
        yPoints[2] = y2 - dy;
        xPoints[3] = x2 + dx;
        yPoints[3] = y2 + dy;

        g.fillPolygon(xPoints, yPoints, 4);
    }

    private static void shearX(Graphics g, int w1, int h1, Color color)
    {

        Random random = new Random();
        int period = random.nextInt(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 + (6.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 = 7;
        for (int i = 0; i < w1; i++)
        {
            double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.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);
            }

        }

    }

    /**
     * 使图片扭曲
     * 
     * @param graphics 图形对象
     * @param width 宽度
     * @param height 高度
     * @param color 颜色对象
     */
    private static void shear(Graphics graphics, int width, int height, Color color)
    {
        shearX(graphics, width, height, color);
        shearY(graphics, width, height, color);
    }

    public int getImageWidth()
    {
        return imageWidth;
    }

    public void setImageWidth(int imageWidth)
    {
        if (imageWidth > 0)
        {
            this.imageWidth = imageWidth;
        }
    }

    public int getImageHeight()
    {
        return imageHeight;
    }

    public void setImageHeight(int imageHeight)
    {
        if (imageHeight > 0)
        {
            this.imageHeight = imageHeight;
        }
    }

    public int getCodeLength()
    {
        return codeLength;
    }

    public void setCodeLength(int codeLength)
    {
        if (codeLength > 0)
        {
            this.codeLength = codeLength;
        }
    }

    public float getYawpRate()
    {
        return yawpRate;
    }

    public void setYawpRate(float yawpRate)
    {
        this.yawpRate = yawpRate;
    }

    public int getFontSize()
    {
        return fontSize;
    }

    public void setFontSize(int fontSize)
    {
        this.fontSize = fontSize;
    }

    public boolean isDistortion()
    {
        return isDistortion;
    }

    public void setDistortion(boolean isDistortion)
    {
        this.isDistortion = isDistortion;
    }
}

 

使用示例:

 

import com.cogcn.framework.util.ImageCodeHandler;

public class Test
{

    public static void main(String[] args) throws Exception
    {
        ImageCodeHandler handler = new ImageCodeHandler();
        handler.setCodeLength(4);
        handler.setImageWidth(100);
        handler.setImageHeight(50);
        handler.setYawpRate(0.2f);
        handler.setFontSize(18);
        handler.createImageFile("D:\\imageCode.jpg");
    }
}

 

分享到:
评论

相关推荐

    java生成图片验证码

    1. ValidateCodeImageCodeMade.java:这可能是验证码生成类的名称,它包含了生成随机字符串和创建图像的逻辑。这个类可能包含生成验证码字符串的方法,以及将字符串转化为图像的方法。其中可能包括对字体、颜色、...

    Java生成图片验证码工具类源码

    源码提供了一个生成图片验证码的工具类,适用于各种需要验证码的场景,如用户注册、...生成的验证码图片背景透明,线条清晰,可轻松辨认。本源码包含了工具类源码及调用示例,可供开发者参考使用,集成到您的项目中。

    Java生成算数运算中文图片验证码

    Java生成算数运算中文图片验证码的实现,结合了编程语言、图像处理和安全验证的多种技术,为用户提供了一种既安全又友好的验证方式。下面我们将深入探讨这个主题。 首先,验证码的核心是生成随机的算数运算表达式。...

    Java随机生成验证码图片

    Java随机生成验证码图片,适用于web登录验证等。个人觉得很不错~

    java 生成图片验证码

    在IT领域,验证码(CAPTCHA)是一...在提供的压缩包文件“图片验证码生成”中,可能包含了实现上述功能的源代码示例,你可以通过学习和理解这些代码,加深对Java生成图片验证码的理解,并根据实际需求进行调整和优化。

    Java生成图片验证码

    在本主题中,我们将深入探讨如何使用Java来生成图片验证码。Java生成图片验证码的过程涉及图像处理、随机数生成以及字符串编码等多个知识点。 首先,验证码的核心是生成一个随机的字符串,通常包含字母和数字。在...

    java生成图片的验证码工具类及其使用

    java生成验证码的工具类,这个现在有依赖可以直接引入调用,但这个工具类没有引入依赖,大家也容易看懂代码,理解其含义。也可直接去工具类中调整生成验证码的宽度、高度、颜色、背景颜色、生成的随机数数量、干扰线...

    Java servlet 自动生成 图片验证码 生成 Java源码

    Java servlet 自动生成 图片验证码 生成 Java源码

    JAVA图片验证码 图片验证码

    JAVA图片验证码 图片验证码JAVA图片验证码 图片验证码JAVA图片验证码 图片验证码JAVA图片验证码 图片验证码JAVA图片验证码 图片验证码JAVA图片验证码 图片验证码

    70.java验证码生成.zip

    70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java验证码生成.zip70.java...

    java 生成动态gif 验证码

    在Java开发中,生成动态GIF验证码是一种常见的安全机制,用于防止自动机器人或者恶意脚本对网站进行非法操作。这种验证码通常包含随机生成的字母、数字或者符号,以动画的形式展示,用户需要输入看到的验证码才能...

    JAVA实现随机图片验证码简单方法

    JAVA实现随机图片验证码简单方法.rtf

    Java实现点击文字验证码与拖动/滑动图片验证码(源码+demo+单元测试+实现思路)

    图片生成随机位置 随机中文文字、随机抠图、拼图都只需要用到BufferedImage和Graphics2D。 3.2.前端熟悉点击事件,根据点击事件的坐标位置、图片的位置、浏览器的滚动位置算 出点击图片的相对位置;熟悉拖动原理...

    java图片滑动验证码

    本资源是java生成图片滑动验证码源码,具体使用可参考https://blog.csdn.net/shiqiangwen/article/details/89888092

    java验证码生成验证

    csdn上三种java验证码生成方法,以及谷歌开源验证码,总共四种验证码生成集合。将生成的四个验证图片放在一个页面上以供比对,全部可以运行。 四种方法分别为: 1. 数字、字母、汉字混合验证码,叠影(给力)、扭曲 ...

    验证码生成工具类

    这个工具类是用Java语言编写的,因此我们可以深入探讨一下Java验证码生成的相关技术和实现。 验证码(CAPTCHA,Completely Automated Public Turing test to tell Computers and Humans Apart)的主要目标是区分...

    《java 图片验证码生成utils工具类》

    java 生成随机图片验证码 ,字母数组随机组合,加干扰线

    java验证码生成类

    这篇博客文章“java验证码生成类”提供了一个简单的示例,下面我们将深入探讨验证码生成的相关知识点。 首先,验证码的基本原理是生成一段随机的、难以由机器识别的文字或数字序列,然后要求用户在限定时间内输入这...

    Java图片验证码生成工具类

    好看的图片验证码,包含干扰线、噪点、扭曲图片等。。

    java完美的验证码生成

    本教程将详细讲解如何在Java环境下实现一个完美的、可定制的验证码生成系统。 首先,验证码的基本原理是生成一串随机字符串,并将其与图像结合,用户在看到图像后需输入对应的字符串,服务器端会验证用户输入的字符...

Global site tag (gtag.js) - Google Analytics