需求:使用一些圖片和用戶輸入的文案合成圖片或者海報
使用三方庫
mvn管理
<!--圖片處理 start -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.6</version>
</dependency>
<!--
Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.6</version>
</dependency>
<!--圖片處理 end -->
實現方法
循環合成所有需求
import com.aaa.bbb.common.utils.HttpsUtils;
import com.aaa.bbb.common.utils.UploadImageUtil;
import com.aaa.bbb.common.vo.loan.LoanUserSynthesisListVo;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @Author
* @Date
**/
public class ImageUtils {
/**
* 操作合成圖片
* @param SynthesisList 操作單張合成圖
* @return
*/
public String optImage(List<SynthesisListVo> SynthesisList) {
try {
// 與前端約定 合成圖片列表的第一張圖片為底圖
SynthesisListVo backgroundImageInfo = SynthesisList.get(0);
//設置圖片大小 寬 高 網絡圖片
// 獲取網絡圖片
BufferedImage getBackgroundUrlImage = this.getUrlImage(backgroundImageInfo.getImageUrl());
BufferedImage background = this.resizeImagePng(backgroundImageInfo.getWidth(), backgroundImageInfo.getHeight(), getBackgroundUrlImage);
// 底部寬
Integer SynthesisListVo = backgroundImageInfo.getWidth();
//在背景圖片中添加入需要寫入的信息,
Graphics2D g = background.createGraphics(); // x58 y74.3
//設置為透明覆蓋
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f));
Boolean isFirst = true;
for (SynthesisListVo SynthesisListItem : SynthesisList) {
if (isFirst) {
isFirst = false;
continue;
}
if (SynthesisListItem.getType().equals("Image")) {
// 圖片處理 創建圖片
// 獲取網絡圖片
BufferedImage getUrlImage = this.getUrlImage(SynthesisListItem.getImageUrl());
// 重新定義圖片尺寸
BufferedImage userImage = this.resizeImagePng(SynthesisListItem.getWidth(), SynthesisListItem.getHeight(), getUrlImage);
// 圖片 偏移x 偏移y 圖片的寬 圖片的高
g.drawImage(userImage, SynthesisListItem.getOffsetX(), SynthesisListItem.getOffsetY(), userImage.getWidth(), userImage.getHeight(), null);
} else if (SynthesisListItem.getType().equals("Text")) {
// Font pinfang_44 = new Font("蘋方-簡 中黑體", Font.BOLD, 44);
Font pinfang = new Font(SynthesisListItem.getTextFontFamily(), Font.PLAIN, SynthesisListItem.getTextFontSize());
// 寫字
//指定字體
FontMetrics metrics = g.getFontMetrics(pinfang);
//指定要繪制的字符串
String useMeg = String.valueOf(SynthesisListItem.getText());
//得到字符串繪制寬度
int logoW = metrics.stringWidth(useMeg);
//計算繪制原點坐標,
//文本最左邊位於x軸logoX
// 判斷是否水平居中
int logoX = 0;
if (SynthesisListItem.getTextAlignCenter() != null && SynthesisListItem.getTextAlignCenter()) {
// 水平居中
logoX = (maxBackgroundWidth - logoW) / 2;
} else {
logoX = SynthesisListItem.getOffsetX();
}
//文本基於logoH
int logoH = SynthesisListItem.getOffsetY() + (metrics.getAscent());
//繪制文本框
g.setFont(pinfang);
g.setColor(new Color(SynthesisListItem.getTextColor().get(0),SynthesisListItem.getTextColor().get(1),SynthesisListItem.getTextColor().get(2)));
g.drawString(useMeg, logoX, logoH);
}
}
g.dispose();
//輸出圖片 上傳七牛
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(background, "png", out);
byte[] b = out.toByteArray();
String hash = UploadImageUtil.uploadByteImage(b);
if (StringUtils.isNotEmpty(hash)) {
// 返回圖片路徑
return UploadImageUtil.IMG_HOST + hash;
}
// ImageIO.write(background, "png", new FileOutputStream(outPutPath));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 獲取網絡圖片數據
* @param url
* @return
*/
public BufferedImage getUrlImage(String url) {
byte[] bytes = HttpsUtils.getBytes(url);
InputStream buffin = new ByteArrayInputStream(bytes,0,bytes.length);
BufferedImage img = null;
try {
img = ImageIO.read(buffin);
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
/**
* 重定義圖片尺寸
* @param x
* @param y
* @param bfi
* @return
*/
public BufferedImage resizeImagePng(int x, int y, BufferedImage bfi) {
BufferedImage bufferedImage = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB);
bufferedImage.getGraphics().drawImage(
bfi.getScaledInstance(x, y, Image.SCALE_SMOOTH), 0, 0, null);
return bufferedImage;
}
}
循環vo
package com.aaa.bbb.common.vo.loan;
import lombok.Data;
import java.util.List;
/**
* @Author
* @Date
**/
@Data
public class SynthesisListVo {
/**
* 類型 image text
*/
private String type;
/**
* 文案字體 type為text時生效
*/
private String textFontFamily;
/**
* 文案字體大小 type為text時生效
*/
private Integer textFontSize;
/**
* 文案是否水平居中 true水平居中 type為text時生效
*/
private Boolean textAlignCenter;
/**
* 文案顏色 type為2時生效
*/
private List<Integer> textColor;
/**
* 水平偏移量 type為text & textAlignCenter為true時失效
*/
private Integer offsetX;
/**
* 垂直偏移量
*/
private Integer offsetY;
/**
* 圖片地址 type為image時生效
*/
private String imageUrl;
/**
* 文案 type為text時生效
*/
private String text;
/**
* 寬度 type為image時生效
*/
private Integer width;
/**
* 高度 type為image時生效
*/
private Integer height;
}
參考文獻
https://blog.csdn.net/long703283343/article/details/102974284
https://www.cnblogs.com/fatetop/p/13914882.html
開發時需要的坑
1、網絡圖片下載的坑
解決:https://www.cnblogs.com/fatetop/p/13914882.html
獲取不到圖片的時候,調用重定義圖片尺寸報錯空指針
2、繪制文字時Windows字體普遍安裝好了,在服務器上沒有安裝文字字體需要安裝
