话不多说,直接上成品
原底图
开始:入口:get()
package com.ruoyi.web.controller.picture;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.ImagEyeCopyHelper;
import com.ruoyi.common.utils.ImageUtils;
import com.ruoyi.system.service.IPictureService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory. annotation .Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation. Request Mapping;
import org.springframework.web.bind.annotation.RestController;
import javax .imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io. File ;
import java.io.FileOutputStream;
@Api(description = "图片生成控制器")
@RestController
@RequestMapping("/picture")
public class PictureController {
@Autowired
private IPictureService iPictureService;
@ApiOperation("生成图片")
@PostMapping("/generate")
public R generate() throws Exception {
return R.ok(iPictureService.generate());
}
public static void main(String[] args) throws Exception {
System.out.println(get());
}
public static String get() throws Exception {
String imageUrl = "";
final BufferedImage thumbImage = ImagEyeCopyHelper.getBaseImage(imageUrl);
// 先添加平铺式水印
ImageUtils.addWaterMark(thumbImage, "@是我小汤圆呀");
// 添加文字内容填充
Font font = new Font("微软雅黑", Font.PLAIN, 45);
Color red = new Color(255, 200, 0,255);
Color black = new Color(0, 0, 0, 255);
ImageUtils.addWaterMark(thumbImage, "大风吹倒梧桐树,自有旁人论短长。", red, font, 180, 320);
ImageUtils.addWaterMark(thumbImage, "针对同一件事,不同的人站在不同的角度,", black, font, 180, 510);
ImageUtils.addWaterMark(thumbImage, "会有不同的看法。任何事情都有评论,不要", black , font, 180, 610);
ImageUtils.addWaterMark(thumbImage, "太计较别人的看法,太计较别人的看法不是", black, font, 180, 710);
ImageUtils.addWaterMark(thumbImage, "一件好事,会迷失自我。", black, font, 180, 810);
ImageUtils.addWaterMark(thumbImage, "2022年10月26日", black, font, 700, 910);
ImageUtils.addWaterMark(thumbImage, "@是我小汤圆呀", black, font, 710, 1010);
// 写到本地
String path = "D:\\" + System.currentTimeMillis() + ".jpg";
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(path));
String formatName = path.substring(path.lastIndexOf(".") + 1);
System.out.println("formatName is :" + formatName);
ImageIO.write(thumbImage, formatName, new File(path));
out.close();
return null;
}
}
ImagEyeCopyHelper.java
package com.ruoyi.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io. InputStream ;
public class ImagEyeCopyHelper {
/**
* left代表图片距离画布最左端的距离
*/ private static final int left = 1320;
/**
* top代表图片距离画布最上端的距离
*/ private static final int top = 80;
/**
* 获取一张基础的图片素材底图
*
* @param userImagUrl 网络图片地址
* @return
* @throws IOException
*/ public static BufferedImage getBaseImage(String userImagUrl) throws IOException {
// 加载本地基础底图图片
InputStream inputStream = ImagEyeCopyHelper.class.getClassLoader().getResourceAsStream("picture/bg-clean-01.jpg");
BufferedImage thumbImage = ImageIO.read(inputStream);
Graphics2D g = thumbImage.createGraphics();
if (StringUtils.isEmpty(userImagUrl)) {
return thumbImage;
}
BufferedImage minImag = ImageUtils.getUrlByBufferedImage(userImagUrl);
// 先裁切成圆形
minImag = ImageUtils.convertCircular(minImag);
// 图片合成
g.drawImage(minImag.getScaledInstance(160, 160, Image.SCALE_SMOOTH), left, top, null);
return thumbImage;
}
}
ImageUtils.java
package com.ruoyi.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font. Font RenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class ImageUtils {
/**
* 通过网络获取图片
*
* @param url
* @return
*/ public static BufferedImage getUrlByBufferedImage(String url) {
try {
URL urlObj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) urlObj.openConnection();
// 连接超时
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setConnectTimeout(25000);
// 读取超时 --服务器响应比较慢,增大时间
conn.setReadTimeout(25000);
conn.setRequestMethod("GET");
conn.addRequestProperty("Accept-Language", "zh-cn");
conn.addRequestProperty("Content-type", "image/jpeg");
conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");
conn.connect();
BufferedImage bufImg = ImageIO.read(conn.getInputStream());
conn.disconnect();
return bufImg;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
*
* @param image 用户头像
* @return
* @throws IOException
*/ public static BufferedImage convertCircular(BufferedImage image) throws IOException {
int min;//若是长方形图片则按照边短的去裁剪成圆,如果没有这个就会变成椭圆
if (image.getWidth() > image.getHeight()) {
min = image.getHeight();
} else {
min = image.getWidth();
}
// 透明底的图片
BufferedImage bi2 = new BufferedImage(min, min, BufferedImage.TYPE_4BYTE_ABGR);
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, min, min);
Graphics2D g2 = bi2.createGraphics();
g2.setClip(shape);
// 使用 setRenderingHint 设置抗锯齿
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawImage(image, 0, 0, null);
// 设置颜色
g2.setBackground(Color.green);
g2.dispose();
return bi2;
}
/**
* 对图片上添加平铺式水印
*
* @param image
* @param text
* @throws IOException
*/ public static void addWaterMark(BufferedImage image, String text) {
if (StringUtils.isEmpty(text)) {
return;
}
int angel = -30;//旋转角度
int xpadding = 400;//每个水印水平间隔
int ypadding = 400;//每个水印垂直间隔
int fontSize = 22;
Graphics2D g = image.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//绘制原图片
float alpha = 1F;
AlphaComposite ac = AlphaComposite. getInstance (AlphaComposite.SRC_OVER, alpha);
g.setComposite(ac);
g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
g.setBackground(Color.BLACK);
//开始绘制水印
//水印字体
Font font = new Font("微软雅黑", Font.BOLD, fontSize);
g.setFont(font);
FontRenderContext frc = g.getFontRenderContext();
TextLayout tl = new TextLayout(text, font, frc);
//水印串宽度
int stringWidth = g.getFontMetrics(g.getFont()).charsWidth(text.toCharArray(), 0, text.length());
//旋转水印
g.rotate(Math.toRadians(angel), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
//水印透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1F));
// 字体色
g.setColor(Color.black);
int x = -image.getHeight() / 2;
int y = -image.getWidth() / 2;
//循环绘制
while (x < image.getWidth() + image.getHeight() / 2) {
y = -image.getWidth() / 2;
while (y < image.getHeight() + image.getWidth() / 2) {
Shape sha = tl.getOutline(AffineTransform.getTranslateInstance(x, y));
g.fill(sha);
y += ypadding;
}
x += stringWidth + xpadding;
}
//释放资源
g.dispose();
}
/**
* 对图片上添加文字 普通文字
*
* @param bufImg 源图片
* @param waterMarkContent 文字内容
* @param markContentColor 文字颜色
* @param font 文字字体
* @param x 坐标 左上角为起点
* @param y 坐标 左上角为起点
*/ public static void addWaterMark(BufferedImage bufImg, String waterMarkContent, Color markContentColor, Font font, int x, int y) {
try {
// 加水印
Graphics2D g = bufImg.createGraphics();
g.drawImage(bufImg, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
g.setColor(markContentColor); //根据图片的背景设置水印颜色
g.setFont(font); //设置字体
//设置水印的坐标
g.drawString(waterMarkContent, x, y); //画出水印
g.dispose();
} catch (Exception e) {
e.printStackTrace();
}
}
}
搞掂收工!
纯属抄书,有错提出,勿喷。