java后端合成圖片的實(shí)現(xiàn)示例
場(chǎng)景
前端有一個(gè)神器——canvas,這個(gè)畫布標(biāo)簽可以處理各種圖片的合成,可以精確到圖片的具體坐標(biāo),加水印,去水印,簡(jiǎn)直不要太簡(jiǎn)單!那java后端可以處理嗎?請(qǐng)大聲的告訴他,能,必須能!今天小編告訴你一個(gè)神器——image-combiner,合成圖片so easy!
環(huán)境
- jdk1.8
- spring boot
搭建
引入pom文件
<dependency> <groupId>com.freewayso</groupId> <artifactId>image-combiner</artifactId> <version>2.2.0</version> </dependency>
定義核心接口ImageService
public interface ImageService { ? ? /** ? ? ?* 簡(jiǎn)單圖片聚合 ? ? ?* @param ? ? ?* @return void ? ? ?* @author liyajie ? ? ?* @createTime 2021/12/17 9:54 ? ? ?**/ ? ? InputStream generateSimpleImage(String text, String bgImageUrl, String todoImage, String localPath, Boolean saveLocal, Boolean saveOss); ? ? /** ? ? ?* 復(fù)雜圖片聚合 ? ? ?* @param ? ? ?* @return void ? ? ?* @author liyajie ? ? ?* @createTime 2021/12/17 9:54 ? ? ?**/ ? ? InputStream generateComplexImage(String title, String content, String bgImageUrl, String qrCodeUrl, String productImageUrl, String waterMarkImageUrl, String avatarImageUrl, String localPath, Boolean saveLocal, Boolean saveOss); }
定義核心接口實(shí)現(xiàn)類ImageServiceImpl
@Service public class ImageServiceImpl implements ImageService { ? ? @Override ? ? public InputStream generateSimpleImage(String text, String bgImageUrl, String todoImage, String localPath, Boolean saveLocal, Boolean saveOss) { ? ? ? ? InputStream is = null; ? ? ? ? try{ ? ? ? ? ? ? // 合成器(指定背景圖和輸出格式,整個(gè)圖片的寬高和相關(guān)計(jì)算依賴于背景圖,所以背景圖的大小是個(gè)基準(zhǔn)) ? ? ? ? ? ? ImageCombiner combiner = new ImageCombiner(bgImageUrl, OutputFormat.JPG); ? ? ? ? ? ? // 加圖片元素,第二個(gè)參數(shù)是左邊界距,第三個(gè)參數(shù)是上邊距 ? ? ? ? ? ? combiner.addImageElement(todoImage, 300, 300); ? ? ? ? ? ? // 加文本元素,第二個(gè)參數(shù)是字體大小,第三個(gè)參數(shù)是左邊界距,第四個(gè)參數(shù)是上邊距 ? ? ? ? ? ? combiner.addTextElement(text, 60, 100, 960); ? ? ? ? ? ? // 執(zhí)行圖片合并 ? ? ? ? ? ? combiner.combine(); ? ? ? ? ? ? // 可以獲取流(并上傳oss等) ? ? ? ? ? ? is = combiner.getCombinedImageStream(); ? ? ? ? ? ? // 保存到本地 ? ? ? ? ? ? if(saveLocal){ ? ? ? ? ? ? ? ? combiner.save(localPath); ? ? ? ? ? ? } ? ? ? ? ? ? // 保存到oss ? ? ? ? ? ? if(saveOss){ ? ? ? ? ? ? ? ? // TODO: 2021/12/17 保存到oss ? ? ? ? ? ? } ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return is; ? ? } ? ? @Override ? ? public InputStream generateComplexImage(String title, String content, String bgImageUrl, String qrCodeUrl, String productImageUrl, String waterMarkImageUrl, String avatarImageUrl, String localPath, Boolean saveLocal, Boolean saveOss) { ? ? ? ? InputStream is = null; ? ? ? ? try{ ? ? ? ? ? ? BufferedImage waterMark = ImageIO.read(new URL(waterMarkImageUrl)); //水印圖 ? ? ? ? ? ? BufferedImage avatar = ImageIO.read(new URL(avatarImageUrl)); ? ? ? //頭像 ? ? ? ? ? ? //創(chuàng)建合成器(指定背景圖和輸出格式,整個(gè)圖片的寬高和相關(guān)計(jì)算依賴于背景圖,所以背景圖的大小是個(gè)基準(zhǔn)) ? ? ? ? ? ? ImageCombiner combiner = new ImageCombiner(bgImageUrl, 1500, 0, ZoomMode.Height, OutputFormat.JPG); ?//v1.1.4之后可以指定背景圖新寬高了(不指定則默認(rèn)用圖片原寬高) ? ? ? ? ? ? //針對(duì)背景和整圖的設(shè)置 ? ? ? ? ? ? combiner.setBackgroundBlur(30); ? ? //設(shè)置背景高斯模糊(毛玻璃效果) ? ? ? ? ? ? combiner.setCanvasRoundCorner(100); //設(shè)置整圖圓角(輸出格式必須為PNG) ? ? ? ? ? ? //標(biāo)題(默認(rèn)字體為阿里普惠、黑色,也可以自己指定Font對(duì)象) ? ? ? ? ? ? combiner.addTextElement(title, 0, 150, 1400) ? ? ? ? ? ? ? ? ? ? .setCenter(true) ? ? ? ?//居中繪制(會(huì)忽略x坐標(biāo),改為自動(dòng)計(jì)算) ? ? ? ? ? ? ? ? ? ? .setAlpha(.8f) ? ? ? ? //透明度(0.0~1.0) ? ? ? ? ? ? ? ? ? ? .setRotate(45) ? ? ? ? //旋轉(zhuǎn)(0~360) ? ? ? ? ? ? ? ? ? ? .setColor(Color.red); ? ?//顏色 ? ? ? ? ? ? //內(nèi)容(設(shè)置文本自動(dòng)換行,需要指定最大寬度(超出則換行)、最大行數(shù)(超出則丟棄)、行高) ? ? ? ? ? ? combiner.addTextElement(content, "微軟雅黑", 40, 150, 1480) ? ? ? ? ? ? ? ? ? ? .setStrikeThrough(true) ? ? ? ? ? ? //刪除線 ? ? ? ? ? ? ? ? ? ? .setAutoBreakLine(837, 2, 60); ? ? ?//自動(dòng)換行 ? ? ? ? ? ? //商品圖(設(shè)置坐標(biāo)、寬高和縮放模式,若按寬度縮放,則高度按比例自動(dòng)計(jì)算) ? ? ? ? ? ? combiner.addImageElement(productImageUrl, 0, 160, 837, 0, ZoomMode.Width) ? ? ? ? ? ? ? ? ? ? .setCenter(true) ? ? ? //居中繪制(會(huì)忽略x坐標(biāo),改為自動(dòng)計(jì)算) ? ? ? ? ? ? ? ? ? ? .setRoundCorner(46); ? ? //設(shè)置圓角 ? ? ? ? ? ? //頭像(圓角設(shè)置一定的大小,可以把頭像變成圓的) ? ? ? ? ? ? combiner.addImageElement(avatar, 200, 1200) ? ? ? ? ? ? ? ? ? ? .setRoundCorner(200); ? //圓角 ? ? ? ? ? ? //水印(設(shè)置透明度,0.0~1.0) ? ? ? ? ? ? combiner.addImageElement(waterMark, 630, 1200) ? ? ? ? ? ? ? ? ? ? .setAlpha(.8f) ? ? ? ? //透明度(0.0~1.0) ? ? ? ? ? ? ? ? ? ? .setRotate(45) ? ? ? ? //旋轉(zhuǎn)(0~360) ? ? ? ? ? ? ? ? ? ? .setBlur(20); ? ? ? ? ? //高斯模糊(1~100) ? ? ? ? ? ? //加入圓角矩形元素(版本>=1.2.0),作為二維碼的底襯 ? ? ? ? ? ? combiner.addRectangleElement(138, 1707, 300, 300) ? ? ? ? ? ? ? ? ? ? .setColor(Color.WHITE) ? ? ? ? ? ? ? ? ? ? .setRoundCorner(50) ? ? //該值大于等于寬高時(shí),就是圓形,如設(shè)為300 ? ? ? ? ? ? ? ? ? ? .setAlpha(.8f); ? ? ? ? ? ? //二維碼(強(qiáng)制按指定寬度、高度縮放) ? ? ? ? ? ? combiner.addImageElement(qrCodeUrl, 138, 1707, 186, 186, ZoomMode.WidthHeight); ? ? ? ? ? ? //價(jià)格(元素對(duì)象也可以直接new,然后手動(dòng)加入待繪制列表) ? ? ? ? ? ? TextElement textPrice = new TextElement("¥1290", 60, 230, 1300); ? ? ? ? ? ? textPrice.setColor(Color.red); ? ? ? ? ?//紅色 ? ? ? ? ? ? textPrice.setStrikeThrough(true); ? ? ? //刪除線 ? ? ? ? ? ? combiner.addElement(textPrice); ? ? ? ? //加入待繪制集合 ? ? ? ? ? ? //執(zhí)行圖片合并 ? ? ? ? ? ? combiner.combine(); ? ? ? ? ? ? //可以獲取流(并上傳oss等) ? ? ? ? ? ? is = combiner.getCombinedImageStream(); ? ? ? ? ? ? //保存到本地 ? ? ? ? ? ? if(saveLocal){ ? ? ? ? ? ? ? ? combiner.save(localPath); ? ? ? ? ? ? } ? ? ? ? ? ? //保存到oss ? ? ? ? ? ? if(saveOss){ ? ? ? ? ? ? ? ? // TODO: 2021/12/17 保存到oss ? ? ? ? ? ? } ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? } ? ? ? ? return is; ? ? } }
測(cè)試ImageController
@RestController @Slf4j public class ImageController { ? ? @Resource ? ? HttpServletResponse response; ? ? @Autowired ? ? ImageService imageService; ? ? /** ? ? ?* 簡(jiǎn)單圖片聚合 ? ? ?* @param ? ? ?* @return void ? ? ?* @author liyajie ? ? ?* @createTime 2021/12/17 10:43 ? ? ?**/ ? ? @GetMapping("/createSimpleImage") ? ? public void createSimpleImage(){ ? ? ? ? OutputStream os = null; ? ? ? ? try { ? ? ? ? ? ? String text = "周末大放送"; ? ? ? ? ? ? String bgImageUrl = "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"; ? ? ? ? ? ? String todoImage = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; ? ? ? ? ? ? // 圖片流 ? ? ? ? ? ? InputStream is = imageService.generateSimpleImage(text, bgImageUrl, todoImage,"",false,false); ? ? ? ? ? ? BufferedImage image = ImageIO.read(is); ? ? ? ? ? ? response.setContentType("image/png"); ? ? ? ? ? ? os = response.getOutputStream(); ? ? ? ? ? ? if (image != null) { ? ? ? ? ? ? ? ? ImageIO.write(image, "png", os); ? ? ? ? ? ? } ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? log.error("獲取圖片異常{}",e.getMessage()); ? ? ? ? } finally { ? ? ? ? ? ? if (os != null) { ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? os.flush(); ? ? ? ? ? ? ? ? ? ? os.close(); ? ? ? ? ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? /** ? ? ?* 復(fù)雜圖片聚合 ? ? ?* @param ? ? ?* @return void ? ? ?* @author liyajie ? ? ?* @createTime 2021/12/17 10:43 ? ? ?**/ ? ? @GetMapping("/createComplexImage") ? ? public void createComplexImage(){ ? ? ? ? // 背景圖 ? ? ? ? String bgImageUrl = "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"; ? ? ? ? // 二維碼 ? ? ? ? String qrCodeUrl = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; ? ? ? ? // 商品圖 ? ? ? ? String productImageUrl = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; ? ? ? ? // 水印圖 ? ? ? ? String waterMark = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; ? ? ? ? // 頭像 ? ? ? ? String avatar = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"; ? ? ? ? // 標(biāo)題文本 ? ? ? ? String title = "# 最愛的家居"; ? ? ? ? // 內(nèi)容文本 ? ? ? ? String content = "蘇格拉底說(shuō):“如果沒(méi)有那個(gè)桌子,可能就沒(méi)有那個(gè)水壺”"; ? ? ? ? OutputStream os = null; ? ? ? ? try{ ? ? ? ? ? ? // 圖片流 ? ? ? ? ? ? InputStream is = imageService.generateComplexImage(title, content, bgImageUrl, qrCodeUrl, productImageUrl, waterMark, avatar,"",false,false); ? ? ? ? ? ? BufferedImage image = ImageIO.read(is); ? ? ? ? ? ? response.setContentType("image/png"); ? ? ? ? ? ? os = response.getOutputStream(); ? ? ? ? ? ? if (image != null) { ? ? ? ? ? ? ? ? ImageIO.write(image, "png", os); ? ? ? ? ? ? } ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? }finally { ? ? ? ? ? ? if (os != null) { ? ? ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? ? ? os.flush(); ? ? ? ? ? ? ? ? ? ? os.close(); ? ? ? ? ? ? ? ? }catch (Exception e){ ? ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? } }
測(cè)試效果
總結(jié)
從測(cè)試效果可以看到:
- 實(shí)現(xiàn)了圖片和圖片的合成
- 實(shí)現(xiàn)了圖片和文字的合成
- 圖片和文字的位置都可以使用參數(shù)來(lái)動(dòng)態(tài)修改(具體可以看代碼)
附上開源地址:https://gitee.com/opensourcechen/image-combiner
到此這篇關(guān)于java后端合成圖片的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)java 合成圖片內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring的@Autowired加到接口上但獲取的是實(shí)現(xiàn)類的問(wèn)題
這篇文章主要介紹了Spring的@Autowired加到接口上但獲取的是實(shí)現(xiàn)類的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目
本文主要介紹了搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02Spring Boot整合Web項(xiàng)目常用功能詳解
這篇文章主要介紹了Spring Boot整合Web項(xiàng)目常用功能詳解,在Web應(yīng)用開發(fā)過(guò)程中,可以通過(guò)Spring Boot的Starter來(lái)將這些常用功能進(jìn)行整合與集中維護(hù),以達(dá)到開箱即用的目的。,需要的朋友可以參考下2019-06-06Java中的可變參數(shù)常見用法實(shí)例總結(jié)
這篇文章主要介紹了Java中的可變參數(shù)常見用法,結(jié)合實(shí)例形式總結(jié)分析了java可變參數(shù)的常見功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-10-10Springboot如何獲取上下文ApplicationContext
這篇文章主要介紹了Springboot如何獲取上下文ApplicationContext,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11