java合并图片与文字

通过java来绘制海报,加载外部字体并设置样式大小与加粗、设置背景图、合并图片,下面是简单示例

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 绘制海报
 * author xiaochi
 * date 2024/11/8
 */
public class PosterCreatorTest{

    public static void main(String[] args) throws Exception {
        // 创建字体
        // 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);
        // 设置文本旋转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();
        }
    }

    /**
     * 创建容器
     * @param combinerWidth 容器宽度
     * @param combinerHeight 容器高度
     * @param bgColor 背景色(默认白色,且背景图会覆盖背景色)
     * @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();
        // 设置背景颜色
        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坐标
     * @param y 待合并的图片y坐标
     */
    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坐标
     * @param y 文字y坐标
     * @param maxWidth 文字最大宽度(0为竖排显示)
     * @param rotate 旋转度数
     * @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();
        //设置字体
        g2d.setFont(font);
        // 设置文字颜色
        if (null != color && !"".equals(color)){
            g2d.setColor(getColor(color));
        }
        // 抗锯齿属性
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); //提升观感
        // 设置旋转
        AffineTransform at = new AffineTransform();
        at.rotate(Math.toRadians(rotate),x,y); // 旋转45度,旋转中心为(文字x坐标,100)
        g2d.setTransform(at);

        FontMetrics fontMetrics = g2d.getFontMetrics(font);
        String[] lines = splitText(text, maxWidth, fontMetrics); //实现文字自动换行
        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(""); //以每个字符做拆分,可根据实际需求做更改,下同
        List<String> lines = new ArrayList<>();
        for (String word : words) {
            // 检查添加新单词后是否会超过最大宽度
            if (wrappedText.length() > 0) {
                // 检查加上新单词后的总长度
                if (fontMetrics.stringWidth(wrappedText.toString() + word) > maxWidth) {
                    // 如果超过最大宽度,将当前字符串添加到行列表,并开始新的一行
                    lines.add(wrappedText.toString());
                    wrappedText = new StringBuilder(word);
                } else {
                    // 如果不超过最大宽度,添加新单词
                    wrappedText.append(word);
                }
            } else {
                wrappedText.append(word);
            }
        }
        // 添加最后一行
        if (wrappedText.length() > 0) {
            lines.add(wrappedText.toString());
        }
        // 将行列表转换为数组
        return lines.toArray(new String[0]);
    }
}

OK了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。