Java 绘制图片工具类

工具类

需要先引用依赖

        <!--图像处理-->
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.17</version>
        </dependency>

绘制工具类,主要用于输出字符串,也可以自行添加更多功能进行增强。

package com.test.draw;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Coordinate;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 绘制图像
 *
 * @author zhangxuetu
 * @date 2022-09-21
 */
public class DrawUtil {

    private BufferedImage image;
    private Graphics2D graphics2D;
    private Rectangle size;

    /**
     * 构造方法
     */
    private DrawUtil(BufferedImage image, Rectangle size, Color color) {
        this.image = image;
        this.size = size;
        resetImage(image, false);
        full(color);
    }

    private DrawUtil(BufferedImage image, Rectangle size) {
        this(image, size, Color.WHITE);
        this.graphics2D.setColor(Color.BLACK);
    }

    /**
     * 获取实例
     *
     * @param size            图像大小
     * @param backgroundColor 背景颜色,默认颜色为黑色
     */
    public static DrawUtil getInstance(Rectangle size, Color backgroundColor) {
        BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
        return new DrawUtil(image, size, backgroundColor);
    }

    public static DrawUtil getInstance(int width, int height, Color backgroundColor) {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        return new DrawUtil(image, new Rectangle(width, height), backgroundColor);
    }

    public static DrawUtil getInstance(int width, int height) {
        final DrawUtil instance = getInstance(width, height, Color.WHITE);
        instance.getGraphics2D().setColor(Color.BLACK);
        return instance;
    }

    public static DrawUtil getInstance(Rectangle rectangle) {
        return getInstance(rectangle.width, rectangle.height);
    }

    /**
     * 获取实例
     *
     * @param image           以这个图片作为绘制对象
     * @param backgroundColor 背景颜色,默认颜色为黑色
     * @return 返回这个图像的操作实例
     */
    public static DrawUtil getInstance(BufferedImage image, Color backgroundColor) {
        return new DrawUtil(image, new Rectangle(image.getWidth(), image.getHeight()), backgroundColor);
    }

    public static DrawUtil getInstance(BufferedImage image) {
        return new DrawUtil(image, new Rectangle(image.getWidth(), image.getHeight()));
    }

    public BufferedImage getImage() {
        return image;
    }

    public Graphics2D getGraphics2D() {
        return graphics2D;
    }

    public Rectangle getSize() {
        return size;
    }

    /**
     * 填充整个画布的颜色
     *
     * @param color 整个画布的颜色
     */
    public DrawUtil full(Color color) {
        // 先用白色画笔填充整张图片的颜色,也就是设置背景
        graphics2D.setColor(color);
        graphics2D.fillRect(0, 0, size.width, size.height);
        return this;
    }

    public DrawUtil setColor(Color color) {
        graphics2D.setColor(color);
        return this;
    }

    public DrawUtil setFont(Font font) {
        graphics2D.setFont(font);
        return this;
    }

    public DrawUtil setStroke(Stroke stroke) {
        graphics2D.setStroke(stroke);
        return this;
    }

    /**
     * 重新设置大小
     *
     * @param newSize 新的大小
     */
    public void resize(Rectangle newSize) {
        this.size = newSize;
        resize(image, newSize.width, newSize.height);

    }

    public void resize(BufferedImage image, int width, int height) {
        final BufferedImage newImage = image.getSubimage(0, 0, width, height);
        resetImage(newImage, true);
    }

    /**
     * 绘制线条
     *
     * @param color      线条颜色
     * @param width      线条粗细
     * @param startPoint 起始点
     * @param endPoint   终点
     */
    public DrawUtil drawLine(Color color, int width, Point startPoint, Point endPoint) {
        BasicStroke bs = new BasicStroke(width);
        graphics2D.setStroke(bs);
        graphics2D.setColor(color);
        for (int i = 0; i < width; i++) {
            graphics2D.drawLine(startPoint.x + i, startPoint.y, endPoint.x, endPoint.y);
        }
        return this;
    }

    public DrawUtil drawLine(int width, Point startPoint, Point endPoint) {
        return drawLine(graphics2D.getColor(), width, startPoint, endPoint);
    }

