Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: GR-PEACH_Camera_in_barcode levkov_ov7670
zbar/decoder/ean.c@1:500d42699c34, 2016-04-19 (annotated)
- 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?
User | Revision | Line number | New 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 |