arm下编译并运行zbar实现图片二维码解析

  1. 目标
    1. 在linux开发板上实现jpg图片二维码的解析功能
  2. 验证流程
    1. 生成指定内容的二维码图片
    2. 利用djpeg将jpg图片解析成rgb数据
    3. 将rgb数据输入到zbar进行内容识别
  3. 二维码生成
    1. 很多网页版可以直接根据输入内容生成二维码图片
    2. 下载图片,另存为jpg格式 hello.jpg
  4. djpeg工具
    1. 下载源码Directory Listing of /files (ijg.org)
    2. 编译
      1. ./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf --prefix=/home/xxx/linux/nfs/rootfs2/bin/jpg
      2. make install
    3. 开发板上面运行测试
      1. cd /bin/jpg
      2. ./djpeg hello.jpg > hw.ppm
  5. ppm格式说明
    1. ppm头部为P6. 图像长度 图像宽度. 最大像素.
      1. P6代表格式为pixelmap binary 
    2. 后面接着的就是长宽对应的各个pixel的rgb数据
  6. zbar库
    1. 下载源码ZBar bar code reader - Download (sourceforge.net)
    2. 编译lib
      1. ./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

      2. make install

      3. 注意:配置里面加了很多--without项,是为了编译通过,免得去折腾那些环境;向zbar本身也是支持直接解析img的,但是编译会报错,因此采取曲线救国方式,通过直接调用zbar的lib来实现解析;本质上大同小异

  7. 调用zbar库的应用程序

    1. 程序主要分为两部分

      1. 一部分是将djpeg生成的ppm文件转换成y800数据

      2. 另一部分是将y800数据输入到zbar的库去解析,这部分主要是参考zbarimg.c

    2. 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);
    3. 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;
      }
    4. 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;
      }
    5. 编译:

      1. arm-linux-gnueabihf-gcc $^ $(CFLAGS) $(LDFLAGS)  -lzbar -o zbar

  8. 运行测试

  • 14
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值