中秋到了,是时候给你的二维码加个月饼了

简介: 又一年的中秋将至,要怎么样才能蹭一波它的热度呢?作为一个coder,是不是可以用代码写首诗?想法是好,可惜难度有点大,那么就简单点,给自己的二维码上,加个月饼吧

又一年的中秋将至,要怎么样才能蹭一波它的热度呢?作为一个coder,是不是可以用代码写首诗?想法是好,可惜难度有点大,那么就简单点,给自己的二维码上,加个月饼吧


1. logo中加月饼?



在二维码中添加月饼,好像没啥难度,直接网上搜一个二维码生成器,然后找个月饼图,作为logo拍上去,game over


image.png

(避免审核不通过,特意抹掉二维码的码眼,无法识别是正常的)


如果仅限于此的话,本文也就没啥意思了,接下来我们看些不一样的东西


2. 拒绝黑白块,满屏二维码



接下来我们使用github上的quick-media:qrcode-plugin来实现更多有意思的二维码定制


首先引入依赖

<dependency>
    <groupId>com.github.liuyueyi.media</groupId>
    <artifactId>qrcode-plugin</artifactId>
    <version>2.6.1</version>
</dependency>
复制代码


接下来我们使用三个月饼图,来生成一张满屏皆是月饼的二维码

image.png


要生成上面的二维码也很简单,实现代码如下

String sourcePrefix = "/Users/user/Documents/qr/";
QrCodeGenWrapper.of(msg)
        .setW(500)
        .setH(500)
        .setErrorCorrection(ErrorCorrectionLevel.M)
        .setDiaphaneityFill(true) // 透明处用背景色填充
        .setDrawBgColor(Color.WHITE)
        .setDrawStyle(QrCodeOptions.DrawStyle.IMAGE_V2)
        .setImgResourcesForV2(RenderImgResourcesV2.create()
                // 下面配置 1 x 1的方块对应的月饼图片
                .addSource(1, 1).addImg(sourcePrefix + "00.png")
                .addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1) // 最后一个1,表示这个月饼只出现一次
                .addImg(sourcePrefix + "03.png")
                .build()
                // 下面配置 2 x 2的方块对应的月饼图片
                .addSource(2, 2)
                .addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
                .addSource(3, 3).addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
        )
        .asFile(sourcePrefix + "/out0.jpg");
复制代码


上面虽然生成了一个满屏就是月饼的二维码,但识别是个问题,关键点就是三个码眼(探测图形)


3. 码眼也要绚起来



既然上面的码眼不够优秀,那就替换掉,用自定义的码眼来代替默认生成的,提高识别率


image.png

要实现上面的这个二维码,方法也很简单,在前面的基础上,指定一下探测图形即可

// 设置左上角码眼
.setLTDetectImg(sourcePrefix + "d1.jpg")
// 设置左下角码眼
.setLDDetectImg(sourcePrefix + "d2.jpg")
// 设置右上角码眼
.setRTDetectImg(sourcePrefix + "d3.jpg")
复制代码


其他的设置方式和前面的也没有什么区别,实现如下

String sourcePrefix = "/Users/user/Documents/qr/";
QrCodeGenWrapper.of(msg)
        .setW(500)
        .setH(500)
        .setErrorCorrection(ErrorCorrectionLevel.M)
        .setDiaphaneityFill(true) // 透明处用背景色填充
        .setDrawBgColor(Color.WHITE)
        .setDrawStyle(QrCodeOptions.DrawStyle.IMAGE_V2)
        .setLTDetectImg(sourcePrefix + "d1.jpg")
        .setLDDetectImg(sourcePrefix + "d2.jpg")
        .setRTDetectImg(sourcePrefix + "d3.jpg")
        .setImgResourcesForV2(RenderImgResourcesV2.create()
                .addSource(1, 1).addImg(sourcePrefix + "00.png")
                .addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png")
                .build()
                .addSource(2, 2)
                .addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
                .addSource(3, 3).addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
        )
        .asFile(sourcePrefix + "/out_d0.jpg");
复制代码


4. 印有诗词的二维码



既然最开始说了中秋要用代码写诗来蹭热度,虽然写诗我不行,但是作为一个专职ctrl+c/ctrl+v的coder,抄我可会了,接下来我们把苏轼大大的千古名篇,给印在我们的二维码上


image.png


上面这个二维码有点意思了,直接用中文来渲染,要实现也很简单,下面几个简单配置即可

