A streamlined version (for embedded use) of Jeff Brown's ZBar library. Visit <http://zbar.sourceforge.net> for more details.
Dependents: BarcodeReader_F103
Diff: decoder/i25.c
- Revision:
- 0:e33621169e44
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/decoder/i25.c Fri Jan 10 20:29:52 2020 +0000 @@ -0,0 +1,238 @@ +/*------------------------------------------------------------------------ + * Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net> + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +#include "../config.h" +#include <string.h> /* memmove */ + +#ifdef ENABLE_I25 + +#include <zbar.h> +#include "../decoder.h" + +#ifdef DEBUG_I25 +# define DEBUG_LEVEL (DEBUG_I25) +#endif +#include "../debug.h" + +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); +} + +static inline unsigned char i25_decode10 (zbar_decoder_t *dcode, + unsigned char offset) +{ + i25_decoder_t *dcode25 = &dcode->i25; + dprintf(2, " s=%d", dcode25->s10); + if(dcode25->s10 < 10) + return(0xff); + + /* threshold bar width ratios */ + unsigned char enc = 0, par = 0; + signed char i; + for(i = 8; i >= 0; i -= 2) { + unsigned char j = offset + ((dcode25->direction) ? i : 8 - i); + enc = i25_decode1(enc, get_width(dcode, j), dcode25->s10); + if(enc == 0xff) + return(0xff); + if(enc & 1) + par++; + } + + dprintf(2, " enc=%02x par=%x", enc, par); + + /* parity check */ + if(par != 2) { + dprintf(2, " [bad parity]"); + return(0xff); + } + + /* decode binary weights */ + enc &= 0xf; + if(enc & 8) { + if(enc == 12) + enc = 0; + else if(--enc > 9) { + dprintf(2, " [invalid encoding]"); + return(0xff); + } + } + + dprintf(2, " => %x", enc); + return(enc); +} + +static inline signed char i25_decode_start (zbar_decoder_t *dcode) +{ + i25_decoder_t *dcode25 = &dcode->i25; + if(dcode25->s10 < 10) + return(ZBAR_NONE); + + unsigned char enc = 0; + unsigned char i = 10; + enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10); + enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10); + enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10); + + if((get_color(dcode) == ZBAR_BAR) + ? enc != 4 + : (enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10))) { + dprintf(4, " i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc); + return(ZBAR_NONE); + } + + /* check leading quiet zone - spec is 10n(?) + * we require 5.25n for w=2n to 6.75n for w=3n + * (FIXME should really factor in w:n ratio) + */ + unsigned quiet = get_width(dcode, i++); + if(quiet && quiet < dcode25->s10 * 3 / 8) { + dprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n", + dcode25->s10, enc, quiet); + return(ZBAR_NONE); + } + + dcode25->direction = get_color(dcode); + dcode25->element = 1; + dcode25->character = 0; + return(ZBAR_PARTIAL); +} + +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); +} + +zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode) +{ + i25_decoder_t *dcode25 = &dcode->i25; + + /* update latest character width */ + dcode25->s10 -= get_width(dcode, 10); + dcode25->s10 += get_width(dcode, 0); + + if(dcode25->character < 0 && + !i25_decode_start(dcode)) + return(ZBAR_NONE); + + if(--dcode25->element == 6 - dcode25->direction) + return(i25_decode_end(dcode)); + else if(dcode25->element) + return(ZBAR_NONE); + + /* FIXME check current character width against previous */ + dcode25->width = dcode25->s10; + + dprintf(2, " i25[%c%02d+%x]", + (dcode25->direction) ? '<' : '>', + dcode25->character, dcode25->element); + + /* lock shared resources */ + if(!dcode25->character && get_lock(dcode, ZBAR_I25)) { + dcode25->character = -1; + dprintf(2, " [locked %d]\n", dcode->lock); + return(ZBAR_PARTIAL); + } + + unsigned char c = i25_decode10(dcode, 1); + dprintf(2, " c=%x", c); + + if(c > 9 || + ((dcode25->character >= BUFFER_MIN) && + size_buf(dcode, dcode25->character + 2))) { + dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n"); + dcode->lock = 0; + dcode25->character = -1; + return(ZBAR_NONE); + } + dcode->buf[dcode25->character++] = c + '0'; + + c = i25_decode10(dcode, 0); + dprintf(2, " c=%x", c); + if(c > 9) { + dprintf(2, " [aborted]\n"); + dcode->lock = 0; + dcode25->character = -1; + return(ZBAR_NONE); + } + else + dprintf(2, "\n"); + + dcode->buf[dcode25->character++] = c + '0'; + dcode25->element = 10; + return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE); +} + +#endif