java 微信海报的实现

Posted mr_raptor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 微信海报的实现相关的知识,希望对你有一定的参考价值。

见效果:

1. 左上角添加头像,带白边

2. 右下角添加二维码

3. 二维码下添加文字

可实现图片圆角处理,设置图片的宽度,描边==

可实现字体添加与样式

(使用原始图片直接不让上传,模糊下内容)

见代码:

/**
 * Created by michaeltang on 2019/9/19.
 *
 * 生成合成图片,以流方式返回给前端显示,用于配置生成海报场景
 * 可以绘制字体和图片,如:二维码,头像,注意元素的添加顺序,后加入的在上面
 */

public class ImagePainter 
    /**
     * 绘制类型:
     */
    public static final String KEY_TYPE = "key_type";

    /**
     * 元素类型:FONT、IMAGE、SQUIRE
     */
    public static final String KEY_ELEMENT = "key_content_element";

    /**
     * 字体封装类
     */
    public static class FontElement 
        public int x;
        public int y;
        public int fontSize = 16;
        public Color fontColor;
        public boolean bold;
        public int fontWeight;
        public String content;
        public FontElement()
        public FontElement(int x, int y, int fontSize, Color fontColor, boolean bold, int fontWeight, String content) 
            this.x = x;
            this.y = y;
            this.fontSize = fontSize;
            this.fontColor = fontColor;
            this.bold = bold;
            this.fontWeight = fontWeight;
            this.content = content;
        
    

    /**
     * 图像封装样式
     */
    public static class ImageElement 
        public int x;
        public int y;
        public int width;
        public int height;
        public boolean round = false;
        public int borderWidth = 1;
        public Color borderColor;
        public Color bkgColor;
        public String imageUrl;
        public ImageElement()
        public ImageElement(int x, int y, int width, int height, boolean round, int borderWidth, Color borderColor, Color bkgColor, String imgUrl)
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.round = round;
            this.borderColor = borderColor;
            this.borderWidth = borderWidth;
            this.bkgColor = bkgColor;
            this.imageUrl = imgUrl;
        
    

    /**
     * 元素类型
     **/
    public static enum ElementType implements BaseEnum<ElementType, String> 
        FONT("FONT", "文字"),
        IMAGE("IMAGE", "图像");

        private String value;
        private String displayName;

        static Map<String, ElementType> enumMap = new HashMap<String, ElementType>();

        static 
            for (ElementType type : ElementType.values()) 
                enumMap.put(type.getValue(), type);
            
        

        private ElementType(String value, String displayName) 
            this.value = value;
            this.displayName = displayName;
        

        @Override
        public String getValue() 
            return this.value;
        

        @Override
        public String getDisplayName() 
            return this.displayName;
        

        public static ElementType getEnum(String value) 
            return enumMap.get(value);
        

    

    /**
     * 生成合成图片,以流方式返回给前端显示,用于配置生成海报场景
     *
     * @param request
     * @param response
     * @param backgroundUrl 大背景图Url
     * @param elements 元素数组,可以是字体,可以是图片,如二维码,头像,注意元素的添加顺序,后加入的在上面
     */
    public static void getPaintedStream(HttpServletRequest request, HttpServletResponse response,
                                   String backgroundUrl, List<HashMap<String, Object>> elements)
        // 设置相应类型,告诉浏览器输出的内容为图片
        response.setContentType("image/jpeg");
        // 设置响应头信息,告诉浏览器不要缓存此内容
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");

        try 
            // 将内存中的图片通过流动形式输出到客户端
            ImageIO.write(paint(backgroundUrl, elements), "JPEG", response.getOutputStream());
         catch (Exception e) 
        
    

    public static BufferedImage paint(String backgroundUrl, List<HashMap<String, Object>> components) 
        if(StringUtils.isEmpty(backgroundUrl)) 
            throw new OpenmoreException("没有指定背景图像");
        
        if(components == null || components.size() == 0) 
            throw new OpenmoreException("至少在图片指定一个绘制的组件");
        
        BufferedImage bkgImage = readUrlImage(backgroundUrl);
        for (HashMap map: components) 
            Object obj = map.get(KEY_TYPE);
            if(obj == null) 
                continue;
            
            ElementType type = (ElementType) map.get(KEY_TYPE);
            if(type == ElementType.FONT) 
                FontElement font = (FontElement)map.get(KEY_ELEMENT);
                drawFont(bkgImage, font);
             else if(type == ElementType.IMAGE) 
                ImageElement image = (ImageElement)map.get(KEY_ELEMENT);
                drawImage(bkgImage, image);
            

        
        return bkgImage;
    

    private static void drawFont(BufferedImage bkgImage, FontElement font)
        Graphics2D g = bkgImage.createGraphics();
        g.setColor(Color.WHITE);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        if(font.bold) 
            g.setFont(new Font("Microsoft YaHei", Font.BOLD, font.fontSize));
         else 
            g.setFont(new Font("Microsoft YaHei", Font.PLAIN, font.fontSize));
        
        g.setColor(font.fontColor);
        g.drawString(font.content , font.x, font.y);
        g.dispose();
    

    private static void drawImage(BufferedImage bkgImage, ImageElement img)
        Graphics2D g = bkgImage.createGraphics();
        g.setColor(Color.WHITE);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        BufferedImage image = readUrlImage(img.imageUrl);
        if(img.round) 
            // 图片切成是一个圆型
            int width = img.width - img.borderWidth * 2;
            Ellipse2D.Double shape = new Ellipse2D.Double(img.x + img.borderWidth, img.y + img.borderWidth, width, width);
            g.setClip(shape);
            g.drawImage(image.getScaledInstance(img.width, img.width, Image.SCALE_SMOOTH), img.x, img.y, img.width, img.width, null);
            g.dispose();
            // 画白边
            Graphics2D g2 = bkgImage.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            Stroke s = new BasicStroke(img.borderWidth * 3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
            g2.setStroke(s);
            g2.setColor(Color.WHITE);
            g2.drawOval(img.x, img.y, img.width, img.width);
            g2.dispose();
         else 
            g.drawImage(image.getScaledInstance(img.width, img.height, Image.SCALE_SMOOTH), img.x, img.y, img.width, img.height, null);
            g.dispose();
        
    

    private static BufferedImage readUrlImage(String urlString)
        try 
            URL url = new URL(urlString);
            DataInputStream dataInputStream = new DataInputStream(url.openStream());
            // 读取背景图
            return ImageIO.read(dataInputStream);
         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
        throw new OpenmoreException("图片生成错误");
    

Controller测试代码:


        String bkgUrl = "http://source.wenxiaoyou.com/test/WechatIMG43.jpeg";
        List<HashMap<String, Object>> elements = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        // 添加二维码
        map.put(ImagePainter.KEY_TYPE, ImagePainter.ElementType.IMAGE);
        ImagePainter.ImageElement image = new ImagePainter.ImageElement();
        image.x = 495;
        image.y = 980;
        image.width = 170;
        image.height = 170;
        image.imageUrl = "http://source.wenxiaoyou.com/image/1568947454861.jpg";
        map.put(ImagePainter.KEY_ELEMENT, image);
        elements.add(map);
        // 添加头像
        HashMap<String, Object> avatarMap = new HashMap<>();
        avatarMap.put(ImagePainter.KEY_TYPE, ImagePainter.ElementType.IMAGE);
        ImagePainter.ImageElement avatar = new ImagePainter.ImageElement();
        avatar.x = 30;
        avatar.y = 30;
        avatar.width = 128;
        avatar.height = 128;
        avatar.borderWidth = 2;
        avatar.round = true;
        avatar.imageUrl = "http://source.wenxiaoyou.com/test/1568886588882.jpg";
        avatarMap.put(ImagePainter.KEY_ELEMENT, avatar);
        elements.add(avatarMap);

        // 添加文字
        HashMap<String, Object> map2 = new HashMap<>();
        map2.put(ImagePainter.KEY_TYPE, ImagePainter.ElementType.FONT);
        ImagePainter.FontElement font = new ImagePainter.FontElement();
        font.content = "扫一扫,领取奖品";
        font.x = 510;
        font.y = 1170;
        font.fontColor = new Color(0, 0, 0);
        map2.put(ImagePainter.KEY_ELEMENT, font);
        elements.add(map2);
        ImagePainter.getPaintedStream(request, response, bkgUrl, elements);

 

以上是关于java 微信海报的实现的主要内容,如果未能解决你的问题,请参考以下文章

怎样在ps中对海报图颜色叠加 教你快速实现颜色叠加方法

用工具实现在微信里面生成带二维码的海报?

利用微信小程序中Canvas API来合成海报生成组件封装

利用微信小程序中Canvas API来合成海报生成组件封装

微信小程序海报 uniapp

微信小程序海报 uniapp