美文网首页
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

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