    /**
     * 偏移点位置
     *
     * @param point  要偏移的点
     * @param offset 追加的偏移值
     */
    public DrawUtil offset(Point point, Point offset) {
        return offset(point, offset.x, offset.y);
    }

    public DrawUtil offset(Point point, int x, int y) {
        point.x += x;
        point.y += y;
        return this;
    }

    /**
     * 偏移到字体高度的位置下面
     *
     * @param point 要偏移的点
     */
    public DrawUtil offsetFontHeight(Point point) {
        return offset(point, 0, getFontHeight());
    }

    /**
     * 绘制文字
     */
    public DrawUtil drawString(String text, Color color, Font font, Point point) {
        // 绘制
        graphics2D.setColor(color);
        graphics2D.setFont(font);
        graphics2D.drawString(text, point.x, point.y);
        return this;
    }

    public DrawUtil drawString(String text, Point point) {
        return drawString(text, graphics2D.getColor(), graphics2D.getFont(), point);
    }

    /**
     * 绘制多行文字,会对文字自动换行
     *
     * @param text     要绘制的文字
     * @param maxWidth 每行文字最大宽度
     */
    public DrawUtil drawMultiRowString(String text, Color color, Font font, Point point, int maxWidth, int lineSpace) {
        final List<String> stringList = textWrap(font, text, maxWidth);
        return drawMultiRowString(stringList, color, font, point, lineSpace);
    }

    public DrawUtil drawMultiRowString(List<String> stringList, Color color, Font font, Point point, int lineSpace) {
        return drawMultiRowString(stringList.toArray(new String[0]), color, font, point, lineSpace);
    }

    /**
     * 获取这些文字的整体宽度
     *
     * @param font 字体
     * @param text 字符串内容
     */
    public int getStringWidth(Font font, String text) {
        final FontMetrics fontMetrics = graphics2D.getFontMetrics(font);
        return fontMetrics.stringWidth(text);
    }

    /**
     * 获取当前的字体的这些字符串的宽度
     *
     * @param text 字符串内容
     */
    public int getStringWidth(String text) {
        final Font font = graphics2D.getFont();
        return getStringWidth(font, text);
    }

    /**
     * 绘制多行文字。绘制完最终 point 的 y 值会偏移一行文字和 lineSpace 的值,有时可能需要自行减去
     *
     * @param strings   字符串列表
     * @param color     字体颜色
     * @param font      字体
     * @param point     开始绘制的位置
     * @param lineSpace 每行字的间隔空间
     */
    public DrawUtil drawMultiRowString(String[] strings, Color color, Font font, Point point, int lineSpace) {
        setFont(font);
        int lineHeight = getFontHeight() + lineSpace;
        for (String text : strings) {
            drawString(text, color, font, point);
            point.y += lineHeight;
        }
        return this;
    }

    /**
     * 释放当前绘制的图像,表示已经绘制完成
     *
     * @param finish 是否已经绘制全部完成
     */
    public void dispose(boolean finish) {
        graphics2D.dispose();
        if (!finish) {
            graphics2D = image.createGraphics();
        } else {
            graphics2D = null;
        }
    }

    public void dispose() {
        dispose(true);
    }

