- 目标
- 在linux开发板上实现jpg图片二维码的解析功能
- 验证流程
- 生成指定内容的二维码图片
- 利用djpeg将jpg图片解析成rgb数据
- 将rgb数据输入到zbar进行内容识别
- 二维码生成
- 很多网页版可以直接根据输入内容生成二维码图片
- 下载图片,另存为jpg格式 hello.jpg
- djpeg工具
- 下载源码Directory Listing of /files (ijg.org)
- 编译
- ./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=/home/xxx/linux/nfs/rootfs2/bin/jpg
- make install
- 开发板上面运行测试
- cd /bin/jpg
- ./djpeg hello.jpg > hw.ppm
- ppm格式说明
- ppm头部为P6. 图像长度 图像宽度. 最大像素.
- P6代表格式为pixelmap binary
- 后面接着的就是长宽对应的各个pixel的rgb数据
- ppm头部为P6. 图像长度 图像宽度. 最大像素.
- zbar库
- 下载源码ZBar bar code reader - Download (sourceforge.net)
- 编译lib
-
./configure --prefix=/home/xxx/linux/nfs/rootfs2/bin/zbar --disable-video --without-imagemagick --without-gtk --without-qt --without-python CFLAGS="" --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
-
make install
-
注意:配置里面加了很多--without项,是为了编译通过,免得去折腾那些环境;向zbar本身也是支持直接解析img的,但是编译会报错,因此采取曲线救国方式,通过直接调用zbar的lib来实现解析;本质上大同小异
-
-
调用zbar库的应用程序
-
程序主要分为两部分
-
一部分是将djpeg生成的ppm文件转换成y800数据
-
另一部分是将y800数据输入到zbar的库去解析,这部分主要是参考zbarimg.c
-
-
code:头文件
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct{ char *filename; int w; int h; char *buf; }ppm_t; int ppm2y800(ppm_t *ppm);
-
code:part1
#include "ppm.h" int ppm2y800(ppm_t *ppm) { FILE *fd = fopen(ppm->filename, "rb"); if (NULL == fd){ printf("open %s failed.\n", ppm->filename); return -1; } fseek(fd, 0, SEEK_END); int len = ftell(fd); printf("%s len:%d\n", ppm->filename, len); fseek(fd, 0, SEEK_SET); unsigned char *pbuf = malloc(len); int ret = fread(pbuf, 1, len, fd); if (ret != len){ printf("read %s failed.\n", ppm->filename); return -2; } if (0x50 != pbuf[0] || 0x36 != pbuf[1] || 0x0a != pbuf[2]){ printf("head:%c %c is not P6. \n", pbuf[0], pbuf[1]); return -3; } // find width int idx = 3; while(pbuf[idx] != 0x20){ idx++; } char str[10] = {0}; memcpy(str, pbuf+3, idx-3); ppm->w = strtol(str, NULL, 10); printf("ppm->w:%d\n", ppm->w); // find height idx++; int idxe = idx; while(pbuf[idxe] != 0x0a){ idxe++; } memcpy(str, pbuf+idx, idxe-idx); str[idxe-idx] = 0; ppm->h = strtol(str, NULL, 10); printf("ppm->h:%d\n", ppm->h); // find head tail idxe++; while(pbuf[idxe] != 0x0a){ idxe++; } // check len is valid or not int explen = idxe + 1 + ppm->w * ppm->h * 3; if (len != explen){ printf("ppm w:%d h:%d idxe:%d explen:%d is not fit len:%d. \n", ppm->w, ppm->h, idxe, explen, len); return -3; } // malloc and set y buf unsigned char *ybuf = malloc(ppm->w * ppm->h); unsigned char r, g, b; for (int i = 0; i < ppm->w * ppm->h; i++){ r = pbuf[idxe + 1 + i * 3]; g = pbuf[idxe + 2 + i * 3]; b = pbuf[idxe + 3 + i * 3]; ybuf[i] = (char)(0.257 * r + 0.504 * g + 0.098 * b + 16); } ppm->buf = ybuf; printf("ybuf[0]:%x rgb:%x %x %x\n", ybuf[0], r, g, b); free(pbuf); fclose(fd); return 0; }
-
code:part2
#include <assert.h> #include <zbar.h> #include "ppm.h" ppm_t ppm = {0}; static zbar_processor_t *processor = NULL; static int notfound = 0, exit_code = 0; static int num_images = 0, num_symbols = 0; static int xmllvl = 0; char *xmlbuf = NULL; unsigned xmlbuflen = 0; int main(char argc, char **argv){ int found = 0; for (int i = 0; i < argc; i++){ printf("%s ", argv[i]); } if (argc < 2){ printf("argc:%d is less than 2.\n", argc); return -1; } ppm.filename = argv[1]; ppm2y800(&ppm); // FILE *fd = fopen("400x400_y800.yuv", "wb"); // fwrite(ppm.buf, 1, ppm.h*ppm.w, fd); // fclose(fd); processor = zbar_processor_create(0); assert(processor); if(zbar_processor_init(processor, NULL, 0)) { zbar_processor_error_spew(processor, 0); return(1); } zbar_image_t *zimage = zbar_image_create(); assert(zimage); zbar_image_set_format(zimage, *(unsigned long*)"Y800"); zbar_image_set_size(zimage, ppm.w, ppm.h); zbar_image_set_data(zimage, ppm.buf, ppm.h*ppm.w, zbar_image_free_data); zbar_process_image(processor, zimage); // output result data const zbar_symbol_t *sym = zbar_image_first_symbol(zimage); for(; sym; sym = zbar_symbol_next(sym)) { zbar_symbol_type_t typ = zbar_symbol_get_type(sym); if(typ == ZBAR_PARTIAL) continue; else if(!xmllvl) printf("%s%s:%s\n", zbar_get_symbol_name(typ), zbar_get_addon_name(typ), zbar_symbol_get_data(sym)); else if(xmllvl < 0) printf("%s\n", zbar_symbol_get_data(sym)); else { if(xmllvl < 3) { xmllvl++; // printf("<index num='%u'>\n", seq); } zbar_symbol_xml(sym, &xmlbuf, &xmlbuflen); printf("%s\n", xmlbuf); } found++; num_symbols++; } if(xmllvl > 2) { xmllvl--; printf("</index>\n"); } fflush(stdout); zbar_image_destroy(zimage); zbar_processor_destroy(processor); return 0; }
-
编译:
-
arm-linux-gnueabihf-gcc $^ $(CFLAGS) $(LDFLAGS) -lzbar -o zbar
-
-
-
运行测试
arm下编译并运行zbar实现图片二维码解析
于 2024-07-06 23:30:07 首次发布