Пример #1
0
static void symbol_handler (zbar_decoder_t *dcode)
{
	zbar_image_scanner_t *iscn = zbar_decoder_get_userdata(dcode);
	zbar_symbol_type_t type = zbar_decoder_get_type(dcode);
	/* FIXME assert(type == ZBAR_PARTIAL) */
	/* FIXME debug flag to save/display all PARTIALs */
	if(type <= ZBAR_PARTIAL)
		return;

#ifdef ENABLE_QRCODE
	if(type == ZBAR_QRCODE) {
		qr_handler(iscn);
		return;
	}
#else
	assert(type != ZBAR_QRCODE);
#endif

	const char *data = zbar_decoder_get_data(dcode);
	unsigned datalen = zbar_decoder_get_data_length(dcode);

	int x = 0, y = 0;
	if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) {
		/* tmp position fixup */
		int w = zbar_scanner_get_width(iscn->scn);
		int u = iscn->umin + iscn->du * zbar_scanner_get_edge(iscn->scn, w, 0);
		if(iscn->dx) {
			x = u;
			y = iscn->v;
		}
		else {
			x = iscn->v;
			y = u;
		}
	}

	/* FIXME need better symbol matching */
	zbar_symbol_t *sym;
	for(sym = iscn->syms->head; sym; sym = sym->next)
		if(sym->type == type &&
		   sym->datalen == datalen &&
		   !memcmp(sym->data, data, datalen)) {
			sym->quality++;
			if(TEST_CFG(iscn, ZBAR_CFG_POSITION))
				/* add new point to existing set */
				/* FIXME should be polygon */
				sym_add_point(sym, x, y);
			return;
		}

	sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen + 1);
	/* FIXME grab decoder buffer */
	memcpy(sym->data, data, datalen + 1);

	/* initialize first point */
	if(TEST_CFG(iscn, ZBAR_CFG_POSITION))
		sym_add_point(sym, x, y);

	_zbar_image_scanner_add_sym(iscn, sym);
}
Пример #2
0
int qr_code_data_list_extract_text(const qr_code_data_list *_qrlist,
                                   zbar_image_scanner_t *iscn,
                                   zbar_image_t *img)
{
#if HAVE_ICONV
	iconv_t              sjis_cd;
  iconv_t              utf8_cd;
  iconv_t              latin1_cd;
#endif
	const qr_code_data  *qrdata;
  int                  nqrdata;
  unsigned char       *mark;
  int                  ntext;
  int                  i;
  qrdata=_qrlist->qrdata;
  nqrdata=_qrlist->nqrdata;
  mark=(unsigned char *)calloc(nqrdata,sizeof(*mark));
  ntext=0;
#if HAVE_ICONV
  /*This is the encoding the standard says is the default.*/
  latin1_cd=iconv_open("UTF-8","ISO8859-1");
  /*But this one is often used, as well.*/
  sjis_cd=iconv_open("UTF-8","SJIS");
  /*This is a trivial conversion just to check validity without extra code.*/
  utf8_cd=iconv_open("UTF-8","UTF-8");
#endif
  for(i=0;i<nqrdata;i++)if(!mark[i]){
    const qr_code_data       *qrdataj;
    const qr_code_data_entry *entry;
#if HAVE_ICONV
    iconv_t                   enc_list[3];
    iconv_t                   eci_cd;
#endif
	int                       sa[16];
    int                       sa_size;
    char                     *sa_text;
    size_t                    sa_ntext;
    size_t                    sa_ctext;
    int                       fnc1;
    int                       eci;
    int                       err;
    int                       j;
    int                       k;
    /*Step 0: Collect the other QR codes belonging to this S-A group.*/
    if(qrdata[i].sa_size){
      unsigned sa_parity;
      sa_size=qrdata[i].sa_size;
      sa_parity=qrdata[i].sa_parity;
      for(j=0;j<sa_size;j++)sa[j]=-1;
      for(j=i;j<nqrdata;j++)if(!mark[j]){
        /*TODO: We could also match version, ECC level, etc. if size and
           parity alone are too ambiguous.*/
        if(qrdata[j].sa_size==sa_size&&qrdata[j].sa_parity==sa_parity&&
         sa[qrdata[j].sa_index]<0){
          sa[qrdata[j].sa_index]=j;
          mark[j]=1;
        }
      }
      /*TODO: If the S-A group is complete, check the parity.*/
    }
    else{
      sa[0]=i;
      sa_size=1;
    }

    sa_ctext=0;
    fnc1=0;
    /*Step 1: Detect FNC1 markers and estimate the required buffer size.*/
    for(j=0;j<sa_size;j++)if(sa[j]>=0){
      qrdataj=qrdata+sa[j];
      for(k=0;k<qrdataj->nentries;k++){
        int shift;
        entry=qrdataj->entries+k;
        shift=0;
        switch(entry->mode){
          /*FNC1 applies to the entire code and ignores subsequent markers.*/
          case QR_MODE_FNC1_1ST:
          case QR_MODE_FNC1_2ND:fnc1=1;break;
          /*2 SJIS bytes will be at most 4 UTF-8 bytes.*/
          case QR_MODE_KANJI:shift++;
          /*We assume at most 4 UTF-8 bytes per input byte.
            I believe this is true for all the encodings we actually use.*/
          case QR_MODE_BYTE:shift++;
          default:{
            /*The remaining two modes are already valid UTF-8.*/
            if(QR_MODE_HAS_DATA(entry->mode)){
              sa_ctext+=entry->payload.data.len<<shift;
            }
          }break;
        }
      }
    }

    /*Step 2: Convert the entries.*/
    sa_text=(char *)malloc((sa_ctext+1)*sizeof(*sa_text));
    sa_ntext=0;
    eci=-1;
#if HAVE_ICONV
    enc_list[0]=sjis_cd;
    enc_list[1]=latin1_cd;
    enc_list[2]=utf8_cd;
    eci_cd=(iconv_t)-1;
#endif
    err=0;
    zbar_symbol_t *syms = NULL, **sym = &syms;
    for(j = 0; j < sa_size && !err; j++, sym = &(*sym)->next) {
      *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
      (*sym)->datalen = sa_ntext;
      if(sa[j]<0){
        /* generic placeholder for unfinished results */
        (*sym)->type = ZBAR_PARTIAL;

        /*Skip all contiguous missing segments.*/
        for(j++;j<sa_size&&sa[j]<0;j++);
        /*If there aren't any more, stop.*/
        if(j>=sa_size)break;

        /* mark break in data */
        sa_text[sa_ntext++]='\0';
        (*sym)->datalen = sa_ntext;

        /* advance to next symbol */
        sym = &(*sym)->next;
        *sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
      }

      qrdataj=qrdata+sa[j];
      /* expose bounding box */
      sym_add_point(*sym, qrdataj->bbox[0][0], qrdataj->bbox[0][1]);
      sym_add_point(*sym, qrdataj->bbox[2][0], qrdataj->bbox[2][1]);
      sym_add_point(*sym, qrdataj->bbox[3][0], qrdataj->bbox[3][1]);
      sym_add_point(*sym, qrdataj->bbox[1][0], qrdataj->bbox[1][1]);

			printf("Decoding %i symbols.\n", qrdataj->nentries);

      for(k=0;k<qrdataj->nentries&&!err;k++){
        size_t              inleft;
        char               *in;
        size_t              outleft;
        char               *out;
        entry=qrdataj->entries+k;
				printf("Symbol %i mode: %i\n", k, entry->mode);
        switch(entry->mode){
          case QR_MODE_NUM:{
            if(sa_ctext-sa_ntext>=(size_t)entry->payload.data.len){
              memcpy(sa_text+sa_ntext,entry->payload.data.buf,
               entry->payload.data.len*sizeof(*sa_text));
              sa_ntext+=entry->payload.data.len;
            }
            else err=1;
          }break;
          case QR_MODE_ALNUM:{
            char *p;
            in=(char *)entry->payload.data.buf;
            inleft=entry->payload.data.len;
            /*FNC1 uses '%' as an escape character.*/
            if(fnc1)for(;;){
              size_t plen;
              char   c;
              p=memchr(in,'%',inleft*sizeof(*in));
              if(p==NULL)break;
              plen=p-in;
              if(sa_ctext-sa_ntext<plen+1)break;
              memcpy(sa_text+sa_ntext,in,plen*sizeof(*in));
              sa_ntext+=plen;
              /*Two '%'s is a literal '%'*/
              if(plen+1<inleft&&p[1]=='%'){
                c='%';
                plen++;
                p++;
              }
              /*One '%' is the ASCII group separator.*/
              else c=0x1D;
              sa_text[sa_ntext++]=c;
              inleft-=plen+1;
              in=p+1;
            }
            else p=NULL;
            if(p!=NULL||sa_ctext-sa_ntext<inleft)err=1;
            else{
              memcpy(sa_text+sa_ntext,in,inleft*sizeof(*sa_text));
              sa_ntext+=inleft;
            }
          }break;
          /*TODO: This will not handle a multi-byte sequence split between
             multiple data blocks.
            Does such a thing occur?
            Is it allowed?
            It requires copying buffers around to handle correctly.*/
          case QR_MODE_BYTE:{
            in=(char *)entry->payload.data.buf;
            inleft=entry->payload.data.len;
#if !HAVE_ICONV
            out=sa_text+sa_ntext;
            outleft=sa_ctext-sa_ntext;
						strncpy(out, in, inleft);
						sa_ntext+=inleft;
						printf("Copied %u bytes.\n", (unsigned)inleft);
#else
            out=sa_text+sa_ntext;
            outleft=sa_ctext-sa_ntext;
            /*If we have no specified encoding, attempt to auto-detect it.*/
            if(eci<0){
              int ei;
              /*First check for the UTF-8 BOM.*/
              if(inleft>=3&&
               in[0]==(char)0xEF&&in[1]==(char)0xBB&&in[2]==(char)0xBF){
                in+=3;
                inleft-=3;
                /*Actually try converting (to check validity).*/
                err=utf8_cd==(iconv_t)-1||
                 iconv(utf8_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
                if(!err){
                  sa_ntext=out-sa_text;
                  enc_list_mtf(enc_list,utf8_cd);
                  continue;
                }
                in=(char *)entry->payload.data.buf;
                inleft=entry->payload.data.len;
                out=sa_text+sa_ntext;
                outleft=sa_ctext-sa_ntext;
              }
              /*If the text is 8-bit clean, prefer UTF-8 over SJIS, since SJIS
                 will corrupt the backslashes used for DoCoMo formats.*/
              else if(text_is_ascii((unsigned char *)in,inleft)){
               enc_list_mtf(enc_list,utf8_cd);
              }
              /*Try our list of encodings.*/
              for(ei=0;ei<3;ei++)if(enc_list[ei]!=(iconv_t)-1){
                /*According to the standard, ISO/IEC 8859-1 (one hyphen) is
                   supposed to be used, but reality is not always so.
                  It's got an invalid range that is used often with SJIS
                   and UTF-8, though, which makes detection easier.
                  However, iconv() does not properly reject characters in
                   those ranges, since ISO-8859-1 (two hyphens) defines a
                   number of seldom-used control code characters there.
                  So if we see any of those characters, move this
                   conversion to the end of the list.*/
                if(ei<2&&enc_list[ei]==latin1_cd&&
                 !text_is_latin1((unsigned char *)in,inleft)){
                  int ej;
                  for(ej=ei+1;ej<3;ej++)enc_list[ej-1]=enc_list[ej];
                  enc_list[2]=latin1_cd;
                }
                err=iconv(enc_list[ei],&in,&inleft,&out,&outleft)==(size_t)-1;
                if(!err){
                  sa_ntext=out-sa_text;
                  enc_list_mtf(enc_list,enc_list[ei]);
                  break;
                }
                in=(char *)entry->payload.data.buf;
                inleft=entry->payload.data.len;
                out=sa_text+sa_ntext;
                outleft=sa_ctext-sa_ntext;
              }
            }
            /*We were actually given a character set; use it.*/
            else{
              err=eci_cd==(iconv_t)-1||
               iconv(eci_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
              if(!err)sa_ntext=out-sa_text;
            }
#endif
          }break;
          /*Kanji mode always uses SJIS.*/
          case QR_MODE_KANJI:{
            in=(char *)entry->payload.data.buf;
            inleft=entry->payload.data.len;
#if HAVE_ICONV
            out=sa_text+sa_ntext;
            outleft=sa_ctext-sa_ntext;
            err=sjis_cd==(iconv_t)-1||
             iconv(sjis_cd,&in,&inleft,&out,&outleft)==(size_t)-1;
            if(!err)sa_ntext=out-sa_text;
#endif
          }break;
#if HAVE_ICONV
          /*Check to see if a character set was specified.*/
          case QR_MODE_ECI:{
            const char *enc;
            char        buf[16];
            unsigned    cur_eci;
            cur_eci=entry->payload.eci;
            if(cur_eci<=QR_ECI_ISO8859_16&&cur_eci!=14){
              if(cur_eci!=QR_ECI_GLI0&&cur_eci!=QR_ECI_CP437){
                sprintf(buf,"ISO8859-%i",QR_MAXI(cur_eci,3)-2);
                enc=buf;
              }
              /*Note that CP437 requires an iconv compiled with
                 --enable-extra-encodings, and thus may not be available.*/
              else enc="CP437";
            }
            else if(cur_eci==QR_ECI_SJIS)enc="SJIS";
            /*Don't know what this ECI code specifies, but not an encoding that
               we recognize.*/
            else continue;
            eci=cur_eci;
            eci_cd=iconv_open("UTF-8",enc);
          }break;
#endif
          /*Silence stupid compiler warnings.*/
          default:break;
        }
      }
      /*If eci should be reset between codes, do so.*/
      if(eci<=QR_ECI_GLI1){
        eci=-1;
#if HAVE_ICONV
        if(eci_cd!=(iconv_t)-1)iconv_close(eci_cd);
#endif
      }
    }
#if HAVE_ICONV
    if(eci_cd!=(iconv_t)-1)iconv_close(eci_cd);
#endif
    if(!err){
      sa_text[sa_ntext++]='\0';
      if(sa_ctext+1>sa_ntext){
        sa_text=(char *)realloc(sa_text,sa_ntext*sizeof(*sa_text));
      }

      zbar_symbol_t *sa_sym;
      if(sa_size == 1)
          sa_sym = syms;
      else {
          /* create "virtual" container symbol for composite result */
          sa_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_QRCODE, 0);
          sa_sym->syms = _zbar_symbol_set_create();
          sa_sym->syms->head = syms;

          /* cheap out w/axis aligned bbox for now */
          int xmin = img->width, xmax = -2;
          int ymin = img->height, ymax = -2;

          /* fixup data references */
          for(; syms; syms = syms->next) {
              _zbar_symbol_refcnt(syms, 1);
              if(syms->type == ZBAR_PARTIAL)
                  sa_sym->type = ZBAR_PARTIAL;
              else
                  for(j = 0; j < (int)syms->npts; j++) {
                      int u = syms->pts[j].x;
                      if(xmin >= u) xmin = u - 1;
                      if(xmax <= u) xmax = u + 1;
                      u = syms->pts[j].y;
                      if(ymin >= u) ymin = u - 1;
                      if(ymax <= u) ymax = u + 1;
                  }
              syms->data = sa_text + syms->datalen;
              int next = (syms->next) ? syms->next->datalen : sa_ntext;
              assert(next > (int)syms->datalen);
              syms->datalen = next - syms->datalen - 1;
          }
          if(xmax >= -1) {
              sym_add_point(sa_sym, xmin, ymin);
              sym_add_point(sa_sym, xmin, ymax);
              sym_add_point(sa_sym, xmax, ymax);
              sym_add_point(sa_sym, xmax, ymin);
          }
      }
      sa_sym->data = sa_text;
      sa_sym->data_alloc = sa_ntext;
      sa_sym->datalen = sa_ntext - 1;

      _zbar_image_scanner_add_sym(iscn, sa_sym);
    }
    else {
        _zbar_image_scanner_recycle_syms(iscn, syms);
        free(sa_text);
    }
  }
#if HAVE_ICONV
  if(utf8_cd!=(iconv_t)-1)iconv_close(utf8_cd);
  if(sjis_cd!=(iconv_t)-1)iconv_close(sjis_cd);
  if(latin1_cd!=(iconv_t)-1)iconv_close(latin1_cd);
#endif
  free(mark);
  return ntext;
}
Пример #3
0
static void symbol_handler (zbar_decoder_t *dcode)
{
    zbar_image_scanner_t *iscn = zbar_decoder_get_userdata(dcode);
    zbar_symbol_type_t type = zbar_decoder_get_type(dcode);
    int x = 0, y = 0, dir;
    const char *data;
    unsigned datalen;
    zbar_symbol_t *sym;

#ifdef ENABLE_QRCODE
    if(type == ZBAR_QRCODE) {
        qr_handler(iscn);
        return;
    }
#else
    assert(type != ZBAR_QRCODE);
#endif

    if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) {
        /* tmp position fixup */
        int w = zbar_scanner_get_width(iscn->scn);
        int u = iscn->umin + iscn->du * zbar_scanner_get_edge(iscn->scn, w, 0);
        if(iscn->dx) {
            x = u;
            y = iscn->v;
        }
        else {
            x = iscn->v;
            y = u;
        }
    }

    /* FIXME debug flag to save/display all PARTIALs */
    if(type <= ZBAR_PARTIAL) {
        zprintf(256, "partial symbol @(%d,%d)\n", x, y);
        return;
    }

    data = zbar_decoder_get_data(dcode);
    datalen = zbar_decoder_get_data_length(dcode);

    /* FIXME need better symbol matching */
    for(sym = iscn->syms->head; sym; sym = sym->next)
        if(sym->type == type &&
           sym->datalen == datalen &&
           !memcmp(sym->data, data, datalen)) {
            sym->quality++;
            zprintf(224, "dup symbol @(%d,%d): dup %s: %.20s\n",
                    x, y, zbar_get_symbol_name(type), data);
            if(TEST_CFG(iscn, ZBAR_CFG_POSITION))
                /* add new point to existing set */
                /* FIXME should be polygon */
                sym_add_point(sym, x, y);
            return;
        }

    sym = _zbar_image_scanner_alloc_sym(iscn, type, datalen + 1);
    sym->configs = zbar_decoder_get_configs(dcode, type);
    sym->modifiers = zbar_decoder_get_modifiers(dcode);
    /* FIXME grab decoder buffer */
    memcpy(sym->data, data, datalen + 1);

    /* initialize first point */
    if(TEST_CFG(iscn, ZBAR_CFG_POSITION)) {
        zprintf(192, "new symbol @(%d,%d): %s: %.20s\n",
                x, y, zbar_get_symbol_name(type), data);
        sym_add_point(sym, x, y);
    }

    dir = zbar_decoder_get_direction(dcode);
    if(dir)
        sym->orient = (iscn->dy != 0) + ((iscn->du ^ dir) & 2);

    _zbar_image_scanner_add_sym(iscn, sym);
}
Пример #4
0
static void symbol_handler (zebra_image_scanner_t *iscn,
                            int x,
                            int y)
{
    zebra_symbol_type_t type = zebra_decoder_get_type(iscn->dcode);
    /* FIXME assert(type == ZEBRA_PARTIAL) */
    /* FIXME debug flag to save/display all PARTIALs */
    if(type <= ZEBRA_PARTIAL)
        return;

    const char *data = zebra_decoder_get_data(iscn->dcode);

    /* FIXME deprecate - instead check (x, y) inside existing polygon */
    zebra_symbol_t *sym;
    for(sym = iscn->img->syms; sym; sym = sym->next)
        if(sym->type == type &&
           !strcmp(sym->data, data)) {
            /* add new point to existing set */
            /* FIXME should be polygon */
            sym_add_point(sym, x, y);
            return;
        }

    sym = alloc_sym(iscn, type, data);

    /* timestamp symbol */
    struct timeval abstime;
    gettimeofday(&abstime, NULL);
    sym->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2;

    /* initialize first point */
    sym->npts = 0;
    sym_add_point(sym, x, y);

    /* attach to current root image */
    sym->next = iscn->img->syms;
    iscn->img->syms = sym;
    iscn->img->nsyms++;

    if(iscn->enable_cache) {
        zebra_symbol_t *entry = cache_lookup(iscn, sym);
        if(!entry) {
            entry = alloc_sym(iscn, sym->type, sym->data);
            entry->time = sym->time - CACHE_HYSTERESIS;
            entry->cache_count = -CACHE_CONSISTENCY;
            /* add to cache */
            entry->next = iscn->cache;
            iscn->cache = entry;
        }

        /* consistency check and hysteresis */
        uint32_t age = sym->time - entry->time;
        entry->time = sym->time;
        int near = (age < CACHE_PROXIMITY);
        int far = (age >= CACHE_HYSTERESIS);
        int dup = (entry->cache_count >= 0);
        if((!dup && !near) || far)
            entry->cache_count = -CACHE_CONSISTENCY;
        else if(dup || near)
            entry->cache_count++;

        sym->cache_count = entry->cache_count;
    }
    else
        sym->cache_count = 0;

    if(iscn->handler)
        iscn->handler(iscn->img, iscn->userdata);
}