图片上绘制文字, 设置颜色, 字体尺寸大小, 位置等
注: 文字框对应坐标点默认是以左下顶点为坐标原点

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.output.ByteArrayOutputStream;

import javax.imageio.ImageIO;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;

@Slf4j
public class PrintImage {

    private static final String FONTNAME = "思源黑体";
    private Font font = new Font(FONTNAME, Font.PLAIN, 25); // 添加字体的属性设置
    private Graphics2D g = null;

    /**
     * 设定文字的字体等
     */
    public void setFont(Font font) {
        this.font = font;
    }

    /**
     * 导入本地图片到缓冲区
     */
    public BufferedImage loadImageLocal(String imgName) {
        try {
            return ImageIO.read(new File(imgName));
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 导入网络图片到缓冲区
     */
    public BufferedImage loadImageUrl(String imgName) {
        try {
            URL url = new URL(imgName);
            return ImageIO.read(url);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 生成新图片到本地
     */
    public void writeImageLocal(String newImage, BufferedImage img) {
        if (newImage != null && img != null) {
            try {
                File outputfile = new File(newImage);
                ImageIO.write(img, "jpg", outputfile);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }
    /**
     * 批量生成图片并返回图片流,用于上传到远程服务器
     * @param imgUrl
     * @param list
     * @return
     * @throws IOException
     */
    private ByteArrayInputStream writeImageStrongest(String imgUrl, List<ModifyImageDto> list) throws IOException {
        BufferedImage bufferedImage = this.printImage(imgUrl, list);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "jpg", output);
        return new ByteArrayInputStream(output.toByteArray());
    }
    /**
     * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
     */
    public BufferedImage modifyImage(BufferedImage img, Object content, int x, int y,Color color) {
        try {
            int w = img.getWidth();
            int h = img.getHeight();
            g = img.createGraphics();
            g.setBackground(Color.BLUE);
            //g.setColor(new Color(120, 120, 110));//设置字体颜色
            g.setColor(color);//设置字体颜色
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
            g.setStroke(new BasicStroke(3));
            if (this.font != null)
                g.setFont(this.font);
            if (content != null) {
                g.translate(w / 2, h / 2);
                //g.rotate(8 * Math.PI / 180);
                g.drawString(content.toString(), x, y);
            }
            g.dispose();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return img;
    }
    /**
     * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
     * @param img
     * @return
     */
    public BufferedImage modifyImageYe(BufferedImage img) {
        try {
            int w = img.getWidth();
            int h = img.getHeight();
            g = img.createGraphics();
            g.setBackground(Color.WHITE);
            g.setColor(Color.blue);//设置字体颜色
            if (this.font != null)
                g.setFont(this.font);
            g.drawString("www.hi.baidu.com?xia_mingjian", w - 85, h - 5);
            g.dispose();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return img;
    }

    public BufferedImage modifyImagetogeter(BufferedImage b, BufferedImage d) {
        try {
            int w = b.getWidth();
            int h = b.getHeight();
            g = d.createGraphics();
            g.drawImage(b, 100, 10, w, h, null);
            g.dispose();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return d;
    }
    /***
     * 插入描边的字体
     * @param img
     * @param content
     * @param w
     * @param h
     * @return
     */
    public BufferedImage modifyShapImg(BufferedImage img, String content, int w, int h) {
        //int w = img.getWidth();
        //int h = img.getHeight();
        g = img.createGraphics();
        //Font f = new Font("Courier New", Font.BOLD, 140);
        GlyphVector v = font.createGlyphVector(g.getFontMetrics(font).getFontRenderContext(), content);
        Shape shape = v.getOutline();
        if (content != null) {
            g.translate(w, h);
            //g.rotate(8 * Math.PI / 180);
            //g.drawString(content.toString(), x, y);
        }
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
        g.setColor(new Color(0,90,160));
        g.fill(shape);
        g.setColor(new Color(248,248,255));
        g.setStroke(new BasicStroke(2));
        g.draw(shape);
        return img;
    }
    /**
     * 图片更新多处文字
     * @param d
     * @param list
     */
    public BufferedImage batchModifyImage(BufferedImage img, List<ModifyImageDto> list) {
        try {
            Graphics2D g = img.createGraphics();
            for (ModifyImageDto modifyImageDto : list) {
                g.setColor(toColorFromString(modifyImageDto.getColour()));//设置字体颜色
                if (modifyImageDto.getCharacterSize() != null && modifyImageDto.getCharacterSize() > 0){
                    g.setFont(new Font(FONTNAME, Font.PLAIN, modifyImageDto.getCharacterSize()));
                }else{
                    g.setFont(this.font);
                }
                if (modifyImageDto.getContent() != null) {
                    g.translate(0, 0);
                    g.drawString(modifyImageDto.getContent(), modifyImageDto.getAxisX(), modifyImageDto.getAxisY());
                }
            }
            g.dispose();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return img;
    }
    /**
     * 批量处理图片
     * @param imgUrl
     * @param list
     * @return
     */
    public BufferedImage printImage(String imgUrl, List<ModifyImageDto> list){
        PrintImage tt = new PrintImage();
        BufferedImage bufferedImage = tt.loadImageUrl(imgUrl);
        tt.batchModifyImage(bufferedImage, list);
        return tt.batchModifyImage(bufferedImage, list);
    }

    /**
     * 16进制字符串转换成Color对象
     * @param colorStr 16进制颜色字符串
     * @return Color对象
     * */
    public static Color toColorFromString(String colorStr){
        if (colorStr.length() == 4){//兼容#000,#FFF等
            colorStr += colorStr.substring(1);
        }
        return new Color(
                Integer.valueOf( colorStr.substring( 1, 3 ), 16 ),
                Integer.valueOf( colorStr.substring( 3, 5 ), 16 ),
                Integer.valueOf( colorStr.substring( 5, 7 ), 16 ));
    }

    /**
     * <p>绘制图片对象</p>
     *
     * @author lcx
     * @since 2021/1/18 15:08
     **/
    @Data
    public class ModifyImageDto {
        /**
         * 文字内容
         */
        private String content;

        /**
         * 字体大小
         */
        private Integer characterSize;

        /**
         * 颜色(默认值:)
         */
        private String colour;

        /**
         * 横坐标
         */
        private Integer axisX;

        /**
         * 纵坐标
         */
        private Integer axisY;
    }
}