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
code128.c
00001 /*------------------------------------------------------------------------ 00002 * Copyright 2007-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_CODE128 00031 # define DEBUG_LEVEL (DEBUG_CODE128) 00032 #endif 00033 #include "zbar_debug.h" 00034 00035 #define NUM_CHARS 108 /* total number of character codes */ 00036 00037 typedef enum code128_char_e { 00038 FNC3 = 0x60, 00039 FNC2 = 0x61, 00040 SHIFT = 0x62, 00041 CODE_C = 0x63, 00042 CODE_B = 0x64, 00043 CODE_A = 0x65, 00044 FNC1 = 0x66, 00045 START_A = 0x67, 00046 START_B = 0x68, 00047 START_C = 0x69, 00048 STOP_FWD = 0x6a, 00049 STOP_REV = 0x6b, 00050 FNC4 = 0x6c, 00051 } code128_char_t; 00052 00053 static const unsigned char characters[NUM_CHARS] = { 00054 0x5c, 0xbf, 0xa1, /* [00] 00 */ 00055 0x2a, 0xc5, 0x0c, 0xa4, /* [03] 01 */ 00056 0x2d, 0xe3, 0x0f, /* [07] 02 */ 00057 0x5f, 0xe4, /* [0a] 03 */ 00058 00059 0x6b, 0xe8, 0x69, 0xa7, 0xe7, /* [0c] 10 */ 00060 0xc1, 0x51, 0x1e, 0x83, 0xd9, 0x00, 0x84, 0x1f, /* [11] 11 */ 00061 0xc7, 0x0d, 0x33, 0x86, 0xb5, 0x0e, 0x15, 0x87, /* [19] 12 */ 00062 0x10, 0xda, 0x11, /* [21] 13 */ 00063 00064 0x36, 0xe5, 0x18, 0x37, /* [24] 20 */ 00065 0xcc, 0x13, 0x39, 0x89, 0x97, 0x14, 0x1b, 0x8a, 0x3a, 0xbd, /* [28] 21 */ 00066 0xa2, 0x5e, 0x01, 0x85, 0xb0, 0x02, 0xa3, /* [32] 22 */ 00067 0xa5, 0x2c, 0x16, 0x88, 0xbc, 0x12, 0xa6, /* [39] 23 */ 00068 00069 0x61, 0xe6, 0x56, 0x62, /* [40] 30 */ 00070 0x19, 0xdb, 0x1a, /* [44] 31 */ 00071 0xa8, 0x32, 0x1c, 0x8b, 0xcd, 0x1d, 0xa9, /* [47] 32 */ 00072 0xc3, 0x20, 0xc4, /* [4e] 33 */ 00073 00074 0x50, 0x5d, 0xc0, /* [51] 0014 0025 0034 */ 00075 0x2b, 0xc6, /* [54] 0134 0143 */ 00076 0x2e, /* [56] 0243 */ 00077 0x53, 0x60, /* [57] 0341 0352 */ 00078 0x31, /* [59] 1024 */ 00079 0x52, 0xc2, /* [5a] 1114 1134 */ 00080 0x34, 0xc8, /* [5c] 1242 1243 */ 00081 0x55, /* [5e] 1441 */ 00082 00083 0x57, 0x3e, 0xce, /* [5f] 4100 5200 4300 */ 00084 0x3b, 0xc9, /* [62] 4310 3410 */ 00085 0x6a, /* [64] 3420 */ 00086 0x54, 0x4f, /* [65] 1430 2530 */ 00087 0x38, /* [67] 4201 */ 00088 0x58, 0xcb, /* [68] 4111 4311 */ 00089 0x2f, 0xca, /* [6a] 2421 3421 */ 00090 }; 00091 00092 static const unsigned char lo_base[8] = { 00093 0x00, 0x07, 0x0c, 0x19, 0x24, 0x32, 0x40, 0x47 00094 }; 00095 00096 static const unsigned char lo_offset[0x80] = { 00097 0xff, 0xf0, 0xff, 0x1f, 0xff, 0xf2, 0xff, 0xff, /* 00 [00] */ 00098 0xff, 0xff, 0xff, 0x3f, 0xf4, 0xf5, 0xff, 0x6f, /* 01 */ 00099 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf1, 0xff, 0x2f, /* 02 [07] */ 00100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x4f, /* 03 */ 00101 0xff, 0x0f, 0xf1, 0xf2, 0xff, 0x3f, 0xff, 0xf4, /* 10 [0c] */ 00102 0xf5, 0xf6, 0xf7, 0x89, 0xff, 0xab, 0xff, 0xfc, /* 11 */ 00103 0xff, 0xff, 0x0f, 0x1f, 0x23, 0x45, 0xf6, 0x7f, /* 12 [19] */ 00104 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf9, 0xaf, /* 13 */ 00105 00106 0xf0, 0xf1, 0xff, 0x2f, 0xff, 0xf3, 0xff, 0xff, /* 20 [24] */ 00107 0x4f, 0x5f, 0x67, 0x89, 0xfa, 0xbf, 0xff, 0xcd, /* 21 */ 00108 0xf0, 0xf1, 0xf2, 0x3f, 0xf4, 0x56, 0xff, 0xff, /* 22 [32] */ 00109 0xff, 0xff, 0x7f, 0x8f, 0x9a, 0xff, 0xbc, 0xdf, /* 23 */ 00110 0x0f, 0x1f, 0xf2, 0xff, 0xff, 0x3f, 0xff, 0xff, /* 30 [40] */ 00111 0xf4, 0xff, 0xf5, 0x6f, 0xff, 0xff, 0xff, 0xff, /* 31 */ 00112 0x0f, 0x1f, 0x23, 0xff, 0x45, 0x6f, 0xff, 0xff, /* 32 [47] */ 00113 0xf7, 0xff, 0xf8, 0x9f, 0xff, 0xff, 0xff, 0xff, /* 33 */ 00114 }; 00115 00116 static inline signed char decode_lo (int sig) 00117 { 00118 unsigned char offset = (((sig >> 1) & 0x01) | 00119 ((sig >> 3) & 0x06) | 00120 ((sig >> 5) & 0x18) | 00121 ((sig >> 7) & 0x60)); 00122 unsigned char idx = lo_offset[offset]; 00123 if(sig & 1) 00124 idx &= 0xf; 00125 else 00126 idx >>= 4; 00127 if(idx == 0xf) 00128 return(-1); 00129 00130 unsigned char base = (sig >> 11) | ((sig >> 9) & 1); 00131 zassert(base < 8, -1, "sig=%x offset=%x idx=%x base=%x\n", 00132 sig, offset, idx, base); 00133 idx += lo_base[base]; 00134 00135 zassert(idx <= 0x50, -1, "sig=%x offset=%x base=%x idx=%x\n", 00136 sig, offset, base, idx); 00137 unsigned char c = characters[idx]; 00138 dprintf(2, " %02x(%x(%02x)/%x(%02x)) => %02x", 00139 idx, base, lo_base[base], offset, lo_offset[offset], 00140 (unsigned char)c); 00141 return(c); 00142 } 00143 00144 static inline signed char decode_hi (int sig) 00145 { 00146 unsigned char rev = (sig & 0x4400) != 0; 00147 if(rev) 00148 sig = (((sig >> 12) & 0x000f) | 00149 ((sig >> 4) & 0x00f0) | 00150 ((sig << 4) & 0x0f00) | 00151 ((sig << 12) & 0xf000)); 00152 dprintf(2, " rev=%x", rev != 0); 00153 00154 unsigned char idx; 00155 switch(sig) { 00156 case 0x0014: idx = 0x0; break; 00157 case 0x0025: idx = 0x1; break; 00158 case 0x0034: idx = 0x2; break; 00159 case 0x0134: idx = 0x3; break; 00160 case 0x0143: idx = 0x4; break; 00161 case 0x0243: idx = 0x5; break; 00162 case 0x0341: idx = 0x6; break; 00163 case 0x0352: idx = 0x7; break; 00164 case 0x1024: idx = 0x8; break; 00165 case 0x1114: idx = 0x9; break; 00166 case 0x1134: idx = 0xa; break; 00167 case 0x1242: idx = 0xb; break; 00168 case 0x1243: idx = 0xc; break; 00169 case 0x1441: idx = 0xd; rev = 0; break; 00170 default: return(-1); 00171 } 00172 if(rev) 00173 idx += 0xe; 00174 unsigned char c = characters[0x51 + idx]; 00175 dprintf(2, " %02x => %02x", idx, c); 00176 return(c); 00177 } 00178 00179 static inline unsigned char calc_check (unsigned char c) 00180 { 00181 if(!(c & 0x80)) 00182 return(0x18); 00183 c &= 0x7f; 00184 if(c < 0x3d) 00185 return((c < 0x30 && c != 0x17) ? 0x10 : 0x20); 00186 if(c < 0x50) 00187 return((c == 0x4d) ? 0x20 : 0x10); 00188 return((c < 0x67) ? 0x20 : 0x10); 00189 } 00190 00191 static inline signed char decode6 (zbar_decoder_t *dcode) 00192 { 00193 /* build edge signature of character */ 00194 unsigned s = dcode->code128.s6; 00195 dprintf(2, " s=%d", s); 00196 if(s < 5) 00197 return(-1); 00198 /* calculate similar edge measurements */ 00199 int sig = (get_color(dcode) == ZBAR_BAR) 00200 ? ((decode_e(get_width(dcode, 0) + get_width(dcode, 1), s, 11) << 12) | 00201 (decode_e(get_width(dcode, 1) + get_width(dcode, 2), s, 11) << 8) | 00202 (decode_e(get_width(dcode, 2) + get_width(dcode, 3), s, 11) << 4) | 00203 (decode_e(get_width(dcode, 3) + get_width(dcode, 4), s, 11))) 00204 : ((decode_e(get_width(dcode, 5) + get_width(dcode, 4), s, 11) << 12) | 00205 (decode_e(get_width(dcode, 4) + get_width(dcode, 3), s, 11) << 8) | 00206 (decode_e(get_width(dcode, 3) + get_width(dcode, 2), s, 11) << 4) | 00207 (decode_e(get_width(dcode, 2) + get_width(dcode, 1), s, 11))); 00208 if(sig < 0) 00209 return(-1); 00210 dprintf(2, " sig=%04x", sig); 00211 /* lookup edge signature */ 00212 signed char c = (sig & 0x4444) ? decode_hi(sig) : decode_lo(sig); 00213 if(c == -1) 00214 return(-1); 00215 00216 /* character validation */ 00217 unsigned bars = (get_color(dcode) == ZBAR_BAR) 00218 ? (get_width(dcode, 0) + get_width(dcode, 2) + get_width(dcode, 4)) 00219 : (get_width(dcode, 1) + get_width(dcode, 3) + get_width(dcode, 5)); 00220 bars = bars * 11 * 4 / s; 00221 unsigned char chk = calc_check(c); 00222 dprintf(2, " bars=%d chk=%d", bars, chk); 00223 if(chk - 7 > bars || bars > chk + 7) 00224 return(-1); 00225 00226 return(c & 0x7f); 00227 } 00228 00229 static inline unsigned char validate_checksum (zbar_decoder_t *dcode) 00230 { 00231 code128_decoder_t *dcode128 = &dcode->code128; 00232 if(dcode128->character < 3) 00233 return(1); 00234 00235 /* add in irregularly weighted start character */ 00236 unsigned idx = (dcode128->direction) ? dcode128->character - 1 : 0; 00237 unsigned sum = dcode->buf[idx]; 00238 if(sum >= 103) 00239 sum -= 103; 00240 00241 /* calculate sum in reverse to avoid multiply operations */ 00242 unsigned i, acc = 0; 00243 for(i = dcode128->character - 3; i; i--) { 00244 zassert(sum < 103, -1, "dir=%x i=%x sum=%x acc=%x %s\n", 00245 dcode128->direction, i, sum, acc, 00246 _zbar_decoder_buf_dump(dcode->buf, dcode128->character)); 00247 idx = (dcode128->direction) ? dcode128->character - 1 - i : i; 00248 acc += dcode->buf[idx]; 00249 if(acc >= 103) 00250 acc -= 103; 00251 zassert(acc < 103, -1, "dir=%x i=%x sum=%x acc=%x %s\n", 00252 dcode128->direction, i, sum, acc, 00253 _zbar_decoder_buf_dump(dcode->buf, dcode128->character)); 00254 sum += acc; 00255 if(sum >= 103) 00256 sum -= 103; 00257 } 00258 00259 /* and compare to check character */ 00260 idx = (dcode128->direction) ? 1 : dcode128->character - 2; 00261 unsigned char check = dcode->buf[idx]; 00262 dprintf(2, " chk=%02x(%02x)", sum, check); 00263 unsigned char err = (sum != check); 00264 if(err) 00265 dprintf(1, " [checksum error]\n"); 00266 return(err); 00267 } 00268 00269 /* expand and decode character set C */ 00270 static inline unsigned postprocess_c (zbar_decoder_t *dcode, 00271 unsigned start, 00272 unsigned end, 00273 unsigned dst) 00274 { 00275 /* expand buffer to accomodate 2x set C characters (2 digits per-char) */ 00276 unsigned delta = end - start; 00277 unsigned newlen = dcode->code128.character + delta; 00278 size_buf(dcode, newlen); 00279 00280 /* relocate unprocessed data to end of buffer */ 00281 memmove(dcode->buf + start + delta, dcode->buf + start, 00282 dcode->code128.character - start); 00283 dcode->code128.character = newlen; 00284 00285 unsigned i, j; 00286 for(i = 0, j = dst; i < delta; i++, j += 2) { 00287 /* convert each set C character into two ASCII digits */ 00288 unsigned char code = dcode->buf[start + delta + i]; 00289 dcode->buf[j] = '0'; 00290 if(code >= 50) { 00291 code -= 50; 00292 dcode->buf[j] += 5; 00293 } 00294 if(code >= 30) { 00295 code -= 30; 00296 dcode->buf[j] += 3; 00297 } 00298 if(code >= 20) { 00299 code -= 20; 00300 dcode->buf[j] += 2; 00301 } 00302 if(code >= 10) { 00303 code -= 10; 00304 dcode->buf[j] += 1; 00305 } 00306 zassert(dcode->buf[j] <= '9', delta, 00307 "start=%x end=%x i=%x j=%x %s\n", start, end, i, j, 00308 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00309 zassert(code <= 9, delta, 00310 "start=%x end=%x i=%x j=%x %s\n", start, end, i, j, 00311 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00312 dcode->buf[j + 1] = '0' + code; 00313 } 00314 return(delta); 00315 } 00316 00317 /* resolve scan direction and convert to ASCII */ 00318 static inline unsigned char postprocess (zbar_decoder_t *dcode) 00319 { 00320 code128_decoder_t *dcode128 = &dcode->code128; 00321 dprintf(2, "\n postproc len=%d", dcode128->character); 00322 unsigned i, j; 00323 unsigned char code = 0; 00324 if(dcode128->direction) { 00325 /* reverse buffer */ 00326 dprintf(2, " (rev)"); 00327 for(i = 0; i < dcode128->character / 2; i++) { 00328 unsigned j = dcode128->character - 1 - i; 00329 code = dcode->buf[i]; 00330 dcode->buf[i] = dcode->buf[j]; 00331 dcode->buf[j] = code; 00332 } 00333 zassert(dcode->buf[dcode128->character - 1] == STOP_REV, 1, 00334 "dir=%x %s\n", dcode128->direction, 00335 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00336 } 00337 else 00338 zassert(dcode->buf[dcode128->character - 1] == STOP_FWD, 1, 00339 "dir=%x %s\n", dcode128->direction, 00340 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00341 00342 code = dcode->buf[0]; 00343 zassert(code >= START_A && code <= START_C, 1, "%s\n", 00344 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00345 00346 unsigned char charset = code - START_A; 00347 unsigned cexp = (code == START_C) ? 1 : 0; 00348 dprintf(2, " start=%c", 'A' + charset); 00349 00350 for(i = 1, j = 0; i < dcode128->character - 2; i++) { 00351 unsigned char code = dcode->buf[i]; 00352 zassert(!(code & 0x80), 1, 00353 "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", 00354 i, j, code, charset, cexp, 00355 _zbar_decoder_buf_dump(dcode->buf, dcode->code128.character)); 00356 00357 if((charset & 0x2) && (code < 100)) 00358 /* defer character set C for expansion */ 00359 continue; 00360 else if(code < 0x60) { 00361 /* convert character set B to ASCII */ 00362 code = code + 0x20; 00363 if((!charset || (charset == 0x81)) && (code >= 0x60)) 00364 /* convert character set A to ASCII */ 00365 code -= 0x60; 00366 dcode->buf[j++] = code; 00367 if(charset & 0x80) 00368 charset &= 0x7f; 00369 } 00370 else { 00371 dprintf(2, " %02x", code); 00372 if(charset & 0x2) { 00373 /* expand character set C to ASCII */ 00374 zassert(cexp, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", 00375 i, j, code, charset, cexp, 00376 _zbar_decoder_buf_dump(dcode->buf, 00377 dcode->code128.character)); 00378 unsigned delta = postprocess_c(dcode, cexp, i, j); 00379 i += delta; 00380 j += delta * 2; 00381 cexp = 0; 00382 } 00383 if(code < CODE_C) { 00384 if(code == SHIFT) 00385 charset |= 0x80; 00386 else if(code == FNC2) 00387 /* FIXME FNC2 - message append */; 00388 else if(code == FNC3) 00389 /* FIXME FNC3 - initialize */; 00390 } 00391 else if(code == FNC1) 00392 /* FIXME FNC1 - Code 128 subsets or ASCII 0x1d */; 00393 else if(code >= START_A) { 00394 dprintf(1, " [truncated]\n"); 00395 return(1); 00396 } 00397 else { 00398 zassert(code >= CODE_C && code <= CODE_A, 1, 00399 "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", 00400 i, j, code, charset, cexp, 00401 _zbar_decoder_buf_dump(dcode->buf, 00402 dcode->code128.character)); 00403 unsigned char newset = CODE_A - code; 00404 if(newset != charset) 00405 charset = newset; 00406 else 00407 /* FIXME FNC4 - extended ASCII */; 00408 } 00409 if(charset & 0x2) 00410 cexp = i + 1; 00411 } 00412 } 00413 if(charset & 0x2) { 00414 zassert(cexp, 1, "i=%x j=%x code=%02x charset=%x cexp=%x %s\n", 00415 i, j, code, charset, cexp, 00416 _zbar_decoder_buf_dump(dcode->buf, 00417 dcode->code128.character)); 00418 j += postprocess_c(dcode, cexp, i, j) * 2; 00419 } 00420 dcode->buflen = j; 00421 dcode->buf[j] = '\0'; 00422 dcode->code128.character = j; 00423 return(0); 00424 } 00425 00426 zbar_symbol_type_t _zbar_decode_code128 (zbar_decoder_t *dcode) 00427 { 00428 code128_decoder_t *dcode128 = &dcode->code128; 00429 00430 /* update latest character width */ 00431 dcode128->s6 -= get_width(dcode, 6); 00432 dcode128->s6 += get_width(dcode, 0); 00433 00434 if(/* process every 6th element of active symbol */ 00435 (dcode128->character >= 0 && 00436 (++dcode128->element) != 6) || 00437 /* decode color based on direction */ 00438 (get_color(dcode) != dcode128->direction)) 00439 return(0); 00440 dcode128->element = 0; 00441 00442 dprintf(2, " code128[%c%02d+%x]:", 00443 (dcode128->direction) ? '<' : '>', 00444 dcode128->character, dcode128->element); 00445 00446 signed char c = decode6(dcode); 00447 if(dcode128->character < 0) { 00448 dprintf(2, " c=%02x", c); 00449 if(c < START_A || c > STOP_REV || c == STOP_FWD) { 00450 dprintf(2, " [invalid]\n"); 00451 return(0); 00452 } 00453 unsigned qz = get_width(dcode, 6); 00454 if(qz && qz < (dcode->code128.s6 * 3) / 4) { 00455 dprintf(2, " [invalid qz %d]\n", qz); 00456 return(0); 00457 } 00458 /* lock shared resources */ 00459 if(get_lock(dcode, ZBAR_CODE128)) { 00460 dprintf(2, " [locked %d]\n", dcode->lock); 00461 dcode128->character = -1; 00462 return(0); 00463 } 00464 /* decoded valid start/stop */ 00465 /* initialize state */ 00466 dcode128->character = 0; 00467 if(c == STOP_REV) { 00468 dcode128->direction = ZBAR_BAR; 00469 dcode128->element = 7; 00470 } 00471 else 00472 dcode128->direction = ZBAR_SPACE; 00473 dprintf(2, " dir=%x [valid start]", dcode128->direction); 00474 } 00475 else if((c < 0) || 00476 ((dcode128->character >= BUFFER_MIN) && 00477 size_buf(dcode, dcode128->character + 1))) { 00478 dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); 00479 dcode->lock = 0; 00480 dcode128->character = -1; 00481 return(0); 00482 } 00483 00484 zassert(dcode->buf_alloc > dcode128->character, 0, 00485 "alloc=%x idx=%x c=%02x %s\n", 00486 dcode->buf_alloc, dcode128->character, c, 00487 _zbar_decoder_buf_dump(dcode->buf, dcode->buf_alloc)); 00488 00489 dcode->buf[dcode128->character++] = c; 00490 00491 if(dcode128->character > 2 && 00492 ((dcode128->direction) 00493 ? c >= START_A && c <= START_C 00494 : c == STOP_FWD)) { 00495 /* FIXME STOP_FWD should check extra bar (and QZ!) */ 00496 zbar_symbol_type_t sym = ZBAR_CODE128; 00497 if(validate_checksum(dcode) || postprocess(dcode)) 00498 sym = ZBAR_NONE; 00499 else if(dcode128->character < CFG(*dcode128, ZBAR_CFG_MIN_LEN) || 00500 (CFG(*dcode128, ZBAR_CFG_MAX_LEN) > 0 && 00501 dcode128->character > CFG(*dcode128, ZBAR_CFG_MAX_LEN))) { 00502 dprintf(2, " [invalid len]\n"); 00503 sym = ZBAR_NONE; 00504 } 00505 else 00506 dprintf(2, " [valid end]\n"); 00507 dcode128->character = -1; 00508 if(!sym) 00509 dcode->lock = 0; 00510 return(sym); 00511 } 00512 00513 dprintf(2, "\n"); 00514 return(0); 00515 } 00516
Generated on Tue Jul 12 2022 18:54:12 by 1.7.2