生成裂变海报
使用用户图像、昵称和邀请二维码,及企业logo、名称生成用户的分享裂变海报。
适用场景:拉新裂变活动,生成用户自己的分享裂变海报。
相关代码
ImageProcessException
public class ImageProcessException extends RuntimeException {
public ImageProcessException() {
}
public ImageProcessException(String message) {
super(message);
}
public ImageProcessException(String message, Throwable cause) {
super(message, cause);
}
public ImageProcessException(Throwable cause) {
super(cause);
}
public ImageProcessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
ImageUtils
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
public class ImageUtils {
/**
* 读取本地图片
*
* @param imgPath 图片读取路径,示例:"D:\\test.png"
*/
public static BufferedImage readFromLocal(String imgPath) {
checkValue(imgPath, "imgPath == null!");
try {
return ImageIO.read(new File(imgPath));
} catch (IOException e) {
throw new ImageProcessException("读取本地图片出错", e);
}
}
/**
* 读取图片数据流
*/
public static BufferedImage readFromStream(InputStream imgStream) {
checkValue(imgStream, "imgStream == null!");
try {
return ImageIO.read(imgStream);
} catch (IOException e) {
throw new ImageProcessException("读取图片数据流出错", e);
}
}
/**
* 读取网络图片
*/
public static BufferedImage readFromUrl(String imgUrl) {
checkValue(imgUrl, "imgUrl == null!");
try {
URL url = new URL(imgUrl);
return ImageIO.read(url);
} catch (IOException e) {
throw new ImageProcessException("读取网络图片出错", e);
}
}
/**
* 保存到本地
*
* @param imgPath 图片存储路径,示例:"D:\\test.png"
*/
public static void writeToLocal(BufferedImage image, String imgPath) {
checkValue(image, "image == null!");
checkValue(imgPath, "imgPath == null!");
int index = imgPath.lastIndexOf(".");
if (index < 0){
throw new ImageProcessException("图片没有设置保存格式后缀");
}
String suffix = imgPath.substring(index + 1);
image = imageFormat(image, suffix);
try {
ImageIO.write(image, suffix, new File(imgPath));
} catch (IOException e) {
throw new ImageProcessException("图片保存到本地出错", e);
}
}
/**
* 保存为 byte数组
*
* @param formatName 图片格式,示例:png、jpg、jpeg 等
*/
public static byte[] writeToBytes(BufferedImage image, String formatName) {
checkValue(image, "image == null!");
checkValue(formatName, "formatName == null!");
image = imageFormat(image, formatName);
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, formatName, os);
return os.toByteArray();
} catch (IOException e) {
throw new ImageProcessException("图片保存为 byte 数组出错", e);
}
}
/**
* 保存到数据流
*
* @param formatName 图片格式,示例:png、jpg、jpeg 等
*/
public static boolean writeToStream(BufferedImage image, String formatName, OutputStream os) {
checkValue(image, "image == null!");
checkValue(formatName, "formatName == null!");
checkValue(os, "os == null!");
image = imageFormat(image, formatName);
try {
return ImageIO.write(image, formatName, os);
} catch (IOException e) {
throw new ImageProcessException("图片保存到数据流出错", e);
}
}
/**
* 添加文字
*
* @param source 源图片
* @param text 添加的文字
* @param color 文字颜色
* @param x 距离左上角的X偏移量
* @param y 距离左上角的Y偏移量
*/
public static void addText(final BufferedImage source, String text, Color color, Font font, int x, int y) {
Graphics2D g = source.createGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
g.setStroke(new BasicStroke(3));
g.setColor(color);
if (font != null) {
g.setFont(font);
}
if (text != null) {
g.translate(0, 0);
g.drawString(text, x, y);
}
g.dispose();
}
/**
* 添加图片
*
* @param source 源图片
* @param addImage 添加的图片
* @param alpha 透明度。0.0~1.0: 完全透明~完全不透明
* @param x 距离左上角的X偏移量
* @param y 距离左上角的Y偏移量
*/
public static void addImage(final BufferedImage source, BufferedImage addImage, float alpha, int x, int y) {
Graphics2D g2d = source.createGraphics();
int width = addImage.getWidth();
int height = addImage.getHeight();
// 在图形和图像中实现混合和透明效果
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
g2d.drawImage(addImage, x, y, width, height, null);
g2d.dispose();
}
/**
* 图片尺寸调整
*
* @param source 源图片
* @param width 宽
* @param height 高
*/
public static BufferedImage resizeImage(BufferedImage source, int width, int height){
// 获取源图片透明度类型
int type = source.getColorModel().getTransparency();
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
BufferedImage image = new BufferedImage(width, height, type);
Graphics2D graphics2d = image.createGraphics();
// 抗锯齿
graphics2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 笔画归一化控制提示值 - 几何应归一化,以提高线条的均匀性或间距以及整体美感。
graphics2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
// 渲染提示值 - 选择渲染算法以优化输出质量。
graphics2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
Image tmp = source.getScaledInstance(sourceWidth, sourceHeight, Image.SCALE_SMOOTH);
graphics2d.drawImage(tmp, 0, 0, width, height, 0, 0, sourceWidth, sourceHeight, null);
graphics2d.dispose();
return image;
}
/**
* 正方形图片转圆形
*
* @param source 源图片
* @param diameter 直径
*/
public static BufferedImage convertCircular(BufferedImage source, int diameter){
// 透明底的图片
BufferedImage image = new BufferedImage(diameter, diameter, BufferedImage.TYPE_4BYTE_ABGR);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0,diameter, diameter);
Graphics2D g2 = image.createGraphics();
g2.setClip(shape);
// 抗锯齿
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 笔画归一化控制提示值 - 几何应归一化,以提高线条的均匀性或间距以及整体美感。
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
// 渲染提示值 - 选择渲染算法以优化输出质量。
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
// 抖动提示值 - 渲染几何时不要抖动。
g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
g2.drawImage(source, 0, 0,diameter, diameter, null);
// 设置颜色
g2.setBackground(Color.green);
g2.dispose();
return image;
}
private static void checkValue(Object value, String errorMsg) {
if (value == null) {
throw new IllegalArgumentException(errorMsg);
}
}
private static BufferedImage imageFormat(BufferedImage image, String formatName) {
if (!formatName.equalsIgnoreCase("jpg") && !formatName.equalsIgnoreCase("jpeg")) {
return image;
}
// 处理 jpg 和 jpeg 格式
BufferedImage formatImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_BGR);
Graphics g = formatImage.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return formatImage;
}
}
测试
public class ImageUtilsTest {
public static void main(String[] args) {
ClassLoader loader = ImageUtilsTest.class.getClassLoader();
BufferedImage image = readFromStream(loader.getResourceAsStream("海报模板.png"));
image = resizeImage(image, 828, 1792);
BufferedImage qrCodeImage = readFromStream(loader.getResourceAsStream("qrCode.png"));
qrCodeImage = resizeImage(qrCodeImage, 150, 150);
BufferedImage logoImage = readFromStream(loader.getResourceAsStream("logo.png"));
logoImage = resizeImage(logoImage, 70, 70);
BufferedImage userImage = readFromStream(loader.getResourceAsStream("用户图像.jpg"));
userImage = convertCircular(userImage, userImage.getHeight());
userImage = resizeImage(userImage, 70, 70);
Font font = new Font("Microsoft YaHei UI Light", Font.BOLD, 26);
addText(image,"测试", new Color(0,0,0), font,131, 127);
addText(image,"张三股份有限公司", new Color(0,0,0),font, 560, 127);
addImage(image, userImage, 1, 40, 80);
addImage(image, logoImage, 1, 470, 80);
addImage(image, qrCodeImage, 1,40, 1571);
writeToLocal(image, getProjectPath() + File.separator + "Image-" + System.currentTimeMillis() +".jpeg");
}
private static String getProjectPath() {
return System.getProperty("user.dir");
}
}
测试结果
本文来自博客园,作者:crazy_dev,转载请注明原文链接:https://www.cnblogs.com/crazy-dev/p/15399497.html