转自HaaS技术社区
1、二维码发展史
二维码这个小图案现在已经是我们生活中不可或缺的一部分了,饭店点餐,添加好友,付钱转账,登录账号等等都只要扫一扫,方便又快捷。二维码的前身其实就是一维码,也就是条形码。
条形码可以在水平方向,通过黑白相间的条纹来存储一些数字或者字母的信息,制作十分简单,但是有着存储容量不足、易复制、无法表示汉字等缺点,为此人们继续考虑同时从水平方向与垂直方向去存储信息,进而在上世纪90年代产生了二维码,并开始广泛运用于生活。二维码用某种特定的几何图形按一定规律在二维空间上分布的黑白相间的图形中记录数据符号信息。
2、跟条形码区别
2.1、承载的信息量远大于条形码
组成条形码的信息部分只能是字母和数字,而且尺寸较大,导致空间利用率较低。这就决定了其信息量不大的局限性。它的数据容量较小一般只可容纳30个字符左右。二维码就不一样了,它的信息承载量很大,最大数据含量可达1850个字符。信息内容可包含字母,数字,汉字,字符,片假名等。信息含量非常丰富。所以二维码也逐渐被市场所接受,汉字的加入更开拓了中国这个大市场。
2.2、信息表达方式不一样
根据其特性及结构可以看到,条形码只能在水平方向单向的表达商品信息,而在垂直方向则不表达任何信息,它有一定高度通常是为了便于条码设备的对准读取。而二维码在水平和垂直方向都可表达信息,也就是说它在二维空间内存储信息。
2.3、外在结构不一样
根据上图可知,它们的结构完全不同。条形码是用条空在水平方向上表达信息的条码。外形更接近矩形。二维码可以说是正方形,在其内部有三个“回”字型的定位点,可以帮助扫码设备对焦,便于读取数据。也正是它们结构的差异,使条形码没有较强的纠错功能,如果有破损就不能被读取。对于二维码来说,即使有破损,也可以正常读取。其破损纠错率可达7%~30%。
2.4、码制不一样
在目前的码制中,条形码和二维码各有自己的码制和组成成员。常用的条形码的码制包括:EAN码、39码、交叉25码、UPC码、128码、93码,ISBN码,及Codabar(库德巴码)等;常用的二维码码制有:PDF417二维条码, Datamatrix二维条码, , QR Code, Code 49, Code 16K ,Code one等。
2.5、优缺点表现
一维码的优点是在一个方向表达信息,其一定的高度通常是为了便于扫描器的对准、一维码可以提高信息录入的速度,减少差错率。缺点是数据的容量比较小,需要计算机数据库,一维码被破坏后便不能读取,容错率低。
二维码的优点是信息容量大,编码范围广,成本较低,容易制作,不需要数据库本身就能储存大量数据,二维码的容错机制保证了图片部分被破坏后还能正确识别,容错率可以高达30%。缺点是容易被不法分子植入病毒盗取用户信息或各种吸费软件。
3、LittlevGL对条形码及二维码的支持
在POS机等支付行业,二维码比条形码更为常用,因此图形框架对二维码的支持也是必须的,在二维码中QR Code对字母,数字,汉字等支持的容量很大,因此GUI图形框架的扩展主要考虑对QR Code的支持。
目前LittlevGL并不支持QR code码,因此添加如下代码,其中int16 width代表生成的二维码的宽跟高,char *cid则是二维码对应的字符串:
lv_obj_t *qrcode_gen(lv_obj_t * par, const char *cid, int px, int py, int width)
{
int src_buf_size, dst_buf_size, qr_w, idx;
int qr_pixel_width = 1;
int version = QR_STD_VERSION;
unsigned char *qr_data;
QRcode *qrcode;
if(par == NULL) par = lv_scr_act();
qrcode = QRcode_encodeString(cid, version, QR_ECLEVEL_Q, QR_MODE_8, 1);
if ((!qrcode) || (qrcode->width <= 0)) {
printf("QRcode_encodeString failed\n");
return NULL;
}
qr_w = qrcode->width;
if(width > qr_w) {
qr_pixel_width = width / qr_w;
}
src_buf_size = qr_w * qr_w * qr_pixel_width * qr_pixel_width * sizeof(lv_color_t);
dst_buf_size = width * width * 2;
lv_color_t *orig_color_map = lv_mem_aligned_alloc(src_buf_size, 32);
if(orig_color_map == NULL) {
printf("qrcode_gen, no memory 1!!\n");
goto err;
}
memset(orig_color_map, 0x00, src_buf_size);
qr_data = qrcode->data;
printf("qr width: %d\n", qrcode->width);
int p1;
for (int y = 0; y < qr_w; y++) {
for (int x = 0; x < qr_w; x++) {
idx = y*qr_w + x;
p1 = y * qr_w * (qr_pixel_width * qr_pixel_width) + x * qr_pixel_width;
if ((qr_data[idx] & 0x1) == 0) { /* white pix */
int i = 0;
int p2 = p1;
for(i = 0; i < qr_pixel_width; i++) {
memset(&orig_color_map[p2], 0xff, sizeof(lv_color_t) * qr_pixel_width);
p2 += (qr_w * qr_pixel_width);
}
}
}
}
lv_color_t *dst_color_map = lv_mem_aligned_alloc(dst_buf_size, 32);
if(dst_color_map == NULL) {
printf("qrcode_gen, no memory 2!!\n");
lv_mem_aligned_free(orig_color_map);
goto err;
}
if(rgb565_scale(qr_w * qr_pixel_width, qr_w * qr_pixel_width, width, width, (uint8_t *)orig_color_map, (uint8_t *)dst_color_map) == 0) {
lv_mem_aligned_free(orig_color_map);
lv_mem_aligned_free(dst_color_map);
goto err;
}
lv_img_dsc_t *img_des = lv_mem_alloc(sizeof(lv_img_dsc_t));
if(img_des == NULL) {
printf("qrcode_gen, no memory 3!!\n");
lv_mem_aligned_free(orig_color_map);
lv_mem_aligned_free(dst_color_map);
goto err;
}
memset(img_des, 0 , sizeof(lv_img_dsc_t));
img_des->header.w = width;
img_des->header.h = width;
img_des->header.cf = LV_IMG_CF_TRUE_COLOR;
img_des->data_size = dst_buf_size;
img_des->data = (const uint8_t *)dst_color_map;
lv_obj_t *img = lv_img_create(par, NULL);
lv_img_set_src(img, img_des);
lv_obj_set_pos(img, px, py);
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(img);
/*The signal and design functions are not copied so set them here*/
lv_obj_set_signal_func(img, qrcode_signal);
QRcode_free(qrcode);
lv_mem_aligned_free(orig_color_map);
return img;
err:
QRcode_free(qrcode);
printf("qrcode_gen failed\n");
return NULL;
}
4、总结
本文讲解了二维码的发展史,已经二维码和条形码的区别,并详细的说明如何在LittlevGL中扩展对条形码及二维码的支持。
开发者支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号。
更多技术与解决方案介绍,请访问HaaS官方网站https://haas.iot.aliyun.com。