593 lines
16 KiB
C
593 lines
16 KiB
C
/*------------------------------------------------------------------------
|
|
* 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);
|
|
}
|