java合并圖片與文字

通過java來繪制海報(bào)射亏,加載外部字體并設(shè)置樣式大小與加粗虫腋、設(shè)置背景圖莽红、合并圖片妥畏,下面是簡單示例

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;

/** java 繪制海報(bào)
 * author xiaochi
 * date 2024/11/8
 */
public class PosterCreatorTest{

    public static void main(String[] args) throws Exception {
        // 創(chuàng)建字體
        // Font font = new Font("微軟雅黑", Font.BOLD, 36);
        // 外部字體
        String fontPath = "D:\\workspace\\demo3\\src\\main\\resources\\font\\SmileySans2.ttf";
        Font font = Font.createFont(Font.TRUETYPE_FONT, new File(fontPath));
        // 合并到圖片上的文字
        String text = "歡迎來到我的世界";

        int width = 854;// 容器寬度
        int height = 1280;// 容器高度
        BufferedImage bgImage = ImageIO.read(new File("D:\\workspace\\demo3\\test1111.png"));
        BufferedImage combiner = combiner(width, height,null, bgImage, bgImage.getWidth(),bgImage.getHeight());
        Graphics2D g2d = combiner.createGraphics();
        // 繪制文本2(不換行)
        g2d.setColor(getColor("#1bdf1a"));
        g2d.drawString(text, 100, 100);
        // 釋放圖形上下文
        g2d.dispose();

        // 繪制文本1(換行)
        wrapText(combiner,text,font.deriveFont(Font.BOLD,26f),100,50,10,0,null);
        // 設(shè)置文本旋轉(zhuǎn)45°
        wrapText(combiner,text,font.deriveFont(26f),500,50,combiner.getWidth(),0,null);
        wrapText(combiner,text,font.deriveFont(26f),500,50,combiner.getWidth(),45,"#ea6f5a");

        // 合并圖片
        BufferedImage mergeImage = ImageIO.read(new File("D:\\02.png"));
        merge(combiner,mergeImage,100,100,100,500);

        try {
            // 保存圖片到文件
            //ImageIO.write(image, "PNG", new File("D:\\workspace\\demo3\\poster.png"));
            // 輸出文件流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(combiner,"png",out);
            byte[] bytes = out.toByteArray();
            out.close();
            FileOutputStream fileOutputStream = new FileOutputStream("D:\\workspace\\demo3\\poster333.png");
            fileOutputStream.write(bytes);
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 創(chuàng)建容器
     * @param combinerWidth 容器寬度
     * @param combinerHeight 容器高度
     * @param bgColor 背景色(默認(rèn)白色,且背景圖會覆蓋背景色)
     * @param bgImage 背景圖
     * @param bgImageWidth 背景圖寬度
     * @param bgImageHeight 背景圖高度
     * @return combiner容器
     */
    public static BufferedImage combiner(int combinerWidth,int combinerHeight,String bgColor,BufferedImage bgImage,int bgImageWidth,int bgImageHeight){
        BufferedImage combiner = new BufferedImage(combinerWidth,combinerHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = combiner.createGraphics();
        // 設(shè)置背景顏色
        g2d.setColor(Color.white);
        if (null != bgColor && !"".equals(bgColor)){
            g2d.setColor(getColor(bgColor));
        }
        g2d.fillRect(0, 0, combinerWidth, combinerHeight);
        // 添加背景圖片
        if (null != bgImage){
            // 添加背景圖片
            g2d.drawImage(bgImage,0,0,bgImageWidth,bgImageHeight,null);
        }
        // 釋放圖形上下文
        g2d.dispose();
        return combiner;
    }

    /**
     * 合并圖片
     * @param combiner 容器
     * @param mergeImage 待合并的圖片
     * @param width  待合并的圖片寬度
     * @param height 待合并的圖片高度
     * @param x 待合并的圖片x坐標(biāo)
     * @param y 待合并的圖片y坐標(biāo)
     */
    public static void merge(BufferedImage combiner,BufferedImage mergeImage,int width,int height,int x,int y){
        //BufferedImage image = new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = combiner.createGraphics();
        g2d.drawImage(mergeImage,x,y,width,height,null);
        g2d.dispose();
    }

    /**
     * 繪制文字
     * @param combiner 容器
     * @param text 文字
     * @param font 字體(包括大小、樣式安吁、顏色)
     * @param x 文字x坐標(biāo)
     * @param y 文字y坐標(biāo)
     * @param maxWidth 文字最大寬度(0為豎排顯示)
     * @param rotate 旋轉(zhuǎn)度數(shù)
     * @param color 文字顏色(如:#ffffff)
     */
    public static void wrapText(BufferedImage combiner,String text,Font font,int x,int y,int maxWidth,double rotate,String color){
        Graphics2D g2d = combiner.createGraphics();
        //設(shè)置字體
        g2d.setFont(font);
        // 設(shè)置文字顏色
        if (null != color && !"".equals(color)){
            g2d.setColor(getColor(color));
        }
        // 抗鋸齒屬性
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //提升觀感
        // 設(shè)置旋轉(zhuǎn)
        AffineTransform at = new AffineTransform();
        at.rotate(Math.toRadians(rotate),x,y); // 旋轉(zhuǎn)45度醉蚁,旋轉(zhuǎn)中心為(文字x坐標(biāo),100)
        g2d.setTransform(at);

        FontMetrics fontMetrics = g2d.getFontMetrics(font);
        String[] lines = splitText(text, maxWidth, fontMetrics); //實(shí)現(xiàn)文字自動(dòng)換行
        int lineHeight = g2d.getFontMetrics().getHeight();
        int ystart = y;
        for (String line : lines) {
            g2d.drawString(line, x, ystart);
            ystart += lineHeight;
        }
        g2d.dispose();
    }

    /**
     * 獲取顏色
     * @param color #2395439
     * @return
     */
    public static Color getColor(String color) {
        if (color.charAt(0) == '#') {
            color = color.substring(1);
        }
        if (color.length() != 6) {
            return null;
        }
        try {
            int r = Integer.parseInt(color.substring(0, 2), 16);
            int g = Integer.parseInt(color.substring(2, 4), 16);
            int b = Integer.parseInt(color.substring(4), 16);
            return new Color(r, g, b);
        } catch (NumberFormatException nfe) {
            return null;
        }
    }

    /**
     * 切割文字
     * @param text
     * @param maxWidth
     * @param fontMetrics
     * @return
     */
    private static String[] splitText(String text, int maxWidth, FontMetrics fontMetrics) {
        StringBuilder wrappedText = new StringBuilder();
        String[] words = text.split(""); //以每個(gè)字符做拆分,可根據(jù)實(shí)際需求做更改鬼店,下同
        List<String> lines = new ArrayList<>();
        for (String word : words) {
            // 檢查添加新單詞后是否會超過最大寬度
            if (wrappedText.length() > 0) {
                // 檢查加上新單詞后的總長度
                if (fontMetrics.stringWidth(wrappedText.toString() + word) > maxWidth) {
                    // 如果超過最大寬度网棍,將當(dāng)前字符串添加到行列表,并開始新的一行
                    lines.add(wrappedText.toString());
                    wrappedText = new StringBuilder(word);
                } else {
                    // 如果不超過最大寬度妇智,添加新單詞
                    wrappedText.append(word);
                }
            } else {
                wrappedText.append(word);
            }
        }
        // 添加最后一行
        if (wrappedText.length() > 0) {
            lines.add(wrappedText.toString());
        }
        // 將行列表轉(zhuǎn)換為數(shù)組
        return lines.toArray(new String[0]);
    }
}

OK了滥玷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市巍棱,隨后出現(xiàn)的幾起案子惑畴,更是在濱河造成了極大的恐慌,老刑警劉巖航徙,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件如贷,死亡現(xiàn)場離奇詭異,居然都是意外死亡到踏,警方通過查閱死者的電腦和手機(jī)杠袱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窝稿,“玉大人霞掺,你說我怎么就攤上這事《锴” “怎么了?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵缠劝,是天一觀的道長潮梯。 經(jīng)常有香客問我,道長惨恭,這世上最難降的妖魔是什么秉馏? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮脱羡,結(jié)果婚禮上萝究,老公的妹妹穿的比我還像新娘免都。我一直安慰自己,他們只是感情好帆竹,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布绕娘。 她就那樣靜靜地躺著,像睡著了一般栽连。 火紅的嫁衣襯著肌膚如雪险领。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天秒紧,我揣著相機(jī)與錄音绢陌,去河邊找鬼。 笑死熔恢,一個(gè)胖子當(dāng)著我的面吹牛脐湾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叙淌,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼秤掌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凿菩?” 一聲冷哼從身側(cè)響起机杜,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衅谷,沒想到半個(gè)月后椒拗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡获黔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年蚀苛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玷氏。...
    茶點(diǎn)故事閱讀 40,769評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堵未,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盏触,到底是詐尸還是另有隱情渗蟹,我是刑警寧澤,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布赞辩,位于F島的核電站雌芽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辨嗽。R本人自食惡果不足惜世落,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糟需。 院中可真熱鬧屉佳,春花似錦谷朝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至髓堪,卻和暖如春送朱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背干旁。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工驶沼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人争群。 一個(gè)月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓回怜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親换薄。 傳聞我的和親對象是個(gè)殘疾皇子玉雾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評論 2 361