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

LICENSE

The ZBar Bar Code Reader is Copyright (C) 2007-2009 Jeff Brown <spadix@users.sourceforge.net> The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry <tterribe@xiph.org>

You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

ISAAC is based on the public domain implementation by Robert J. Jenkins Jr., and is itself public domain.

Portions of the bit stream reader are copyright (C) The Xiph.Org Foundation 1994-2008, and are licensed under a BSD-style license.

The Reed-Solomon decoder is derived from an implementation (C) 1991-1995 Henry Minsky (hqm@ua.com, hqm@ai.mit.edu), and is licensed under the LGPL with permission.

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