Java實現圖片合成的示例詳解

場景

前端有一個神器——canvas,這個畫佈標簽可以處理各種圖片的合成,可以精確到圖片的具體坐標,加水印,去水印,簡直不要太簡單!那java後端可以處理嗎?請大聲的告訴他,能,必須能!今天小編告訴你一個神器——image-combiner,合成圖片so easy!

環境

  • jdk1.8
  • spring boot

搭建

引入pom文件

<dependency>
    <groupId>com.freewayso</groupId>
    <artifactId>image-combiner</artifactId>
    <version>2.2.0</version>
</dependency>

定義核心接口ImageService

public interface ImageService {
    /**
     * 簡單圖片聚合
     * @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);

    /**
     * 復雜圖片聚合
     * @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);
}

定義核心接口實現類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{
            // 合成器(指定背景圖和輸出格式,整個圖片的寬高和相關計算依賴於背景圖,所以背景圖的大小是個基準)
            ImageCombiner combiner = new ImageCombiner(bgImageUrl, OutputFormat.JPG);
            // 加圖片元素,第二個參數是左邊界距,第三個參數是上邊距
            combiner.addImageElement(todoImage, 300, 300);
            // 加文本元素,第二個參數是字體大小,第三個參數是左邊界距,第四個參數是上邊距
            combiner.addTextElement(text, 60, 100, 960);
            // 執行圖片合並
            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));       //頭像
            //創建合成器(指定背景圖和輸出格式,整個圖片的寬高和相關計算依賴於背景圖,所以背景圖的大小是個基準)
            ImageCombiner combiner = new ImageCombiner(bgImageUrl, 1500, 0, ZoomMode.Height, OutputFormat.JPG);  //v1.1.4之後可以指定背景圖新寬高瞭(不指定則默認用圖片原寬高)

            //針對背景和整圖的設置
            combiner.setBackgroundBlur(30);     //設置背景高斯模糊(毛玻璃效果)
            combiner.setCanvasRoundCorner(100); //設置整圖圓角(輸出格式必須為PNG)

            //標題(默認字體為阿裡普惠、黑色,也可以自己指定Font對象)
            combiner.addTextElement(title, 0, 150, 1400)
                    .setCenter(true)        //居中繪制(會忽略x坐標,改為自動計算)
                    .setAlpha(.8f)         //透明度(0.0~1.0)
                    .setRotate(45)         //旋轉(0~360)
                    .setColor(Color.red);    //顏色

            //內容(設置文本自動換行,需要指定最大寬度(超出則換行)、最大行數(超出則丟棄)、行高)
            combiner.addTextElement(content, "微軟雅黑", 40, 150, 1480)
                    .setStrikeThrough(true)             //刪除線
                    .setAutoBreakLine(837, 2, 60);      //自動換行

            //商品圖(設置坐標、寬高和縮放模式,若按寬度縮放,則高度按比例自動計算)
            combiner.addImageElement(productImageUrl, 0, 160, 837, 0, ZoomMode.Width)
                    .setCenter(true)       //居中繪制(會忽略x坐標,改為自動計算)
                    .setRoundCorner(46);     //設置圓角

            //頭像(圓角設置一定的大小,可以把頭像變成圓的)
            combiner.addImageElement(avatar, 200, 1200)
                    .setRoundCorner(200);   //圓角

            //水印(設置透明度,0.0~1.0)
            combiner.addImageElement(waterMark, 630, 1200)
                    .setAlpha(.8f)         //透明度(0.0~1.0)
                    .setRotate(45)         //旋轉(0~360)
                    .setBlur(20);           //高斯模糊(1~100)

            //加入圓角矩形元素(版本>=1.2.0),作為二維碼的底襯
            combiner.addRectangleElement(138, 1707, 300, 300)
                    .setColor(Color.WHITE)
                    .setRoundCorner(50)     //該值大於等於寬高時,就是圓形,如設為300
                    .setAlpha(.8f);

            //二維碼(強制按指定寬度、高度縮放)
            combiner.addImageElement(qrCodeUrl, 138, 1707, 186, 186, ZoomMode.WidthHeight);

            //價格(元素對象也可以直接new,然後手動加入待繪制列表)
            TextElement textPrice = new TextElement("¥1290", 60, 230, 1300);
            textPrice.setColor(Color.red);          //紅色
            textPrice.setStrikeThrough(true);       //刪除線
            combiner.addElement(textPrice);         //加入待繪制集合

            //執行圖片合並
            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;
    }
}

測試ImageController

@RestController
@Slf4j
public class ImageController {

    @Resource
    HttpServletResponse response;

    @Autowired
    ImageService imageService;

    /**
     * 簡單圖片聚合
     * @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();
                }
            }
        }
    }

    /**
     * 復雜圖片聚合
     * @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";
        // 標題文本
        String title = "# 最愛的傢居";
        // 內容文本
        String content = "蘇格拉底說:“如果沒有那個桌子,可能就沒有那個水壺”";
        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();
                }
            }
        }
    }
}

測試效果

總結

從測試效果可以看到:

  • 實現瞭圖片和圖片的合成
  • 實現瞭圖片和文字的合成
  • 圖片和文字的位置都可以使用參數來動態修改(具體可以看代碼)

以上就是Java實現圖片合成的示例詳解的詳細內容,更多關於Java圖片合成的資料請關註WalkonNet其它相關文章!

推薦閱讀: