Ryo Hagimoto / zbar_010

Dependents:   GR-PEACH_Camera_in_barcode levkov_ov7670

Committer:
RyoheiHagimoto
Date:
Tue Apr 19 02:19:39 2016 +0000
Revision:
1:500d42699c34
Parent:
0:56c5742b9e2b
Add copying.txt and license.txt

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RyoheiHagimoto 0:56c5742b9e2b 1 /*------------------------------------------------------------------------
RyoheiHagimoto 0:56c5742b9e2b 2 * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
RyoheiHagimoto 0:56c5742b9e2b 3 *
RyoheiHagimoto 0:56c5742b9e2b 4 * This file is part of the ZBar Bar Code Reader.
RyoheiHagimoto 0:56c5742b9e2b 5 *
RyoheiHagimoto 0:56c5742b9e2b 6 * The ZBar Bar Code Reader is free software; you can redistribute it
RyoheiHagimoto 0:56c5742b9e2b 7 * and/or modify it under the terms of the GNU Lesser Public License as
RyoheiHagimoto 0:56c5742b9e2b 8 * published by the Free Software Foundation; either version 2.1 of
RyoheiHagimoto 0:56c5742b9e2b 9 * the License, or (at your option) any later version.
RyoheiHagimoto 0:56c5742b9e2b 10 *
RyoheiHagimoto 0:56c5742b9e2b 11 * The ZBar Bar Code Reader is distributed in the hope that it will be
RyoheiHagimoto 0:56c5742b9e2b 12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
RyoheiHagimoto 0:56c5742b9e2b 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
RyoheiHagimoto 0:56c5742b9e2b 14 * GNU Lesser Public License for more details.
RyoheiHagimoto 0:56c5742b9e2b 15 *
RyoheiHagimoto 0:56c5742b9e2b 16 * You should have received a copy of the GNU Lesser Public License
RyoheiHagimoto 0:56c5742b9e2b 17 * along with the ZBar Bar Code Reader; if not, write to the Free
RyoheiHagimoto 0:56c5742b9e2b 18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
RyoheiHagimoto 0:56c5742b9e2b 19 * Boston, MA 02110-1301 USA
RyoheiHagimoto 0:56c5742b9e2b 20 *
RyoheiHagimoto 0:56c5742b9e2b 21 * http://sourceforge.net/projects/zbar
RyoheiHagimoto 0:56c5742b9e2b 22 *------------------------------------------------------------------------*/
RyoheiHagimoto 0:56c5742b9e2b 23
RyoheiHagimoto 0:56c5742b9e2b 24 #include <config.h>
RyoheiHagimoto 0:56c5742b9e2b 25 #include <zbar.h>
RyoheiHagimoto 0:56c5742b9e2b 26 #include "decoder.h"
RyoheiHagimoto 0:56c5742b9e2b 27
RyoheiHagimoto 0:56c5742b9e2b 28 #ifdef DEBUG_EAN
RyoheiHagimoto 0:56c5742b9e2b 29 # define DEBUG_LEVEL (DEBUG_EAN)
RyoheiHagimoto 0:56c5742b9e2b 30 #endif
RyoheiHagimoto 0:56c5742b9e2b 31 #include "zbar_debug.h"
RyoheiHagimoto 0:56c5742b9e2b 32
RyoheiHagimoto 0:56c5742b9e2b 33 /* partial decode symbol location */
RyoheiHagimoto 0:56c5742b9e2b 34 typedef enum symbol_partial_e {
RyoheiHagimoto 0:56c5742b9e2b 35 EAN_LEFT = 0x0000,
RyoheiHagimoto 0:56c5742b9e2b 36 EAN_RIGHT = 0x1000,
RyoheiHagimoto 0:56c5742b9e2b 37 } symbol_partial_t;
RyoheiHagimoto 0:56c5742b9e2b 38
RyoheiHagimoto 0:56c5742b9e2b 39 /* convert compact encoded D2E1E2 to character (bit4 is parity) */
RyoheiHagimoto 0:56c5742b9e2b 40 static const unsigned char digits[] = { /* E1 E2 */
RyoheiHagimoto 0:56c5742b9e2b 41 0x06, 0x10, 0x04, 0x13, /* 2 2-5 */
RyoheiHagimoto 0:56c5742b9e2b 42 0x19, 0x08, 0x11, 0x05, /* 3 2-5 (d2 <= thr) */
RyoheiHagimoto 0:56c5742b9e2b 43 0x09, 0x12, 0x07, 0x15, /* 4 2-5 (d2 <= thr) */
RyoheiHagimoto 0:56c5742b9e2b 44 0x16, 0x00, 0x14, 0x03, /* 5 2-5 */
RyoheiHagimoto 0:56c5742b9e2b 45 0x18, 0x01, 0x02, 0x17, /* E1E2=43,44,33,34 (d2 > thr) */
RyoheiHagimoto 0:56c5742b9e2b 46 };
RyoheiHagimoto 0:56c5742b9e2b 47
RyoheiHagimoto 0:56c5742b9e2b 48 static const unsigned char parity_decode[] = {
RyoheiHagimoto 0:56c5742b9e2b 49 0xf0, /* [xx] BBBBBB = RIGHT half EAN-13 */
RyoheiHagimoto 0:56c5742b9e2b 50
RyoheiHagimoto 0:56c5742b9e2b 51 /* UPC-E check digit encoding */
RyoheiHagimoto 0:56c5742b9e2b 52 0xff,
RyoheiHagimoto 0:56c5742b9e2b 53 0xff,
RyoheiHagimoto 0:56c5742b9e2b 54 0x0f, /* [07] BBBAAA = 0 */
RyoheiHagimoto 0:56c5742b9e2b 55 0xff,
RyoheiHagimoto 0:56c5742b9e2b 56 0x1f, /* [0b] BBABAA = 1 */
RyoheiHagimoto 0:56c5742b9e2b 57 0x2f, /* [0d] BBAABA = 2 */
RyoheiHagimoto 0:56c5742b9e2b 58 0xf3, /* [0e] BBAAAB = 3 */
RyoheiHagimoto 0:56c5742b9e2b 59 0xff,
RyoheiHagimoto 0:56c5742b9e2b 60 0x4f, /* [13] BABBAA = 4 */
RyoheiHagimoto 0:56c5742b9e2b 61 0x7f, /* [15] BABABA = 7 */
RyoheiHagimoto 0:56c5742b9e2b 62 0xf8, /* [16] BABAAB = 8 */
RyoheiHagimoto 0:56c5742b9e2b 63 0x5f, /* [19] BAABBA = 5 */
RyoheiHagimoto 0:56c5742b9e2b 64 0xf9, /* [1a] BAABAB = 9 */
RyoheiHagimoto 0:56c5742b9e2b 65 0xf6, /* [1c] BAAABB = 6 */
RyoheiHagimoto 0:56c5742b9e2b 66 0xff,
RyoheiHagimoto 0:56c5742b9e2b 67
RyoheiHagimoto 0:56c5742b9e2b 68 /* LEFT half EAN-13 leading digit */
RyoheiHagimoto 0:56c5742b9e2b 69 0xff,
RyoheiHagimoto 0:56c5742b9e2b 70 0x6f, /* [23] ABBBAA = 6 */
RyoheiHagimoto 0:56c5742b9e2b 71 0x9f, /* [25] ABBABA = 9 */
RyoheiHagimoto 0:56c5742b9e2b 72 0xf5, /* [26] ABBAAB = 5 */
RyoheiHagimoto 0:56c5742b9e2b 73 0x8f, /* [29] ABABBA = 8 */
RyoheiHagimoto 0:56c5742b9e2b 74 0xf7, /* [2a] ABABAB = 7 */
RyoheiHagimoto 0:56c5742b9e2b 75 0xf4, /* [2c] ABAABB = 4 */
RyoheiHagimoto 0:56c5742b9e2b 76 0xff,
RyoheiHagimoto 0:56c5742b9e2b 77 0x3f, /* [31] AABBBA = 3 */
RyoheiHagimoto 0:56c5742b9e2b 78 0xf2, /* [32] AABBAB = 2 */
RyoheiHagimoto 0:56c5742b9e2b 79 0xf1, /* [34] AABABB = 1 */
RyoheiHagimoto 0:56c5742b9e2b 80 0xff,
RyoheiHagimoto 0:56c5742b9e2b 81 0xff,
RyoheiHagimoto 0:56c5742b9e2b 82 0xff,
RyoheiHagimoto 0:56c5742b9e2b 83 0xff,
RyoheiHagimoto 0:56c5742b9e2b 84 0x0f, /* [3f] AAAAAA = 0 */
RyoheiHagimoto 0:56c5742b9e2b 85 };
RyoheiHagimoto 0:56c5742b9e2b 86
RyoheiHagimoto 0:56c5742b9e2b 87 #ifdef DEBUG_EAN
RyoheiHagimoto 0:56c5742b9e2b 88 static unsigned char debug_buf[0x18];
RyoheiHagimoto 0:56c5742b9e2b 89
RyoheiHagimoto 0:56c5742b9e2b 90 static inline const unsigned char *dsprintbuf(ean_decoder_t *ean)
RyoheiHagimoto 0:56c5742b9e2b 91 {
RyoheiHagimoto 0:56c5742b9e2b 92 int i;
RyoheiHagimoto 0:56c5742b9e2b 93 for(i = 0; i < 7; i++)
RyoheiHagimoto 0:56c5742b9e2b 94 debug_buf[i] = ((ean->buf[0] < 0 || ean->buf[i] < 0)
RyoheiHagimoto 0:56c5742b9e2b 95 ? '-'
RyoheiHagimoto 0:56c5742b9e2b 96 : ean->buf[i] + '0');
RyoheiHagimoto 0:56c5742b9e2b 97 debug_buf[i] = ' ';
RyoheiHagimoto 0:56c5742b9e2b 98 for(; i < 13; i++)
RyoheiHagimoto 0:56c5742b9e2b 99 debug_buf[i + 1] = ((ean->buf[7] < 0 || ean->buf[i] < 0)
RyoheiHagimoto 0:56c5742b9e2b 100 ? '-'
RyoheiHagimoto 0:56c5742b9e2b 101 : ean->buf[i] + '0');
RyoheiHagimoto 0:56c5742b9e2b 102 debug_buf[i + 1] = ' ';
RyoheiHagimoto 0:56c5742b9e2b 103 for(; i < 18; i++)
RyoheiHagimoto 0:56c5742b9e2b 104 debug_buf[i + 2] = ((ean->buf[13] < 0 || ean->buf[i] < 0)
RyoheiHagimoto 0:56c5742b9e2b 105 ? '-'
RyoheiHagimoto 0:56c5742b9e2b 106 : ean->buf[i] + '0');
RyoheiHagimoto 0:56c5742b9e2b 107 debug_buf[i + 2] = '\0';
RyoheiHagimoto 0:56c5742b9e2b 108 return(debug_buf);
RyoheiHagimoto 0:56c5742b9e2b 109 }
RyoheiHagimoto 0:56c5742b9e2b 110 #endif
RyoheiHagimoto 0:56c5742b9e2b 111
RyoheiHagimoto 0:56c5742b9e2b 112 /* evaluate previous N (>= 2) widths as auxiliary pattern,
RyoheiHagimoto 0:56c5742b9e2b 113 * using preceding 4 as character width
RyoheiHagimoto 0:56c5742b9e2b 114 */
RyoheiHagimoto 0:56c5742b9e2b 115 static inline signed char aux_end (zbar_decoder_t *dcode,
RyoheiHagimoto 0:56c5742b9e2b 116 unsigned char fwd)
RyoheiHagimoto 0:56c5742b9e2b 117 {
RyoheiHagimoto 0:56c5742b9e2b 118 /* reference width from previous character */
RyoheiHagimoto 0:56c5742b9e2b 119 unsigned s = calc_s(dcode, 4 + fwd, 4);
RyoheiHagimoto 0:56c5742b9e2b 120
RyoheiHagimoto 0:56c5742b9e2b 121 /* check quiet zone */
RyoheiHagimoto 0:56c5742b9e2b 122 unsigned qz = get_width(dcode, 0);
RyoheiHagimoto 0:56c5742b9e2b 123 if(!fwd && qz && qz < s * 3 / 4) {
RyoheiHagimoto 0:56c5742b9e2b 124 dprintf(2, " [invalid quiet]");
RyoheiHagimoto 0:56c5742b9e2b 125 return(-1);
RyoheiHagimoto 0:56c5742b9e2b 126 }
RyoheiHagimoto 0:56c5742b9e2b 127
RyoheiHagimoto 0:56c5742b9e2b 128 dprintf(2, " (");
RyoheiHagimoto 0:56c5742b9e2b 129 signed char code = 0;
RyoheiHagimoto 0:56c5742b9e2b 130 unsigned char i;
RyoheiHagimoto 0:56c5742b9e2b 131 for(i = 1 - fwd; i < 3 + fwd; i++) {
RyoheiHagimoto 0:56c5742b9e2b 132 unsigned e = get_width(dcode, i) + get_width(dcode, i + 1);
RyoheiHagimoto 0:56c5742b9e2b 133 dprintf(2, " %d", e);
RyoheiHagimoto 0:56c5742b9e2b 134 code = (code << 2) | decode_e(e, s, 7);
RyoheiHagimoto 0:56c5742b9e2b 135 if(code < 0) {
RyoheiHagimoto 0:56c5742b9e2b 136 dprintf(2, " [invalid end guard]");
RyoheiHagimoto 0:56c5742b9e2b 137 return(-1);
RyoheiHagimoto 0:56c5742b9e2b 138 }
RyoheiHagimoto 0:56c5742b9e2b 139 }
RyoheiHagimoto 0:56c5742b9e2b 140 dprintf(2, ") s=%d aux=%x", s, code);
RyoheiHagimoto 0:56c5742b9e2b 141 return(code);
RyoheiHagimoto 0:56c5742b9e2b 142 }
RyoheiHagimoto 0:56c5742b9e2b 143
RyoheiHagimoto 0:56c5742b9e2b 144 /* determine possible auxiliary pattern
RyoheiHagimoto 0:56c5742b9e2b 145 * using current 4 as possible character
RyoheiHagimoto 0:56c5742b9e2b 146 */
RyoheiHagimoto 0:56c5742b9e2b 147 static inline signed char aux_start (zbar_decoder_t *dcode)
RyoheiHagimoto 0:56c5742b9e2b 148 {
RyoheiHagimoto 0:56c5742b9e2b 149 /* FIXME NB add-on has no guard in reverse */
RyoheiHagimoto 0:56c5742b9e2b 150 unsigned e2 = get_width(dcode, 5) + get_width(dcode, 6);
RyoheiHagimoto 0:56c5742b9e2b 151 if(decode_e(e2, dcode->ean.s4, 7)) {
RyoheiHagimoto 0:56c5742b9e2b 152 dprintf(2, " [invalid any]");
RyoheiHagimoto 0:56c5742b9e2b 153 return(/*FIXME (get_color(dcode) == ZBAR_SPACE) ? STATE_ADDON : */-1);
RyoheiHagimoto 0:56c5742b9e2b 154 }
RyoheiHagimoto 0:56c5742b9e2b 155
RyoheiHagimoto 0:56c5742b9e2b 156 unsigned e1 = get_width(dcode, 4) + get_width(dcode, 5);
RyoheiHagimoto 0:56c5742b9e2b 157 unsigned char E1 = decode_e(e1, dcode->ean.s4, 7);
RyoheiHagimoto 0:56c5742b9e2b 158
RyoheiHagimoto 0:56c5742b9e2b 159 if(get_color(dcode) == ZBAR_BAR) {
RyoheiHagimoto 0:56c5742b9e2b 160 /* check for quiet-zone */
RyoheiHagimoto 0:56c5742b9e2b 161 unsigned qz = get_width(dcode, 7);
RyoheiHagimoto 0:56c5742b9e2b 162 if(!qz || qz >= dcode->ean.s4 * 3 / 4) {
RyoheiHagimoto 0:56c5742b9e2b 163 if(!E1) {
RyoheiHagimoto 0:56c5742b9e2b 164 dprintf(2, " [valid normal]");
RyoheiHagimoto 0:56c5742b9e2b 165 return(0); /* normal symbol start */
RyoheiHagimoto 0:56c5742b9e2b 166 }
RyoheiHagimoto 0:56c5742b9e2b 167 else if(E1 == 1) {
RyoheiHagimoto 0:56c5742b9e2b 168 dprintf(2, " [valid add-on]");
RyoheiHagimoto 0:56c5742b9e2b 169 return(STATE_ADDON); /* add-on symbol start */
RyoheiHagimoto 0:56c5742b9e2b 170 }
RyoheiHagimoto 0:56c5742b9e2b 171 }
RyoheiHagimoto 0:56c5742b9e2b 172 dprintf(2, " [invalid start]");
RyoheiHagimoto 0:56c5742b9e2b 173 return(-1);
RyoheiHagimoto 0:56c5742b9e2b 174 }
RyoheiHagimoto 0:56c5742b9e2b 175
RyoheiHagimoto 0:56c5742b9e2b 176 if(!E1) {
RyoheiHagimoto 0:56c5742b9e2b 177 /* attempting decode from SPACE => validate center guard */
RyoheiHagimoto 0:56c5742b9e2b 178 unsigned e3 = get_width(dcode, 6) + get_width(dcode, 7);
RyoheiHagimoto 0:56c5742b9e2b 179 if(!decode_e(e3, dcode->ean.s4, 7)) {
RyoheiHagimoto 0:56c5742b9e2b 180 dprintf(2, " [valid center]");
RyoheiHagimoto 0:56c5742b9e2b 181 return(0); /* start after center guard */
RyoheiHagimoto 0:56c5742b9e2b 182 }
RyoheiHagimoto 0:56c5742b9e2b 183 }
RyoheiHagimoto 0:56c5742b9e2b 184 dprintf(2, " [invalid center]");
RyoheiHagimoto 0:56c5742b9e2b 185 return(/*STATE_ADDON*/-1);
RyoheiHagimoto 0:56c5742b9e2b 186 }
RyoheiHagimoto 0:56c5742b9e2b 187
RyoheiHagimoto 0:56c5742b9e2b 188 /* attempt to decode previous 4 widths (2 bars and 2 spaces) as a character */
RyoheiHagimoto 0:56c5742b9e2b 189 static inline signed char decode4 (zbar_decoder_t *dcode)
RyoheiHagimoto 0:56c5742b9e2b 190 {
RyoheiHagimoto 0:56c5742b9e2b 191 /* calculate similar edge measurements */
RyoheiHagimoto 0:56c5742b9e2b 192 unsigned e1 = ((get_color(dcode) == ZBAR_BAR)
RyoheiHagimoto 0:56c5742b9e2b 193 ? get_width(dcode, 0) + get_width(dcode, 1)
RyoheiHagimoto 0:56c5742b9e2b 194 : get_width(dcode, 2) + get_width(dcode, 3));
RyoheiHagimoto 0:56c5742b9e2b 195 unsigned e2 = get_width(dcode, 1) + get_width(dcode, 2);
RyoheiHagimoto 0:56c5742b9e2b 196 dprintf(2, "\n e1=%d e2=%d", e1, e2);
RyoheiHagimoto 0:56c5742b9e2b 197
RyoheiHagimoto 0:56c5742b9e2b 198 /* create compacted encoding for direct lookup */
RyoheiHagimoto 0:56c5742b9e2b 199 signed char code = ((decode_e(e1, dcode->ean.s4, 7) << 2) |
RyoheiHagimoto 0:56c5742b9e2b 200 decode_e(e2, dcode->ean.s4, 7));
RyoheiHagimoto 0:56c5742b9e2b 201 if(code < 0)
RyoheiHagimoto 0:56c5742b9e2b 202 return(-1);
RyoheiHagimoto 0:56c5742b9e2b 203 dprintf(2, " code=%x", code);
RyoheiHagimoto 0:56c5742b9e2b 204
RyoheiHagimoto 0:56c5742b9e2b 205 /* 4 combinations require additional determinant (D2)
RyoheiHagimoto 0:56c5742b9e2b 206 E1E2 == 34 (0110)
RyoheiHagimoto 0:56c5742b9e2b 207 E1E2 == 43 (1001)
RyoheiHagimoto 0:56c5742b9e2b 208 E1E2 == 33 (0101)
RyoheiHagimoto 0:56c5742b9e2b 209 E1E2 == 44 (1010)
RyoheiHagimoto 0:56c5742b9e2b 210 */
RyoheiHagimoto 0:56c5742b9e2b 211 if((1 << code) & 0x0660) {
RyoheiHagimoto 0:56c5742b9e2b 212 /* use sum of bar widths */
RyoheiHagimoto 0:56c5742b9e2b 213 unsigned d2 = ((get_color(dcode) == ZBAR_BAR)
RyoheiHagimoto 0:56c5742b9e2b 214 ? get_width(dcode, 0) + get_width(dcode, 2)
RyoheiHagimoto 0:56c5742b9e2b 215 : get_width(dcode, 1) + get_width(dcode, 3));
RyoheiHagimoto 0:56c5742b9e2b 216 d2 *= 7;
RyoheiHagimoto 0:56c5742b9e2b 217 unsigned char mid = (((1 << code) & 0x0420)
RyoheiHagimoto 0:56c5742b9e2b 218 ? 3 /* E1E2 in 33,44 */
RyoheiHagimoto 0:56c5742b9e2b 219 : 4); /* E1E2 in 34,43 */
RyoheiHagimoto 0:56c5742b9e2b 220 unsigned char alt = d2 > (mid * dcode->ean.s4);
RyoheiHagimoto 0:56c5742b9e2b 221 if(alt)
RyoheiHagimoto 0:56c5742b9e2b 222 code = ((code >> 1) & 3) | 0x10; /* compress code space */
RyoheiHagimoto 0:56c5742b9e2b 223 dprintf(2, " (d2=%d(%d) alt=%d)", d2, mid * dcode->ean.s4, alt);
RyoheiHagimoto 0:56c5742b9e2b 224 }
RyoheiHagimoto 0:56c5742b9e2b 225 dprintf(2, " char=%02x", digits[(unsigned char)code]);
RyoheiHagimoto 0:56c5742b9e2b 226 zassert(code < 0x14, -1, "code=%02x e1=%x e2=%x s4=%x color=%x\n",
RyoheiHagimoto 0:56c5742b9e2b 227 code, e1, e2, dcode->ean.s4, get_color(dcode));
RyoheiHagimoto 0:56c5742b9e2b 228 return(code);
RyoheiHagimoto 0:56c5742b9e2b 229 }
RyoheiHagimoto 0:56c5742b9e2b 230
RyoheiHagimoto 0:56c5742b9e2b 231 static inline zbar_symbol_type_t ean_part_end4 (ean_pass_t *pass,
RyoheiHagimoto 0:56c5742b9e2b 232 unsigned char fwd)
RyoheiHagimoto 0:56c5742b9e2b 233 {
RyoheiHagimoto 0:56c5742b9e2b 234 /* extract parity bits */
RyoheiHagimoto 0:56c5742b9e2b 235 unsigned char par = ((pass->raw[1] & 0x10) >> 1 |
RyoheiHagimoto 0:56c5742b9e2b 236 (pass->raw[2] & 0x10) >> 2 |
RyoheiHagimoto 0:56c5742b9e2b 237 (pass->raw[3] & 0x10) >> 3 |
RyoheiHagimoto 0:56c5742b9e2b 238 (pass->raw[4] & 0x10) >> 4);
RyoheiHagimoto 0:56c5742b9e2b 239
RyoheiHagimoto 0:56c5742b9e2b 240 dprintf(2, " par=%x", par);
RyoheiHagimoto 0:56c5742b9e2b 241 if(par && par != 0xf)
RyoheiHagimoto 0:56c5742b9e2b 242 /* invalid parity combination */
RyoheiHagimoto 0:56c5742b9e2b 243 return(ZBAR_NONE);
RyoheiHagimoto 0:56c5742b9e2b 244
RyoheiHagimoto 0:56c5742b9e2b 245 if(!par == fwd) {
RyoheiHagimoto 0:56c5742b9e2b 246 /* reverse sampled digits */
RyoheiHagimoto 0:56c5742b9e2b 247 unsigned char tmp = pass->raw[1];
RyoheiHagimoto 0:56c5742b9e2b 248 pass->raw[1] = pass->raw[4];
RyoheiHagimoto 0:56c5742b9e2b 249 pass->raw[4] = tmp;
RyoheiHagimoto 0:56c5742b9e2b 250 tmp = pass->raw[2];
RyoheiHagimoto 0:56c5742b9e2b 251 pass->raw[2] = pass->raw[3];
RyoheiHagimoto 0:56c5742b9e2b 252 pass->raw[3] = tmp;
RyoheiHagimoto 0:56c5742b9e2b 253 }
RyoheiHagimoto 0:56c5742b9e2b 254
RyoheiHagimoto 0:56c5742b9e2b 255 dprintf(2, "\n");
RyoheiHagimoto 0:56c5742b9e2b 256 dprintf(1, "decode4=%x%x%x%x\n",
RyoheiHagimoto 0:56c5742b9e2b 257 pass->raw[1] & 0xf, pass->raw[2] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 258 pass->raw[3] & 0xf, pass->raw[4] & 0xf);
RyoheiHagimoto 0:56c5742b9e2b 259 if(!par)
RyoheiHagimoto 0:56c5742b9e2b 260 return(ZBAR_EAN8 | EAN_RIGHT);
RyoheiHagimoto 0:56c5742b9e2b 261 return(ZBAR_EAN8 | EAN_LEFT);
RyoheiHagimoto 0:56c5742b9e2b 262 }
RyoheiHagimoto 0:56c5742b9e2b 263
RyoheiHagimoto 0:56c5742b9e2b 264 static inline zbar_symbol_type_t ean_part_end7 (ean_decoder_t *ean,
RyoheiHagimoto 0:56c5742b9e2b 265 ean_pass_t *pass,
RyoheiHagimoto 0:56c5742b9e2b 266 unsigned char fwd)
RyoheiHagimoto 0:56c5742b9e2b 267 {
RyoheiHagimoto 0:56c5742b9e2b 268 /* calculate parity index */
RyoheiHagimoto 0:56c5742b9e2b 269 unsigned char par = ((fwd)
RyoheiHagimoto 0:56c5742b9e2b 270 ? ((pass->raw[1] & 0x10) << 1 |
RyoheiHagimoto 0:56c5742b9e2b 271 (pass->raw[2] & 0x10) |
RyoheiHagimoto 0:56c5742b9e2b 272 (pass->raw[3] & 0x10) >> 1 |
RyoheiHagimoto 0:56c5742b9e2b 273 (pass->raw[4] & 0x10) >> 2 |
RyoheiHagimoto 0:56c5742b9e2b 274 (pass->raw[5] & 0x10) >> 3 |
RyoheiHagimoto 0:56c5742b9e2b 275 (pass->raw[6] & 0x10) >> 4)
RyoheiHagimoto 0:56c5742b9e2b 276 : ((pass->raw[1] & 0x10) >> 4 |
RyoheiHagimoto 0:56c5742b9e2b 277 (pass->raw[2] & 0x10) >> 3 |
RyoheiHagimoto 0:56c5742b9e2b 278 (pass->raw[3] & 0x10) >> 2 |
RyoheiHagimoto 0:56c5742b9e2b 279 (pass->raw[4] & 0x10) >> 1 |
RyoheiHagimoto 0:56c5742b9e2b 280 (pass->raw[5] & 0x10) |
RyoheiHagimoto 0:56c5742b9e2b 281 (pass->raw[6] & 0x10) << 1));
RyoheiHagimoto 0:56c5742b9e2b 282
RyoheiHagimoto 0:56c5742b9e2b 283 /* lookup parity combination */
RyoheiHagimoto 0:56c5742b9e2b 284 pass->raw[0] = parity_decode[par >> 1];
RyoheiHagimoto 0:56c5742b9e2b 285 if(par & 1)
RyoheiHagimoto 0:56c5742b9e2b 286 pass->raw[0] >>= 4;
RyoheiHagimoto 0:56c5742b9e2b 287 pass->raw[0] &= 0xf;
RyoheiHagimoto 0:56c5742b9e2b 288 dprintf(2, " par=%02x(%x)", par, pass->raw[0]);
RyoheiHagimoto 0:56c5742b9e2b 289
RyoheiHagimoto 0:56c5742b9e2b 290 if(pass->raw[0] == 0xf)
RyoheiHagimoto 0:56c5742b9e2b 291 /* invalid parity combination */
RyoheiHagimoto 0:56c5742b9e2b 292 return(ZBAR_NONE);
RyoheiHagimoto 0:56c5742b9e2b 293
RyoheiHagimoto 0:56c5742b9e2b 294 if(!par == fwd) {
RyoheiHagimoto 0:56c5742b9e2b 295 /* reverse sampled digits */
RyoheiHagimoto 0:56c5742b9e2b 296 unsigned char i;
RyoheiHagimoto 0:56c5742b9e2b 297 for(i = 1; i < 4; i++) {
RyoheiHagimoto 0:56c5742b9e2b 298 unsigned char tmp = pass->raw[i];
RyoheiHagimoto 0:56c5742b9e2b 299 pass->raw[i] = pass->raw[7 - i];
RyoheiHagimoto 0:56c5742b9e2b 300 pass->raw[7 - i] = tmp;
RyoheiHagimoto 0:56c5742b9e2b 301 }
RyoheiHagimoto 0:56c5742b9e2b 302 }
RyoheiHagimoto 0:56c5742b9e2b 303
RyoheiHagimoto 0:56c5742b9e2b 304 dprintf(2, "\n");
RyoheiHagimoto 0:56c5742b9e2b 305 dprintf(1, "decode=%x%x%x%x%x%x%x(%02x)\n",
RyoheiHagimoto 0:56c5742b9e2b 306 pass->raw[0] & 0xf, pass->raw[1] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 307 pass->raw[2] & 0xf, pass->raw[3] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 308 pass->raw[4] & 0xf, pass->raw[5] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 309 pass->raw[6] & 0xf, par);
RyoheiHagimoto 0:56c5742b9e2b 310
RyoheiHagimoto 0:56c5742b9e2b 311 if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE)) {
RyoheiHagimoto 0:56c5742b9e2b 312 if(!par)
RyoheiHagimoto 0:56c5742b9e2b 313 return(ZBAR_EAN13 | EAN_RIGHT);
RyoheiHagimoto 0:56c5742b9e2b 314 if(par & 0x20)
RyoheiHagimoto 0:56c5742b9e2b 315 return(ZBAR_EAN13 | EAN_LEFT);
RyoheiHagimoto 0:56c5742b9e2b 316 }
RyoheiHagimoto 0:56c5742b9e2b 317 if(par && !(par & 0x20))
RyoheiHagimoto 0:56c5742b9e2b 318 return(ZBAR_UPCE);
RyoheiHagimoto 0:56c5742b9e2b 319
RyoheiHagimoto 0:56c5742b9e2b 320 return(ZBAR_NONE);
RyoheiHagimoto 0:56c5742b9e2b 321 }
RyoheiHagimoto 0:56c5742b9e2b 322
RyoheiHagimoto 0:56c5742b9e2b 323 /* update state for one of 4 parallel passes */
RyoheiHagimoto 0:56c5742b9e2b 324 static inline zbar_symbol_type_t decode_pass (zbar_decoder_t *dcode,
RyoheiHagimoto 0:56c5742b9e2b 325 ean_pass_t *pass)
RyoheiHagimoto 0:56c5742b9e2b 326 {
RyoheiHagimoto 0:56c5742b9e2b 327 pass->state++;
RyoheiHagimoto 0:56c5742b9e2b 328 unsigned char idx = pass->state & STATE_IDX;
RyoheiHagimoto 0:56c5742b9e2b 329 unsigned char fwd = pass->state & 1;
RyoheiHagimoto 0:56c5742b9e2b 330
RyoheiHagimoto 0:56c5742b9e2b 331 if(get_color(dcode) == ZBAR_SPACE &&
RyoheiHagimoto 0:56c5742b9e2b 332 (idx == 0x10 || idx == 0x11) &&
RyoheiHagimoto 0:56c5742b9e2b 333 TEST_CFG(dcode->ean.ean8_config, ZBAR_CFG_ENABLE) &&
RyoheiHagimoto 0:56c5742b9e2b 334 !aux_end(dcode, fwd)) {
RyoheiHagimoto 0:56c5742b9e2b 335 dprintf(2, " fwd=%x", fwd);
RyoheiHagimoto 0:56c5742b9e2b 336 zbar_symbol_type_t part = ean_part_end4(pass, fwd);
RyoheiHagimoto 0:56c5742b9e2b 337 pass->state = -1;
RyoheiHagimoto 0:56c5742b9e2b 338 return(part);
RyoheiHagimoto 0:56c5742b9e2b 339 }
RyoheiHagimoto 0:56c5742b9e2b 340
RyoheiHagimoto 0:56c5742b9e2b 341 if(!(idx & 0x03) && idx <= 0x14) {
RyoheiHagimoto 0:56c5742b9e2b 342 if(!dcode->ean.s4)
RyoheiHagimoto 0:56c5742b9e2b 343 return(0);
RyoheiHagimoto 0:56c5742b9e2b 344 /* validate guard bars before decoding first char of symbol */
RyoheiHagimoto 0:56c5742b9e2b 345 if(!pass->state) {
RyoheiHagimoto 0:56c5742b9e2b 346 pass->state = aux_start(dcode);
RyoheiHagimoto 0:56c5742b9e2b 347 if(pass->state < 0)
RyoheiHagimoto 0:56c5742b9e2b 348 return(0);
RyoheiHagimoto 0:56c5742b9e2b 349 idx = pass->state & STATE_IDX;
RyoheiHagimoto 0:56c5742b9e2b 350 }
RyoheiHagimoto 0:56c5742b9e2b 351 signed char code = decode4(dcode);
RyoheiHagimoto 0:56c5742b9e2b 352 if(code < 0)
RyoheiHagimoto 0:56c5742b9e2b 353 pass->state = -1;
RyoheiHagimoto 0:56c5742b9e2b 354 else {
RyoheiHagimoto 0:56c5742b9e2b 355 dprintf(2, "\n raw[%x]=%02x =>", idx >> 2,
RyoheiHagimoto 0:56c5742b9e2b 356 digits[(unsigned char)code]);
RyoheiHagimoto 0:56c5742b9e2b 357 pass->raw[(idx >> 2) + 1] = digits[(unsigned char)code];
RyoheiHagimoto 0:56c5742b9e2b 358 dprintf(2, " raw=%d%d%d%d%d%d%d",
RyoheiHagimoto 0:56c5742b9e2b 359 pass->raw[0] & 0xf, pass->raw[1] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 360 pass->raw[2] & 0xf, pass->raw[3] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 361 pass->raw[4] & 0xf, pass->raw[5] & 0xf,
RyoheiHagimoto 0:56c5742b9e2b 362 pass->raw[6] & 0xf);
RyoheiHagimoto 0:56c5742b9e2b 363 }
RyoheiHagimoto 0:56c5742b9e2b 364 }
RyoheiHagimoto 0:56c5742b9e2b 365
RyoheiHagimoto 0:56c5742b9e2b 366 if(get_color(dcode) == ZBAR_SPACE &&
RyoheiHagimoto 0:56c5742b9e2b 367 (idx == 0x18 || idx == 0x19)) {
RyoheiHagimoto 0:56c5742b9e2b 368 zbar_symbol_type_t part = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 369 dprintf(2, " fwd=%x", fwd);
RyoheiHagimoto 0:56c5742b9e2b 370 if(!aux_end(dcode, fwd))
RyoheiHagimoto 0:56c5742b9e2b 371 part = ean_part_end7(&dcode->ean, pass, fwd);
RyoheiHagimoto 0:56c5742b9e2b 372 pass->state = -1;
RyoheiHagimoto 0:56c5742b9e2b 373 return(part);
RyoheiHagimoto 0:56c5742b9e2b 374 }
RyoheiHagimoto 0:56c5742b9e2b 375 return(0);
RyoheiHagimoto 0:56c5742b9e2b 376 }
RyoheiHagimoto 0:56c5742b9e2b 377
RyoheiHagimoto 0:56c5742b9e2b 378 static inline signed char ean_verify_checksum (ean_decoder_t *ean,
RyoheiHagimoto 0:56c5742b9e2b 379 int n)
RyoheiHagimoto 0:56c5742b9e2b 380 {
RyoheiHagimoto 0:56c5742b9e2b 381 unsigned char chk = 0;
RyoheiHagimoto 0:56c5742b9e2b 382 unsigned char i;
RyoheiHagimoto 0:56c5742b9e2b 383 for(i = 0; i < n; i++) {
RyoheiHagimoto 0:56c5742b9e2b 384 unsigned char d = ean->buf[i];
RyoheiHagimoto 0:56c5742b9e2b 385 zassert(d < 10, -1, "i=%x d=%x chk=%x %s\n", i, d, chk,
RyoheiHagimoto 0:56c5742b9e2b 386 _zbar_decoder_buf_dump((void*)ean->buf, 18));
RyoheiHagimoto 0:56c5742b9e2b 387 chk += d;
RyoheiHagimoto 0:56c5742b9e2b 388 if((i ^ n) & 1) {
RyoheiHagimoto 0:56c5742b9e2b 389 chk += d << 1;
RyoheiHagimoto 0:56c5742b9e2b 390 if(chk >= 20)
RyoheiHagimoto 0:56c5742b9e2b 391 chk -= 20;
RyoheiHagimoto 0:56c5742b9e2b 392 }
RyoheiHagimoto 0:56c5742b9e2b 393 if(chk >= 10)
RyoheiHagimoto 0:56c5742b9e2b 394 chk -= 10;
RyoheiHagimoto 0:56c5742b9e2b 395 }
RyoheiHagimoto 0:56c5742b9e2b 396 zassert(chk < 10, -1, "chk=%x n=%x %s", chk, n,
RyoheiHagimoto 0:56c5742b9e2b 397 _zbar_decoder_buf_dump((void*)ean->buf, 18));
RyoheiHagimoto 0:56c5742b9e2b 398 if(chk)
RyoheiHagimoto 0:56c5742b9e2b 399 chk = 10 - chk;
RyoheiHagimoto 0:56c5742b9e2b 400 unsigned char d = ean->buf[n];
RyoheiHagimoto 0:56c5742b9e2b 401 zassert(d < 10, -1, "n=%x d=%x chk=%x %s\n", n, d, chk,
RyoheiHagimoto 0:56c5742b9e2b 402 _zbar_decoder_buf_dump((void*)ean->buf, 18));
RyoheiHagimoto 0:56c5742b9e2b 403 if(chk != d) {
RyoheiHagimoto 0:56c5742b9e2b 404 dprintf(1, "\nchecksum mismatch %d != %d (%s)\n",
RyoheiHagimoto 0:56c5742b9e2b 405 chk, d, dsprintbuf(ean));
RyoheiHagimoto 0:56c5742b9e2b 406 return(-1);
RyoheiHagimoto 0:56c5742b9e2b 407 }
RyoheiHagimoto 0:56c5742b9e2b 408 return(0);
RyoheiHagimoto 0:56c5742b9e2b 409 }
RyoheiHagimoto 0:56c5742b9e2b 410
RyoheiHagimoto 0:56c5742b9e2b 411 static inline unsigned char isbn10_calc_checksum (ean_decoder_t *ean)
RyoheiHagimoto 0:56c5742b9e2b 412 {
RyoheiHagimoto 0:56c5742b9e2b 413 unsigned int chk = 0;
RyoheiHagimoto 0:56c5742b9e2b 414 unsigned char w;
RyoheiHagimoto 0:56c5742b9e2b 415 for(w = 10; w > 1; w--) {
RyoheiHagimoto 0:56c5742b9e2b 416 unsigned char d = ean->buf[13 - w];
RyoheiHagimoto 0:56c5742b9e2b 417 zassert(d < 10, '?', "w=%x d=%x chk=%x %s\n", w, d, chk,
RyoheiHagimoto 0:56c5742b9e2b 418 _zbar_decoder_buf_dump((void*)ean->buf, 18));
RyoheiHagimoto 0:56c5742b9e2b 419 chk += d * w;
RyoheiHagimoto 0:56c5742b9e2b 420 }
RyoheiHagimoto 0:56c5742b9e2b 421 chk = chk % 11;
RyoheiHagimoto 0:56c5742b9e2b 422 if(!chk)
RyoheiHagimoto 0:56c5742b9e2b 423 return('0');
RyoheiHagimoto 0:56c5742b9e2b 424 chk = 11 - chk;
RyoheiHagimoto 0:56c5742b9e2b 425 if(chk < 10)
RyoheiHagimoto 0:56c5742b9e2b 426 return(chk + '0');
RyoheiHagimoto 0:56c5742b9e2b 427 return('X');
RyoheiHagimoto 0:56c5742b9e2b 428 }
RyoheiHagimoto 0:56c5742b9e2b 429
RyoheiHagimoto 0:56c5742b9e2b 430 static inline void ean_expand_upce (ean_decoder_t *ean,
RyoheiHagimoto 0:56c5742b9e2b 431 ean_pass_t *pass)
RyoheiHagimoto 0:56c5742b9e2b 432 {
RyoheiHagimoto 0:56c5742b9e2b 433 int i = 0;
RyoheiHagimoto 0:56c5742b9e2b 434 /* parity encoded digit is checksum */
RyoheiHagimoto 0:56c5742b9e2b 435 ean->buf[12] = pass->raw[i++];
RyoheiHagimoto 0:56c5742b9e2b 436
RyoheiHagimoto 0:56c5742b9e2b 437 unsigned char decode = pass->raw[6] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 438 ean->buf[0] = 0;
RyoheiHagimoto 0:56c5742b9e2b 439 ean->buf[1] = 0;
RyoheiHagimoto 0:56c5742b9e2b 440 ean->buf[2] = pass->raw[i++] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 441 ean->buf[3] = pass->raw[i++] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 442 ean->buf[4] = (decode < 3) ? decode : pass->raw[i++] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 443 ean->buf[5] = (decode < 4) ? 0 : pass->raw[i++] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 444 ean->buf[6] = (decode < 5) ? 0 : pass->raw[i++] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 445 ean->buf[7] = 0;
RyoheiHagimoto 0:56c5742b9e2b 446 ean->buf[8] = 0;
RyoheiHagimoto 0:56c5742b9e2b 447 ean->buf[9] = (decode < 3) ? pass->raw[i++] & 0xf : 0;
RyoheiHagimoto 0:56c5742b9e2b 448 ean->buf[10] = (decode < 4) ? pass->raw[i++] & 0xf : 0;
RyoheiHagimoto 0:56c5742b9e2b 449 ean->buf[11] = (decode < 5) ? pass->raw[i++] & 0xf : decode;
RyoheiHagimoto 0:56c5742b9e2b 450 }
RyoheiHagimoto 0:56c5742b9e2b 451
RyoheiHagimoto 0:56c5742b9e2b 452 static inline zbar_symbol_type_t integrate_partial (ean_decoder_t *ean,
RyoheiHagimoto 0:56c5742b9e2b 453 ean_pass_t *pass,
RyoheiHagimoto 0:56c5742b9e2b 454 zbar_symbol_type_t part)
RyoheiHagimoto 0:56c5742b9e2b 455 {
RyoheiHagimoto 0:56c5742b9e2b 456 /* copy raw data into holding buffer */
RyoheiHagimoto 0:56c5742b9e2b 457 /* if same partial is not consistent, reset others */
RyoheiHagimoto 0:56c5742b9e2b 458 dprintf(2, " integrate part=%x (%s)", part, dsprintbuf(ean));
RyoheiHagimoto 0:56c5742b9e2b 459 signed char i, j;
RyoheiHagimoto 0:56c5742b9e2b 460 if(part & ZBAR_ADDON) {
RyoheiHagimoto 0:56c5742b9e2b 461 /* FIXME TBD */
RyoheiHagimoto 0:56c5742b9e2b 462 for(i = (part == ZBAR_ADDON5) ? 4 : 1; i >= 0; i--) {
RyoheiHagimoto 0:56c5742b9e2b 463 unsigned char digit = pass->raw[i] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 464 if(ean->addon && ean->buf[i + 13] != digit) {
RyoheiHagimoto 0:56c5742b9e2b 465 /* partial mismatch - reset collected parts */
RyoheiHagimoto 0:56c5742b9e2b 466 ean->left = ean->right = ean->addon = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 467 }
RyoheiHagimoto 0:56c5742b9e2b 468 ean->buf[i + 13] = digit;
RyoheiHagimoto 0:56c5742b9e2b 469 }
RyoheiHagimoto 0:56c5742b9e2b 470 ean->addon = part;
RyoheiHagimoto 0:56c5742b9e2b 471 }
RyoheiHagimoto 0:56c5742b9e2b 472 else {
RyoheiHagimoto 0:56c5742b9e2b 473 if((ean->left && ((part & ZBAR_SYMBOL) != ean->left)) ||
RyoheiHagimoto 0:56c5742b9e2b 474 (ean->right && ((part & ZBAR_SYMBOL) != ean->right))) {
RyoheiHagimoto 0:56c5742b9e2b 475 /* partial mismatch - reset collected parts */
RyoheiHagimoto 0:56c5742b9e2b 476 dprintf(2, " rst(type %x %x)", ean->left, ean->right);
RyoheiHagimoto 0:56c5742b9e2b 477 ean->left = ean->right = ean->addon = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 478 }
RyoheiHagimoto 0:56c5742b9e2b 479
RyoheiHagimoto 0:56c5742b9e2b 480 if(part & EAN_RIGHT) {
RyoheiHagimoto 0:56c5742b9e2b 481 part &= ZBAR_SYMBOL;
RyoheiHagimoto 0:56c5742b9e2b 482 j = (part == ZBAR_EAN13) ? 12 : 7;
RyoheiHagimoto 0:56c5742b9e2b 483 for(i = (part == ZBAR_EAN13) ? 6 : 4; i; i--, j--) {
RyoheiHagimoto 0:56c5742b9e2b 484 unsigned char digit = pass->raw[i] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 485 if(ean->right && ean->buf[j] != digit) {
RyoheiHagimoto 0:56c5742b9e2b 486 /* partial mismatch - reset collected parts */
RyoheiHagimoto 0:56c5742b9e2b 487 dprintf(2, " rst(right)");
RyoheiHagimoto 0:56c5742b9e2b 488 ean->left = ean->right = ean->addon = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 489 }
RyoheiHagimoto 0:56c5742b9e2b 490 ean->buf[j] = digit;
RyoheiHagimoto 0:56c5742b9e2b 491 }
RyoheiHagimoto 0:56c5742b9e2b 492 ean->right = part;
RyoheiHagimoto 0:56c5742b9e2b 493 }
RyoheiHagimoto 0:56c5742b9e2b 494 else if(part != ZBAR_UPCE) /* EAN_LEFT */ {
RyoheiHagimoto 0:56c5742b9e2b 495 j = (part == ZBAR_EAN13) ? 6 : 3;
RyoheiHagimoto 0:56c5742b9e2b 496 for(i = (part == ZBAR_EAN13) ? 6 : 4; j >= 0; i--, j--) {
RyoheiHagimoto 0:56c5742b9e2b 497 unsigned char digit = pass->raw[i] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 498 if(ean->left && ean->buf[j] != digit) {
RyoheiHagimoto 0:56c5742b9e2b 499 /* partial mismatch - reset collected parts */
RyoheiHagimoto 0:56c5742b9e2b 500 dprintf(2, " rst(left)");
RyoheiHagimoto 0:56c5742b9e2b 501 ean->left = ean->right = ean->addon = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 502 }
RyoheiHagimoto 0:56c5742b9e2b 503 ean->buf[j] = digit;
RyoheiHagimoto 0:56c5742b9e2b 504 }
RyoheiHagimoto 0:56c5742b9e2b 505 ean->left = part;
RyoheiHagimoto 0:56c5742b9e2b 506 }
RyoheiHagimoto 0:56c5742b9e2b 507 else /* ZBAR_UPCE */
RyoheiHagimoto 0:56c5742b9e2b 508 ean_expand_upce(ean, pass);
RyoheiHagimoto 0:56c5742b9e2b 509 }
RyoheiHagimoto 0:56c5742b9e2b 510
RyoheiHagimoto 0:56c5742b9e2b 511 if((part & ZBAR_SYMBOL) != ZBAR_UPCE) {
RyoheiHagimoto 0:56c5742b9e2b 512 part = (ean->left & ean->right);
RyoheiHagimoto 0:56c5742b9e2b 513 if(!part)
RyoheiHagimoto 0:56c5742b9e2b 514 part = ZBAR_PARTIAL;
RyoheiHagimoto 0:56c5742b9e2b 515 }
RyoheiHagimoto 0:56c5742b9e2b 516
RyoheiHagimoto 0:56c5742b9e2b 517 if(((part == ZBAR_EAN13 ||
RyoheiHagimoto 0:56c5742b9e2b 518 part == ZBAR_UPCE) && ean_verify_checksum(ean, 12)) ||
RyoheiHagimoto 0:56c5742b9e2b 519 (part == ZBAR_EAN8 && ean_verify_checksum(ean, 7)))
RyoheiHagimoto 0:56c5742b9e2b 520 /* invalid parity */
RyoheiHagimoto 0:56c5742b9e2b 521 part = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 522
RyoheiHagimoto 0:56c5742b9e2b 523 if(part == ZBAR_EAN13) {
RyoheiHagimoto 0:56c5742b9e2b 524 /* special case EAN-13 subsets */
RyoheiHagimoto 0:56c5742b9e2b 525 if(!ean->buf[0] && TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
RyoheiHagimoto 0:56c5742b9e2b 526 part = ZBAR_UPCA;
RyoheiHagimoto 0:56c5742b9e2b 527 else if(ean->buf[0] == 9 && ean->buf[1] == 7) {
RyoheiHagimoto 0:56c5742b9e2b 528 /* ISBN-10 has priority over ISBN-13(?) */
RyoheiHagimoto 0:56c5742b9e2b 529 if(ean->buf[2] == 8 &&
RyoheiHagimoto 0:56c5742b9e2b 530 TEST_CFG(ean->isbn10_config, ZBAR_CFG_ENABLE))
RyoheiHagimoto 0:56c5742b9e2b 531 part = ZBAR_ISBN10;
RyoheiHagimoto 0:56c5742b9e2b 532 else if((ean->buf[2] == 8 || ean->buf[2] == 9) &&
RyoheiHagimoto 0:56c5742b9e2b 533 TEST_CFG(ean->isbn13_config, ZBAR_CFG_ENABLE))
RyoheiHagimoto 0:56c5742b9e2b 534 part = ZBAR_ISBN13;
RyoheiHagimoto 0:56c5742b9e2b 535 }
RyoheiHagimoto 0:56c5742b9e2b 536 }
RyoheiHagimoto 0:56c5742b9e2b 537 else if(part == ZBAR_UPCE) {
RyoheiHagimoto 0:56c5742b9e2b 538 if(TEST_CFG(ean->upce_config, ZBAR_CFG_ENABLE)) {
RyoheiHagimoto 0:56c5742b9e2b 539 /* UPC-E was decompressed for checksum verification,
RyoheiHagimoto 0:56c5742b9e2b 540 * but user requested compressed result
RyoheiHagimoto 0:56c5742b9e2b 541 */
RyoheiHagimoto 0:56c5742b9e2b 542 ean->buf[0] = ean->buf[1] = 0;
RyoheiHagimoto 0:56c5742b9e2b 543 for(i = 2; i < 8; i++)
RyoheiHagimoto 0:56c5742b9e2b 544 ean->buf[i] = pass->raw[i - 1] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 545 ean->buf[i] = pass->raw[0] & 0xf;
RyoheiHagimoto 0:56c5742b9e2b 546 }
RyoheiHagimoto 0:56c5742b9e2b 547 else if(TEST_CFG(ean->upca_config, ZBAR_CFG_ENABLE))
RyoheiHagimoto 0:56c5742b9e2b 548 /* UPC-E reported as UPC-A has priority over EAN-13 */
RyoheiHagimoto 0:56c5742b9e2b 549 part = ZBAR_UPCA;
RyoheiHagimoto 0:56c5742b9e2b 550 else if(TEST_CFG(ean->ean13_config, ZBAR_CFG_ENABLE))
RyoheiHagimoto 0:56c5742b9e2b 551 part = ZBAR_EAN13;
RyoheiHagimoto 0:56c5742b9e2b 552 else
RyoheiHagimoto 0:56c5742b9e2b 553 part = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 554 }
RyoheiHagimoto 0:56c5742b9e2b 555
RyoheiHagimoto 0:56c5742b9e2b 556 if(part > ZBAR_PARTIAL)
RyoheiHagimoto 0:56c5742b9e2b 557 part |= ean->addon;
RyoheiHagimoto 0:56c5742b9e2b 558
RyoheiHagimoto 0:56c5742b9e2b 559 dprintf(2, " %x/%x=%x", ean->left, ean->right, part);
RyoheiHagimoto 0:56c5742b9e2b 560 return(part);
RyoheiHagimoto 0:56c5742b9e2b 561 }
RyoheiHagimoto 0:56c5742b9e2b 562
RyoheiHagimoto 0:56c5742b9e2b 563 /* copy result to output buffer */
RyoheiHagimoto 0:56c5742b9e2b 564 static inline void postprocess (zbar_decoder_t *dcode,
RyoheiHagimoto 0:56c5742b9e2b 565 zbar_symbol_type_t sym)
RyoheiHagimoto 0:56c5742b9e2b 566 {
RyoheiHagimoto 0:56c5742b9e2b 567 ean_decoder_t *ean = &dcode->ean;
RyoheiHagimoto 0:56c5742b9e2b 568 zbar_symbol_type_t base = sym & ZBAR_SYMBOL;
RyoheiHagimoto 0:56c5742b9e2b 569 int i = 0, j = 0;
RyoheiHagimoto 0:56c5742b9e2b 570 if(base > ZBAR_PARTIAL) {
RyoheiHagimoto 0:56c5742b9e2b 571 if(base == ZBAR_UPCA)
RyoheiHagimoto 0:56c5742b9e2b 572 i = 1;
RyoheiHagimoto 0:56c5742b9e2b 573 else if(base == ZBAR_UPCE) {
RyoheiHagimoto 0:56c5742b9e2b 574 i = 1;
RyoheiHagimoto 0:56c5742b9e2b 575 base--;
RyoheiHagimoto 0:56c5742b9e2b 576 }
RyoheiHagimoto 0:56c5742b9e2b 577 else if(base == ZBAR_ISBN13)
RyoheiHagimoto 0:56c5742b9e2b 578 base = ZBAR_EAN13;
RyoheiHagimoto 0:56c5742b9e2b 579 else if(base == ZBAR_ISBN10)
RyoheiHagimoto 0:56c5742b9e2b 580 i = 3;
RyoheiHagimoto 0:56c5742b9e2b 581
RyoheiHagimoto 0:56c5742b9e2b 582 if(base == ZBAR_ISBN10 ||
RyoheiHagimoto 0:56c5742b9e2b 583 !TEST_CFG(ean_get_config(ean, sym), ZBAR_CFG_EMIT_CHECK))
RyoheiHagimoto 0:56c5742b9e2b 584 base--;
RyoheiHagimoto 0:56c5742b9e2b 585
RyoheiHagimoto 0:56c5742b9e2b 586 for(; j < base && ean->buf[i] >= 0; i++, j++)
RyoheiHagimoto 0:56c5742b9e2b 587 dcode->buf[j] = ean->buf[i] + '0';
RyoheiHagimoto 0:56c5742b9e2b 588
RyoheiHagimoto 0:56c5742b9e2b 589 if((sym & ZBAR_SYMBOL) == ZBAR_ISBN10 && j == 9 &&
RyoheiHagimoto 0:56c5742b9e2b 590 TEST_CFG(ean->isbn10_config, ZBAR_CFG_EMIT_CHECK))
RyoheiHagimoto 0:56c5742b9e2b 591 /* recalculate ISBN-10 check digit */
RyoheiHagimoto 0:56c5742b9e2b 592 dcode->buf[j++] = isbn10_calc_checksum(ean);
RyoheiHagimoto 0:56c5742b9e2b 593 }
RyoheiHagimoto 0:56c5742b9e2b 594 if(sym & ZBAR_ADDON)
RyoheiHagimoto 0:56c5742b9e2b 595 for(i = 13; ean->buf[i] >= 0; i++, j++)
RyoheiHagimoto 0:56c5742b9e2b 596 dcode->buf[j] = ean->buf[i] + '0';
RyoheiHagimoto 0:56c5742b9e2b 597 dcode->buflen = j;
RyoheiHagimoto 0:56c5742b9e2b 598 dcode->buf[j] = '\0';
RyoheiHagimoto 0:56c5742b9e2b 599 }
RyoheiHagimoto 0:56c5742b9e2b 600
RyoheiHagimoto 0:56c5742b9e2b 601 zbar_symbol_type_t _zbar_decode_ean (zbar_decoder_t *dcode)
RyoheiHagimoto 0:56c5742b9e2b 602 {
RyoheiHagimoto 0:56c5742b9e2b 603 /* process upto 4 separate passes */
RyoheiHagimoto 0:56c5742b9e2b 604 zbar_symbol_type_t sym = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 605 unsigned char pass_idx = dcode->idx & 3;
RyoheiHagimoto 0:56c5742b9e2b 606
RyoheiHagimoto 0:56c5742b9e2b 607 /* update latest character width */
RyoheiHagimoto 0:56c5742b9e2b 608 dcode->ean.s4 -= get_width(dcode, 4);
RyoheiHagimoto 0:56c5742b9e2b 609 dcode->ean.s4 += get_width(dcode, 0);
RyoheiHagimoto 0:56c5742b9e2b 610
RyoheiHagimoto 0:56c5742b9e2b 611 unsigned char i;
RyoheiHagimoto 0:56c5742b9e2b 612 for(i = 0; i < 4; i++) {
RyoheiHagimoto 0:56c5742b9e2b 613 ean_pass_t *pass = &dcode->ean.pass[i];
RyoheiHagimoto 0:56c5742b9e2b 614 if(pass->state >= 0 ||
RyoheiHagimoto 0:56c5742b9e2b 615 i == pass_idx)
RyoheiHagimoto 0:56c5742b9e2b 616 {
RyoheiHagimoto 0:56c5742b9e2b 617 dprintf(2, " ean[%x/%x]: idx=%x st=%d s=%d",
RyoheiHagimoto 0:56c5742b9e2b 618 pass_idx, i, dcode->idx, pass->state, dcode->ean.s4);
RyoheiHagimoto 0:56c5742b9e2b 619 zbar_symbol_type_t part = decode_pass(dcode, pass);
RyoheiHagimoto 0:56c5742b9e2b 620 if(part) {
RyoheiHagimoto 0:56c5742b9e2b 621 /* update accumulated data from new partial decode */
RyoheiHagimoto 0:56c5742b9e2b 622 sym = integrate_partial(&dcode->ean, pass, part);
RyoheiHagimoto 0:56c5742b9e2b 623 if(sym) {
RyoheiHagimoto 0:56c5742b9e2b 624 /* this pass valid => _reset_ all passes */
RyoheiHagimoto 0:56c5742b9e2b 625 dprintf(2, " sym=%x", sym);
RyoheiHagimoto 0:56c5742b9e2b 626 dcode->ean.pass[0].state = dcode->ean.pass[1].state = -1;
RyoheiHagimoto 0:56c5742b9e2b 627 dcode->ean.pass[2].state = dcode->ean.pass[3].state = -1;
RyoheiHagimoto 0:56c5742b9e2b 628 if(sym > ZBAR_PARTIAL) {
RyoheiHagimoto 0:56c5742b9e2b 629 if(!get_lock(dcode, ZBAR_EAN13))
RyoheiHagimoto 0:56c5742b9e2b 630 postprocess(dcode, sym);
RyoheiHagimoto 0:56c5742b9e2b 631 else {
RyoheiHagimoto 0:56c5742b9e2b 632 dprintf(1, " [locked %d]", dcode->lock);
RyoheiHagimoto 0:56c5742b9e2b 633 sym = ZBAR_PARTIAL;
RyoheiHagimoto 0:56c5742b9e2b 634 }
RyoheiHagimoto 0:56c5742b9e2b 635 }
RyoheiHagimoto 0:56c5742b9e2b 636 }
RyoheiHagimoto 0:56c5742b9e2b 637 }
RyoheiHagimoto 0:56c5742b9e2b 638 dprintf(2, "\n");
RyoheiHagimoto 0:56c5742b9e2b 639 }
RyoheiHagimoto 0:56c5742b9e2b 640 }
RyoheiHagimoto 0:56c5742b9e2b 641 return(sym);
RyoheiHagimoto 0:56c5742b9e2b 642 }
RyoheiHagimoto 0:56c5742b9e2b 643