zbar_symbol_type_t _zbar_find_qr (zbar_decoder_t *dcode) { unsigned s; int ei; unsigned qz; unsigned w; qr_finder_t *qrf = &dcode->qrf; /* update latest finder pattern width */ qrf->s5 -= get_width(dcode, 6); qrf->s5 += get_width(dcode, 1); s = qrf->s5; if(get_color(dcode) != ZBAR_SPACE || s < 7) return(0); dprintf(2, " qrf: s=%d", s); ei = decode_e(pair_width(dcode, 1), s, 7); dprintf(2, " %d", ei); if(ei) goto invalid; ei = decode_e(pair_width(dcode, 2), s, 7); dprintf(2, "%d", ei); if(ei != 2) goto invalid; ei = decode_e(pair_width(dcode, 3), s, 7); dprintf(2, "%d", ei); if(ei != 2) goto invalid; ei = decode_e(pair_width(dcode, 4), s, 7); dprintf(2, "%d", ei); if(ei) goto invalid; /* valid QR finder symbol * mark positions needed by decoder */ qz = get_width(dcode, 0); w = get_width(dcode, 1); qrf->line.eoffs = qz + (w + 1) / 2; qrf->line.len = qz + w + get_width(dcode, 2); qrf->line.pos[0] = qrf->line.len + get_width(dcode, 3); qrf->line.pos[1] = qrf->line.pos[0]; w = get_width(dcode, 5); qrf->line.boffs = qrf->line.pos[0] + get_width(dcode, 4) + (w + 1) / 2; dprintf(2, " boff=%d pos=%d len=%d eoff=%d [valid]\n", qrf->line.boffs, qrf->line.pos[0], qrf->line.len, qrf->line.eoffs); return(ZBAR_QRCODE); invalid: dprintf(2, " [invalid]\n"); return(0); }
static inline signed char i25_decode_end (zbar_decoder_t *dcode) { i25_decoder_t *dcode25 = &dcode->i25; /* check trailing quiet zone */ unsigned quiet = get_width(dcode, 0); if((quiet && quiet < dcode25->width * 3 / 8) || decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 || decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) { dprintf(3, " s=%d q=%d [invalid qz]\n", dcode25->width, quiet); return(ZBAR_NONE); } /* check exit condition */ unsigned char E = decode_e(get_width(dcode, 3), dcode25->width, 45); if((!dcode25->direction) ? E - 3 > 4 : (E > 2 || decode_e(get_width(dcode, 4), dcode25->width, 45) > 2)) return(ZBAR_NONE); if(dcode25->direction) { /* reverse buffer */ dprintf(2, " (rev)"); int i; for(i = 0; i < dcode25->character / 2; i++) { unsigned j = dcode25->character - 1 - i; char c = dcode->buf[i]; dcode->buf[i] = dcode->buf[j]; dcode->buf[j] = c; } } if(dcode25->character < CFG(*dcode25, ZBAR_CFG_MIN_LEN) || (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 && dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) { dprintf(2, " [invalid len]\n"); dcode->lock = 0; dcode25->character = -1; return(ZBAR_NONE); } dcode->buflen = dcode25->character; dcode->buf[dcode25->character] = '\0'; dprintf(2, " [valid end]\n"); dcode25->character = -1; return(ZBAR_I25); }
/* evaluate previous N (>= 2) widths as auxiliary pattern, * using preceding 4 as character width */ static inline signed char aux_end (zbar_decoder_t *dcode, unsigned char fwd) { /* reference width from previous character */ unsigned s = calc_s(dcode, 4 + fwd, 4); /* check quiet zone */ unsigned qz = get_width(dcode, 0); if(!fwd && qz && qz < s * 3 / 4) { dprintf(2, " [invalid quiet]"); return(-1); } dprintf(2, " ("); signed char code = 0; unsigned char i; for(i = 1 - fwd; i < 3 + fwd; i++) { unsigned e = get_width(dcode, i) + get_width(dcode, i + 1); dprintf(2, " %d", e); code = (code << 2) | decode_e(e, s, 7); if(code < 0) { dprintf(2, " [invalid end guard]"); return(-1); } } dprintf(2, ") s=%d aux=%x", s, code); return(code); }
/* determine possible auxiliary pattern * using current 4 as possible character */ static inline signed char aux_start (zbar_decoder_t *dcode) { /* FIXME NB add-on has no guard in reverse */ unsigned e1, e2 = get_width(dcode, 5) + get_width(dcode, 6); unsigned char E1; if(dcode->ean.s4 < 6) return(-1); if(decode_e(e2, dcode->ean.s4, 7)) { dbprintf(2, " [invalid any]"); return(-1); } e1 = get_width(dcode, 4) + get_width(dcode, 5); E1 = decode_e(e1, dcode->ean.s4, 7); if(get_color(dcode) == ZBAR_BAR) { /* check for quiet-zone */ unsigned qz = get_width(dcode, 7); if(!qz || qz > dcode->ean.s4 * 3 / 4) { if(!E1) { dbprintf(2, " [valid normal]"); return(0); /* normal symbol start */ } else if(E1 == 1) { dbprintf(2, " [valid add-on]"); return(STATE_ADDON); /* add-on symbol start */ } } dbprintf(2, " [invalid start]"); return(-1); } if(!E1) { /* attempting decode from SPACE => validate center guard */ unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7); unsigned e4 = get_width(dcode, 7) + get_width(dcode, 8); if(!decode_e(e3, dcode->ean.s4, 7) && !decode_e(e4, dcode->ean.s4, 7)) { dbprintf(2, " [valid center]"); return(0); /* start after center guard */ } } dbprintf(2, " [invalid center]"); return(-1); }
/* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */ static inline signed char decode4 (zbar_decoder_t *dcode) { signed char code; /* calculate similar edge measurements */ unsigned e1 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 1) : get_width(dcode, 2) + get_width(dcode, 3)); unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2); dbprintf(2, "\n e1=%d e2=%d", e1, e2); if(dcode->ean.s4 < 6) return(-1); /* create compacted encoding for direct lookup */ code = ((decode_e(e1, dcode->ean.s4, 7) << 2) | decode_e(e2, dcode->ean.s4, 7)); if(code < 0) return(-1); dbprintf(2, " code=%x", code); /* 4 combinations require additional determinant (D2) E1E2 == 34 (0110) E1E2 == 43 (1001) E1E2 == 33 (0101) E1E2 == 44 (1010) */ if((1 << code) & 0x0660) { unsigned char mid, alt; /* use sum of bar widths */ unsigned d2 = ((get_color(dcode) == ZBAR_BAR) ? get_width(dcode, 0) + get_width(dcode, 2) : get_width(dcode, 1) + get_width(dcode, 3)); d2 *= 7; mid = (((1 << code) & 0x0420) ? 3 /* E1E2 in 33,44 */ : 4); /* E1E2 in 34,43 */ alt = d2 > (mid * dcode->ean.s4); if(alt) code = ((code >> 1) & 3) | 0x10; /* compress code space */ dbprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt); }
static inline unsigned char i25_decode1 (unsigned char enc, unsigned e, unsigned s) { unsigned char E = decode_e(e, s, 45); if(E > 7) return(0xff); enc <<= 1; if(E > 2) enc |= 1; return(enc); }
/* determine possible auxiliary pattern * using current 4 as possible character */ static inline signed char aux_start (zebra_decoder_t *dcode) { /* FIXME NB add-on has no guard in reverse */ unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6); if(decode_e(e2, dcode->ean.s4, 7)) { dprintf(2, " [invalid any]"); return(/*FIXME (get_color(dcode) == ZEBRA_SPACE) ? STATE_ADDON : */-1); } unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5); unsigned char E1 = decode_e(e1, dcode->ean.s4, 7); if(get_color(dcode) == ZEBRA_BAR) { /* check for quiet-zone */ if((get_width(dcode, 7) * 14 + 1) / dcode->ean.s4 >= 3) { if(!E1) { dprintf(2, " [valid normal]"); return(0); /* normal symbol start */ } else if(E1 == 1) { dprintf(2, " [valid add-on]"); return(STATE_ADDON); /* add-on symbol start */ } } dprintf(2, " [invalid start]"); return(-1); } if(!E1) { /* attempting decode from SPACE => validate center guard */ unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7); if(!decode_e(e3, dcode->ean.s4, 7)) { dprintf(2, " [valid center]"); return(0); /* start after center guard */ } } dprintf(2, " [invalid center]"); return(/*STATE_ADDON*/-1); }
/* evaluate previous N (>= 2) widths as auxiliary pattern, * using preceding 4 as character width */ static inline signed char aux_end (zebra_decoder_t *dcode, unsigned char n) { /* reference width from previous character */ unsigned s = calc_s(dcode, n, 4); dprintf(2, " ("); signed char code = 0; unsigned char i; for(i = 0; i < n - 1; i++) { unsigned e = get_width(dcode, i) + get_width(dcode, i + 1); dprintf(2, " %d", e); code = (code << 2) | decode_e(e, s, 7); if(code < 0) return(-1); } dprintf(2, ") s=%d aux=%x", s, code); return(code); }
/* check addon delimiter using current 4 as character */ static inline signed char aux_mid (zbar_decoder_t *dcode) { unsigned e = get_width(dcode, 4) + get_width(dcode, 5); return(decode_e(e, dcode->ean.s4, 7)); }