zoukankan      html  css  js  c++  java
  • java-使用Graphics2d合成图片和文字

    需求:使用一些图片和用户输入的文案合成图片或者海报

    使用三方库

    mvn管理

    <!--图片处理 start -->
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-jpeg</artifactId>
        <version>3.6</version>
    </dependency>
    <dependency>
        <groupId>com.twelvemonkeys.imageio</groupId>
        <artifactId>imageio-tiff</artifactId>
        <version>3.6</version>
    </dependency>
    <!--
    Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
    Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
    -->
    <dependency>
        <groupId>com.twelvemonkeys.servlet</groupId>
        <artifactId>servlet</artifactId>
        <version>3.6</version>
    </dependency>
    <!--图片处理 end -->

    实现方法

    循环合成所有需求

    import com.aaa.bbb.common.utils.HttpsUtils;
    import com.aaa.bbb.common.utils.UploadImageUtil;
    import com.aaa.bbb.common.vo.loan.LoanUserSynthesisListVo;
    import org.apache.commons.lang3.StringUtils;
    
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * @Author
     * @Date
     **/
    public class ImageUtils {
    
        /**
         * 操作合成图片
         * @param SynthesisList 操作单张合成图
         * @return
         */
        public String optImage(List<SynthesisListVo> SynthesisList) {
            try {
                // 与前端约定  合成图片列表的第一张图片为底图
                SynthesisListVo backgroundImageInfo = SynthesisList.get(0);
                //设置图片大小  宽  高  网络图片
                // 获取网络图片
                BufferedImage getBackgroundUrlImage = this.getUrlImage(backgroundImageInfo.getImageUrl());
                BufferedImage background = this.resizeImagePng(backgroundImageInfo.getWidth(), backgroundImageInfo.getHeight(), getBackgroundUrlImage);
                // 底部宽
                Integer SynthesisListVo = backgroundImageInfo.getWidth();
                //在背景图片中添加入需要写入的信息,
                Graphics2D g = background.createGraphics();  // x58  y74.3
                //设置为透明覆盖
                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f));
                Boolean isFirst  = true;
                for (SynthesisListVo SynthesisListItem : SynthesisList) {
                    if (isFirst) {
                        isFirst = false;
                        continue;
                    }
                    if (SynthesisListItem.getType().equals("Image")) {
                        // 图片处理 创建图片
                        // 获取网络图片
                        BufferedImage getUrlImage = this.getUrlImage(SynthesisListItem.getImageUrl());
                        // 重新定义图片尺寸
                        BufferedImage userImage = this.resizeImagePng(SynthesisListItem.getWidth(), SynthesisListItem.getHeight(), getUrlImage);
                        // 图片 偏移x  偏移y 图片的宽 图片的高
                        g.drawImage(userImage, SynthesisListItem.getOffsetX(), SynthesisListItem.getOffsetY(), userImage.getWidth(), userImage.getHeight(), null);
                    } else if (SynthesisListItem.getType().equals("Text")) {
                        // Font pinfang_44 = new Font("苹方-简 中黑体", Font.BOLD, 44);
                        Font pinfang = new Font(SynthesisListItem.getTextFontFamily(), Font.PLAIN, SynthesisListItem.getTextFontSize());
                        // 写字
                        //指定字体
                        FontMetrics metrics = g.getFontMetrics(pinfang);
                        //指定要绘制的字符串
                        String useMeg = String.valueOf(SynthesisListItem.getText());
                        //得到字符串绘制宽度
                        int logoW = metrics.stringWidth(useMeg);
                        //计算绘制原点坐标,
                        //文本最左边位于x轴logoX
                        // 判断是否水平居中
                        int logoX = 0;
                        if (SynthesisListItem.getTextAlignCenter() != null && SynthesisListItem.getTextAlignCenter()) {
                            // 水平居中
                            logoX = (maxBackgroundWidth - logoW) / 2;
                        } else {
                            logoX = SynthesisListItem.getOffsetX();
                        }
                        //文本基于logoH
                        int logoH = SynthesisListItem.getOffsetY() + (metrics.getAscent());
                        //绘制文本框
                        g.setFont(pinfang);
                        g.setColor(new Color(SynthesisListItem.getTextColor().get(0),SynthesisListItem.getTextColor().get(1),SynthesisListItem.getTextColor().get(2)));
                        g.drawString(useMeg, logoX, logoH);
                    }
                }
                g.dispose();
                //输出图片 上传七牛
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ImageIO.write(background, "png", out);
                byte[] b = out.toByteArray();
                String hash = UploadImageUtil.uploadByteImage(b);
                if (StringUtils.isNotEmpty(hash)) {
                    // 返回图片路径
                    return UploadImageUtil.IMG_HOST + hash;
                }
    //            ImageIO.write(background, "png", new FileOutputStream(outPutPath));
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 获取网络图片数据
         * @param url
         * @return
         */
        public BufferedImage getUrlImage(String url) {
            byte[] bytes = HttpsUtils.getBytes(url);
            InputStream buffin = new ByteArrayInputStream(bytes,0,bytes.length);
            BufferedImage img = null;
            try {
                img = ImageIO.read(buffin);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return img;
        }
    
        /**
         * 重定义图片尺寸
         * @param x
         * @param y
         * @param bfi
         * @return
         */
        public BufferedImage resizeImagePng(int x, int y, BufferedImage bfi) {
            BufferedImage bufferedImage = new BufferedImage(x, y, BufferedImage.TYPE_INT_ARGB);
            bufferedImage.getGraphics().drawImage(
                    bfi.getScaledInstance(x, y, Image.SCALE_SMOOTH), 0, 0, null);
            return bufferedImage;
        }
    
    }

    循环vo

    package com.aaa.bbb.common.vo.loan;
    
    import lombok.Data;
    
    import java.util.List;
    
    /**
     * @Author
     * @Date
     **/
    @Data
    public class SynthesisListVo {
    
        /**
         * 类型  image  text
         */
        private String type;
    
        /**
         * 文案字体 type为text时生效
         */
        private String textFontFamily;
    
        /**
         * 文案字体大小 type为text时生效
         */
        private Integer textFontSize;
    
        /**
         * 文案是否水平居中 true水平居中 type为text时生效
         */
        private Boolean textAlignCenter;
    
        /**
         * 文案颜色 type为2时生效
         */
        private List<Integer> textColor;
    
        /**
         * 水平偏移量 type为text & textAlignCenter为true时失效
         */
        private Integer offsetX;
    
        /**
         * 垂直偏移量
         */
        private Integer offsetY;
    
        /**
         * 图片地址 type为image时生效
         */
        private String imageUrl;
    
        /**
         * 文案 type为text时生效
         */
        private String text;
    
        /**
         * 宽度 type为image时生效
         */
        private Integer width;
    
        /**
         * 高度 type为image时生效
         */
        private Integer height;
    }

    参考文献

    https://blog.csdn.net/long703283343/article/details/102974284

    https://www.cnblogs.com/fatetop/p/13914882.html

    开发时需要的坑

    1、网络图片下载的坑

    解决:https://www.cnblogs.com/fatetop/p/13914882.html

    获取不到图片的时候,调用重定义图片尺寸报错空指针

    2、绘制文字时Windows字体普遍安装好了,在服务器上没有安装文字字体需要安装

    https://www.cnblogs.com/Azi-mi/p/9955743.html

  • 相关阅读:
    HDU 4492 Mystery (水题)
    UVA 10480 Sabotage (最大流)
    POJ 2446 Chessboard (二分匹配)
    VS2008下用MFC 的MSComm控件编写串口程序
    退役了~~~
    STL Algorithms 之 unique
    cocos2d中CCCallFuncND传参数的注意事项
    好太太晾衣架市场价格表(仅供参考)
    Linux VNC黑屏(转)
    C++ TinyXml操作(含源码下载)
  • 原文地址:https://www.cnblogs.com/fatetop/p/13985075.html
Copyright © 2011-2022 走看看