趣味二维码生成

1

背景介绍       

最近在 Github 看到了一个有趣的项目 amazing-qr,它支持生成普通二维码,带图片的艺术二维码,动态二维码。

项目是用 python 编写的,以命令行的方式运行生成,不太方便调用,因此,我把它封装成了 Api

2

示例展示       

1. 普通二维码

c0062aa22c2d312269b32a4f3e3c6ce5.png

2. 图片二维码

192d18f646dfe90b5d9a4013db433ca6.png

04352ba5c1f91e1d53255e697df20da7.png

3. 动态二维码

032510c9170ec7aa3b071ed3153c46ac.gif

4ab902e49e082b68c4b2f57e6604b242.gif

4f8b9267ecce80b10e31a02be54f1277.gif

3

如何使用       

  1. 克隆代码 https://github.com/ErikXu/qrcode-service.git

  2. 安装 docker

  3. 执行 bash build.sh 指令编译程序

  4. 执行 bash pack.sh 指令打包镜像

  5. 执行 bash run.sh 运行容器

  6. 访问 http://localhost:5000/swagger

4

指令介绍       

1. 说明

amzqr Words                   # 用来生成二维码的内容[-v {1,2,3,...,40}]     # 二维码是正方形的,此参数表示二维码的边长,范围 1-40,不指定将基于二维码内容长度和纠错等级判断[-l {L,M,Q,H}]          # 纠错等级,范围是 L、M、Q、H,从左到右依次升高,默认为 H[-n output-filename]    # 输出二维码文件名[-d output-directory]   # 输出二维码文件夹[-p picture_file]       # 用于合成二维码的图片[-c]                    # 是否生成彩色二维码[-con contrast]         # 对比度,表示原始图片,更小的值表示更低对比度,更大反之,默认值为 1.0[-bri brightness]       # 亮度,用法和取值与 -con 相同,默认值为 1.0

2. 示例

# 生成普通二维码
amzqr https://github.com# 生成普通二维码,设置边长为 10, 纠错等级为 M
amzqr https://github.com -v 10 -l M# 生成普通二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.png
amzqr https://github.com -v 10 -l M -n qrcode.png -d /tmp# 生成黑白图片二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.png
amzqr https://github.com -v 10 -l M -n qrcode.png -d /tmp -p github.png# 生成彩色图片二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.png
amzqr https://github.com -v 10 -l M -n qrcode.png -d /tmp -p github.png -c# 生成彩色图片二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.png,对比度为 1.0,亮度为 1.0
amzqr https://github.com -v 10 -l M -n qrcode.png -d /tmp -p github.png -c -con 1.0 -bri 1.0# 生成动态二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.gif
amzqr https://github.com -v 10 -l M -n qrcode.gif -d /tmp -p github.gif -c# 生成动态二维码,设置边长为 10, 纠错等级为 M,输出到 /tmp/qrcode.gif,对比度为 1.0,亮度为 1.0
amzqr https://github.com -v 10 -l M -n qrcode.gif -d /tmp -p github.gif -c -con 1.0 -bri 1.0

5

代码实现       

有了上述指令介绍,Api 只需要根据输入参数生成对应的指令进行执行即可,以下是指令参数翻译过来的实体类:

public class QRCodeForm
{/// <summary>/// Content to gen to qrcode/// </summary>[Required]public string? Text { get; set; }/// <summary>/// Length of the qrcode image range 1 to 40/// </summary>[Range(1, 40)]public int? Version { get; set; } = null;/// <summary>/// Error correction level, is one of L, M, Q and H, default H/// </summary>[DefaultValue("H")][LevelValidation]public string Level { get; set; } = "H";/// <summary>/// Is qrcode image colorized/// </summary>public bool Colorized { get; set; } = false;/// <summary>/// The contrast of the qrcode image, defaule 1.0/// </summary>[DefaultValue(1.0)]public double Contrast { get; set; } = 1.0;/// <summary>/// The brightness of the qrcode image, defaule 1.0/// </summary>[DefaultValue(1.0)]public double Brightness { get; set; } = 1.0;
}

根据输入参数生成指令:

[HttpPost]
public async Task<IActionResult> Generate([FromForm] QRCodeForm form, IFormFile? file)
{var outDir = Directory.GetCurrentDirectory();var isUnix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux);if (isUnix){outDir = "/tmp";}var command = $"amzqr {form.Text} -l {form.Level.ToUpper()}";var isGif = false;var tmpPath = string.Empty;if (file != null){var ext = Path.GetExtension(file.FileName).ToLower();if (ext == ".gif"){isGif = true;}tmpPath = Path.Combine(outDir, isGif ? $"{Guid.NewGuid()}.gif" : $"{Guid.NewGuid()}.png");await using var stream = System.IO.File.Create(tmpPath);await file.CopyToAsync(stream);command = form.Colorized ? $"{command} -p {tmpPath} -c" : $"{command} -p {tmpPath}";if (form.Version == null){form.Version = 10;}}if (form.Version != null){command = $"{command} -v {form.Version}";}var filename = isGif ? $"{Guid.NewGuid()}.gif" : $"{Guid.NewGuid()}.png";var filePath = Path.Combine(outDir, filename);command = $"{command} -n {filePath} -d {outDir} -con {form.Contrast} -bri {form.Brightness}";var (code, message) = ExecuteCommand(command);if (code != 0){return StatusCode(StatusCodes.Status500InternalServerError, new { Message = message });}var bytes = await System.IO.File.ReadAllBytesAsync(filePath);System.IO.File.Delete(filePath);if (!string.IsNullOrWhiteSpace(tmpPath)){System.IO.File.Delete(tmpPath);}var contentType = isGif ? "image/gif" : "image/png";return File(bytes, contentType, filename);
}

.Net 执行指令:

private (int, string) ExecuteCommand(string command)
{var isUnix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux);var escapedArgs = command.Replace("\"", "\\\"");var process = new Process{StartInfo = new ProcessStartInfo{FileName = isUnix ? "/bin/sh" : "powershell",Arguments = isUnix ? $"-c \"{escapedArgs}\"" : command,RedirectStandardOutput = true,RedirectStandardError = true,UseShellExecute = false,CreateNoWindow = true}};process.Start();process.WaitForExit();var message = process.StandardOutput.ReadToEnd();if (process.ExitCode != 0){message = process.StandardError.ReadToEnd();}return (process.ExitCode, message);
}

6


镜像分析       

由于使用 amzqr 需要 python 环境,因此,我们需要在镜像中安装 python 和 amzqr。这里采用的是 .Net --self-contained 及 SingleFile 的发布模式,基础镜像使用 Alpine 即可,这样镜像会比较小,最终镜像信息如下:

docker images
REPOSITORY                                            TAG                     IMAGE ID            CREATED             SIZE
qrcode-service                                        1.0.0                   ed951bd0f183        11 hours ago        579MBdocker history qrcode-service:1.0.0
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
ed951bd0f183        11 hours ago        /bin/sh -c #(nop)  ENTRYPOINT ["/app/QRCodeS…   0B
5d8233b13569        11 hours ago        /bin/sh -c #(nop)  EXPOSE 5000                  0B
243defd1dbf8        11 hours ago        /bin/sh -c #(nop) WORKDIR /app                  0B
35107ba54a38        11 hours ago        /bin/sh -c #(nop) COPY dir:41655fe6f5c1f2696…   89.7MB              # .Net 程序大小
6397fd089666        11 hours ago        /bin/sh -c pip install amzqr                    163MB               # amzpr 大小
dd22ff3f30f3        11 hours ago        /bin/sh -c apk add build-base python3-dev       239MB               # gcc + python-dev 大小
ebfe625d9bbf        11 hours ago        /bin/sh -c pip3 install --no-cache --upgrade…   17.8MB              # setuptools 大小
27b796e1ee1b        11 hours ago        /bin/sh -c python3 -m ensurepip                 12.8MB              # pip 大小
897ce778f7ac        11 hours ago        /bin/sh -c apk add --update --no-cache pytho…   44.4MB              # python 大小
f50f70c2e77e        11 hours ago        /bin/sh -c #(nop)  ENV PYTHONUNBUFFERED=1       0B
383310ca7431        11 hours ago        /bin/sh -c apk add --no-cache         ca-cer…   4.32MB              # .Net 依赖大小
b5cadfbc43c4        11 hours ago        /bin/sh -c apk update                           2.16MB              # 升级 apk 源增加的大小
c594ce5ebfef        11 hours ago        /bin/sh -c sed -i 's/dl-cdn.alpinelinux.org/…   95B
021b3423115f        9 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           9 months ago        /bin/sh -c #(nop) ADD file:34eb5c40aa0002892…   5.6MB               # Alpine 镜像大小

