java-使用Graphics2d合成圖片和文字


需求:使用一些圖片和用戶輸入的文案合成圖片或者海報

使用三方庫

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字體普遍安裝好了,在服務器上沒有安裝文字字體需要安裝

https://www.cnblogs.com/Azi-mi/p/9955743.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM