summaryrefslogtreecommitdiffstats
path: root/zbar/decoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'zbar/decoder.h')
-rw-r--r--zbar/decoder.h292
1 files changed, 292 insertions, 0 deletions
diff --git a/zbar/decoder.h b/zbar/decoder.h
new file mode 100644
index 0000000..260dc43
--- /dev/null
+++ b/zbar/decoder.h
@@ -0,0 +1,292 @@
+/*------------------------------------------------------------------------
+ * Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
+ *
+ * This file is part of the ZBar Bar Code Reader.
+ *
+ * The ZBar Bar Code Reader is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The ZBar Bar Code Reader 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 Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser Public License
+ * along with the ZBar Bar Code Reader; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ *
+ * http://sourceforge.net/projects/zbar
+ *------------------------------------------------------------------------*/
+#ifndef _DECODER_H_
+#define _DECODER_H_
+
+#include "config.h"
+#include <limits.h>
+#include <stdlib.h> /* realloc */
+
+#include <zbar.h>
+
+#include "debug.h"
+
+#define NUM_CFGS (ZBAR_CFG_MAX_LEN - ZBAR_CFG_MIN_LEN + 1)
+
+#if ENABLE_EAN == 1
+#include "decoder/ean.h"
+#endif
+#if ENABLE_I25 == 1
+#include "decoder/i25.h"
+#endif
+#if ENABLE_DATABAR == 1
+#include "decoder/databar.h"
+#endif
+#if ENABLE_CODABAR == 1
+#include "decoder/codabar.h"
+#endif
+#if ENABLE_CODE39 == 1
+#include "decoder/code39.h"
+#endif
+#if ENABLE_CODE93 == 1
+#include "decoder/code93.h"
+#endif
+#if ENABLE_CODE128 == 1
+#include "decoder/code128.h"
+#endif
+#if ENABLE_PDF417 == 1
+#include "decoder/pdf417.h"
+#endif
+#if ENABLE_QRCODE == 1
+#include "decoder/qr_finder.h"
+#endif
+#if ENABLE_SQCODE == 1
+#include "decoder/sq_finder.h"
+#endif
+
+/* size of bar width history (implementation assumes power of two) */
+#ifndef DECODE_WINDOW
+#define DECODE_WINDOW 16
+#endif
+
+/* initial data buffer allocation */
+#ifndef BUFFER_MIN
+#define BUFFER_MIN 0x20
+#endif
+
+/* maximum data buffer allocation
+ * (longer symbols are rejected)
+ */
+#ifndef BUFFER_MAX
+#define BUFFER_MAX 0x100
+#endif
+
+/* buffer allocation increment */
+#ifndef BUFFER_INCR
+#define BUFFER_INCR 0x10
+#endif
+
+#define CFG(dcode, cfg) ((dcode).configs[(cfg)-ZBAR_CFG_MIN_LEN])
+#define TEST_CFG(config, cfg) (((config) >> (cfg)) & 1)
+#define MOD(mod) (1 << (mod))
+
+/* symbology independent decoder state */
+struct zbar_decoder_s {
+ unsigned char idx; /* current width index */
+ unsigned w[DECODE_WINDOW]; /* window of last N bar widths */
+ zbar_symbol_type_t type; /* type of last decoded data */
+ zbar_symbol_type_t lock; /* buffer lock */
+ unsigned modifiers; /* symbology modifier */
+ int direction; /* direction of last decoded data */
+ unsigned s6; /* 6-element character width */
+
+ /* everything above here is automatically reset */
+ unsigned buf_alloc; /* dynamic buffer allocation */
+ unsigned buflen; /* binary data length */
+ unsigned char *buf; /* decoded characters */
+ void *userdata; /* application data */
+ zbar_decoder_handler_t *handler; /* application callback */
+
+ /* symbology specific state */
+#if ENABLE_EAN == 1
+ ean_decoder_t ean; /* EAN/UPC parallel decode attempts */
+#endif
+#if ENABLE_I25 == 1
+ i25_decoder_t i25; /* Interleaved 2 of 5 decode state */
+#endif
+#if ENABLE_DATABAR == 1
+ databar_decoder_t databar; /* DataBar decode state */
+#endif
+#if ENABLE_CODABAR == 1
+ codabar_decoder_t codabar; /* Codabar decode state */
+#endif
+#if ENABLE_CODE39 == 1
+ code39_decoder_t code39; /* Code 39 decode state */
+#endif
+#if ENABLE_CODE93 == 1
+ code93_decoder_t code93; /* Code 93 decode state */
+#endif
+#if ENABLE_CODE128 == 1
+ code128_decoder_t code128; /* Code 128 decode state */
+#endif
+#if ENABLE_PDF417 == 1
+ pdf417_decoder_t pdf417; /* PDF417 decode state */
+#endif
+#if ENABLE_QRCODE == 1
+ qr_finder_t qrf; /* QR Code finder state */
+#endif
+#if ENABLE_SQCODE == 1
+ sq_finder_t sqf; /* SQ Code finder state */
+#endif
+};
+
+/* return current element color */
+static inline char get_color(const zbar_decoder_t *dcode)
+{
+ return (dcode->idx & 1);
+}
+
+/* retrieve i-th previous element width */
+static inline unsigned get_width(const zbar_decoder_t *dcode,
+ unsigned char offset)
+{
+ return (dcode->w[(dcode->idx - offset) & (DECODE_WINDOW - 1)]);
+}
+
+/* retrieve bar+space pair width starting at offset i */
+static inline unsigned pair_width(const zbar_decoder_t *dcode,
+ unsigned char offset)
+{
+ return (get_width(dcode, offset) + get_width(dcode, offset + 1));
+}
+
+/* calculate total character width "s"
+ * - start of character identified by context sensitive offset
+ * (<= DECODE_WINDOW - n)
+ * - size of character is n elements
+ */
+static inline unsigned calc_s(const zbar_decoder_t *dcode, unsigned char offset,
+ unsigned char n)
+{
+ /* FIXME check that this gets unrolled for constant n */
+ unsigned s = 0;
+ while (n--)
+ s += get_width(dcode, offset++);
+ return (s);
+}
+
+/* fixed character width decode assist
+ * bar+space width are compared as a fraction of the reference dimension "x"
+ * - +/- 1/2 x tolerance
+ * - measured total character width (s) compared to symbology baseline (n)
+ * (n = 7 for EAN/UPC, 11 for Code 128)
+ * - bar+space *pair width* "e" is used to factor out bad "exposures"
+ * ("blooming" or "swelling" of dark or light areas)
+ * => using like-edge measurements avoids these issues
+ * - n should be > 3
+ */
+static inline int decode_e(unsigned e, unsigned s, unsigned n)
+{
+ /* result is encoded number of units - 2
+ * (for use as zero based index)
+ * or -1 if invalid
+ */
+ unsigned char E = ((e * n * 2 + 1) / s - 3) / 2;
+ return ((E >= n - 3) ? -1 : E);
+}
+
+/* sort three like-colored elements and return ordering
+ */
+static inline unsigned decode_sort3(zbar_decoder_t *dcode, int i0)
+{
+ unsigned w0 = get_width(dcode, i0);
+ unsigned w2 = get_width(dcode, i0 + 2);
+ unsigned w4 = get_width(dcode, i0 + 4);
+ if (w0 < w2) {
+ if (w2 < w4)
+ return ((i0 << 8) | ((i0 + 2) << 4) | (i0 + 4));
+ if (w0 < w4)
+ return ((i0 << 8) | ((i0 + 4) << 4) | (i0 + 2));
+ return (((i0 + 4) << 8) | (i0 << 4) | (i0 + 2));
+ }
+ if (w4 < w2)
+ return (((i0 + 4) << 8) | ((i0 + 2) << 4) | i0);
+ if (w0 < w4)
+ return (((i0 + 2) << 8) | (i0 << 4) | (i0 + 4));
+ return (((i0 + 2) << 8) | ((i0 + 4) << 4) | i0);
+}
+
+/* sort N like-colored elements and return ordering
+ */
+static inline unsigned decode_sortn(zbar_decoder_t *dcode, int n, int i0)
+{
+ unsigned mask = 0, sort = 0;
+ int i;
+ for (i = n - 1; i >= 0; i--) {
+ unsigned wmin = UINT_MAX;
+ int jmin = -1, j;
+ for (j = n - 1; j >= 0; j--) {
+ unsigned w;
+ if ((mask >> j) & 1)
+ continue;
+ w = get_width(dcode, i0 + j * 2);
+ if (wmin >= w) {
+ wmin = w;
+ jmin = j;
+ }
+ }
+ zassert(jmin >= 0, 0, "sortn(%d,%d) jmin=%d", n, i0, jmin);
+ sort <<= 4;
+ mask |= 1 << jmin;
+ sort |= i0 + jmin * 2;
+ }
+ return (sort);
+}
+
+/* acquire shared state lock */
+static inline char acquire_lock(zbar_decoder_t *dcode, zbar_symbol_type_t req)
+{
+ if (dcode->lock) {
+ dbprintf(2, " [locked %d]\n", dcode->lock);
+ return (1);
+ }
+ dcode->lock = req;
+ return (0);
+}
+
+/* check and release shared state lock */
+static inline char release_lock(zbar_decoder_t *dcode, zbar_symbol_type_t req)
+{
+ zassert(dcode->lock == req, 1, "lock=%d req=%d\n", dcode->lock, req);
+ dcode->lock = 0;
+ return (0);
+}
+
+/* ensure output buffer has sufficient allocation for request */
+static inline char size_buf(zbar_decoder_t *dcode, unsigned len)
+{
+ unsigned char *buf;
+ if (len <= BUFFER_MIN)
+ return (0);
+ if (len < dcode->buf_alloc)
+ /* FIXME size reduction heuristic? */
+ return (0);
+ if (len > BUFFER_MAX)
+ return (1);
+ if (len < dcode->buf_alloc + BUFFER_INCR) {
+ len = dcode->buf_alloc + BUFFER_INCR;
+ if (len > BUFFER_MAX)
+ len = BUFFER_MAX;
+ }
+ buf = realloc(dcode->buf, len);
+ if (!buf)
+ return (1);
+ dcode->buf = buf;
+ dcode->buf_alloc = len;
+ return (0);
+}
+
+extern const char *_zbar_decoder_buf_dump(unsigned char *buf,
+ unsigned int buflen);
+
+#endif