ZBar bar code reader . http://zbar.sourceforge.net/ ZBar is licensed under the GNU LGPL 2.1 to enable development of both open source and commercial projects.

Dependents:   GR-PEACH_Camera_in_barcode levkov_ov7670

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers i25.c Source File

i25.c

00001 /*------------------------------------------------------------------------
00002  *  Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
00003  *
00004  *  This file is part of the ZBar Bar Code Reader.
00005  *
00006  *  The ZBar Bar Code Reader is free software; you can redistribute it
00007  *  and/or modify it under the terms of the GNU Lesser Public License as
00008  *  published by the Free Software Foundation; either version 2.1 of
00009  *  the License, or (at your option) any later version.
00010  *
00011  *  The ZBar Bar Code Reader is distributed in the hope that it will be
00012  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00013  *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU Lesser Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser Public License
00017  *  along with the ZBar Bar Code Reader; if not, write to the Free
00018  *  Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00019  *  Boston, MA  02110-1301  USA
00020  *
00021  *  http://sourceforge.net/projects/zbar
00022  *------------------------------------------------------------------------*/
00023 
00024 #include <config.h>
00025 #include <string.h>     /* memmove */
00026 
00027 #include <zbar.h>
00028 #include "decoder.h"
00029 
00030 #ifdef DEBUG_I25
00031 # define DEBUG_LEVEL (DEBUG_I25)
00032 #endif
00033 #include "zbar_debug.h"
00034 
00035 static inline unsigned char i25_decode1 (unsigned char enc,
00036                                          unsigned e,
00037                                          unsigned s)
00038 {
00039     unsigned char E = decode_e(e, s, 45);
00040     if(E > 7)
00041         return(0xff);
00042     enc <<= 1;
00043     if(E > 2)
00044         enc |= 1;
00045     return(enc);
00046 }
00047 
00048 static inline unsigned char i25_decode10 (zbar_decoder_t *dcode,
00049                                           unsigned char offset)
00050 {
00051     i25_decoder_t *dcode25 = &dcode->i25;
00052     dprintf(2, " s=%d", dcode25->s10);
00053     if(dcode25->s10 < 10)
00054         return(0xff);
00055 
00056     /* threshold bar width ratios */
00057     unsigned char enc = 0, par = 0;
00058     signed char i;
00059     for(i = 8; i >= 0; i -= 2) {
00060         unsigned char j = offset + ((dcode25->direction) ? i : 8 - i);
00061         enc = i25_decode1(enc, get_width(dcode, j), dcode25->s10);
00062         if(enc == 0xff)
00063             return(0xff);
00064         if(enc & 1)
00065             par++;
00066     }
00067 
00068     dprintf(2, " enc=%02x par=%x", enc, par);
00069 
00070     /* parity check */
00071     if(par != 2) {
00072         dprintf(2, " [bad parity]");
00073         return(0xff);
00074     }
00075 
00076     /* decode binary weights */
00077     enc &= 0xf;
00078     if(enc & 8) {
00079         if(enc == 12)
00080             enc = 0;
00081         else if(--enc > 9) {
00082             dprintf(2, " [invalid encoding]");
00083             return(0xff);
00084         }
00085     }
00086 
00087     dprintf(2, " => %x", enc);
00088     return(enc);
00089 }
00090 
00091 static inline signed char i25_decode_start (zbar_decoder_t *dcode)
00092 {
00093     i25_decoder_t *dcode25 = &dcode->i25;
00094     if(dcode25->s10 < 10)
00095         return(ZBAR_NONE);
00096 
00097     unsigned char enc = 0;
00098     unsigned char i = 10;
00099     enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
00100     enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
00101     enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
00102 
00103     if((get_color(dcode) == ZBAR_BAR)
00104        ? enc != 4
00105        : (enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10))) {
00106         dprintf(4, "      i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc);
00107         return(ZBAR_NONE);
00108     }
00109 
00110     /* check leading quiet zone - spec is 10n(?)
00111      * we require 5.25n for w=2n to 6.75n for w=3n
00112      * (FIXME should really factor in w:n ratio)
00113      */
00114     unsigned quiet = get_width(dcode, i++);
00115     if(quiet && quiet < dcode25->s10 * 3 / 8) {
00116         dprintf(3, "      i25: s=%d enc=%x q=%d [invalid qz]\n",
00117                 dcode25->s10, enc, quiet);
00118         return(ZBAR_NONE);
00119     }
00120 
00121     dcode25->direction = get_color(dcode);
00122     dcode25->element = 1;
00123     dcode25->character = 0;
00124     return(ZBAR_PARTIAL);
00125 }
00126 
00127 static inline signed char i25_decode_end (zbar_decoder_t *dcode)
00128 {
00129     i25_decoder_t *dcode25 = &dcode->i25;
00130 
00131     /* check trailing quiet zone */
00132     unsigned quiet = get_width(dcode, 0);
00133     if((quiet && quiet < dcode25->width * 3 / 8) ||
00134        decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 ||
00135        decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) {
00136         dprintf(3, " s=%d q=%d [invalid qz]\n", dcode25->width, quiet);
00137         return(ZBAR_NONE);
00138     }
00139 
00140     /* check exit condition */
00141     unsigned char E = decode_e(get_width(dcode, 3), dcode25->width, 45);
00142     if((!dcode25->direction)
00143        ? E - 3 > 4
00144        : (E > 2 ||
00145           decode_e(get_width(dcode, 4), dcode25->width, 45) > 2))
00146         return(ZBAR_NONE);
00147 
00148     if(dcode25->direction) {
00149         /* reverse buffer */
00150         dprintf(2, " (rev)");
00151         int i;
00152         for(i = 0; i < dcode25->character / 2; i++) {
00153             unsigned j = dcode25->character - 1 - i;
00154             char c = dcode->buf[i];
00155             dcode->buf[i] = dcode->buf[j];
00156             dcode->buf[j] = c;
00157         }
00158     }
00159 
00160     if(dcode25->character < CFG(*dcode25, ZBAR_CFG_MIN_LEN) ||
00161        (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 &&
00162         dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) {
00163         dprintf(2, " [invalid len]\n");
00164         dcode->lock = 0;
00165         dcode25->character = -1;
00166         return(ZBAR_NONE);
00167     }
00168 
00169     dcode->buflen = dcode25->character;
00170     dcode->buf[dcode25->character] = '\0';
00171     dprintf(2, " [valid end]\n");
00172     dcode25->character = -1;
00173     return(ZBAR_I25);
00174 }
00175 
00176 zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode)
00177 {
00178     i25_decoder_t *dcode25 = &dcode->i25;
00179 
00180 #if (ENABLE_I25)
00181 #else
00182     return(ZBAR_NONE);
00183 #endif
00184 
00185     /* update latest character width */
00186     dcode25->s10 -= get_width(dcode, 10);
00187     dcode25->s10 += get_width(dcode, 0);
00188 
00189     if(dcode25->character < 0 &&
00190        !i25_decode_start(dcode))
00191         return(ZBAR_NONE);
00192 
00193     if(--dcode25->element == 6 - dcode25->direction)
00194         return(i25_decode_end(dcode));
00195     else if(dcode25->element)
00196         return(ZBAR_NONE);
00197 
00198     /* FIXME check current character width against previous */
00199     dcode25->width = dcode25->s10;
00200 
00201     dprintf(2, "      i25[%c%02d+%x]",
00202             (dcode25->direction) ? '<' : '>',
00203             dcode25->character, dcode25->element);
00204 
00205     /* lock shared resources */
00206     if(!dcode25->character && get_lock(dcode, ZBAR_I25)) {
00207         dcode25->character = -1;
00208         dprintf(2, " [locked %d]\n", dcode->lock);
00209         return(ZBAR_PARTIAL);
00210     }
00211 
00212     unsigned char c = i25_decode10(dcode, 1);
00213     dprintf(2, " c=%x", c);
00214 
00215     if(c > 9 ||
00216        ((dcode25->character >= BUFFER_MIN) &&
00217         size_buf(dcode, dcode25->character + 2))) {
00218         dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n");
00219         dcode->lock = 0;
00220         dcode25->character = -1;
00221         return(ZBAR_NONE);
00222     }
00223     dcode->buf[dcode25->character++] = c + '0';
00224 
00225     c = i25_decode10(dcode, 0);
00226     dprintf(2, " c=%x", c);
00227     if(c > 9) {
00228         dprintf(2, " [aborted]\n");
00229         dcode->lock = 0;
00230         dcode25->character = -1;
00231         return(ZBAR_NONE);
00232     }
00233     else
00234         dprintf(2, "\n");
00235 
00236     dcode->buf[dcode25->character++] = c + '0';
00237     dcode25->element = 10;
00238     return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE);
00239 }
00240