.Net 发布压缩参数 PublishTrimmed=true 在 .Net 6 貌似失效了,不然 .Net 程序的大小应该在 40M 左右。

7


开发要求       

1. 操作系统

可以在 Windows,Linux,Mac 上进行开发,比较推荐 Linux,在 Windows 环境下使用图片合成时会有文件占用的问题。

2. 环境依赖

python3 以及 amzpr。

8


项目地址       

https://github.com/ErikXu/qrcode-service

欢迎大家 star,提 pr,提 issue,在文章或者在公众号 - 跬步之巅留言交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/287673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《零基础看得懂的C++入门教程 》——(1)第一个C++程序就让你知其所以然

一、学习目标 了解第一个C程序了解第一个C程序结构了解什么是注释了解什么是命名空间了解C语言的输出&#xff08;如何在程序运行时显示内容&#xff09;了解语句结束后需要使用什么符号表示结束 了解程序入口 目录 预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;…

1、Locust压力测试环境搭建

环境准备&#xff1a;阿里云服务器一台、python2.7、pip Locust 介绍Locust 是一个开源负载测试工具。使用 Python 代码定义用户行为&#xff0c;也可以仿真百万个用户。 Locust 简单易用&#xff0c;分布式&#xff0c;用户负载测试工具。Locust 主要为网站或者其他系统进行负…

交互式 .Net

1名词解析 1. 交互式交互式是指输入代码后可直接运行该代码&#xff0c;然后持续输入运行代码。2. 交互式 .Net.Net 是一种编译型语言&#xff0c;不像 python 这类的脚本型语言&#xff0c;可以边输入代码边运行结果。幸运的是&#xff0c;软微推出了 interactive 这个项…

mysql signed 长度_浅谈mysql字段长度设置

mysql 中最常用的数据类型是tinyint,smallint,int,bigint,char,varchar;char(n)和varchar(n)存储固定长度的字符数据&#xff0c;长度最大为254字节。使用 ‘n’字节的存储空间;有符号和无符号区别:有符号可以存储负值,无符号只能存储0和非负值数值;tinyint 占用1字节的存储空间…

R语言-异常数据处理2

在R中进行基于稳健马氏距离的异常检验 前言 我们研究的数据中经常包含着一些不同寻常的样本&#xff0c;这称之为异常值(Outlier)。这些异常值会极大的影响回归或分类的效果。异常值产生的原因有很多&#xff0c;其中可能是人为错误、数据测量误差&#xff0c;或者是实际确实存…

《零基础看得懂的C++入门教程 》——(2)什么是数据类型、变量?一看便会

一、学习目标 了解基本常用的数据类型了解什么是变量 目录 预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;C与C使用的软件是一样的&#xff0c;查看这篇即可&#xff1a;《软件介绍》 想了解编译原理和学习方法点这篇&#xff0c;学习方法和一些原理C与C都是相同的…

pycharm 快捷键介绍

CtrlN (Navigate | Class) 打开输入框输入要查找的类名 Ctrl空格 代码自动补全 Ctrl空格&#xff08;按两次&#xff09;对于没有导入的类自动完成导入代码并自动补全 AltF7 查找方法变量在工程中的所有应用 CtrlQ (View | Quick Documentation). 快速查看文档 …

db2和mysql语句区别_db2和mysql语法的区别是什么

MySQL默认使用大小写敏感的数据库名、表名和列名(可以通过lower_case_table_names参数控制是否大小写敏感)&#xff0c;DB2数据库对大小写不敏感。虽然MySQL与DB2都遵循并符合SQL92标准且大多数SQL相互兼容&#xff0c;但是在一些细节的实现上有一些不同的地方。比如&#xff1…

查缺补漏系统学习 EF Core 6 - 数据查询

这是 EF Core 系列的第四篇文章&#xff0c;上一篇文章讲述了 EF Core 中的实体迁移与数据播种。这篇文章盘点一下 EF Core 的几种数据查询方式&#xff0c;内容较多分上下两篇。点击上方或后方蓝字&#xff0c;阅读 EF Core 系列合集。简单查询在 EF Core 中&#xff0c;每个查…

《零基础看得懂的C++入门教程 》——(3)表达式花样挺多鸭

