A streamlined version (for embedded use) of Jeff Brown's ZBar library. Visit <http://zbar.sourceforge.net> for more details.
Dependents: BarcodeReader_F103
decoder.h@1:4f5c042a2d34, 2020-01-10 (annotated)
- Committer:
- hudakz
- Date:
- Fri Jan 10 22:06:18 2020 +0000
- Revision:
- 1:4f5c042a2d34
- Parent:
- 0:e33621169e44
Streamlined barcode reader library.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hudakz | 0:e33621169e44 | 1 | /*------------------------------------------------------------------------ |
hudakz | 0:e33621169e44 | 2 | * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net> |
hudakz | 0:e33621169e44 | 3 | * |
hudakz | 0:e33621169e44 | 4 | * This file is part of the ZBar Bar Code Reader. |
hudakz | 0:e33621169e44 | 5 | * |
hudakz | 0:e33621169e44 | 6 | * The ZBar Bar Code Reader is free software; you can redistribute it |
hudakz | 0:e33621169e44 | 7 | * and/or modify it under the terms of the GNU Lesser Public License as |
hudakz | 0:e33621169e44 | 8 | * published by the Free Software Foundation; either version 2.1 of |
hudakz | 0:e33621169e44 | 9 | * the License, or (at your option) any later version. |
hudakz | 0:e33621169e44 | 10 | * |
hudakz | 0:e33621169e44 | 11 | * The ZBar Bar Code Reader is distributed in the hope that it will be |
hudakz | 0:e33621169e44 | 12 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty |
hudakz | 0:e33621169e44 | 13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
hudakz | 0:e33621169e44 | 14 | * GNU Lesser Public License for more details. |
hudakz | 0:e33621169e44 | 15 | * |
hudakz | 0:e33621169e44 | 16 | * You should have received a copy of the GNU Lesser Public License |
hudakz | 0:e33621169e44 | 17 | * along with the ZBar Bar Code Reader; if not, write to the Free |
hudakz | 0:e33621169e44 | 18 | * Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
hudakz | 0:e33621169e44 | 19 | * Boston, MA 02110-1301 USA |
hudakz | 0:e33621169e44 | 20 | * |
hudakz | 0:e33621169e44 | 21 | * http://sourceforge.net/projects/zbar |
hudakz | 0:e33621169e44 | 22 | *------------------------------------------------------------------------*/ |
hudakz | 0:e33621169e44 | 23 | #ifndef _DECODER_H_ |
hudakz | 0:e33621169e44 | 24 | #define _DECODER_H_ |
hudakz | 0:e33621169e44 | 25 | |
hudakz | 0:e33621169e44 | 26 | #include "config.h" |
hudakz | 0:e33621169e44 | 27 | #include <stdlib.h> /* realloc */ |
hudakz | 0:e33621169e44 | 28 | |
hudakz | 0:e33621169e44 | 29 | #include <zbar.h> |
hudakz | 0:e33621169e44 | 30 | |
hudakz | 0:e33621169e44 | 31 | #define NUM_CFGS (ZBAR_CFG_MAX_LEN - ZBAR_CFG_MIN_LEN + 1) |
hudakz | 0:e33621169e44 | 32 | |
hudakz | 0:e33621169e44 | 33 | #ifdef ENABLE_EAN |
hudakz | 0:e33621169e44 | 34 | # include "decoder/ean.h" |
hudakz | 0:e33621169e44 | 35 | #endif |
hudakz | 0:e33621169e44 | 36 | #ifdef ENABLE_I25 |
hudakz | 0:e33621169e44 | 37 | # include "decoder/i25.h" |
hudakz | 0:e33621169e44 | 38 | #endif |
hudakz | 0:e33621169e44 | 39 | #ifdef ENABLE_CODE39 |
hudakz | 0:e33621169e44 | 40 | # include "decoder/code39.h" |
hudakz | 0:e33621169e44 | 41 | #endif |
hudakz | 0:e33621169e44 | 42 | #ifdef ENABLE_CODE128 |
hudakz | 0:e33621169e44 | 43 | # include "decoder/code128.h" |
hudakz | 0:e33621169e44 | 44 | #endif |
hudakz | 0:e33621169e44 | 45 | #ifdef ENABLE_PDF417 |
hudakz | 0:e33621169e44 | 46 | # include "decoder/pdf417.h" |
hudakz | 0:e33621169e44 | 47 | #endif |
hudakz | 0:e33621169e44 | 48 | #ifdef ENABLE_QRCODE |
hudakz | 0:e33621169e44 | 49 | # include "decoder/qr_finder.h" |
hudakz | 0:e33621169e44 | 50 | #endif |
hudakz | 0:e33621169e44 | 51 | |
hudakz | 0:e33621169e44 | 52 | /* size of bar width history (implementation assumes power of two) */ |
hudakz | 0:e33621169e44 | 53 | #ifndef DECODE_WINDOW |
hudakz | 0:e33621169e44 | 54 | # define DECODE_WINDOW 16 |
hudakz | 0:e33621169e44 | 55 | #endif |
hudakz | 0:e33621169e44 | 56 | |
hudakz | 0:e33621169e44 | 57 | /* initial data buffer allocation */ |
hudakz | 0:e33621169e44 | 58 | #ifndef BUFFER_MIN |
hudakz | 0:e33621169e44 | 59 | # define BUFFER_MIN 0x20 |
hudakz | 0:e33621169e44 | 60 | #endif |
hudakz | 0:e33621169e44 | 61 | |
hudakz | 0:e33621169e44 | 62 | /* maximum data buffer allocation |
hudakz | 0:e33621169e44 | 63 | * (longer symbols are rejected) |
hudakz | 0:e33621169e44 | 64 | */ |
hudakz | 0:e33621169e44 | 65 | #ifndef BUFFER_MAX |
hudakz | 0:e33621169e44 | 66 | # define BUFFER_MAX 0x100 |
hudakz | 0:e33621169e44 | 67 | #endif |
hudakz | 0:e33621169e44 | 68 | |
hudakz | 0:e33621169e44 | 69 | /* buffer allocation increment */ |
hudakz | 0:e33621169e44 | 70 | #ifndef BUFFER_INCR |
hudakz | 0:e33621169e44 | 71 | # define BUFFER_INCR 0x10 |
hudakz | 0:e33621169e44 | 72 | #endif |
hudakz | 0:e33621169e44 | 73 | |
hudakz | 0:e33621169e44 | 74 | #define CFG(dcode, cfg) ((dcode).configs[(cfg) - ZBAR_CFG_MIN_LEN]) |
hudakz | 0:e33621169e44 | 75 | #define TEST_CFG(config, cfg) (((config) >> (cfg)) & 1) |
hudakz | 0:e33621169e44 | 76 | |
hudakz | 0:e33621169e44 | 77 | /* symbology independent decoder state */ |
hudakz | 0:e33621169e44 | 78 | struct zbar_decoder_s { |
hudakz | 0:e33621169e44 | 79 | unsigned char idx; /* current width index */ |
hudakz | 0:e33621169e44 | 80 | unsigned w[DECODE_WINDOW]; /* window of last N bar widths */ |
hudakz | 0:e33621169e44 | 81 | zbar_symbol_type_t type; /* type of last decoded data */ |
hudakz | 0:e33621169e44 | 82 | zbar_symbol_type_t lock; /* buffer lock */ |
hudakz | 0:e33621169e44 | 83 | |
hudakz | 0:e33621169e44 | 84 | /* everything above here is automatically reset */ |
hudakz | 0:e33621169e44 | 85 | unsigned buf_alloc; /* dynamic buffer allocation */ |
hudakz | 0:e33621169e44 | 86 | unsigned buflen; /* binary data length */ |
hudakz | 0:e33621169e44 | 87 | unsigned char *buf; /* decoded characters */ |
hudakz | 0:e33621169e44 | 88 | void *userdata; /* application data */ |
hudakz | 0:e33621169e44 | 89 | zbar_decoder_handler_t *handler; /* application callback */ |
hudakz | 0:e33621169e44 | 90 | |
hudakz | 0:e33621169e44 | 91 | /* symbology specific state */ |
hudakz | 0:e33621169e44 | 92 | #ifdef ENABLE_EAN |
hudakz | 0:e33621169e44 | 93 | ean_decoder_t ean; /* EAN/UPC parallel decode attempts */ |
hudakz | 0:e33621169e44 | 94 | #endif |
hudakz | 0:e33621169e44 | 95 | #ifdef ENABLE_I25 |
hudakz | 0:e33621169e44 | 96 | i25_decoder_t i25; /* Interleaved 2 of 5 decode state */ |
hudakz | 0:e33621169e44 | 97 | #endif |
hudakz | 0:e33621169e44 | 98 | #ifdef ENABLE_CODE39 |
hudakz | 0:e33621169e44 | 99 | code39_decoder_t code39; /* Code 39 decode state */ |
hudakz | 0:e33621169e44 | 100 | #endif |
hudakz | 0:e33621169e44 | 101 | #ifdef ENABLE_CODE128 |
hudakz | 0:e33621169e44 | 102 | code128_decoder_t code128; /* Code 128 decode state */ |
hudakz | 0:e33621169e44 | 103 | #endif |
hudakz | 0:e33621169e44 | 104 | #ifdef ENABLE_PDF417 |
hudakz | 0:e33621169e44 | 105 | pdf417_decoder_t pdf417; /* PDF417 decode state */ |
hudakz | 0:e33621169e44 | 106 | #endif |
hudakz | 0:e33621169e44 | 107 | #ifdef ENABLE_QRCODE |
hudakz | 0:e33621169e44 | 108 | qr_finder_t qrf; /* QR Code finder state */ |
hudakz | 0:e33621169e44 | 109 | #endif |
hudakz | 0:e33621169e44 | 110 | }; |
hudakz | 0:e33621169e44 | 111 | |
hudakz | 0:e33621169e44 | 112 | /* return current element color */ |
hudakz | 0:e33621169e44 | 113 | static inline char get_color (const zbar_decoder_t *dcode) |
hudakz | 0:e33621169e44 | 114 | { |
hudakz | 0:e33621169e44 | 115 | return(dcode->idx & 1); |
hudakz | 0:e33621169e44 | 116 | } |
hudakz | 0:e33621169e44 | 117 | |
hudakz | 0:e33621169e44 | 118 | /* retrieve i-th previous element width */ |
hudakz | 0:e33621169e44 | 119 | static inline unsigned get_width (const zbar_decoder_t *dcode, |
hudakz | 0:e33621169e44 | 120 | unsigned char offset) |
hudakz | 0:e33621169e44 | 121 | { |
hudakz | 0:e33621169e44 | 122 | return(dcode->w[(dcode->idx - offset) & (DECODE_WINDOW - 1)]); |
hudakz | 0:e33621169e44 | 123 | } |
hudakz | 0:e33621169e44 | 124 | |
hudakz | 0:e33621169e44 | 125 | /* retrieve bar+space pair width starting at offset i */ |
hudakz | 0:e33621169e44 | 126 | static inline unsigned pair_width (const zbar_decoder_t *dcode, |
hudakz | 0:e33621169e44 | 127 | unsigned char offset) |
hudakz | 0:e33621169e44 | 128 | { |
hudakz | 0:e33621169e44 | 129 | return(get_width(dcode, offset) + get_width(dcode, offset + 1)); |
hudakz | 0:e33621169e44 | 130 | } |
hudakz | 0:e33621169e44 | 131 | |
hudakz | 0:e33621169e44 | 132 | /* calculate total character width "s" |
hudakz | 0:e33621169e44 | 133 | * - start of character identified by context sensitive offset |
hudakz | 0:e33621169e44 | 134 | * (<= DECODE_WINDOW - n) |
hudakz | 0:e33621169e44 | 135 | * - size of character is n elements |
hudakz | 0:e33621169e44 | 136 | */ |
hudakz | 0:e33621169e44 | 137 | static inline unsigned calc_s (const zbar_decoder_t *dcode, |
hudakz | 0:e33621169e44 | 138 | unsigned char offset, |
hudakz | 0:e33621169e44 | 139 | unsigned char n) |
hudakz | 0:e33621169e44 | 140 | { |
hudakz | 0:e33621169e44 | 141 | /* FIXME check that this gets unrolled for constant n */ |
hudakz | 0:e33621169e44 | 142 | unsigned s = 0; |
hudakz | 0:e33621169e44 | 143 | while(n--) |
hudakz | 0:e33621169e44 | 144 | s += get_width(dcode, offset++); |
hudakz | 0:e33621169e44 | 145 | return(s); |
hudakz | 0:e33621169e44 | 146 | } |
hudakz | 0:e33621169e44 | 147 | |
hudakz | 0:e33621169e44 | 148 | /* fixed character width decode assist |
hudakz | 0:e33621169e44 | 149 | * bar+space width are compared as a fraction of the reference dimension "x" |
hudakz | 0:e33621169e44 | 150 | * - +/- 1/2 x tolerance |
hudakz | 0:e33621169e44 | 151 | * - measured total character width (s) compared to symbology baseline (n) |
hudakz | 0:e33621169e44 | 152 | * (n = 7 for EAN/UPC, 11 for Code 128) |
hudakz | 0:e33621169e44 | 153 | * - bar+space *pair width* "e" is used to factor out bad "exposures" |
hudakz | 0:e33621169e44 | 154 | * ("blooming" or "swelling" of dark or light areas) |
hudakz | 0:e33621169e44 | 155 | * => using like-edge measurements avoids these issues |
hudakz | 0:e33621169e44 | 156 | * - n should be > 3 |
hudakz | 0:e33621169e44 | 157 | */ |
hudakz | 0:e33621169e44 | 158 | static inline int decode_e (unsigned e, |
hudakz | 0:e33621169e44 | 159 | unsigned s, |
hudakz | 0:e33621169e44 | 160 | unsigned n) |
hudakz | 0:e33621169e44 | 161 | { |
hudakz | 0:e33621169e44 | 162 | /* result is encoded number of units - 2 |
hudakz | 0:e33621169e44 | 163 | * (for use as zero based index) |
hudakz | 0:e33621169e44 | 164 | * or -1 if invalid |
hudakz | 0:e33621169e44 | 165 | */ |
hudakz | 0:e33621169e44 | 166 | unsigned char E = ((e * n * 2 + 1) / s - 3) / 2; |
hudakz | 0:e33621169e44 | 167 | return((E >= n - 3) ? -1 : E); |
hudakz | 0:e33621169e44 | 168 | } |
hudakz | 0:e33621169e44 | 169 | |
hudakz | 0:e33621169e44 | 170 | /* acquire shared state lock */ |
hudakz | 0:e33621169e44 | 171 | static inline char get_lock (zbar_decoder_t *dcode, |
hudakz | 0:e33621169e44 | 172 | zbar_symbol_type_t req) |
hudakz | 0:e33621169e44 | 173 | { |
hudakz | 0:e33621169e44 | 174 | if(dcode->lock) |
hudakz | 0:e33621169e44 | 175 | return(1); |
hudakz | 0:e33621169e44 | 176 | dcode->lock = req; |
hudakz | 0:e33621169e44 | 177 | return(0); |
hudakz | 0:e33621169e44 | 178 | } |
hudakz | 0:e33621169e44 | 179 | |
hudakz | 0:e33621169e44 | 180 | /* ensure output buffer has sufficient allocation for request */ |
hudakz | 0:e33621169e44 | 181 | static inline char size_buf (zbar_decoder_t *dcode, |
hudakz | 0:e33621169e44 | 182 | unsigned len) |
hudakz | 0:e33621169e44 | 183 | { |
hudakz | 0:e33621169e44 | 184 | if(len < dcode->buf_alloc) |
hudakz | 0:e33621169e44 | 185 | /* FIXME size reduction heuristic? */ |
hudakz | 0:e33621169e44 | 186 | return(0); |
hudakz | 0:e33621169e44 | 187 | if(len > BUFFER_MAX) |
hudakz | 0:e33621169e44 | 188 | return(1); |
hudakz | 0:e33621169e44 | 189 | if(len < dcode->buf_alloc + BUFFER_INCR) { |
hudakz | 0:e33621169e44 | 190 | len = dcode->buf_alloc + BUFFER_INCR; |
hudakz | 0:e33621169e44 | 191 | if(len > BUFFER_MAX) |
hudakz | 0:e33621169e44 | 192 | len = BUFFER_MAX; |
hudakz | 0:e33621169e44 | 193 | } |
hudakz | 0:e33621169e44 | 194 | unsigned char *buf = realloc(dcode->buf, len); |
hudakz | 0:e33621169e44 | 195 | if(!buf) |
hudakz | 0:e33621169e44 | 196 | return(1); |
hudakz | 0:e33621169e44 | 197 | dcode->buf = buf; |
hudakz | 0:e33621169e44 | 198 | dcode->buf_alloc = len; |
hudakz | 0:e33621169e44 | 199 | return(0); |
hudakz | 0:e33621169e44 | 200 | } |
hudakz | 0:e33621169e44 | 201 | |
hudakz | 0:e33621169e44 | 202 | extern const char *_zbar_decoder_buf_dump (unsigned char *buf, |
hudakz | 0:e33621169e44 | 203 | unsigned int buflen); |
hudakz | 0:e33621169e44 | 204 | |
hudakz | 0:e33621169e44 | 205 | #endif |