spring 小红书 旋转圆形验证码,实现方案
package io.github.smilexizheng.smileboot.common.utils.captcha;
import lombok.SneakyThrows;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
/**
* 旋转图形验证码
* 抗锯齿化,旋转图形不变形 等等
* 工具类
*
* @author smile
*/
public class CaptchaImageUtil {
private final static Logger log = LogManager.getLogger(CaptchaImageUtil.class);
/**
* 中心区域
*/
private static final int cropSize = 200;
/**
* 描边区域
*/
private static final int borderSize = 4;
/**
* 去图片的中心 为圆形
*
* @param is
* @return
*/
@SneakyThrows
public static BufferedImage cutCenterToCircle(InputStream is) {
BufferedImage originalImage = ImageIO.read(is);
int x = (originalImage.getWidth() - cropSize) / 2;
int y = (originalImage.getHeight() - cropSize) / 2;
BufferedImage croppedImage = Thumbnails.of(originalImage)
.sourceRegion(x, y, cropSize, cropSize)
.size(cropSize, cropSize)
.asBufferedImage();
BufferedImage resultImage = new BufferedImage(cropSize + borderSize * 2, cropSize + borderSize * 2, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resultImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillOval(0, 0, cropSize + borderSize * 2, cropSize + borderSize * 2);
g.setComposite(AlphaComposite.SrcIn);
g.setClip(new Ellipse2D.Float(borderSize, borderSize, cropSize, cropSize));
g.drawImage(croppedImage, borderSize, borderSize, null);
g.dispose();
return resultImage;
}
/**
* 图片中心置为为黑色
*
* @param is
* @return
*/
public static BufferedImage centerToBlack(InputStream is) {
return centerToColor(is, Color.BLACK, false);
}
/**
* 将图片中心改成任意颜色
*
* @param is 流
* @param color 颜色
* @param alpha 完全透明
* @return
*/
@SneakyThrows
public static BufferedImage centerToColor(InputStream is, Color color, boolean alpha) {
BufferedImage originalImage = ImageIO.read(is);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
int centerX = width / 2;
int centerY = height / 2;
BufferedImage resultImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resultImage.createGraphics();
g.drawImage(originalImage, 0, 0, null);
int x = centerX - cropSize / 2;
int y = centerY - cropSize / 2;
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 设置抗锯齿渲染
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (alpha) {
// 设置透明度为0,即完全透明
g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0));
} else {
g.setColor(color);
}
g.fillOval(x, y, cropSize, cropSize);
g.dispose();
return resultImage;
}
/**
* 旋转图片
*
* @param originalImage
* @param angle
* @return
*/
@SneakyThrows
public static BufferedImage rotate(BufferedImage originalImage, double angle) {
int width = originalImage.getWidth();
int height = originalImage.getHeight();
double radians = Math.toRadians(angle);
AffineTransform at = new AffineTransform();
at.rotate(radians, width / 2.0, height / 2.0);
BufferedImage rotatedImage = new BufferedImage(width, height, originalImage.getType());
Graphics2D g = rotatedImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 设置抗锯齿渲染
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(originalImage, at, null);
g.dispose();
return rotatedImage;
}
public static String toFile(BufferedImage bufferedImage, String fileName) throws Exception {
Assert.hasText(fileName, "输出路径不可为空!");
String path = new File(ResourceUtils.getURL("classpath:").getPath()).getAbsolutePath();
String s = "/static/" + fileName;
File file = new File(path, s);
Thumbnails.of(bufferedImage).scale(1).toFile(file);
return s;
}
public static String toFile(BufferedImage bufferedImage, String fileName, int width, int height) throws Exception {
Assert.hasText(fileName, "输出路径不可为空!");
String path = new File(ResourceUtils.getURL("classpath:").getPath()).getAbsolutePath();
String s = "/static/" + fileName;
File file = new File(path, s);
Thumbnails.of(bufferedImage).size(width, height).toFile(file);
return s;
}
}