String sourcePrefix = "/Users/user/Documents/qr/";
QrCodeGenWrapper.of(msg)
        .setDetectSpecial() // 三个码眼还是用标砖的码眼
        .setDrawStyle(QrCodeOptions.DrawStyle.TXT)
        .setQrText("明月几时有把酒问青天不知天上宫阙今夕是何年我欲乘风归去又恐琼楼玉宇高处不胜寒起舞弄清影何似在人间" +
                "转朱阁低绮户照无眠不应有恨何事长向别时圆人有悲欢离合月有阴晴圆缺此事古难全但愿人长久千里共婵娟")
        .setLogo(sourcePrefix+"/logo2.jpg") // 添加一个logo
        .setLogoStyle(QrCodeOptions.LogoStyle.ROUND)
        .setLogoBorderBgColor(Color.GRAY)
        .asFile(sourcePrefix + "/ft.jpg");
复制代码


5. 有诗词,也有月饼的二维码



只有诗词没有月饼不好看;只有月饼没有诗词不够秀,那就合起来,生成一个类似下面的二维码

image.png


需要注意的是,上面的包中,并没有提供这种混编的方式,需要我们拉到源码自定义改造一番,重写QrCodeOption.DrawStyle中的方法


IMAGE_V2 {
    @Override
    public void draw(Graphics2D g2d, int x, int y, int w, int h, BufferedImage img, String txt) {
        String source  = "明月几时有把酒问青天不知天上宫阙今夕是何年我欲乘风归去又恐琼楼玉宇高处不胜寒起舞弄清影何似在人间" +
                "转朱阁低绮户照无眠不应有恨何事长向别时圆人有悲欢离合月有阴晴圆缺此事古难全但愿人长久千里共婵娟";
        if ("false".equals(txt)) {
            if (Math.random() < 0.8f) {
                if (Math.random() < 0.6f) {
                    int offsetX = w / 5, offsetY = h / 5;
                    int width = w - offsetX * 2, height = h - offsetY * 2;
                    g2d.fillRect(x + offsetX, y + offsetY, width, height);
                    return;
                }
                int index = QuickQrUtil.getIndex();
                if (index >= source.length()) {
                    int offsetX = w / 5, offsetY = h / 5;
                    int width = w - offsetX * 2, height = h - offsetY * 2;
                    g2d.fillRect(x + offsetX, y + offsetY, width, height);
                } else {
                    Font oldFont = g2d.getFont();
                    if (oldFont.getSize() != w) {
                        Font newFont = QuickQrUtil.font(oldFont.getName(), oldFont.getStyle(), w);
                        g2d.setFont(newFont);
                    }
                    g2d.drawString(source.substring(index, index+1), x, y + w);
                    g2d.setFont(oldFont);
                }
            } else {
                g2d.drawImage(img.getScaledInstance(w, h, Image.SCALE_SMOOTH), x, y, null);
            }
        } else {
            g2d.drawImage(img.getScaledInstance(w, h, Image.SCALE_SMOOTH), x, y, null);
        }
    }
    @Override
    public boolean expand(DotSize dotSize) {
        return true;
    }
}
复制代码


6. 让二维码动起来



上面的这些都是静态的,接下来我们赋予它动起来的能力,生成一个gif版的二维码,需要我们做的事情也不多,找个gif背景图即可


image.png

上面这个动态二维码的生成方式也很简单,基本配置与前面一致,区别在于指定背景gif图

String sourcePrefix = "/Users/user/Documents/qr/";
QrCodeGenWrapper.of(msg)
        .setW(160)
        .setH(160)
        .setErrorCorrection(ErrorCorrectionLevel.M)
        .setDiaphaneityFill(true) // 透明处用背景色填充
        .setDrawBgColor(Color.WHITE)
        .setPadding(0)
        .setDrawStyle(QrCodeOptions.DrawStyle.IMAGE_V2)
        .setDetectSpecial()
        .setImgResourcesForV2(RenderImgResourcesV2.create()
                .addSource(1, 1).addImg(sourcePrefix + "00.png")
                .addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png")
                .build()
                .addSource(2, 2)
                .addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
                .addSource(3, 3).addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
        )
        .setLogo(sourcePrefix+"/logo.jpg")
        .setLogoRate(12)
        .setLogoStyle(QrCodeOptions.LogoStyle.ROUND)
        .setLogoBorderBgColor(Color.GRAY)
        // 下面是设置背景图,表示将二维码覆盖在背景图的指定坐标上
        .setBgImg(sourcePrefix + "/bg4.gif")
        .setBgStyle(QrCodeOptions.BgImgStyle.FILL)
        .setBgStartX(10)
        .setBgStartY(120)
        .asFile(sourcePrefix + "/out3.gif");
}
复制代码


