美文网首页
ImageBuilder

ImageBuilder

作者: 翼徳 | 来源:发表于2018-11-13 14:59 被阅读14次

目标

用 Java 绘制分享图,需要将文字、用户头像、二维码等元素合成到背景图上。

外部依赖

Maven 依赖:

<!-- 绘制二维码 -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>(the current version)</version>
 </dependency>

源代码

import com.google.zxing.BarcodeFormat;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Objects;

/**
 * <p>
 * 图像合成工具类
 * </p>
 * Created by scott on 2018-11-13.
 */
public class ImageBuilder {

    private Graphics2D graphics;
    private BufferedImage bgImage;

    /**
     * <pre>
     *     BufferedImage bgImage;
     *     // 从网络加载
     *     bgImage = ImageIO.read(url);
     *     // 从文件中加载
     *     bgImage = ImageIO.read(file);
     * </pre>
     *
     * @param bgImage 背景图
     */
    public ImageBuilder(BufferedImage bgImage) {
        Objects.requireNonNull(bgImage);
        this.bgImage = bgImage;
        graphics = this.bgImage.createGraphics();
    }

    public ImageBuilder withText(Font font, Color color, int x, int y, String text) {
        Objects.requireNonNull(font, "font 不能为 null");
        Objects.requireNonNull(color, "color 不能为 null");

        graphics.setFont(font);
        graphics.setColor(color);
        graphics.drawString(text, x, y);
        return this;
    }

    /**
     * 在底图上画圆形头像
     */
    public ImageBuilder withCircularAvatar(BufferedImage avatar, int x, int y, int diameter) {
        try {
            Ellipse2D.Double shape = new Ellipse2D.Double(x, y, diameter, diameter);
            graphics.setClip(shape);
            graphics.drawImage(avatar.getScaledInstance(diameter, diameter, Image.SCALE_SMOOTH), x, y, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * 在底图上画二维码
     *
     * @param x 二维码中心坐标点
     * @param y 二维码中心坐标点
     */
    public ImageBuilder withQRCode(String contents, int x, int y, int width) {
        try {
            QRCodeWriter writer = new QRCodeWriter();

            // 生成二维码数据点
            BitMatrix matrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, width);
            int matrixWidth = matrix.getWidth();

            // 计算二维码的原点(留2个像素作为边框)
            int p = getMatrixOriginPoint(matrix, matrixWidth) - 2;

            int aw = matrixWidth / 2 - p;

            // 填充二维码背景色
            graphics.setColor(Color.WHITE);
            graphics.fillRect(x - aw, y - aw, aw * 2, aw * 2);

            // 填充二维码
            graphics.setColor(Color.BLACK);
            for (int i = 0; i < matrixWidth; i++) {
                for (int j = 0; j < matrixWidth; j++) {
                    if (matrix.get(i, j)) {
                        graphics.fillRect(x - aw + i - p, y - aw + j - p, 1, 1);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    /**
     * 获取二维码原点
     */
    private int getMatrixOriginPoint(BitMatrix matrix, int matrixWidth) {
        for (int i = 0; i < matrixWidth; i++) {
            for (int j = 0; j < matrixWidth; j++) {
                if (matrix.get(i, j)) {
                    return i;
                }
            }
        }
        return 0;
    }

    /**
     * 在底图上画一个已有的图片
     *
     * @param width  在底图上要画的图片宽度
     * @param height 在底图上要画的图片高度
     */
    public ImageBuilder withImage(BufferedImage material, int x, int y, int width, int height) {
        graphics.drawImage(material, x, y, width, height, null);
        return this;
    }

    /**
     * 在底图上画一个已有的图片
     * <p>
     * 使用小图片默认
     * </p>
     */
    public ImageBuilder withImage(BufferedImage material, int x, int y) throws IOException {
        return withImage(material, x, y, material.getWidth(), material.getHeight());
    }

    /**
     * 生成图片
     */
    public BufferedImage build() {
        graphics.dispose();
        return bgImage;
    }

    /**
     * 生成本地图片
     *
     * @param formatName 生成的文件格式名称(例如:jpg、png),要与背景图的格式保持一致
     * @param output     生成的图片
     */
    public boolean writeTo(String formatName, File output) throws IOException {
        return ImageIO.write(bgImage, formatName, output);
    }
}

示例

public class ImageBuilderTest {

    public static void main(String[] args) {
        String inputPath = "C:\\Users\\scott\\Pictures\\01.png";
        String outputPath = "C:\\Users\\scott\\Pictures\\01_out.png";
        try {
            BufferedImage bgImg = ImageIO.read(new File(inputPath));

            ImageBuilder builder = new ImageBuilder(bgImg);

            String text = "我是共产主义接班人";
            builder.withText(new Font("黑体", Font.BOLD, 20), Color.black, 40, 40, text);
            builder.build();

            ImageIO.write(bgImg, "png", new File(outputPath));

            System.out.println("done");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

相关文章

  • ImageBuilder

    目标 用 Java 绘制分享图,需要将文字、用户头像、二维码等元素合成到背景图上。 外部依赖 Maven 依赖: ...

  • (转)使用ImageBuilder制作MT7621潘多拉/Pan

    基于ubuntu 18.04(实际测试在14.04也可以),本文在原作者上稍作修改,更容易看懂。原作者URL:ht...

网友评论

      本文标题:ImageBuilder

      本文链接:https://www.haomeiwen.com/subject/jqclfqtx.html