来源 | HaaS技术社区
1、简介
条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)排成图案。条形码可以标出物品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等许多信息,因而在商品、图书管理、邮政管理、银行系统等许多领域都得到广泛的应用,如今在我们的日常生活中也是随处可见。
2、条形码发展史
随着社会文化以及生活形态的变化,美国的零售业从上世纪30年代从封闭式转为开放式,随之而来的是结账成为重大瓶颈,在1948年费城煤气科技学院一位名叫伯纳德·塞尔沃的研究生无意中听到当地一家连锁超市的总裁恳请院长发明一种可以在收银台处自动记录商品销售的方法,就开始尝试着手研发条形码,用以在收银台处自动记录商品。1969年起IBM也开始研究,并于4年后推出了一种既易于打印同时也能有效传递信息的长方形条形码。这种条形码最终得到了当时的符号选择委员会的认可,被命名为标准商品码UPC(Uniform Product Code)。1974年在美国俄亥俄州特洛伊城的一个超市,卖出了世界上第一个印有条码的商品——箭牌口香糖,这个商品目前还收藏在美国的国家博物馆里。在中国,1988年12月,经国务院批准成立了国家物品编码协会。“八五”期间,国务院电子信息系统推广应用办公室也将条码技术作为重点推广应用的10项工作之一。1992年我国第一家POS系统问世,标志着我国正式开始使用商品条码。
3、条形码码制
一个完整的条形码由两侧的静区,起始字符,数据字符,校验字符,终止字符组成:
静区:位于条形码两侧,无任何符号及信息的白色区域,提示条码阅读器准备扫描。
起始字符:第一个字符,标志开始,阅读器确认此字符存在后开始处理扫描脉冲。
数据字符:位于起始字符后面的字符,其结构异于起始字符,可允许双向扫描,由0-9构成,这些数字有国码,厂商号码,商品代号,检验码。
校验字符:代表一种运算的结果,阅读器在扫描的时候,对读入的各字符进行运算,如果运算结果跟校验字符相同,则代表本次扫描有效。
终止字符:最后一个字符,阅读器确认此字符存在后结束扫描。
世界上常用的码制比较多,常用的主要有以下几种:
3.1、Code 128条形码
Code 128条形码为目前国内企业内部的自定义码制,可以根据需要确定条形码的长度和信息,它编码的信息可以是数字,也可以包含字母,主要应用于工业生产线领域、图书管理等,如表示产品序列号、图书、文档编号等。
有三种不同的版本:A(数字、大写字母、控制字符)B(数字、大小字母、字符)C(双位数字)
CODE128A:标准数字和大写字母,控制符,特殊字符
CODE128B:标准数字和大写字母,小写字母,特殊字符
CODE128C:[00]-[99]的数字对集合,共100个
3.2、Code 39条形码
Code 39条形码是一种字符集为数字跟字符的条形码,长度可变,不连续型,信息量大,相对密度较低,印刷方便,主要用于制造业,图书及票证自动化管理上。
3.3、Code 93码
Code 93码是一种类似于Code 39码的条形码,相比Code 39码它的密度较高,同样适用于工业制造领域 。
3.4、EAN条形码
EAN条形码是国际通用的符号体系,是一种长度固定、无含意的条形码,所表达的信息全部为数字,主要应用于商品标识。
我国的EAN-13码的编码规则如下:
国家(地区)代码 |
厂商代码 |
商品代码 |
校验码 |
13,12,11 |
10,9,8,7 |
6,5,4,3,2 |
1 |
EAN-8码是EAN-13码的缩短码,由8位数字及条形码组成,主要用于一些印刷面较小的零售商品上面。
国家(地区)代码 |
商品代码 |
校验码 |
8,7,6 |
5,4,3,2 |
1 |
3.5、UPC条形码
UPC条形码(统一产品代码)只能表示数字,有A、B、C、D、E五个版本,版本A-12位数字,版本E-7位数字,最后一位为校验位,大小是宽1.5英寸(1英寸 - 2.54cm),高1英寸,而且背景要清晰,主要在美国和加拿大使用,用于工业、医药、仓储等部门。
UPC条形码的最后一位是校验位。 扫描器通过校验位判断是否扫描了正确的号码。 下面介绍如何用另外的11位数生成校验位:
- 将所有奇数位置(第1、3、5、7、9和11位)上的数字相加。1+3+5+6+8+0=23
- 然后,将该数乘以3。23*3=69
- 将所有偶数位置(第2、4、6、8和10位)上的数字相加。2+4+6+7+9=28
- 然后,将该和与第2步所得的值相加。69+28=97
- 保存第4步的值。要创建校验位,需要确定一个值,当将该值与步骤4所得的值相加时,结果为10的倍数。97+3=100因此,校验位为3。
3.6、25条形码
25条形码只能表示数字0-9,长度可变,条形码呈连续性,空不表示信息,较多用于机场中。
交叉25条形码(也叫穿插25码):只能表示数字0-9,长度可变,条形码呈连续性,所有条与空都表示代码,第一个数字由条开始,第二个数字由空组成,应用于商品批发、仓库、机场、生产(包装)识别、商业中,条形码的识读率高,可用于固定扫描器的可靠扫描,在所有一维条形码中的密度最高。
3.7、库德巴条形码
库德巴条形码( Codabar)也称“血库用码”,可表示数字0-9,字符$、+、-,还有只能用作起始和终止符的a、b、c、d四个字符,空白区比窄条宽10倍,非连续性条形码,每个字符表示为4条3空,条形码长度可变,没有校验位,主要应用于血站的献血员管理和血库管理,也可作物料管理、图书馆、机场包裹发送中。
4、LittlevGL对条形码的支持
在POS机等支付行业,条形码是必须用到的,同样图形框架对条形码的支持也是必须的,Code 128码(包含了EAN128码)可表示较全面的字符(数字、字母和符号),在同样长度的条码中可容纳的字符长度较长(高密度),Code 128码与Code 39码有很多的相近性,都广泛运用在企业内部管理、生产流程、物流控制系统方面。不同的在于Code 128比Code 39能表现更多的字符,单位长度里的编码密度更高。当单位长度里不能容下Code 39编码或编码字符超出了Code 39的限制时,就可选择Code 128来编码。所以Code 128比Code 39更具灵活性。所以Code 128码是企业内部管理系统最为广泛使用的条码码制。
AliOS Things已经集成了LittleVGL了,因此这个轻量级GUI图形框架的扩展主要考虑对Code 128码的支持了。
如何支持条形码
目前littlevgl并不支持Code 128码,为此需要根据Code 128码的生成规则,添加如下代码,其中uint16_t width,跟uint16_t height代表生成的条形码的宽跟高,char *bc_buf则是条形码对应的字符串:
-
lv_obj_t *barcode_create(lv_obj_t * par, uint16_t width, uint16_t height, const char *bc_buf)
-
-
{
-
-
lv_obj_t *obj = NULL;
-
-
if(par == NULL || bc_buf == NULL || width == 0 || height == 0) {
-
-
printf( "barcode_create, param error!!\n");
-
-
return NULL;
-
-
}
-
-
-
-
size_t size = code128_estimate_len(bc_buf);
-
-
uint8_t *barcode_data = lv_mem_alloc(size);
-
-
if(barcode_data == NULL) {
-
-
printf( "barcode_create, no memory 0!!\n");
-
-
return NULL;
-
-
}
-
-
size = code128_encode_gs1(bc_buf, ( char *)barcode_data, size);
-
-
-
-
lv_color_t *orig_color_map = lv_mem_aligned_alloc(size*height* 2, 32);
-
-
if(orig_color_map == NULL) {
-
-
printf( "barcode_create, no memory 1!!\n");
-
-
lv_mem_free(barcode_data);
-
-
return NULL;
-
-
}
-
-
memset(orig_color_map, 0xff, size*height* 2);
-
-
-
-
int i = 0, j = 0;
-
-
for(i= 0; i
-
-
if(barcode_data[i]) {
-
-
for(j= 0; j
-
-
memset(&orig_color_map[j*size + i], 0x0, sizeof( lv_color_t));
-
-
}
-
-
}
-
-
}
-
-
-
-
lv_color_t *dst_color_map = lv_mem_aligned_alloc(width*height* 2, 32);
-
-
if(dst_color_map == NULL) {
-
-
printf( "barcode_create, no memory 2!!\n");
-
-
goto end;
-
-
}
-
-
-
-
if(rgb565_scale(size, height, width, height, ( uint8_t *)orig_color_map, ( uint8_t *)dst_color_map) == 0) {
-
-
lv_mem_aligned_free(dst_color_map);
-
-
goto end;
-
-
}
-
-
-
-
lv_img_dsc_t *img_des = lv_mem_alloc( sizeof( lv_img_dsc_t));
-
-
if(img_des == NULL) {
-
-
printf( "barcode_create, no memory 3!!\n");
-
-
lv_mem_aligned_free(dst_color_map);
-
-
goto end;
-
-
}
-
-
memset(img_des, 0 , sizeof( lv_img_dsc_t));
-
-
img_des->header.w = width;
-
-
img_des->header.h = height;
-
-
img_des->header.cf = LV_IMG_CF_TRUE_COLOR;
-
-
img_des->data_size = width*height* 2;
-
-
img_des->data = ( const uint8_t *)dst_color_map;
-
-
-
-
obj = lv_img_create(par, NULL);
-
-
lv_img_set_src(obj, img_des);
-
-
-
-
if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_func(obj);
-
-
/*The signal and design functions are not copied so set them here*/
-
-
lv_obj_set_signal_func(obj, barcode_signal);
-
-
-
-
end:
-
-
lv_mem_aligned_free(orig_color_map);
-
-
lv_mem_free(barcode_data);
-
-
return obj;
-
-
}
code128_encode_gs1以及rgb565_scale会将字符串通过Code 128码转换成一个图片,并最终lv_img_create将这个图片显示在屏幕上,如下图:
开发者支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号。
更多技术与解决方案介绍,请访问HaaS官方网站https://haas.iot.aliyun.com。