summaryrefslogtreecommitdiffstats
path: root/zbar/decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'zbar/decoder.c')
-rw-r--r--zbar/decoder.c592
1 files changed, 592 insertions, 0 deletions
diff --git a/zbar/decoder.c b/zbar/decoder.c
new file mode 100644
index 0000000..6c41b7f
--- /dev/null
+++ b/zbar/decoder.c
@@ -0,0 +1,592 @@
+/*------------------------------------------------------------------------
+ * 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
+ *------------------------------------------------------------------------*/
+
+#include "config.h"
+#include <stdio.h> /* snprintf */
+#include <stdlib.h> /* malloc, calloc, free */
+#include <string.h> /* memset, strlen */
+
+#include <zbar.h>
+
+#if defined(DEBUG_DECODER) || defined(DEBUG_EAN) || defined(DEBUG_CODE93) || \
+ defined(DEBUG_CODE39) || defined(DEBUG_CODABAR) || defined(DEBUG_I25) || \
+ defined(DEBUG_DATABAR) || defined(DEBUG_CODE128) || \
+ defined(DEBUG_SQ_FINDER) || defined(DEBUG_QR_FINDER) || \
+ (defined(DEBUG_PDF417) && (DEBUG_PDF417 >= 4))
+#define DEBUG_LEVEL 1
+#endif
+#include "debug.h"
+#include "decoder.h"
+
+zbar_decoder_t *zbar_decoder_create()
+{
+ zbar_decoder_t *dcode = calloc(1, sizeof(zbar_decoder_t));
+ dcode->buf_alloc = BUFFER_MIN;
+ dcode->buf = malloc(dcode->buf_alloc);
+
+ /* initialize default configs */
+#if ENABLE_EAN == 1
+ dcode->ean.enable = 1;
+ dcode->ean.ean13_config =
+ ((1 << ZBAR_CFG_ENABLE) | (1 << ZBAR_CFG_EMIT_CHECK));
+ dcode->ean.ean8_config =
+ ((1 << ZBAR_CFG_ENABLE) | (1 << ZBAR_CFG_EMIT_CHECK));
+ dcode->ean.upca_config = 1 << ZBAR_CFG_EMIT_CHECK;
+ dcode->ean.upce_config = 1 << ZBAR_CFG_EMIT_CHECK;
+ dcode->ean.isbn10_config = 1 << ZBAR_CFG_EMIT_CHECK;
+ dcode->ean.isbn13_config = 1 << ZBAR_CFG_EMIT_CHECK;
+#ifdef FIXME_ADDON_SYNC
+ dcode->ean.ean2_config = 1 << ZBAR_CFG_ENABLE;
+ dcode->ean.ean5_config = 1 << ZBAR_CFG_ENABLE;
+#endif
+#endif
+#if ENABLE_I25 == 1
+ dcode->i25.config = 1 << ZBAR_CFG_ENABLE;
+ CFG(dcode->i25, ZBAR_CFG_MIN_LEN) = 6;
+#endif
+#if ENABLE_DATABAR == 1
+ dcode->databar.config =
+ ((1 << ZBAR_CFG_ENABLE) | (1 << ZBAR_CFG_EMIT_CHECK));
+ dcode->databar.config_exp =
+ ((1 << ZBAR_CFG_ENABLE) | (1 << ZBAR_CFG_EMIT_CHECK));
+ dcode->databar.csegs = 4;
+ dcode->databar.segs = calloc(4, sizeof(*dcode->databar.segs));
+#endif
+#if ENABLE_CODABAR == 1
+ dcode->codabar.config = 1 << ZBAR_CFG_ENABLE;
+ CFG(dcode->codabar, ZBAR_CFG_MIN_LEN) = 4;
+#endif
+#if ENABLE_CODE39 == 1
+ dcode->code39.config = 1 << ZBAR_CFG_ENABLE;
+ CFG(dcode->code39, ZBAR_CFG_MIN_LEN) = 1;
+#endif
+#if ENABLE_CODE93 == 1
+ dcode->code93.config = 1 << ZBAR_CFG_ENABLE;
+#endif
+#if ENABLE_CODE128 == 1
+ dcode->code128.config = 1 << ZBAR_CFG_ENABLE;
+#endif
+#if ENABLE_PDF417 == 1
+ dcode->pdf417.config = 1 << ZBAR_CFG_ENABLE;
+#endif
+#if ENABLE_QRCODE == 1
+ dcode->qrf.config = 1 << ZBAR_CFG_ENABLE;
+#endif
+#if ENABLE_SQCODE == 1
+ dcode->sqf.config = 1 << ZBAR_CFG_ENABLE;
+#endif
+
+ zbar_decoder_reset(dcode);
+ return (dcode);
+}
+
+void zbar_decoder_destroy(zbar_decoder_t *dcode)
+{
+#if ENABLE_DATABAR == 1
+ if (dcode->databar.segs)
+ free(dcode->databar.segs);
+#endif
+ if (dcode->buf)
+ free(dcode->buf);
+ free(dcode);
+}
+
+void zbar_decoder_reset(zbar_decoder_t *dcode)
+{
+ memset(dcode, 0, (long)&dcode->buf_alloc - (long)dcode);
+#if ENABLE_EAN == 1
+ ean_reset(&dcode->ean);
+#endif
+#if ENABLE_I25 == 1
+ i25_reset(&dcode->i25);
+#endif
+#if ENABLE_DATABAR == 1
+ databar_reset(&dcode->databar);
+#endif
+#if ENABLE_CODABAR == 1
+ codabar_reset(&dcode->codabar);
+#endif
+#if ENABLE_CODE39 == 1
+ code39_reset(&dcode->code39);
+#endif
+#if ENABLE_CODE93 == 1
+ code93_reset(&dcode->code93);
+#endif
+#if ENABLE_CODE128 == 1
+ code128_reset(&dcode->code128);
+#endif
+#if ENABLE_PDF417 == 1
+ pdf417_reset(&dcode->pdf417);
+#endif
+#if ENABLE_QRCODE == 1
+ qr_finder_reset(&dcode->qrf);
+#endif
+}
+
+void zbar_decoder_new_scan(zbar_decoder_t *dcode)
+{
+ /* soft reset decoder */
+ memset(dcode->w, 0, sizeof(dcode->w));
+ dcode->lock = 0;
+ dcode->idx = 0;
+ dcode->s6 = 0;
+#if ENABLE_EAN == 1
+ ean_new_scan(&dcode->ean);
+#endif
+#if ENABLE_I25 == 1
+ i25_reset(&dcode->i25);
+#endif
+#if ENABLE_DATABAR == 1
+ databar_new_scan(&dcode->databar);
+#endif
+#if ENABLE_CODABAR == 1
+ codabar_reset(&dcode->codabar);
+#endif
+#if ENABLE_CODE39 == 1
+ code39_reset(&dcode->code39);
+#endif
+#if ENABLE_CODE93 == 1
+ code93_reset(&dcode->code93);
+#endif
+#if ENABLE_CODE128 == 1
+ code128_reset(&dcode->code128);
+#endif
+#if ENABLE_PDF417 == 1
+ pdf417_reset(&dcode->pdf417);
+#endif
+#if ENABLE_QRCODE == 1
+ qr_finder_reset(&dcode->qrf);
+#endif
+}
+
+zbar_color_t zbar_decoder_get_color(const zbar_decoder_t *dcode)
+{
+ return (get_color(dcode));
+}
+
+const char *zbar_decoder_get_data(const zbar_decoder_t *dcode)
+{
+ return ((char *)dcode->buf);
+}
+
+unsigned int zbar_decoder_get_data_length(const zbar_decoder_t *dcode)
+{
+ return (dcode->buflen);
+}
+
+int zbar_decoder_get_direction(const zbar_decoder_t *dcode)
+{
+ return (dcode->direction);
+}
+
+zbar_decoder_handler_t *
+zbar_decoder_set_handler(zbar_decoder_t *dcode, zbar_decoder_handler_t *handler)
+{
+ zbar_decoder_handler_t *result = dcode->handler;
+ dcode->handler = handler;
+ return (result);
+}
+
+void zbar_decoder_set_userdata(zbar_decoder_t *dcode, void *userdata)
+{
+ dcode->userdata = userdata;
+}
+
+void *zbar_decoder_get_userdata(const zbar_decoder_t *dcode)
+{
+ return (dcode->userdata);
+}
+
+zbar_symbol_type_t zbar_decoder_get_type(const zbar_decoder_t *dcode)
+{
+ return (dcode->type);
+}
+
+unsigned int zbar_decoder_get_modifiers(const zbar_decoder_t *dcode)
+{
+ return (dcode->modifiers);
+}
+
+zbar_symbol_type_t zbar_decode_width(zbar_decoder_t *dcode, unsigned w)
+{
+ zbar_symbol_type_t tmp, sym = ZBAR_NONE;
+
+ dcode->w[dcode->idx & (DECODE_WINDOW - 1)] = w;
+ dbprintf(1, " decode[%x]: w=%d (%g)\n", dcode->idx, w, (w / 32.));
+
+ /* update shared character width */
+ dcode->s6 -= get_width(dcode, 7);
+ dcode->s6 += get_width(dcode, 1);
+
+ /* each decoder processes width stream in parallel */
+#if ENABLE_QRCODE == 1
+ if (TEST_CFG(dcode->qrf.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_find_qr(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_EAN == 1
+ if ((dcode->ean.enable) && (tmp = _zbar_decode_ean(dcode)))
+ sym = tmp;
+#endif
+#if ENABLE_CODE39 == 1
+ if (TEST_CFG(dcode->code39.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_code39(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_CODE93 == 1
+ if (TEST_CFG(dcode->code93.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_code93(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_CODE128 == 1
+ if (TEST_CFG(dcode->code128.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_code128(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_DATABAR == 1
+ if (TEST_CFG(dcode->databar.config | dcode->databar.config_exp,
+ ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_databar(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_CODABAR == 1
+ if (TEST_CFG(dcode->codabar.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_codabar(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_I25 == 1
+ if (TEST_CFG(dcode->i25.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_i25(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+#if ENABLE_PDF417 == 1
+ if (TEST_CFG(dcode->pdf417.config, ZBAR_CFG_ENABLE) &&
+ (tmp = _zbar_decode_pdf417(dcode)) > ZBAR_PARTIAL)
+ sym = tmp;
+#endif
+
+ dcode->idx++;
+ dcode->type = sym;
+ if (sym) {
+ if (dcode->lock && sym > ZBAR_PARTIAL && sym != ZBAR_QRCODE)
+ release_lock(dcode, sym);
+ if (dcode->handler)
+ dcode->handler(dcode);
+ }
+ return (sym);
+}
+
+static inline const unsigned int *
+decoder_get_configp(const zbar_decoder_t *dcode, zbar_symbol_type_t sym)
+{
+ const unsigned int *config;
+ switch (sym) {
+#if ENABLE_EAN == 1
+ case ZBAR_EAN13:
+ config = &dcode->ean.ean13_config;
+ break;
+
+ case ZBAR_EAN2:
+ config = &dcode->ean.ean2_config;
+ break;
+
+ case ZBAR_EAN5:
+ config = &dcode->ean.ean5_config;
+ break;
+
+ case ZBAR_EAN8:
+ config = &dcode->ean.ean8_config;
+ break;
+
+ case ZBAR_UPCA:
+ config = &dcode->ean.upca_config;
+ break;
+
+ case ZBAR_UPCE:
+ config = &dcode->ean.upce_config;
+ break;
+
+ case ZBAR_ISBN10:
+ config = &dcode->ean.isbn10_config;
+ break;
+
+ case ZBAR_ISBN13:
+ config = &dcode->ean.isbn13_config;
+ break;
+#endif
+
+#if ENABLE_I25 == 1
+ case ZBAR_I25:
+ config = &dcode->i25.config;
+ break;
+#endif
+
+#if ENABLE_DATABAR == 1
+ case ZBAR_DATABAR:
+ config = &dcode->databar.config;
+ break;
+ case ZBAR_DATABAR_EXP:
+ config = &dcode->databar.config_exp;
+ break;
+#endif
+
+#if ENABLE_CODABAR == 1
+ case ZBAR_CODABAR:
+ config = &dcode->codabar.config;
+ break;
+#endif
+
+#if ENABLE_CODE39 == 1
+ case ZBAR_CODE39:
+ config = &dcode->code39.config;
+ break;
+#endif
+
+#if ENABLE_CODE93 == 1
+ case ZBAR_CODE93:
+ config = &dcode->code93.config;
+ break;
+#endif
+
+#if ENABLE_CODE128 == 1
+ case ZBAR_CODE128:
+ config = &dcode->code128.config;
+ break;
+#endif
+
+#if ENABLE_PDF417 == 1
+ case ZBAR_PDF417:
+ config = &dcode->pdf417.config;
+ break;
+#endif
+
+#if ENABLE_QRCODE == 1
+ case ZBAR_QRCODE:
+ config = &dcode->qrf.config;
+ break;
+#endif
+
+#if ENABLE_SQCODE == 1
+ case ZBAR_SQCODE:
+ config = &dcode->sqf.config;
+ break;
+#endif
+
+ default:
+ config = NULL;
+ }
+ return (config);
+}
+
+unsigned int zbar_decoder_get_configs(const zbar_decoder_t *dcode,
+ zbar_symbol_type_t sym)
+{
+ const unsigned *config = decoder_get_configp(dcode, sym);
+ if (!config)
+ return (0);
+ return (*config);
+}
+
+static inline int decoder_set_config_bool(zbar_decoder_t *dcode,
+ zbar_symbol_type_t sym,
+ zbar_config_t cfg, int val)
+{
+ unsigned *config = (void *)decoder_get_configp(dcode, sym);
+ if (!config || cfg >= ZBAR_CFG_NUM)
+ return (1);
+
+ if (!val)
+ *config &= ~(1 << cfg);
+ else if (val == 1)
+ *config |= (1 << cfg);
+ else
+ return (1);
+
+#if ENABLE_EAN == 1
+ dcode->ean.enable =
+ TEST_CFG(dcode->ean.ean13_config | dcode->ean.ean2_config |
+ dcode->ean.ean5_config | dcode->ean.ean8_config |
+ dcode->ean.upca_config | dcode->ean.upce_config |
+ dcode->ean.isbn10_config | dcode->ean.isbn13_config,
+ ZBAR_CFG_ENABLE);
+#endif
+
+ return (0);
+}
+
+static inline int decoder_set_config_int(zbar_decoder_t *dcode,
+ zbar_symbol_type_t sym,
+ zbar_config_t cfg, int val)
+{
+ switch (sym) {
+#if ENABLE_I25 == 1
+ case ZBAR_I25:
+ CFG(dcode->i25, cfg) = val;
+ break;
+#endif
+#if ENABLE_CODABAR == 1
+ case ZBAR_CODABAR:
+ CFG(dcode->codabar, cfg) = val;
+ break;
+#endif
+#if ENABLE_CODE39 == 1
+ case ZBAR_CODE39:
+ CFG(dcode->code39, cfg) = val;
+ break;
+#endif
+#if ENABLE_CODE93 == 1
+ case ZBAR_CODE93:
+ CFG(dcode->code93, cfg) = val;
+ break;
+#endif
+#if ENABLE_CODE128 == 1
+ case ZBAR_CODE128:
+ CFG(dcode->code128, cfg) = val;
+ break;
+#endif
+#if ENABLE_PDF417 == 1
+ case ZBAR_PDF417:
+ CFG(dcode->pdf417, cfg) = val;
+ break;
+#endif
+
+ default:
+ return (1);
+ }
+ return (0);
+}
+
+int zbar_decoder_get_config(zbar_decoder_t *dcode, zbar_symbol_type_t sym,
+ zbar_config_t cfg, int *val)
+{
+ const unsigned *config = decoder_get_configp(dcode, sym);
+
+ /* Return error if symbol doesn't have config */
+ if (sym <= ZBAR_PARTIAL || sym > ZBAR_CODE128 || sym == ZBAR_COMPOSITE)
+ return 1;
+
+ /* Return decoder boolean configs */
+ if (cfg < ZBAR_CFG_NUM) {
+ *val = (*config & (1 << cfg)) != 0;
+ return 0;
+ }
+
+ /* Return decoder integer configs */
+ if (cfg >= ZBAR_CFG_MIN_LEN && cfg <= ZBAR_CFG_MAX_LEN) {
+ switch (sym) {
+#if ENABLE_I25 == 1
+ case ZBAR_I25:
+ *val = CFG(dcode->i25, cfg);
+ return 0;
+#endif
+#if ENABLE_CODABAR == 1
+ case ZBAR_CODABAR:
+ *val = CFG(dcode->codabar, cfg);
+ return 0;
+#endif
+#if ENABLE_CODE39 == 1
+ case ZBAR_CODE39:
+ *val = CFG(dcode->code39, cfg);
+ return 0;
+#endif
+#if ENABLE_CODE93 == 1
+ case ZBAR_CODE93:
+ *val = CFG(dcode->code93, cfg);
+ return 0;
+#endif
+#if ENABLE_CODE128 == 1
+ case ZBAR_CODE128:
+ *val = CFG(dcode->code128, cfg);
+ return 0;
+#endif
+#if ENABLE_PDF417 == 1
+ case ZBAR_PDF417:
+ *val = CFG(dcode->pdf417, cfg);
+ return 0;
+#endif
+ default:
+ return 1;
+ }
+ }
+ return 1;
+}
+
+int zbar_decoder_set_config(zbar_decoder_t *dcode, zbar_symbol_type_t sym,
+ zbar_config_t cfg, int val)
+{
+ if (sym == ZBAR_NONE) {
+ static const zbar_symbol_type_t all[] = { ZBAR_EAN13,
+ ZBAR_EAN2,
+ ZBAR_EAN5,
+ ZBAR_EAN8,
+ ZBAR_UPCA,
+ ZBAR_UPCE,
+ ZBAR_ISBN10,
+ ZBAR_ISBN13,
+ ZBAR_I25,
+ ZBAR_DATABAR,
+ ZBAR_DATABAR_EXP,
+ ZBAR_CODABAR,
+ ZBAR_CODE39,
+ ZBAR_CODE93,
+ ZBAR_CODE128,
+ ZBAR_QRCODE,
+ ZBAR_SQCODE,
+ ZBAR_PDF417,
+ 0 };
+ const zbar_symbol_type_t *symp;
+ for (symp = all; *symp; symp++)
+ zbar_decoder_set_config(dcode, *symp, cfg, val);
+ return (0);
+ }
+
+ if (cfg >= 0 && cfg < ZBAR_CFG_NUM)
+ return (decoder_set_config_bool(dcode, sym, cfg, val));
+ else if (cfg >= ZBAR_CFG_MIN_LEN && cfg <= ZBAR_CFG_MAX_LEN)
+ return (decoder_set_config_int(dcode, sym, cfg, val));
+ else
+ return (1);
+}
+
+static char *decoder_dump = NULL;
+static unsigned decoder_dumplen = 0;
+
+const char *_zbar_decoder_buf_dump(unsigned char *buf, unsigned int buflen)
+{
+ int dumplen = (buflen * 3) + 12;
+ char *p;
+ int i;
+
+ if (!decoder_dump || dumplen > decoder_dumplen) {
+ if (decoder_dump)
+ free(decoder_dump);
+ decoder_dump = malloc(dumplen);
+ decoder_dumplen = dumplen;
+ }
+ p = decoder_dump +
+ snprintf(decoder_dump, 12,
+ "buf[%04x]=", (buflen > 0xffff) ? 0xffff : buflen);
+ for (i = 0; i < buflen; i++)
+ p += snprintf(p, 4, "%s%02x", (i) ? " " : "", buf[i]);
+ return (decoder_dump);
+}