功能介绍:通过Graphics2D在一张背景图上添加文字描述和图片。
合成效果示意图:
代码示例:
在代码中对每步操作做了详细的注释
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sinolife.sf.store.SFFile;
import com.sinolife.sf.store.TempFileFactory;
public class DrawImgtest{
private static final Logger logger = LoggerFactory.getLogger(DrawImgtest.class);
private static TempFileFactory temFileFactory = TempFileFactory.getInstance(DrawImgtest.class);
public static final String realPath = "C:\\Users\\yyyL\\Desktop\\合成\\";
public static final String backgroundImage = "background.png"; // 背景图片
public static final String qrCode = "qrCode.png"; // 二维码图片
public static final String card = "card-big-8.png"; // 插入的小卡片
private static String userId="121212122";
public static void main(String[] args) throws Exception {
Map<String, String> imageInfo1 = new HashMap<String, String>();
imageInfo1.put("img", card);
imageInfo1.put("desc", "小图上面的描述");
ByteArrayOutputStream outStream = compose(imageInfo1);
// TODO 保存生成的新图片
File outputfile = new File(realPath+"合成.png");
if (!outputfile.getParentFile().exists()) {
outputfile.getParentFile().mkdirs();
}
FileOutputStream fs = new FileOutputStream(outputfile);
fs.write(outStream.toByteArray());
fs.flush();
fs.close();
FileOutputStream out = null;
try {
// 将文件临时保存
SFFile tempFile = temFileFactory.createTempFile();
out = tempFile.openOutputStream();
byte[] b = outStream.toByteArray();
out.write(b);
out.flush();
// TODO 后面可以通过 tempFile进行文件上传啥的
} catch (Exception e) {
try {
if (outStream != null) {
outStream.close();
}
if (out != null) {
out.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private static ByteArrayOutputStream compose(Map<String,String> imageInfo1) {
OutputStream out = null;
try {
// 加载背景图片
BufferedImage imageLocal = ImageIO.read(new File(realPath+backgroundImage));
int backgroundWidth = imageLocal.getWidth();
int backgroundHeight = imageLocal.getHeight();
addText(imageLocal, "1张贺岁卡", new Font("微软雅黑", Font.PLAIN, 35),new Color(238, 65, 53),backgroundWidth,250);
// 待插入卡片图片
BufferedImage image1 = ImageIO.read(new File(realPath+imageInfo1.get("img")));
addText(image1, imageInfo1.get("desc"), new Font("微软雅黑", Font.PLAIN, 48),new Color(252, 219, 179),image1.getWidth(),70);
// 待插入二维码 190 200
BufferedImage qrCodeImg = ImageIO.read(new File(realPath+qrCode));
// 以背景图片为模板
Graphics2D g2d = imageLocal.createGraphics();
// 这里必须要先压缩小图大小,然后再合成,不压缩直接合成会造成小图不清晰
image1 = disposeImage(image1, 410, 550);
// TODO 输出小图
File outputfile1 = new File(realPath+"小图.png");
if (!outputfile1.getParentFile().exists()) {
outputfile1.getParentFile().mkdirs();
}
ImageIO.write(image1, "png", outputfile1);
// 将小图绘画在背景图片上,生成新图片, drawImage方法参数的x和y:绘制点距离左边距和上边距的像素。 width和height:表示绘制的小图的大小
g2d.drawImage(image1, (backgroundWidth - 410)/2, (backgroundHeight - 550)/2-90, 410, 550, null);
g2d.drawImage(qrCodeImg, (backgroundWidth - 150)/2, backgroundHeight-260, 150, 150, null);
g2d.dispose();
// 生成的新图片写入文件流
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ImageIO.write(imageLocal, "png", outStream);
return outStream;
} catch (Exception e) {
logger.error("DrawImgtest compose Exception: userId={}", userId, e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
}
}
}
return null;
}
/**
* 压缩图片大小
* @param src
* @param newWidth 新图片的宽度
* @param newHeight 新图片的高度
* @return
* @date 2021年11月23日
*/
private static BufferedImage disposeImage(BufferedImage image, int newWidth, int newHeight) {
// 得到源图长
BufferedImage newImg = null;
// 判断输入图片的类型
switch (image.getType()) {
case 13:
newImg = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_4BYTE_ABGR);
break;
default:
newImg = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
break;
}
Graphics2D g = newImg.createGraphics();
g.drawImage(image.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
g.dispose();
return newImg;
}
/**
* 渲染文字
* @param image1
* @param text
* @param font
* @param color
* @param width
* @param height
* @date 2021年12月15日
*/
private static void addText(BufferedImage image1,String text,Font font,Color color, int width, int height) {
if(StringUtils.isBlank(text)) {
return;
}
Graphics2D g2d = image1.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
JLabel jLabel = new JLabel();
FontMetrics fm = jLabel.getFontMetrics(font);
int textLength = fm.stringWidth(text);
g2d.setFont(font);
g2d.setColor(color);
g2d.drawString(text, (width - textLength) / 2,height); // 设置文字的内容居中,渲染位置
g2d.dispose();// 主动释放Graphics
}
}