A streamlined version (for embedded use) of Jeff Brown's ZBar library. Visit <http://zbar.sourceforge.net> for more details.

Dependents:   BarcodeReader_F103

Committer:
hudakz
Date:
Fri Jan 10 20:29:52 2020 +0000
Revision:
0:e33621169e44
Streamlined barcode reader library.

Who changed what in which revision?

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