需求:使用一些圖片和用戶輸入的文案合成圖片或者海報
使用三方庫
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字體普遍安裝好了,在服務器上沒有安裝文字字體需要安裝