海报合成技术

我们有的时候营销的时候,需要把给每一位用户生成单独的海报。比如微信营销的时候,需要给每一个用户单独生成。这个时候,需要把用户昵称和头像放到海报里。这个如何开发呢?下面我们介绍下。

先给背景图片中添加头像,并且根据位置和长宽等。确定位置。

接着把文字添加进去,核心代码如下:


/**
 * 把两张图片合并
 */
public class QrPicUtil {

    private static Logger logger = LoggerFactory.getLogger(QrPicUtil.class);

    private Font font = new Font("宋体", Font.PLAIN, 12); // 添加字体的属性设置

    private static Graphics2D g = null;

    private  int fontsize = 0;

    private int x = 0;

    private int y = 0;

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

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

    /**
     * 生成新图片到本地
     */
    public static 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) {
                System.out.println(e.getMessage());
            }
        }
    }

    /**
     * 设定文字的字体等
     */
    public void setFont(String fontStyle, int fontSize) {
        this.fontsize = fontSize;
        this.font = new Font(fontStyle, Font.PLAIN, fontSize);
    }

    /**
     * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
     */
    public BufferedImage modifyImage(BufferedImage img, Object content, int x, int y) {

        try {
            int w = img.getWidth();
            int h = img.getHeight();
            g = img.createGraphics();
            g.setBackground(Color.WHITE);
            g.setColor(Color.orange);//设置字体颜色
            if (this.font != null){
                g.setFont(this.font);
            }

            // 验证输出位置的纵坐标和横坐标
            if (x >= h || y >= w) {
                this.x = h - this.fontsize + 2;
                this.y = w;
            } else {
                this.x = x;
                this.y = y;
            }
            if (content != null) {
                g.drawString(content.toString(), this.x, this.y);
            }
            g.dispose();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return img;
    }

    /**
     * 修改图片,返回修改后的图片缓冲区(输出多个文本段) xory:true表示将内容在一行中输出;false表示将内容多行输出
     */
    public BufferedImage modifyImage(BufferedImage img, Object[] contentArr, int x, int y,
                                     boolean xory) {
        try {
            int w = img.getWidth();
            int h = img.getHeight();
            g = img.createGraphics();
            g.setBackground(Color.WHITE);
            g.setColor(Color.RED);
            if (this.font != null){
                g.setFont(this.font);
            }

            // 验证输出位置的纵坐标和横坐标
            if (x >= h || y >= w) {
                this.x = h - this.fontsize + 2;
                this.y = w;
            } else {
                this.x = x;
                this.y = y;
            }
            if (contentArr != null) {
                int arrlen = contentArr.length;
                if (xory) {
                    for (int i = 0; i < arrlen; i++) {
                        g.drawString(contentArr[i].toString(), this.x, this.y);
                        this.x += contentArr[i].toString().length() * this.fontsize / 2 + 5;// 重新计算文本输出位置
                    }
                } else {
                    for (int i = 0; i < arrlen; i++) {
                        g.drawString(contentArr[i].toString(), this.x, this.y);
                        this.y += this.fontsize + 2;// 重新计算文本输出位置
                    }
                }
            }
            g.dispose();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        return img;
    }

    /**
     * 修改图片,返回修改后的图片缓冲区(只输出一行文本)
     * <p>
     * 时间:2007-10-8
     *
     * @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) {
            System.out.println(e.getMessage());
        }

        return img;
    }

    /**
     *
     * @param b head
     * @param d  bg
     * @param banner
     * @return
     */
    public static BufferedImage modifyImagetogeter(BufferedImage b, BufferedImage d, ActivityBanner banner) {
        try {
            g = d.createGraphics();


            Integer length = banner.getAvetarLength()*banner.getPicRate();
            if (length == null) {
                length = 300;
            }
            Integer width = banner.getAvetarWidth()*banner.getPicRate();
            if (width == null) {
                width = 455;
            }


            Integer x = banner.getAvetarX()*banner.getPicRate();
            if (x == null) {
                x = 300;
            }
            Integer y = banner.getAvetarY()*banner.getPicRate();
            if (y == null) {
                y = 455;
            }
            if (banner.getAvetarType() != null && banner.getAvetarType() == 0) {
                Ellipse2D.Double shape = new Ellipse2D.Double(x,y,width, length);
                g.setClip(shape);
            }
            g.drawImage(b, x, y, width, length, null);
            g.dispose();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return d;
    }

    /**
     *
     * @param b head
     * @param d bg
     * @param tempUrl
     * @param nickName
     * @param banner
     * @return
     * @throws Exception
     */
    public static BufferedImage addWater(BufferedImage b, BufferedImage d, String tempUrl, String nickName, ActivityBanner banner) throws Exception {
        BufferedImage image = null;
        //用户头像启用。1启用,0是禁用
        if (banner.getAvatarStatus() != null && banner.getAvatarStatus() == 1) {
            image = modifyImagetogeter(b, d, banner);
           // return image;
        } else {
            image = d;
        }
        Graphics2D gd = image.createGraphics();
        // 3、设置对线段的锯齿状边缘处理
        gd.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        //用户昵称状态 1启用 0禁用
        if (banner.getBannerNicknameStatus() != null && banner.getBannerNicknameStatus() == 1) {
            logger.info("昵称:"+nickName);
           // nickName="会吃人的蘑菇:mushroom: ₆₆₆⁶⁶⁶";
           // nickName="大锤锤";
            nickName=EmojiParser.parseToUnicode(nickName);
            if(containsEmoji(nickName)){
                logger.info("包含emoji");
            }
            logger.info("nickName:"+nickName);
            // 5、设置水印文字颜色
            if(banner.getBannerNicknameColor()==null){
                gd.setColor(Color.WHITE);
            }else{
                try {
                    String color=banner.getBannerNicknameColor();
                    color=color.replace("#","");
                    if(color.length()!=6){
                        gd.setColor(Color.WHITE);
                    }else{
                        String s1=color.substring(0,2);

                        String s2=color.substring(2,4);
                        String s3=color.substring(4,6);
                        gd.setColor(new Color((int)Long.parseLong(s1,  16), (int)Long.parseLong(s2,  16), (int)Long.parseLong(s3,  16)));
                    }
                }catch (Exception e){
                    logger.error("字体颜色转换异常,{}",e);
                    gd.setColor(Color.WHITE);
                }
            }



            // 6、设置水印文字Font
            String font = banner.getBannerNicknameFont();
            Integer size=0;
            if (font == null) {
                size=35;
            }else{

                size=Integer.parseInt(font)+18;
            }
            gd.setFont(new Font("微软雅黑", Font.BOLD, size));
            // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
            Integer x = banner.getBannerNicknameX()*banner.getPicRate();
            if (x == null) {
                x = 340;
            }
            Integer y = banner.getBannerNicknameY()*banner.getPicRate()+22;
            if (y == null) {
                y = 660;
            }
            gd.drawString(nickName, x, y);
        }

        //使用工具类生成二维码
        Integer length = banner.getBannerScanLength()*banner.getPicRate();
        if (length == null) {
            length = 400;
        }
        Integer width = banner.getBannerScanWidth()*banner.getPicRate();
        if (width == null) {
            width = 320;
        }

        Image scImage = createQrCode(tempUrl, length, width);
        //将小图片绘到大图片上,500,300 .表示你的小图片在大图片上的位置。

        Integer bx = banner.getBannerScanX()*banner.getPicRate();
        if (bx == null) {
            bx = 175;
        }
        Integer by = banner.getBannerScanY()*banner.getPicRate();
        if (by == null) {
            by = 1020;
        }
        gd.drawImage(scImage, bx, by, null);

        gd.dispose();
        return image;
    }

    /**
     * 将链接生成二维码的Image
     *
     * @param content
     * @param width
     * @param height
     * @return
     * @throws Exception
     */
    private static BufferedImage createQrCode(String content, int width, int height) throws Exception {
        QrConfig config = new QrConfig(width, height);
        //  Image image = ImageIO.read(getUrl(headImg));
        // config.setImg(image);
        //   config.setErrorCorrection(ErrorCorrectionLevel.H);
        return QrCodeUtil.generate(
                content,
                config);
    }

    /**
     * 生成海报方法
     *
     * @param exitUrl  生成海报存储的位置
     * @param bgPic    背景图片
     * @param headUrl  用户头像
     * @param nickName 用户昵称
     * @param tempUrl  用户二维码
     * @param banner   海报生成规则
     * @throws Exception
     */
    public static void addPic(String exitUrl, String bgPic, String headUrl, String nickName, String tempUrl, ActivityBanner banner) throws Exception {
        logger.info("生成在图片上的昵称:" + nickName + ",banner的JSON::::" + JSON.toJSONString(banner));
        BufferedImage bg = loadImageUrl(bgPic);
        BufferedImage head = loadImageUrl(headUrl);
        //往图片上写文件
        writeImageLocal(exitUrl, addWater(head, bg, tempUrl, nickName, banner));
        //将多张图片合在一起
        logger.info("生成海报成功");
    }


    /**
     * 检测是否有emoji字符
     * @param source
     * @return 一旦含有就抛出
     */
    public static boolean containsEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return false;
        }

        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);

            // 文字
            if (!isEmojiCharacter(codePoint)) {
                return true;
            }
        }

        return false;
    }

    public static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) ||
                (codePoint == 0x9) ||
                (codePoint == 0xA) ||
                (codePoint == 0xD) ||
                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    public static void main(String[] args) throws Exception {
        ActivityBanner banner = new ActivityBanner();
        banner.setAvatarStatus(1);
        banner.setBannerNicknameStatus(1);
        banner.setAvetarType(0);
        banner.setBannerNicknameFont("18");
        QrPicUtil.addPic("D:\\pic\\a.jpg", "http://wedo918map.oss-cn-shenzhen.aliyuncs.com/images/CBIvZAmVaZi5bQjh3cScnmoblWgGzNYxI0OGfZYX.jpeg", "http://thirdwx.qlogo.cn/mmopen/Q3auHgzwzM7Vvr3wBsvm8TkUW4LplsJxEuqJLTDwjXylYqxB174ITaxSGhyicaLNKhmQLjbqaaTSz55uibdyA3LLAB8vwiaWnREcM0ojayE3Qs/132", "测试", "http://weixin.qq.com/q/02DFd6hnQOdDC1JRz0xwcE", banner);
    }
}

特别说明:因为我们这边默认的是微软雅黑,所以如果你在本地部署启动一切正常,但是如果你要是部署到linux服务器上,生成的海报中中文名字可能不显示。这是因为linux中是没有微软雅黑字体,所以需要我们把微软雅黑的字体(msyhbd.ttf 和msyh.ttf 在C:/windows/fonts/里有)放到部署的jre中。记得要放到jre/lib/fonts下。然后重启你的项目就可以了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值