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 ean.c Source File

ean.c

00001 /*------------------------------------------------------------------------
00002  *  Copyright 2007-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 <zbar.h>
00026 #include "decoder.h"
00027 
00028 #ifdef DEBUG_EAN
00029 # define DEBUG_LEVEL (DEBUG_EAN)
00030 #endif
00031 #include "zbar_debug.h"
00032 
00033 /* partial decode symbol location */
00034 typedef enum symbol_partial_e {
00035     EAN_LEFT   = 0x0000,
00036     EAN_RIGHT  = 0x1000,
00037 } symbol_partial_t;
00038 
00039 /* convert compact encoded D2E1E2 to character (bit4 is parity) */
00040 static const unsigned char digits[] = {  /* E1   E2 */
00041     0x06, 0x10, 0x04, 0x13,              /*  2  2-5 */
00042     0x19, 0x08, 0x11, 0x05,              /*  3  2-5 (d2 <= thr) */
00043     0x09, 0x12, 0x07, 0x15,              /*  4  2-5 (d2 <= thr) */
00044     0x16, 0x00, 0x14, 0x03,              /*  5  2-5 */
00045     0x18, 0x01, 0x02, 0x17,              /* E1E2=43,44,33,34 (d2 > thr) */
00046 };
00047 
00048 static const unsigned char parity_decode[] = {
00049     0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */
00050 
00051     /* UPC-E check digit encoding */
00052     0xff,
00053     0xff,
00054     0x0f, /* [07] BBBAAA = 0 */
00055     0xff,
00056     0x1f, /* [0b] BBABAA = 1 */
00057     0x2f, /* [0d] BBAABA = 2 */
00058     0xf3, /* [0e] BBAAAB = 3 */
00059     0xff,
00060     0x4f, /* [13] BABBAA = 4 */
00061     0x7f, /* [15] BABABA = 7 */
00062     0xf8, /* [16] BABAAB = 8 */
00063     0x5f, /* [19] BAABBA = 5 */
00064     0xf9, /* [1a] BAABAB = 9 */
00065     0xf6, /* [1c] BAAABB = 6 */
00066     0xff,
00067 
00068     /* LEFT half EAN-13 leading digit */
00069     0xff,
00070     0x6f, /* [23] ABBBAA = 6 */
00071     0x9f, /* [25] ABBABA = 9 */
00072     0xf5, /* [26] ABBAAB = 5 */
00073     0x8f, /* [29] ABABBA = 8 */
00074     0xf7, /* [2a] ABABAB = 7 */
00075     0xf4, /* [2c] ABAABB = 4 */
00076     0xff,
00077     0x3f, /* [31] AABBBA = 3 */
00078     0xf2, /* [32] AABBAB = 2 */
00079     0xf1, /* [34] AABABB = 1 */
00080     0xff,
00081     0xff,
00082     0xff,
00083     0xff,
00084     0x0f, /* [3f] AAAAAA = 0 */
00085 };
00086 
00087 #ifdef DEBUG_EAN
00088 static unsigned char debug_buf[0x18];
00089 
00090 static inline const unsigned char *dsprintbuf(ean_decoder_t *ean)
00091 {
00092     int i;
00093     for(i = 0; i < 7; i++)
00094         debug_buf[i] = ((ean->buf[0] < 0 || ean->buf[i] < 0)
00095                         ? '-'
00096                         : ean->buf[i] + '0');
00097     debug_buf[i] = ' ';
00098     for(; i < 13; i++)
00099         debug_buf[i + 1] = ((ean->buf[7] < 0 || ean->buf[i] < 0)
00100                             ? '-'
00101                             : ean->buf[i] + '0');
00102     debug_buf[i + 1] = ' ';
00103     for(; i < 18; i++)
00104         debug_buf[i + 2] = ((ean->buf[13] < 0 || ean->buf[i] < 0)
00105                             ? '-'
00106                             : ean->buf[i] + '0');
00107     debug_buf[i + 2] = '\0';
00108     return(debug_buf);
00109 }
00110 #endif
00111 
00112 /* evaluate previous N (>= 2) widths as auxiliary pattern,
00113  * using preceding 4 as character width
00114  */
00115 static inline signed char aux_end (zbar_decoder_t *dcode,
00116                                    unsigned char fwd)
00117 {
00118     /* reference width from previous character */
00119     unsigned s = calc_s(dcode, 4 + fwd, 4);
00120 
00121     /* check quiet zone */
00122     unsigned qz = get_width(dcode, 0);
00123     if(!fwd && qz && qz < s * 3 / 4) {
00124         dprintf(2, " [invalid quiet]");
00125         return(-1);
00126     }
00127 
00128     dprintf(2, " (");
00129     signed char code = 0;
00130     unsigned char i;
00131     for(i = 1 - fwd; i < 3 + fwd; i++) {
00132         unsigned e = get_width(dcode, i) + get_width(dcode, i + 1);
00133         dprintf(2, " %d", e);
00134         code = (code << 2) | decode_e(e, s, 7);
00135         if(code < 0) {
00136             dprintf(2, " [invalid end guard]");
00137             return(-1);
00138         }
00139     }
00140     dprintf(2, ") s=%d aux=%x", s, code);
00141     return(code);
00142 }
00143 
00144 /* determine possible auxiliary pattern
00145  * using current 4 as possible character
00146  */
00147 static inline signed char aux_start (zbar_decoder_t *dcode)
00148 {
00149     /* FIXME NB add-on has no guard in reverse */
00150     unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6);
00151     if(decode_e(e2, dcode->ean.s4, 7)) {
00152         dprintf(2, " [invalid any]");
00153         return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1);
00154     }
00155 
00156     unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5);
00157     unsigned char E1 = decode_e(e1, dcode->ean.s4, 7);
00158 
00159     if(get_color(dcode) == ZBAR_BAR) {
00160         /* check for quiet-zone */
00161         unsigned qz = get_width(dcode, 7);
00162         if(!qz || qz >= dcode->ean.s4 * 3 / 4) {
00163             if(!E1) {
00164                 dprintf(2, " [valid normal]");
00165                 return(0); /* normal symbol start */
00166             }
00167             else if(E1 == 1) {
00168                 dprintf(2, " [valid add-on]");
00169                 return(STATE_ADDON); /* add-on symbol start */
00170             }
00171         }
00172         dprintf(2, " [invalid start]");
00173         return(-1);
00174     }
00175 
00176     if(!E1) {
00177         /* attempting decode from SPACE => validate center guard */
00178         unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7);
00179         if(!decode_e(e3, dcode->ean.s4, 7)) {
00180             dprintf(2, " [valid center]");
00181             return(0); /* start after center guard */
00182         }
00183     }
00184     dprintf(2, " [invalid center]");
00185     return(/*STATE_ADDON*/-1);
00186 }
00187 
00188 /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */
00189 static inline signed char decode4 (zbar_decoder_t *dcode)
00190 {
00191     /* calculate similar edge measurements */
00192     unsigned e1 = ((get_color(dcode) == ZBAR_BAR)
00193                    ? get_width(dcode, 0) + get_width(dcode, 1)
00194                    : get_width(dcode, 2) + get_width(dcode, 3));
00195     unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2);
00196     dprintf(2, "\n        e1=%d e2=%d", e1, e2);
00197 
00198     /* create compacted encoding for direct lookup */
00199     signed char code = ((decode_e(e1, dcode->ean.s4, 7) << 2) |
00200                         decode_e(e2, dcode->ean.s4, 7));
00201     if(code < 0)
00202         return(-1);
00203     dprintf(2, " code=%x", code);
00204 
00205     /* 4 combinations require additional determinant (D2)
00206        E1E2 == 34 (0110)
00207        E1E2 == 43 (1001)
00208        E1E2 == 33 (0101)
00209        E1E2 == 44 (1010)
00210      */
00211     if((1 << code) & 0x0660) {
00212         /* use sum of bar widths */
00213         unsigned d2 = ((get_color(dcode) == ZBAR_BAR)
00214                        ? get_width(dcode, 0) + get_width(dcode, 2)
00215                        : get_width(dcode, 1) + get_width(dcode, 3));
00216         d2 *= 7;
00217         unsigned char mid = (((1 << code) & 0x0420)
00218                              ? 3     /* E1E2 in 33,44 */
00219                              : 4);   /* E1E2 in 34,43 */
00220         unsigned char alt = d2 > (mid * dcode->ean.s4);
00221         if(alt)
00222             code = ((code >> 1) & 3) | 0x10; /* compress code space */
00223         dprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt);
00224     }
00225     dprintf(2, " char=%02x", digits[(unsigned char)code]);
00226     zassert(code < 0x14, -1, "code=%02x e1=%x e2=%x s4=%x color=%x\n",
00227             code, e1, e2, dcode->ean.s4, get_color(dcode));
00228     return(code);
00229 }
00230 
00231 static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass,
00232                                                 unsigned char fwd)
00233 {
00234     /* extract parity bits */
00235     unsigned char par = ((pass->raw[1] & 0x10) >> 1 |
00236                          (pass->raw[2] & 0x10) >> 2 |
00237                          (pass->raw[3] & 0x10) >> 3 |
00238                          (pass->raw[4] & 0x10) >> 4);
00239 
00240     dprintf(2, " par=%x", par);
00241     if(par && par != 0xf)
00242         /* invalid parity combination */
00243         return(ZBAR_NONE);
00244 
00245     if(!par == fwd) {
00246         /* reverse sampled digits */
00247         unsigned char tmp = pass->raw[1];
00248         pass->raw[1] = pass->raw[4];
00249         pass->raw[4] = tmp;
00250         tmp = pass->raw[2];
00251         pass->raw[2] = pass->raw[3];
00252         pass->raw[3] = tmp;
00253     }
00254 
00255     dprintf(2, "\n");
00256     dprintf(1, "decode4=%x%x%x%x\n",
00257             pass->raw[1] & 0xf, pass->raw[2] & 0xf,
00258             pass->raw[3] & 0xf, pass->raw[4] & 0xf);
00259     if(!par)
00260         return(ZBAR_EAN8 | EAN_RIGHT);
00261     return(ZBAR_EAN8 | EAN_LEFT);
00262 }
00263 
00264 static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean,
00265                                                 ean_pass_t *pass,
00266                                                 unsigned char fwd)
00267 {
00268     /* calculate parity index */
00269     unsigned char par = ((fwd)
00270                          ? ((pass->raw[1] & 0x10) << 1 |
00271                             (pass->raw[2] & 0x10) |
00272                             (pass->raw[3] & 0x10) >> 1 |
00273                             (pass->raw[4] & 0x10) >> 2 |
00274                             (pass->raw[5] & 0x10) >> 3 |
00275                             (pass->raw[6] & 0x10) >> 4)
00276                          : ((pass->raw[1] & 0x10) >> 4 |
00277                             (pass->raw[2] & 0x10) >> 3 |
00278                             (pass->raw[3] & 0x10) >> 2 |
00279                             (pass->raw[4] & 0x10) >> 1 |
00280                             (pass->raw[5] & 0x10) |
00281                             (pass->raw[6] & 0x10) << 1));
00282 
00283     /* lookup parity combination */
00284     pass->raw[0] = parity_decode[par >> 1];
00285     if(par & 1)
00286         pass->raw[0] >>= 4;
00287     pass->raw[0] &= 0xf;
00288     dprintf(2, " par=%02x(%x)", par, pass->raw[0]);
00289 
00290     if(pass->raw[0] == 0xf)
00291         /* invalid parity combination */
00292         return(ZBAR_NONE);
00293 
00294     if(!par == fwd) {
00295         /* reverse sampled digits */
00296         unsigned char i;
00297         for(i = 1; i < 4; i++) {
00298             unsigned char tmp = pass->raw[i];
00299             pass->raw[i] = pass->raw[7 - i];
00300             pass->raw[7 - i] = tmp;
00301         }
00302     }
00303 
00304     dprintf(2, "\n");
00305     dprintf(1, "decode=%x%x%x%x%x%x%x(%02x)\n",
00306             pass->raw[0] & 0xf, pass->raw[1] & 0xf,
00307             pass->raw[2] & 0xf, pass->raw[3] & 0xf,
00308             pass->raw[4] & 0xf, pass->raw[5] & 0xf,
00309             pass->raw[6] & 0xf, par);
00310 
00311     if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) {
00312         if(!par)
00313             return(ZBAR_EAN13 | EAN_RIGHT);
00314         if(par & 0x20)
00315             return(ZBAR_EAN13 | EAN_LEFT);
00316     }
00317     if(par && !(par & 0x20))
00318         return(ZBAR_UPCE);
00319 
00320     return(ZBAR_NONE);
00321 }
00322 
00323 /* update state for one of 4 parallel passes */
00324 static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode,
00325                                               ean_pass_t *pass)
00326 {
00327     pass->state++;
00328     unsigned char idx = pass->state & STATE_IDX;
00329     unsigned char fwd = pass->state & 1;
00330 
00331     if(get_color(dcode) == ZBAR_SPACE &&
00332        (idx == 0x10 || idx == 0x11) &&
00333        TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) &&
00334        !aux_end(dcode, fwd)) {
00335         dprintf(2, " fwd=%x", fwd);
00336         zbar_symbol_type_t part = ean_part_end4(pass, fwd);
00337         pass->state = -1;
00338         return(part);
00339     }
00340 
00341     if(!(idx & 0x03) && idx <= 0x14) {
00342         if(!dcode->ean.s4)
00343             return(0);
00344         /* validate guard bars before decoding first char of symbol */
00345         if(!pass->state) {
00346             pass->state = aux_start(dcode);
00347             if(pass->state < 0)
00348                 return(0);
00349             idx = pass->state & STATE_IDX;
00350         }
00351         signed char code = decode4(dcode);
00352         if(code < 0)
00353             pass->state = -1;
00354         else {
00355             dprintf(2, "\n        raw[%x]=%02x =>", idx >> 2,
00356                     digits[(unsigned char)code]);
00357             pass->raw[(idx >> 2) + 1] = digits[(unsigned char)code];
00358             dprintf(2, " raw=%d%d%d%d%d%d%d",
00359                     pass->raw[0] & 0xf, pass->raw[1] & 0xf,
00360                     pass->raw[2] & 0xf, pass->raw[3] & 0xf,
00361                     pass->raw[4] & 0xf, pass->raw[5] & 0xf,
00362                     pass->raw[6] & 0xf);
00363         }
00364     }
00365 
00366     if(get_color(dcode) == ZBAR_SPACE &&
00367        (idx == 0x18 || idx == 0x19)) {
00368         zbar_symbol_type_t part = ZBAR_NONE;
00369         dprintf(2, " fwd=%x", fwd);
00370         if(!aux_end(dcode, fwd))
00371             part = ean_part_end7(&dcode->ean, pass, fwd);
00372         pass->state = -1;
00373         return(part);
00374     }
00375     return(0);
00376 }
00377 
00378 static inline signed char ean_verify_checksum (ean_decoder_t *ean,
00379                                                int n)
00380 {
00381     unsigned char chk = 0;
00382     unsigned char i;
00383     for(i = 0; i < n; i++) {
00384         unsigned char d = ean->buf[i];
00385         zassert(d < 10, -1, "i=%x d=%x chk=%x %s\n", i, d, chk,
00386                 _zbar_decoder_buf_dump((void*)ean->buf, 18));
00387         chk += d;
00388         if((i ^ n) & 1) {
00389             chk += d << 1;
00390             if(chk >= 20)
00391                 chk -= 20;
00392         }
00393         if(chk >= 10)
00394             chk -= 10;
00395     }
00396     zassert(chk < 10, -1, "chk=%x n=%x %s", chk, n,
00397             _zbar_decoder_buf_dump((void*)ean->buf, 18));
00398     if(chk)
00399         chk = 10 - chk;
00400     unsigned char d = ean->buf[n];
00401     zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk,
00402             _zbar_decoder_buf_dump((void*)ean->buf, 18));
00403     if(chk != d) {
00404         dprintf(1, "\nchecksum mismatch %d != %d (%s)\n",
00405                 chk, d, dsprintbuf(ean));
00406         return(-1);
00407     }
00408     return(0);
00409 }
00410 
00411 static inline unsigned char isbn10_calc_checksum (ean_decoder_t *ean)
00412 {
00413     unsigned int chk = 0;
00414     unsigned char w;
00415     for(w = 10; w > 1; w--) {
00416         unsigned char d = ean->buf[13 - w];
00417         zassert(d < 10, '?', "w=%x d=%x chk=%x %s\n", w, d, chk,
00418                 _zbar_decoder_buf_dump((void*)ean->buf, 18));
00419         chk += d * w;
00420     }
00421     chk = chk % 11;
00422     if(!chk)
00423         return('0');
00424     chk = 11 - chk;
00425     if(chk < 10)
00426         return(chk + '0');
00427     return('X');
00428 }
00429 
00430 static inline void ean_expand_upce (ean_decoder_t *ean,
00431                                     ean_pass_t *pass)
00432 {
00433     int i = 0;
00434     /* parity encoded digit is checksum */
00435     ean->buf[12] = pass->raw[i++];
00436 
00437     unsigned char decode = pass->raw[6] & 0xf;
00438     ean->buf[0] = 0;
00439     ean->buf[1] = 0;
00440     ean->buf[2] = pass->raw[i++] & 0xf;
00441     ean->buf[3] = pass->raw[i++] & 0xf;
00442     ean->buf[4] = (decode < 3) ? decode : pass->raw[i++] & 0xf;
00443     ean->buf[5] = (decode < 4) ? 0 : pass->raw[i++] & 0xf;
00444     ean->buf[6] = (decode < 5) ? 0 : pass->raw[i++] & 0xf;
00445     ean->buf[7] = 0;
00446     ean->buf[8] = 0;
00447     ean->buf[9] = (decode < 3) ? pass->raw[i++] & 0xf : 0;
00448     ean->buf[10] = (decode < 4) ? pass->raw[i++] & 0xf : 0;
00449     ean->buf[11] = (decode < 5) ? pass->raw[i++] & 0xf : decode;
00450 }
00451 
00452 static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean,
00453                                                     ean_pass_t *pass,
00454                                                     zbar_symbol_type_t part)
00455 {
00456     /* copy raw data into holding buffer */
00457     /* if same partial is not consistent, reset others */
00458     dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean));
00459     signed char i, j;
00460     if(part & ZBAR_ADDON) {
00461         /* FIXME TBD */
00462         for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) {
00463             unsigned char digit = pass->raw[i] & 0xf;
00464             if(ean->addon && ean->buf[i + 13] != digit) {
00465                 /* partial mismatch - reset collected parts */
00466                 ean->left = ean->right = ean->addon = ZBAR_NONE;
00467             }
00468             ean->buf[i + 13] = digit;
00469         }
00470         ean->addon = part;
00471     }
00472     else {
00473         if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) ||
00474            (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) {
00475             /* partial mismatch - reset collected parts */
00476             dprintf(2, " rst(type %x %x)", ean->left, ean->right);
00477             ean->left = ean->right = ean->addon = ZBAR_NONE;
00478         }
00479 
00480         if(part & EAN_RIGHT) {
00481             part &= ZBAR_SYMBOL;
00482             j = (part == ZBAR_EAN13) ? 12 : 7;
00483             for(i = (part == ZBAR_EAN13) ? 6 : 4; i; i--, j--) {
00484                 unsigned char digit = pass->raw[i] & 0xf;
00485                 if(ean->right && ean->buf[j] != digit) {
00486                     /* partial mismatch - reset collected parts */
00487                     dprintf(2, " rst(right)");
00488                     ean->left = ean->right = ean->addon = ZBAR_NONE;
00489                 }
00490                 ean->buf[j] = digit;
00491             }
00492             ean->right = part;
00493         }
00494         else if(part != ZBAR_UPCE) /* EAN_LEFT */ {
00495             j = (part == ZBAR_EAN13) ? 6 : 3;
00496             for(i = (part == ZBAR_EAN13) ? 6 : 4; j >= 0; i--, j--) {
00497                 unsigned char digit = pass->raw[i] & 0xf;
00498                 if(ean->left && ean->buf[j] != digit) {
00499                     /* partial mismatch - reset collected parts */
00500                     dprintf(2, " rst(left)");
00501                     ean->left = ean->right = ean->addon = ZBAR_NONE;
00502                 }
00503                 ean->buf[j] = digit;
00504             }
00505             ean->left = part;
00506         }
00507         else /* ZBAR_UPCE */
00508             ean_expand_upce(ean, pass);
00509     }
00510 
00511     if((part & ZBAR_SYMBOL) != ZBAR_UPCE) {
00512         part = (ean->left & ean->right);
00513         if(!part)
00514             part = ZBAR_PARTIAL;
00515     }
00516 
00517     if(((part == ZBAR_EAN13 ||
00518          part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) ||
00519        (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7)))
00520         /* invalid parity */
00521         part = ZBAR_NONE;
00522 
00523     if(part == ZBAR_EAN13) {
00524         /* special case EAN-13 subsets */
00525         if(!ean->buf[0] && TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
00526             part = ZBAR_UPCA;
00527         else if(ean->buf[0] == 9 && ean->buf[1] == 7) {
00528             /* ISBN-10 has priority over ISBN-13(?) */
00529             if(ean->buf[2] == 8 &&
00530                TEST_CFG(ean->isbn10_config, ZBAR_CFG_ENABLE))
00531                 part = ZBAR_ISBN10;
00532             else if((ean->buf[2] == 8 || ean->buf[2] == 9) &&
00533                TEST_CFG(ean->isbn13_config, ZBAR_CFG_ENABLE))
00534                 part = ZBAR_ISBN13;
00535         }
00536     }
00537     else if(part == ZBAR_UPCE) {
00538         if(TEST_CFG(ean->upce_config, ZBAR_CFG_ENABLE)) {
00539             /* UPC-E was decompressed for checksum verification,
00540              * but user requested compressed result
00541              */
00542             ean->buf[0] = ean->buf[1] = 0;
00543             for(i = 2; i < 8; i++)
00544                 ean->buf[i] = pass->raw[i - 1] & 0xf;
00545             ean->buf[i] = pass->raw[0] & 0xf;
00546         }
00547         else if(TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
00548             /* UPC-E reported as UPC-A has priority over EAN-13 */
00549             part = ZBAR_UPCA;
00550         else if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE))
00551             part = ZBAR_EAN13;
00552         else
00553             part = ZBAR_NONE;
00554     }
00555 
00556     if(part > ZBAR_PARTIAL)
00557         part |= ean->addon;
00558 
00559     dprintf(2, " %x/%x=%x", ean->left, ean->right, part);
00560     return(part);
00561 }
00562 
00563 /* copy result to output buffer */
00564 static inline void postprocess (zbar_decoder_t *dcode,
00565                                 zbar_symbol_type_t sym)
00566 {
00567     ean_decoder_t *ean = &dcode->ean;
00568     zbar_symbol_type_t base = sym & ZBAR_SYMBOL;
00569     int i = 0, j = 0;
00570     if(base > ZBAR_PARTIAL) {
00571         if(base == ZBAR_UPCA)
00572             i = 1;
00573         else if(base == ZBAR_UPCE) {
00574             i = 1;
00575             base--;
00576         }
00577         else if(base == ZBAR_ISBN13)
00578             base = ZBAR_EAN13;
00579         else if(base == ZBAR_ISBN10)
00580             i = 3;
00581 
00582         if(base == ZBAR_ISBN10 ||
00583            !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK))
00584             base--;
00585 
00586         for(; j < base && ean->buf[i] >= 0; i++, j++)
00587             dcode->buf[j] = ean->buf[i] + '0';
00588 
00589         if((sym & ZBAR_SYMBOL) == ZBAR_ISBN10 && j == 9 &&
00590            TEST_CFG(ean->isbn10_config, ZBAR_CFG_EMIT_CHECK))
00591             /* recalculate ISBN-10 check digit */
00592             dcode->buf[j++] = isbn10_calc_checksum(ean);
00593     }
00594     if(sym & ZBAR_ADDON)
00595         for(i = 13; ean->buf[i] >= 0; i++, j++)
00596             dcode->buf[j] = ean->buf[i] + '0';
00597     dcode->buflen = j;
00598     dcode->buf[j] = '\0';
00599 }
00600 
00601 zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode)
00602 {
00603     /* process upto 4 separate passes */
00604     zbar_symbol_type_t sym = ZBAR_NONE;
00605     unsigned char pass_idx = dcode->idx & 3;
00606 
00607     /* update latest character width */
00608     dcode->ean.s4 -= get_width(dcode, 4);
00609     dcode->ean.s4 += get_width(dcode, 0);
00610 
00611     unsigned char i;
00612     for(i = 0; i < 4; i++) {
00613         ean_pass_t *pass = &dcode->ean.pass[i];
00614         if(pass->state >= 0 ||
00615            i == pass_idx)
00616         {
00617             dprintf(2, "      ean[%x/%x]: idx=%x st=%d s=%d",
00618                     pass_idx, i, dcode->idx, pass->state, dcode->ean.s4);
00619             zbar_symbol_type_t part = decode_pass(dcode, pass);
00620             if(part) {
00621                 /* update accumulated data from new partial decode */
00622                 sym = integrate_partial(&dcode->ean, pass, part);
00623                 if(sym) {
00624                     /* this pass valid => _reset_ all passes */
00625                     dprintf(2, " sym=%x", sym);
00626                     dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1;
00627                     dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1;
00628                     if(sym > ZBAR_PARTIAL) {
00629                         if(!get_lock(dcode, ZBAR_EAN13))
00630                             postprocess(dcode, sym);
00631                         else {
00632                             dprintf(1, " [locked %d]", dcode->lock);
00633                             sym = ZBAR_PARTIAL;
00634                         }
00635                     }
00636                 }
00637             }
00638             dprintf(2, "\n");
00639         }
00640     }
00641     return(sym);
00642 }
00643