除了上面这种动态之外,还可以实现类似logo的动图效果,如

image.png


实现姿势也很简单,借助FtImg来指定前置的gif图即可

String sourcePrefix = "/Users/user/Documents/qr/";
QrCodeGenWrapper.of(msg)
        .setW(500)
        .setH(500)
        .setDiaphaneityFill(true) // 透明处用背景色填充
        .setDrawBgColor(ColorUtil.OFF_WHITE) // 设置背景色为米黄色,方便gif图的显示效果
        .setDrawStyle(QrCodeOptions.DrawStyle.IMAGE_V2)
        .setDetectSpecial()
        .setImgResourcesForV2(RenderImgResourcesV2.create()
                .addSource(1, 1).addImg(sourcePrefix + "00.png")
                .addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png")
                .build()
                .addSource(2, 2)
                .addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
                .addSource(3, 3).addImg(sourcePrefix + "00.png").addImg(sourcePrefix + "01.png")
                .addImg(sourcePrefix + "02.png", 1)
                .addImg(sourcePrefix + "03.png").build()
        )
        // 直接从网络下载gif图,缩放为 112 * 120, 在二维码中间绘制
        .setFtImg("https://b-ssl.duitang.com/uploads/item/201609/14/20160914224309_WNUaE.gif")
        .setFtW(112)
        .setFtH(120)
        .setFtStartX(-194)
        .setFtStartY(-190)
        .asFile(sourcePrefix + "/out_ft1.gif");
复制代码


7. 最后的最后



最后声明,本文中所有资源来自网络,如有侵权,联系即删,本文中所有的二维码生成,都是基于开源项目quick-media来生成的, 有兴趣的小伙伴可以尝鲜一下github.com/liuyueyi/qu…,毕竟月饼节到了,怎么着也得吃个吧



相关文章
|
7月前
|
JavaScript 前端开发 API
告别Vue 2时代:Composables,你的下一代状态逻辑复用神器
告别Vue 2时代:Composables,你的下一代状态逻辑复用神器
277 6
|
7月前
|
存储 人工智能 并行计算
阿里云技术加持!钉钉AI表格突破1000万热行
钉钉AI表格突破单表1000万热行,首创存算一体架构,助力企业高效应对双11数据洪峰。已应用于德香苑、森马等品牌,实现海量数据秒级响应,告别“人工分表”,提升运营效率与决策精准度。
453 0
|
机器学习/深度学习 人工智能 搜索推荐
PaSa:字节跳动开源学术论文检索智能体,自动调用搜索引擎、浏览相关论文并追踪引文网络
PaSa 是字节跳动推出的基于强化学习的学术论文检索智能体,能够自动调用搜索引擎、阅读论文并追踪引文网络,帮助用户快速获取精准的学术文献。
1214 15
|
JSON JavaScript 数据格式
JS 将 json 对象转成字符串并保留格式 - JSON.stringify()
JS 将 json 对象转成字符串并保留格式 - JSON.stringify()
709 0
|
人工智能 机器人
LeCun 的世界模型初步实现!基于预训练视觉特征,看一眼任务就能零样本规划
纽约大学Gaoyue Zhou等人提出DINO World Model(DINO-WM),利用预训练视觉特征构建世界模型,实现零样本规划。该方法具备离线训练、测试时行为优化和任务无关性三大特性,通过预测未来补丁特征学习离线行为轨迹。实验表明,DINO-WM在迷宫导航、桌面推动等任务中表现出强大的泛化能力,无需依赖专家演示或奖励建模。论文地址:https://arxiv.org/pdf/2411.04983v1。
493 21
|
Kubernetes 安全 Docker
在K8S中,在服务上线的时候Pod起不来怎么进行排查?
在K8S中,在服务上线的时候Pod起不来怎么进行排查?
|
存储 网络协议 网络安全
|
算法 Python
【Leetcode刷题Python】73. 矩阵置零
本文介绍了LeetCode第73题的解法,题目要求在给定矩阵中将所有值为0的元素所在的行和列全部置为0,并提供了一种原地算法的Python实现。
427 0
【Leetcode刷题Python】73. 矩阵置零
|
人工智能 自然语言处理 算法

热门文章

最新文章