JAVA中图片验证码的生成
程序员文章站
2022-05-11 23:20:09
...
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"); } }
上一篇: maven安装与配置参考
下一篇: mybatis中的jdbcType配置