All Downloads are FREE. Search and download functionalities are using the official Maven repository.

me.aifaq.commons.lang.ImageVerifyCodeUtil Maven / Gradle / Ivy

The newest version!
package me.aifaq.commons.lang;

import com.google.common.base.Preconditions;
import me.aifaq.commons.lang.annotation.ThreadSafe;
import org.apache.commons.lang3.tuple.Pair;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 获取图片验证码
 */
@ThreadSafe
public class ImageVerifyCodeUtil {
	public static final ImageVerifyCodeUtil INSTANCE = new ImageVerifyCodeUtil();

	private static final int DEFAULT_IMG_WIDTH = 112;
	private static final int DEFAULT_IMG_HEIGHT = 56;
	// 默认的验证码数量,默认四个
	private static final int DEFAULT_CODE_COUNT = 4;

	public static enum CodeType {
		// 数字
		NUMBER,
		// 字母
		CHAR,
		// 混合
		MIXED,
	}

	private final int imgWidth;
	private final int imgHeight;
	private final CodeType codeType;
	private final int codeCount;

	private final int codeX;

	private final int fontHeight;

	private final int codeY;

	ImageVerifyCodeUtil() {
		this(DEFAULT_IMG_WIDTH, DEFAULT_IMG_HEIGHT, CodeType.MIXED, DEFAULT_CODE_COUNT);
	}

	/**
	 * @param imgWidth  验证码图片宽度
	 * @param imgHeight 验证码图片高度
	 * @param codeType  验证码类型
	 * @param codeCount 验证码数量
	 */
	public ImageVerifyCodeUtil(int imgWidth, int imgHeight, CodeType codeType, int codeCount) {
		Preconditions.checkArgument(imgWidth > 0);
		Preconditions.checkArgument(imgHeight > 0);
		Preconditions.checkNotNull(codeType);
		Preconditions.checkArgument(codeCount > 0);

		this.imgWidth = imgWidth;
		this.imgHeight = imgHeight;
		this.codeType = codeType;
		this.codeCount = codeCount;

		this.codeX = imgWidth / (codeCount + 1);
		this.fontHeight = imgHeight - 2;
		this.codeY = imgHeight - 12;
	}

	/**
	 * 生成图片验证码
	 *
	 * @return Pair<验证码, 图片流>
	 */
	public Pair generate() {
		// 在内存中创建图象
		BufferedImage image = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);

		// 获取图形上下文
		Graphics2D g = image.createGraphics();
		image = g.getDeviceConfiguration()
				.createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);

		g.dispose();

		g = image.createGraphics();

		// 设定背景色
		//	g.setColor(new Color(250,0,0));
		//	g.fillRect(0, 0, imgWidth, imgHeight);

		// 设定字体
		g.setFont(new Font(Font.SANS_SERIF, Font.PLAIN + Font.ITALIC, fontHeight));

		// 画边框
		//g.setColor(new Color(55, 55, 12));
		//g.drawRect(0, 0, imgWidth - 1, imgHeight - 1);

		// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 160; i++) {
			int x = ThreadLocalRandom.current().nextInt(imgWidth);
			int y = ThreadLocalRandom.current().nextInt(imgHeight);
			int xl = ThreadLocalRandom.current().nextInt(12);
			int yl = ThreadLocalRandom.current().nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}

		// 取随机产生的认证码(4位数字)
		String sRand = "";
		int red = 0, green = 0, blue = 0;
		char[] arr;
		switch (codeType) {
		case NUMBER:
			arr = getNumberChar(codeCount);
			break;
		case CHAR:
			arr = getLetterChar(codeCount);
			break;
		default:
			arr = getMixedChar(codeCount);
			break;
		}

		for (int i = 0; i < codeCount; i++) {
			red = ThreadLocalRandom.current().nextInt(255);
			green = ThreadLocalRandom.current().nextInt(255);
			blue = ThreadLocalRandom.current().nextInt(255);
			sRand += String.valueOf(arr[i]);
			g.setColor(new Color(red, green, blue));
			g.drawString(String.valueOf(arr[i]), (i) * codeX + codeX / 3, codeY);
		}
		// 图象生效
		g.dispose();

		return Pair.of(sRand, image);
	}

	/**
	 * 给定范围获得随机颜色
	 */
	static Color getRandColor(int fc, int bc) {
		if (fc > 255) {
			fc = 255;
		}
		if (bc > 255) {
			bc = 255;
		}
		int r = fc + ThreadLocalRandom.current().nextInt(bc - fc);
		int g = fc + ThreadLocalRandom.current().nextInt(bc - fc);
		int b = fc + ThreadLocalRandom.current().nextInt(bc - fc);
		return new Color(r, g, b);
	}

	static char[] getNumberChar(int codeCount) {
		char[] arr = new char[codeCount];
		for (int i = 0; i < codeCount; i++) {
			int r = ThreadLocalRandom.current().nextInt(10) + 48;
			arr[i] = (char) r;
		}
		return arr;
	}

	static char[] getLetterChar(int codeCount) {
		char[] arr = new char[codeCount];
		for (int i = 0; i < codeCount; i++) {
			int r = ThreadLocalRandom.current().nextInt(26);
			int t = ThreadLocalRandom.current().nextInt(2);
			// 小写
			if (t == 0) {
				r += 97;
			}
			// 大写
			else {
				r += 65;
			}
			arr[i] = (char) r;
		}
		return arr;
	}

	static char[] getMixedChar(int codeCount) {
		char[] arr = new char[codeCount];
		for (int i = 0; i < codeCount; i++) {
			int r = ThreadLocalRandom.current().nextInt(26);
			int t = ThreadLocalRandom.current().nextInt(3);
			// 小写
			if (t == 0) {
				r += 97;
			}
			// 大写
			else if (t == 1) {
				r += 65;
			}
			//数字
			else {
				r = r % 10 + 48;
			}
			arr[i] = (char) r;
		}
		return arr;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy