java 分享商品生成海报到微信+二维码

参考博客:https://blog.csdn.net/linhaibing009/article/details/89576594?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

效果图

第一步:生成自定义的二维码

1 导入依赖

  <!-- 二维码 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.2.1</version>
        </dependency>
        <!-- 二维码 end-->

2 二维码工具类


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;

import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

/**
 *  喷二维码
 * @Author: zhangYuHui
 * @Date: 2020/4/21 15:31
 */
public class QrCodeUtil {


    /**
     * 生成二维码
     * @param url 参数路径
     * @param fileName 文件名称
     * @return
     */
    public static String createQrCode(String url,String fileName) {
        //生成的地址
        String path = FileSystemView.getFileSystemView().getHomeDirectory() + File.separator + "testQrcode";
        try {
            Map<EncodeHintType, String> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 220, 220, hints);
            File file = new File(path, fileName);
            if (file.exists() || ((file.getParentFile().exists() || file.getParentFile().mkdirs()) && file.createNewFile())) {
                writeToFile(bitMatrix, "png", file);
                return file.getPath();

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        if (!ImageIO.write(image, format, file)) {
            throw new IOException("Could not write an image of format " + format + " to " + file);
        }
    }

    static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        if (!ImageIO.write(image, format, stream)) {
            throw new IOException("Could not write an image of format " + format);
        }
    }

    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;

    /**
     * 生成内容
     * @param matrix
     * @return
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }


}

第二步,生成海报工具类


import com.xcds.shequ.common.constant.Constants;
import com.xcds.shequ.project.promote.entity.GoodsInfoVO;

import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;


/**
 * 图片生成海报
 * @Author: zhangYuHui
 * @Date: 2020/7/1 17:52
 */
public class ImgUtils {

    public static final String IMAGE_SUFFIX = ".png";


    /**
     * 合成图片
     * @param bgImgUrl  背景图(可以自定义背景)
     * @param headImgUrl 天猫,淘宝,pdd 小图标,
     * @param goodsInfoVO 商品集合
     * @return url
     * @throws IOException
     */
    public static String drawImage(InputStream bgImgUrl,InputStream headImgUrl,GoodsInfoVO goodsInfoVO) throws IOException {

        int width = 620;
        int height = 1004;
        // RGB形式,自定义背景
//        BufferedImage bgBufImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        BufferedImage bgBufImage = ImageIO.read(bgImgUrl);
        Graphics2D bgBufImageGraphics = bgBufImage.createGraphics();
        // 设置背景色
        bgBufImageGraphics.setBackground(Color.WHITE);

        // 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
       // bgBufImageGraphics.clearRect(0, 0, width, height);

        // 设置画笔,设置Paint属性 ==>设置标题文字
        bgBufImageGraphics.setPaint(Color.black);
        Font font = new Font("PingFangSC-Medium", Font.BOLD, 28);
        bgBufImageGraphics.setFont(font);
        //商品标题,大于23个子,用点代替
        String title = goodsInfoVO.getTitle();
        if(title.length()>22){
            title=title.substring(0,21)+"...";
        }
        bgBufImageGraphics.drawString(title, 70, 80);


        // 设置卷后价
        Font font1 = new Font("PingFangSC-Medium", Font.BOLD, 60);
        bgBufImageGraphics.setPaint(Color.red);
        bgBufImageGraphics.setFont(font1);
        bgBufImageGraphics.drawString(goodsInfoVO.getOrgPrice(), 160, 180);

        //获取上次的文字宽度 + 上一次的x轴+ 隔离距离
        FontMetrics fm = bgBufImageGraphics.getFontMetrics(font1);
        int width1 = fm.stringWidth(goodsInfoVO.getOrgPrice())+165;
        // 设置原价后价
        HashMap<TextAttribute,Object> hm = new HashMap<>(Constants.MAP_LENG);
        hm.put(TextAttribute.FAMILY,"PingFangSC-Medium");
        hm.put(TextAttribute.SIZE, 28);
        hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
        //粗体
        hm.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
        //删除线
        hm.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
        Font font2 = new Font(hm);
        bgBufImageGraphics.setPaint(Color.lightGray);
        bgBufImageGraphics.setFont(font2);
        bgBufImageGraphics.drawString("原价¥"+goodsInfoVO.getPrice(), width1, 180);

        // 设置购买人数
        Font font3 = new Font("PingFangSC-Medium", Font.BOLD, 20);
        bgBufImageGraphics.setPaint(Color.gray);
        bgBufImageGraphics.setFont(font3);
        bgBufImageGraphics.drawString(goodsInfoVO.getMonthSales()+" 人已买", 60, 220);

        // 设置优惠卷金额
        Font font4 = new Font("PingFangSC-Medium", Font.BOLD, 30);
        bgBufImageGraphics.setPaint(Color.white);
        bgBufImageGraphics.setFont(font4);
        bgBufImageGraphics.drawString("¥"+goodsInfoVO.getCouponPrice(), 580, 190);

        // 抗锯齿
        bgBufImageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // BufferedImage posterBufImage = ImageIO.read(new URL(posterImgUrl));
        // //直接使用图片做背景,自定义背景使用上面方式
        // Graphics2D posterBufImageGraphics = posterBufImage.createGraphics();

        //商品图片
        BufferedImage posterBufImage = ImageIO.read(new URL(goodsInfoVO.getPicUrl()));
        //读取本地图片 二维码
        BufferedImage qrCodeImage = ImageIO.read(new FileInputStream(goodsInfoVO.getQrCodeImgUrl()));
        //标识图片,天猫
        BufferedImage headImage = ImageIO.read(headImgUrl);

        // 设置圆形图片
        BufferedImage roundHeadImg = new BufferedImage(headImage.getWidth(), headImage.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        Graphics2D roundHeadGraphics = roundHeadImg.createGraphics();
        Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, roundHeadImg.getWidth(), roundHeadImg.getHeight());
        roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        roundHeadImg = roundHeadGraphics.getDeviceConfiguration().createCompatibleImage(headImage.getWidth(),
                headImage.getHeight(), Transparency.TRANSLUCENT);
        roundHeadGraphics = roundHeadImg.createGraphics();
        // 使用 setRenderingHint 设置抗锯齿
        roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        roundHeadGraphics.setClip(shape);
        roundHeadGraphics.drawImage(headImage, 0, 0, null);
        roundHeadGraphics.dispose();


        // bgBufImageGraphics.drawImage(qrCodeImage, (posterBufImage.getWidth()
        // - qrCodeImage.getWidth()), 10, qrCodeImage.getWidth(),
        // qrCodeImage.getHeight(), null);
        // posterBufImageGraphics.drawImage(roundHeadImg, 50, 100,
        // HEAD_URL_WIDTH, HEAD_URL_HEIGHT, null);

         //二维码
        bgBufImageGraphics.drawImage(qrCodeImage, 520, 970, 220, 210, null);

        //天猫图片
        bgBufImageGraphics.drawImage(roundHeadImg, 32, 45, 30, 30, null);

        //商品图片
        bgBufImageGraphics.drawImage(posterBufImage, 32, 250, 680, 680, null);

        bgBufImageGraphics.dispose();

        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        ImageOutputStream imgOut = ImageIO.createImageOutputStream(bs);
        ImageIO.write(bgBufImage, "png", imgOut);
        // 上传到服务器上
        String url = QiniuCloudUtil.uploadObject2OSS(bs.toByteArray());
        //字节写入到本地
        //QiniuCloudUtil.uploadImgLocalHost(bs.toByteArray());
        return url;
    }


}

3 接收参数的实体

package com.xcds.shequ.project.promote.entity;

import lombok.Data;

/**
 * @Author: zhangYuHui
 * @Date: 2020/7/1 17:56
 */
@Data
public class GoodsInfoVO {

    /**商品id*/
    private String id;
    /**用户渠道id*/
    private String rid;
    /**标题*/
    private String title;
    /**商品图片*/
    private String picUrl;
    /**标识,tm 天猫,tb 淘宝,pdd 拼多多*/
    private String from;
    /**原价*/
    private String price;
    /**卷后价*/
    private String orgPrice;
   /**售量*/
    private String monthSales;
    /**优惠卷价格*/
    private String couponPrice;
    /**二维码图片*/
    private String qrCodeImgUrl;

}

4调用方法

 /**
     * 生成海报
     * @param goodsInfoVO
     * @return
     */
    @GetMapping("poster")
    public AjaxResult poster(GoodsInfoVO goodsInfoVO) throws IOException {
        SysUser user = getUser();
        if(StringUtils.isNotEmpty(user.getRelationId())){
            //生成二维码
            String qrCode = QrCodeUtil.createQrCode("www.baidu.com", "temp.jpg");
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("static/app/imgs/"+goodsInfoVO.getFrom()+".png");
            InputStream bgImg = this.getClass().getClassLoader().getResourceAsStream("static/app/imgs/bg.png");

            goodsInfoVO.setQrCodeImgUrl(qrCode);
            String url = ImgUtils.drawImage(bgImg,inputStream,goodsInfoVO);

            System.out.println("二维码:"+qrCode+"清除:"+ FileUtils.deleteFile(qrCode));
            //成功之后,删除临时二维码文件
            return AjaxResult.success(url);
      }
        return AjaxResult.error("请绑定渠道");

    }

注意:这个只是小图标和背景图,

背景图片,相当于填空题一样,把对应的参数填入到指定的地方

 

postman测试

部署到linux 环境图片文字可能会乱码,需要linux安装正确的字体,参考博客https://blog.csdn.net/weixin_30292745/article/details/98614816?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

底图加平方字体下载

链接:https://pan.baidu.com/s/1VzfC-7aR079m8SJQ64worQ 
提取码:oais

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值