    /**
     * 保存图片
     *
     * @param path 图片路径
     * @return 返回是否保存成功
     */
    public boolean saveImage(String path) {
        try {
            File outFile = new File(path);
            // 输出jpg图片
            ImageIO.write(image, "jpg", outFile);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 文字换行拆分,根据计算将字符串拆分成多个,进行换行
     *
     * @param font     字体
     * @param text     字符串内容
     * @param maxWidth 最大宽度
     * @return 返回换行后的字符串列表
     */
    public List<String> textWrap(Font font, String text, int maxWidth) {
        FontMetrics fm = graphics2D.getFontMetrics(font);

        // 可拆分的行
        List<String> list = new ArrayList<>();
        int beginIndex = 0;
        String tempString;
        for (int i = 0; i < text.length(); i++) {
            tempString = text.substring(beginIndex, i);
            if (fm.stringWidth(tempString) >= maxWidth) {
                list.add(text.substring(beginIndex, i));
                beginIndex = i;
            }
        }
        if (beginIndex < text.length()) {
            list.add(text.substring(beginIndex));
        }
        return list;
    }

    /**
     * 获取字符串在宽度中的 x 位置
     *
     * @param width 宽度
     * @param font  字体
     * @param text  字符串
     */
    public int getHorizontalCenterPos(int width, Font font, String text) {
        final int stringWidth = getStringWidth(font, text);
        return (width - stringWidth) / 2;
    }

    /**
     * 添加水印
     */
    public boolean watermark(Point position, BufferedImage image) {
        return watermark(position, image, 1.0F);
    }

    public boolean watermark(int x, int y, BufferedImage image) {
        return watermark(new Point(x, y), image);
    }

    /**
     * 添加水印
     *
     * @param position 添加到的位置
     */
    public boolean watermark(Point position, BufferedImage image, float transparency) {
        return watermark(new Coordinate(position.x, position.y), image, transparency, 1.0F);
    }

    /**
     * 添加水印
     *
     * @param scale 缩放水印大小
     */
    public boolean watermark(Point position, BufferedImage image, float transparency, float scale) {
        return watermark(new Coordinate(position.x, position.y), image, transparency, scale);
    }

    /**
     * 添加水印
     *
     * @param position     添加到的位置
     * @param image        水印图片
     * @param transparency 透明度
     * @param scale        缩放
     */
    public boolean watermark(Coordinate position, BufferedImage image, float transparency, float scale) {
        try {
            if (scale != 1.0F) {
                image = Thumbnails.of(image).scale(scale).asBufferedImage();
            }

            // 对图片进行添加水印
            final BufferedImage newImage = Thumbnails.of(this.image)
                    .size(size.width, size.height)
                    .watermark(position, image, transparency)
                    .asBufferedImage();

            // 重新设置 Image
            resetImage(newImage, true);

            return true;
        } catch (IOException e) {
//            throw new RuntimeException(e);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 重新设置 Image
     *
     * @param newImage                     新的 BufferedImage
     * @param keepPreviousGraphicsProperty 保持之前的 Graphics2D 的一些属性
     */
    public DrawUtil resetImage(BufferedImage newImage, boolean keepPreviousGraphicsProperty) {
        // 之前的属性
        Font previousFont = null;
        Color previousColor = null;
        Stroke previousStroke = null;
        if (keepPreviousGraphicsProperty) {
            previousFont = graphics2D.getFont();
            previousColor = graphics2D.getColor();
            previousStroke = graphics2D.getStroke();
        }

        this.image = newImage;
        this.graphics2D = this.image.createGraphics();
        this.graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        if (keepPreviousGraphicsProperty) {
            this.graphics2D.setFont(previousFont);
            this.graphics2D.setColor(previousColor);
            this.graphics2D.setStroke(previousStroke);
        }

        return this;
    }

    /**
     * 获取字体高度
     */
    public int getFontHeight() {
        final Font font = graphics2D.getFont();
        return getFontHeight(font);
    }

    public int getFontHeight(Font font) {
        final FontMetrics fontMetrics = graphics2D.getFontMetrics(font);
        return fontMetrics.getHeight();
    }

}

测试代码

import java.awt.*;

public class Main {

    public static void main(String[] args) {

        // 开始绘制的点的位置
        Point drawPoint = new Point(10, 10);

        // 创建 200x200 大小的图片
        final DrawUtil drawUtil = DrawUtil.getInstance(200, 200);
        drawUtil.setFont(new Font("宋体", Font.PLAIN, 20))
                .offsetFontHeight(drawPoint)
                .drawString("text", drawPoint)
                .offset(drawPoint, new Point(0, 10))
                .drawLine(1, new Point(10, drawPoint.y), new Point(190, drawPoint.y))
                .offsetFontHeight(drawPoint)
                .drawString("abzxc 绘制文字", drawPoint)
                .dispose();

        boolean result = drawUtil.saveImage("C:\\Users\\Administrator\\Desktop\\test.jpg");

        System.out.println(result ? "保存成功" : "保存失败");
    }

}

输出图片如下:

相关链接

发表评论