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
code39.c
00001 /*------------------------------------------------------------------------ 00002 * Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net> 00003 * 00004 * This file is part of the ZBar Bar Code Reader. 00005 * 00006 * The ZBar Bar Code Reader is free software; you can redistribute it 00007 * and/or modify it under the terms of the GNU Lesser Public License as 00008 * published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * The ZBar Bar Code Reader is distributed in the hope that it will be 00012 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00013 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser Public License 00017 * along with the ZBar Bar Code Reader; if not, write to the Free 00018 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, 00019 * Boston, MA 02110-1301 USA 00020 * 00021 * http://sourceforge.net/projects/zbar 00022 *------------------------------------------------------------------------*/ 00023 00024 #include <config.h> 00025 #include <string.h> /* memmove */ 00026 00027 #include <zbar.h> 00028 #include "decoder.h" 00029 00030 #ifdef DEBUG_CODE39 00031 # define DEBUG_LEVEL (DEBUG_CODE39) 00032 #endif 00033 #include "zbar_debug.h" 00034 00035 #define NUM_CHARS (0x2c) 00036 00037 static const unsigned char code39_hi[32] = { 00038 0x80 | 0x00, /* 2 next */ 00039 0x40 | 0x02, /* 4 */ 00040 0x80 | 0x06, /* 2 next */ 00041 0xc0 | 0x08, /* 2 skip */ 00042 0x40 | 0x0a, /* 4 */ 00043 0x80 | 0x0e, /* 2 next */ 00044 0xc0 | 0x10, /* 2 skip */ 00045 0x00 | 0x12, /* direct */ 00046 00047 0x80 | 0x13, /* 2 next */ 00048 0xc0 | 0x15, /* 2 skip */ 00049 0x80 | 0x17, /* 2 next */ 00050 0xff, 00051 0xc0 | 0x19, /* 2 skip */ 00052 0x00 | 0x1b, /* direct */ 00053 0xff, 00054 0xff, 00055 00056 0x40 | 0x1c, /* 4 */ 00057 0x80 | 0x20, /* 2 next */ 00058 0xc0 | 0x22, /* 2 skip */ 00059 0x00 | 0x24, /* direct */ 00060 0x80 | 0x25, /* 2 next */ 00061 0xff, 00062 0x00 | 0x27, /* direct */ 00063 0xff, 00064 00065 0xc0 | 0x28, /* 2 skip */ 00066 0x00 | 0x2a, /* direct */ 00067 0xff, 00068 0xff, 00069 0x00 | 0x2b, /* direct */ 00070 0xff, 00071 0xff, 00072 0xff, 00073 }; 00074 00075 typedef struct char39_s { 00076 unsigned char chk, rev, fwd; 00077 } char39_t; 00078 00079 static const char39_t code39_encodings[NUM_CHARS] = { 00080 { 0x07, 0x1a, 0x20 }, /* 00 */ 00081 { 0x0d, 0x10, 0x03 }, /* 01 */ 00082 { 0x13, 0x17, 0x22 }, /* 02 */ 00083 { 0x16, 0x1d, 0x23 }, /* 03 */ 00084 { 0x19, 0x0d, 0x05 }, /* 04 */ 00085 { 0x1c, 0x13, 0x06 }, /* 05 */ 00086 { 0x25, 0x07, 0x0c }, /* 06 */ 00087 { 0x2a, 0x2a, 0x27 }, /* 07 */ 00088 { 0x31, 0x04, 0x0e }, /* 08 */ 00089 { 0x34, 0x00, 0x0f }, /* 09 */ 00090 { 0x43, 0x15, 0x25 }, /* 0a */ 00091 { 0x46, 0x1c, 0x26 }, /* 0b */ 00092 { 0x49, 0x0b, 0x08 }, /* 0c */ 00093 { 0x4c, 0x12, 0x09 }, /* 0d */ 00094 { 0x52, 0x19, 0x2b }, /* 0e */ 00095 { 0x58, 0x0f, 0x00 }, /* 0f */ 00096 { 0x61, 0x02, 0x11 }, /* 10 */ 00097 { 0x64, 0x09, 0x12 }, /* 11 */ 00098 { 0x70, 0x06, 0x13 }, /* 12 */ 00099 { 0x85, 0x24, 0x16 }, /* 13 */ 00100 { 0x8a, 0x29, 0x28 }, /* 14 */ 00101 { 0x91, 0x21, 0x18 }, /* 15 */ 00102 { 0x94, 0x2b, 0x19 }, /* 16 */ 00103 { 0xa2, 0x28, 0x29 }, /* 17 */ 00104 { 0xa8, 0x27, 0x2a }, /* 18 */ 00105 { 0xc1, 0x1f, 0x1b }, /* 19 */ 00106 { 0xc4, 0x26, 0x1c }, /* 1a */ 00107 { 0xd0, 0x23, 0x1d }, /* 1b */ 00108 { 0x03, 0x14, 0x1e }, /* 1c */ 00109 { 0x06, 0x1b, 0x1f }, /* 1d */ 00110 { 0x09, 0x0a, 0x01 }, /* 1e */ 00111 { 0x0c, 0x11, 0x02 }, /* 1f */ 00112 { 0x12, 0x18, 0x21 }, /* 20 */ 00113 { 0x18, 0x0e, 0x04 }, /* 21 */ 00114 { 0x21, 0x01, 0x0a }, /* 22 */ 00115 { 0x24, 0x08, 0x0b }, /* 23 */ 00116 { 0x30, 0x05, 0x0d }, /* 24 */ 00117 { 0x42, 0x16, 0x24 }, /* 25 */ 00118 { 0x48, 0x0c, 0x07 }, /* 26 */ 00119 { 0x60, 0x03, 0x10 }, /* 27 */ 00120 { 0x81, 0x1e, 0x14 }, /* 28 */ 00121 { 0x84, 0x25, 0x15 }, /* 29 */ 00122 { 0x90, 0x22, 0x17 }, /* 2a */ 00123 { 0xc0, 0x20, 0x1a }, /* 2b */ 00124 }; 00125 00126 static const unsigned char code39_characters[NUM_CHARS] = 00127 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*"; 00128 00129 static inline unsigned char code39_decode1 (unsigned char enc, 00130 unsigned e, 00131 unsigned s) 00132 { 00133 unsigned char E = decode_e(e, s, 36); 00134 if(E > 7) 00135 return(0xff); 00136 enc <<= 1; 00137 if(E > 2) { 00138 enc |= 1; 00139 dprintf(2, "1"); 00140 } 00141 else 00142 dprintf(2, "0"); 00143 return(enc); 00144 } 00145 00146 static inline signed char code39_decode9 (zbar_decoder_t *dcode) 00147 { 00148 code39_decoder_t *dcode39 = &dcode->code39; 00149 00150 dprintf(2, " s=%d ", dcode39->s9); 00151 if(dcode39->s9 < 9) 00152 return(-1); 00153 00154 /* threshold bar width ratios */ 00155 unsigned char i, enc = 0; 00156 for(i = 0; i < 5; i++) { 00157 enc = code39_decode1(enc, get_width(dcode, i), dcode39->s9); 00158 if(enc == 0xff) 00159 return(-1); 00160 } 00161 zassert(enc < 0x20, -1, " enc=%x s9=%x\n", enc, dcode39->s9); 00162 00163 /* lookup first 5 encoded widths for coarse decode */ 00164 unsigned char idx = code39_hi[enc]; 00165 if(idx == 0xff) 00166 return(-1); 00167 00168 /* encode remaining widths (NB first encoded width is lost) */ 00169 for(; i < 9; i++) { 00170 enc = code39_decode1(enc, get_width(dcode, i), dcode39->s9); 00171 if(enc == 0xff) 00172 return(-1); 00173 } 00174 00175 if((idx & 0xc0) == 0x80) 00176 idx = (idx & 0x3f) + ((enc >> 3) & 1); 00177 else if((idx & 0xc0) == 0xc0) 00178 idx = (idx & 0x3f) + ((enc >> 2) & 1); 00179 else if(idx & 0xc0) 00180 idx = (idx & 0x3f) + ((enc >> 2) & 3); 00181 zassert(idx < 0x2c, -1, " idx=%x enc=%x s9=%x\n", idx, enc, dcode39->s9); 00182 00183 const char39_t *c = &code39_encodings[idx]; 00184 dprintf(2, " i=%02x chk=%02x c=%02x/%02x", idx, c->chk, c->fwd, c->rev); 00185 if(enc != c->chk) 00186 return(-1); 00187 00188 dcode39->width = dcode39->s9; 00189 return((dcode39->direction) ? c->rev : c->fwd); 00190 } 00191 00192 static inline signed char code39_decode_start (zbar_decoder_t *dcode) 00193 { 00194 code39_decoder_t *dcode39 = &dcode->code39; 00195 00196 signed char c = code39_decode9(dcode); 00197 if(c == 0x19) 00198 dcode39->direction ^= 1; 00199 else if(c != 0x2b) { 00200 dprintf(2, "\n"); 00201 return(ZBAR_NONE); 00202 } 00203 00204 /* check leading quiet zone - spec is 10x */ 00205 unsigned quiet = get_width(dcode, 9); 00206 if(quiet && quiet < dcode39->s9 / 2) { 00207 dprintf(2, " [invalid quiet]\n"); 00208 return(ZBAR_NONE); 00209 } 00210 00211 dcode39->element = 9; 00212 dcode39->character = 0; 00213 dprintf(1, " dir=%x [valid start]\n", dcode39->direction); 00214 return(ZBAR_PARTIAL); 00215 } 00216 00217 static inline void code39_postprocess (zbar_decoder_t *dcode) 00218 { 00219 code39_decoder_t *dcode39 = &dcode->code39; 00220 int i; 00221 if(dcode39->direction) { 00222 /* reverse buffer */ 00223 dprintf(2, " (rev)"); 00224 for(i = 0; i < dcode39->character / 2; i++) { 00225 unsigned j = dcode39->character - 1 - i; 00226 char code = dcode->buf[i]; 00227 dcode->buf[i] = dcode->buf[j]; 00228 dcode->buf[j] = code; 00229 } 00230 } 00231 for(i = 0; i < dcode39->character; i++) 00232 dcode->buf[i] = ((dcode->buf[i] < 0x2b) 00233 ? code39_characters[(unsigned)dcode->buf[i]] 00234 : '?'); 00235 dcode->buflen = i; 00236 dcode->buf[i] = '\0'; 00237 } 00238 00239 zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) 00240 { 00241 code39_decoder_t *dcode39 = &dcode->code39; 00242 00243 /* update latest character width */ 00244 dcode39->s9 -= get_width(dcode, 9); 00245 dcode39->s9 += get_width(dcode, 0); 00246 00247 if(dcode39->character < 0) { 00248 if(get_color(dcode) != ZBAR_BAR) 00249 return(ZBAR_NONE); 00250 dprintf(2, " code39:"); 00251 return(code39_decode_start(dcode)); 00252 } 00253 00254 if(++dcode39->element < 9) 00255 return(ZBAR_NONE); 00256 00257 dprintf(2, " code39[%c%02d+%x]", 00258 (dcode39->direction) ? '<' : '>', 00259 dcode39->character, dcode39->element); 00260 00261 if(dcode39->element == 10) { 00262 unsigned space = get_width(dcode, 0); 00263 if(dcode39->character && 00264 dcode->buf[dcode39->character - 1] == 0x2b) { /* STOP */ 00265 /* trim STOP character */ 00266 dcode39->character--; 00267 zbar_symbol_type_t sym = ZBAR_CODE39; 00268 00269 /* trailing quiet zone check */ 00270 if(space && space < dcode39->width / 2) { 00271 dprintf(2, " [invalid qz]\n"); 00272 sym = ZBAR_NONE; 00273 } 00274 else if(dcode39->character < CFG(*dcode39, ZBAR_CFG_MIN_LEN) || 00275 (CFG(*dcode39, ZBAR_CFG_MAX_LEN) > 0 && 00276 dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) { 00277 dprintf(2, " [invalid len]\n"); 00278 sym = ZBAR_NONE; 00279 } 00280 else { 00281 /* FIXME checksum (needs config enable) */ 00282 code39_postprocess(dcode); 00283 dprintf(2, " [valid end]\n"); 00284 } 00285 dcode39->character = -1; 00286 if(!sym) 00287 dcode->lock = 0; 00288 return(sym); 00289 } 00290 if(space > dcode39->width / 2) { 00291 /* inter-character space check failure */ 00292 dcode->lock = 0; 00293 dcode39->character = -1; 00294 dprintf(2, " ics>%d [invalid ics]", dcode39->width); 00295 } 00296 dcode39->element = 0; 00297 dprintf(2, "\n"); 00298 return(ZBAR_NONE); 00299 } 00300 00301 signed char c = code39_decode9(dcode); 00302 dprintf(2, " c=%d", c); 00303 00304 /* lock shared resources */ 00305 if(!dcode39->character && get_lock(dcode, ZBAR_CODE39)) { 00306 dcode39->character = -1; 00307 dprintf(1, " [locked %d]\n", dcode->lock); 00308 return(ZBAR_PARTIAL); 00309 } 00310 00311 if(c < 0 || 00312 ((dcode39->character >= BUFFER_MIN) && 00313 size_buf(dcode, dcode39->character + 1))) { 00314 dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); 00315 dcode->lock = 0; 00316 dcode39->character = -1; 00317 return(ZBAR_NONE); 00318 } 00319 else { 00320 zassert(c < 0x2c, ZBAR_NONE, "c=%02x s9=%x\n", c, dcode39->s9); 00321 dprintf(2, "\n"); 00322 } 00323 00324 dcode->buf[dcode39->character++] = c; 00325 00326 return(ZBAR_NONE); 00327 } 00328
Generated on Tue Jul 12 2022 18:54:12 by 1.7.2