一、学习目标 了解变量之间的计算了解什么是表达式了解什么是自增、自减 目录 预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;C与C使用的软件是一样的&#xff0c;查看这篇即可&#xff1a;《软件介绍》 想了解编译原理和学习方法点这篇&#xff0c;学习方法和一些…

prometheus python client

为什么80%的码农都做不了架构师&#xff1f;>>> 当我刚开始准备使用Python写一个promethues的client的时候&#xff0c;并没有想到过程这么麻烦。github上的大佬们也没兴趣帮我解决这些细节的问题。以下是我在使用prometheus_client遇到的一些问题&#xff0c;仅供…

【遥感数字图像处理】实验:遥感影像分类(监督、非监督分类)完整流程(Erdas版)

一.实验目的: 理解计算机图像分类的基本原理,掌握数字图像非监督分类以及监督分类的具体方法和过程,以及两种分类方法的区别。 二.实验平台:ERDAS IMAGINE 9.1 三.实验要求:掌握非监督分类;非监督分类结果评价;监督分类;监督分类结果评价;分类后处理。 四.实验…

重大跨越!Windows 11 23H2 25115 推送:2023 年更新测试开启,水印回归

面向 Dev 频道的 Windows 预览体验成员&#xff0c;微软现已发布 Windows 11 预览版 Build 25115。主要变化1.微软宣布从 Dev 频道切换到 Beta 频道的选项正式关闭&#xff0c;Beta 频道将继续测试 Windows 11 版本 22H2&#xff0c;而 Dev 频道将开启 2023 年更新 Windows 11 …

《零基础看得懂的C++入门教程 》——(4)条件判断原来如此

一、学习目标 了解什么是条件判断了解多个条件判断了解输入了解什么是逻辑与、逻辑或 目录 预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;C与C使用的软件是一样的&#xff0c;查看这篇即可&#xff1a;《软件介绍》 想了解编译原理和学习方法点这篇&#xff0c;学…

Django学习笔记(4)

为什么80%的码农都做不了架构师&#xff1f;>>> 首先提一个问题&#xff1a;在Django中如何处理CRSF(Cross-site request forgery)? 先看一下CSRF原理。 其实就是恶意网站利用正常网站的cookie去非法请求。 ##Java处理方式## 一般做法需要后台和前端配合采取策略去…

.NET版OCR紧随PP-OCRv3重磅发布

.net版OCR地址PaddleOCRSharp&#xff1a;https://gitee.com/raoyutian/paddle-ocrsharpPaddleOCRSharp是一个基于PaddleOCR的C代码修改并封装的.NET的工具类库。包含文本识别、文本检测、基于文本检测结果的统计分析的表格识别功能&#xff0c;同时针对小图识别不准的情况下&a…

《零基础看得懂的C++入门教程 》——(5) 容我套个娃 循环

一、学习目标 了解循环的使用方法 目录 预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;C与C使用的软件是一样的&#xff0c;查看这篇即可&#xff1a;《软件介绍》 想了解编译原理和学习方法点这篇&#xff0c;学习方法和一些原理C与C都是相同的《脱离学习误区》 …

Android两个注意事项.深入了解Intent和IntentFilter(两)

深入理解Intent和IntentFiler(二)转载请表明出处&#xff1a;http://blog.csdn.net/u012637501(嵌入式_小J的天空) 在上一篇文章中&#xff0c;我们比較具体学习了"Intent"的相关知识&#xff0c;如今将学习怎样设置Intent对象的这些属性以及怎样使用他们来启动组件。…

Oracle常用sql语句(一)

Sql的分类DDL操作数据库表列等表基本的操作主键索引视图 常用数据类型字符串类型数字类型日期类型LOB类型LONG类型 数据转换character datenumbercharacter通用函数条件表达式Sql的分类 DDL &#xff08;Data Definition Language&#xff09;&#xff1a;数据定义语言&#xf…

ASP.NET Web API 实现客户端Basic(基本)认证 之简单实现

优点是逻辑简单明了、设置简单。 缺点显而易见&#xff0c;即使是BASE64后也是可见的明文&#xff0c;很容易被破解、非法利用&#xff0c;使用HTTPS是一个解决方案。 还有就是HTTP是无状态的&#xff0c;同一客户端每次都需要验证。 实现&#xff1a; 客户端在用户输入用户名及…