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

LICENSE

The ZBar Bar Code Reader is Copyright (C) 2007-2009 Jeff Brown <spadix@users.sourceforge.net> The QR Code reader is Copyright (C) 1999-2009 Timothy B. Terriberry <tterribe@xiph.org>

You can redistribute this library and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.

This library 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 General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

ISAAC is based on the public domain implementation by Robert J. Jenkins Jr., and is itself public domain.

Portions of the bit stream reader are copyright (C) The Xiph.Org Foundation 1994-2008, and are licensed under a BSD-style license.

The Reed-Solomon decoder is derived from an implementation (C) 1991-1995 Henry Minsky (hqm@ua.com, hqm@ai.mit.edu), and is licensed under the LGPL with permission.

Committer:
RyoheiHagimoto
Date:
Tue Apr 19 02:19:39 2016 +0000
Revision:
1:500d42699c34
Parent:
0:56c5742b9e2b
Add copying.txt and license.txt

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RyoheiHagimoto 0:56c5742b9e2b 1 /*------------------------------------------------------------------------
RyoheiHagimoto 0:56c5742b9e2b 2 * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
RyoheiHagimoto 0:56c5742b9e2b 3 *
RyoheiHagimoto 0:56c5742b9e2b 4 * This file is part of the ZBar Bar Code Reader.
RyoheiHagimoto 0:56c5742b9e2b 5 *
RyoheiHagimoto 0:56c5742b9e2b 6 * The ZBar Bar Code Reader is free software; you can redistribute it
RyoheiHagimoto 0:56c5742b9e2b 7 * and/or modify it under the terms of the GNU Lesser Public License as
RyoheiHagimoto 0:56c5742b9e2b 8 * published by the Free Software Foundation; either version 2.1 of
RyoheiHagimoto 0:56c5742b9e2b 9 * the License, or (at your option) any later version.
RyoheiHagimoto 0:56c5742b9e2b 10 *
RyoheiHagimoto 0:56c5742b9e2b 11 * The ZBar Bar Code Reader is distributed in the hope that it will be
RyoheiHagimoto 0:56c5742b9e2b 12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
RyoheiHagimoto 0:56c5742b9e2b 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
RyoheiHagimoto 0:56c5742b9e2b 14 * GNU Lesser Public License for more details.
RyoheiHagimoto 0:56c5742b9e2b 15 *
RyoheiHagimoto 0:56c5742b9e2b 16 * You should have received a copy of the GNU Lesser Public License
RyoheiHagimoto 0:56c5742b9e2b 17 * along with the ZBar Bar Code Reader; if not, write to the Free
RyoheiHagimoto 0:56c5742b9e2b 18 * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
RyoheiHagimoto 0:56c5742b9e2b 19 * Boston, MA 02110-1301 USA
RyoheiHagimoto 0:56c5742b9e2b 20 *
RyoheiHagimoto 0:56c5742b9e2b 21 * http://sourceforge.net/projects/zbar
RyoheiHagimoto 0:56c5742b9e2b 22 *------------------------------------------------------------------------*/
RyoheiHagimoto 0:56c5742b9e2b 23
RyoheiHagimoto 0:56c5742b9e2b 24 #include <config.h>
RyoheiHagimoto 0:56c5742b9e2b 25 #include <stdlib.h> /* malloc, free, abs */
RyoheiHagimoto 0:56c5742b9e2b 26 #include <string.h> /* memset */
RyoheiHagimoto 0:56c5742b9e2b 27
RyoheiHagimoto 0:56c5742b9e2b 28 #include <zbar.h>
RyoheiHagimoto 0:56c5742b9e2b 29 #include "svg.h"
RyoheiHagimoto 0:56c5742b9e2b 30
RyoheiHagimoto 0:56c5742b9e2b 31 #ifdef DEBUG_SCANNER
RyoheiHagimoto 0:56c5742b9e2b 32 # define DEBUG_LEVEL (DEBUG_SCANNER)
RyoheiHagimoto 0:56c5742b9e2b 33 #endif
RyoheiHagimoto 0:56c5742b9e2b 34 #include "zbar_debug.h"
RyoheiHagimoto 0:56c5742b9e2b 35
RyoheiHagimoto 0:56c5742b9e2b 36 #ifndef ZBAR_FIXED
RyoheiHagimoto 0:56c5742b9e2b 37 # define ZBAR_FIXED 5
RyoheiHagimoto 0:56c5742b9e2b 38 #endif
RyoheiHagimoto 0:56c5742b9e2b 39 #define ROUND (1 << (ZBAR_FIXED - 1))
RyoheiHagimoto 0:56c5742b9e2b 40
RyoheiHagimoto 0:56c5742b9e2b 41 /* FIXME add runtime config API for these */
RyoheiHagimoto 0:56c5742b9e2b 42 #ifndef ZBAR_SCANNER_THRESH_MIN
RyoheiHagimoto 0:56c5742b9e2b 43 # define ZBAR_SCANNER_THRESH_MIN 4
RyoheiHagimoto 0:56c5742b9e2b 44 #endif
RyoheiHagimoto 0:56c5742b9e2b 45
RyoheiHagimoto 0:56c5742b9e2b 46 #ifndef ZBAR_SCANNER_THRESH_INIT_WEIGHT
RyoheiHagimoto 0:56c5742b9e2b 47 # define ZBAR_SCANNER_THRESH_INIT_WEIGHT .44
RyoheiHagimoto 0:56c5742b9e2b 48 #endif
RyoheiHagimoto 0:56c5742b9e2b 49 #define THRESH_INIT ((unsigned)((ZBAR_SCANNER_THRESH_INIT_WEIGHT \
RyoheiHagimoto 0:56c5742b9e2b 50 * (1 << (ZBAR_FIXED + 1)) + 1) / 2))
RyoheiHagimoto 0:56c5742b9e2b 51
RyoheiHagimoto 0:56c5742b9e2b 52 #ifndef ZBAR_SCANNER_THRESH_FADE
RyoheiHagimoto 0:56c5742b9e2b 53 # define ZBAR_SCANNER_THRESH_FADE 8
RyoheiHagimoto 0:56c5742b9e2b 54 #endif
RyoheiHagimoto 0:56c5742b9e2b 55
RyoheiHagimoto 0:56c5742b9e2b 56 #ifndef ZBAR_SCANNER_EWMA_WEIGHT
RyoheiHagimoto 0:56c5742b9e2b 57 # define ZBAR_SCANNER_EWMA_WEIGHT .78
RyoheiHagimoto 0:56c5742b9e2b 58 #endif
RyoheiHagimoto 0:56c5742b9e2b 59 #define EWMA_WEIGHT ((unsigned)((ZBAR_SCANNER_EWMA_WEIGHT \
RyoheiHagimoto 0:56c5742b9e2b 60 * (1 << (ZBAR_FIXED + 1)) + 1) / 2))
RyoheiHagimoto 0:56c5742b9e2b 61
RyoheiHagimoto 0:56c5742b9e2b 62 /* scanner state */
RyoheiHagimoto 0:56c5742b9e2b 63 struct zbar_scanner_s {
RyoheiHagimoto 0:56c5742b9e2b 64 zbar_decoder_t *decoder; /* associated bar width decoder */
RyoheiHagimoto 0:56c5742b9e2b 65 unsigned y1_min_thresh; /* minimum threshold */
RyoheiHagimoto 0:56c5742b9e2b 66
RyoheiHagimoto 0:56c5742b9e2b 67 unsigned x; /* relative scan position of next sample */
RyoheiHagimoto 0:56c5742b9e2b 68 int y0[4]; /* short circular buffer of average intensities */
RyoheiHagimoto 0:56c5742b9e2b 69
RyoheiHagimoto 0:56c5742b9e2b 70 int y1_sign; /* slope at last crossing */
RyoheiHagimoto 0:56c5742b9e2b 71 unsigned y1_thresh; /* current slope threshold */
RyoheiHagimoto 0:56c5742b9e2b 72
RyoheiHagimoto 0:56c5742b9e2b 73 unsigned cur_edge; /* interpolated position of tracking edge */
RyoheiHagimoto 0:56c5742b9e2b 74 unsigned last_edge; /* interpolated position of last located edge */
RyoheiHagimoto 0:56c5742b9e2b 75 unsigned width; /* last element width */
RyoheiHagimoto 0:56c5742b9e2b 76 };
RyoheiHagimoto 0:56c5742b9e2b 77
RyoheiHagimoto 0:56c5742b9e2b 78 zbar_scanner_t *zbar_scanner_create (zbar_decoder_t *dcode)
RyoheiHagimoto 0:56c5742b9e2b 79 {
RyoheiHagimoto 0:56c5742b9e2b 80 zbar_scanner_t *scn = malloc(sizeof(zbar_scanner_t));
RyoheiHagimoto 0:56c5742b9e2b 81 scn->decoder = dcode;
RyoheiHagimoto 0:56c5742b9e2b 82 scn->y1_min_thresh = ZBAR_SCANNER_THRESH_MIN;
RyoheiHagimoto 0:56c5742b9e2b 83 zbar_scanner_reset(scn);
RyoheiHagimoto 0:56c5742b9e2b 84 return(scn);
RyoheiHagimoto 0:56c5742b9e2b 85 }
RyoheiHagimoto 0:56c5742b9e2b 86
RyoheiHagimoto 0:56c5742b9e2b 87 void zbar_scanner_destroy (zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 88 {
RyoheiHagimoto 0:56c5742b9e2b 89 free(scn);
RyoheiHagimoto 0:56c5742b9e2b 90 }
RyoheiHagimoto 0:56c5742b9e2b 91
RyoheiHagimoto 0:56c5742b9e2b 92 zbar_symbol_type_t zbar_scanner_reset (zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 93 {
RyoheiHagimoto 0:56c5742b9e2b 94 memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x);
RyoheiHagimoto 0:56c5742b9e2b 95 scn->y1_thresh = scn->y1_min_thresh;
RyoheiHagimoto 0:56c5742b9e2b 96 if(scn->decoder)
RyoheiHagimoto 0:56c5742b9e2b 97 zbar_decoder_reset(scn->decoder);
RyoheiHagimoto 0:56c5742b9e2b 98 return(ZBAR_NONE);
RyoheiHagimoto 0:56c5742b9e2b 99 }
RyoheiHagimoto 0:56c5742b9e2b 100
RyoheiHagimoto 0:56c5742b9e2b 101 unsigned zbar_scanner_get_width (const zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 102 {
RyoheiHagimoto 0:56c5742b9e2b 103 return(scn->width);
RyoheiHagimoto 0:56c5742b9e2b 104 }
RyoheiHagimoto 0:56c5742b9e2b 105
RyoheiHagimoto 0:56c5742b9e2b 106 unsigned zbar_scanner_get_edge (const zbar_scanner_t *scn,
RyoheiHagimoto 0:56c5742b9e2b 107 unsigned offset,
RyoheiHagimoto 0:56c5742b9e2b 108 int prec)
RyoheiHagimoto 0:56c5742b9e2b 109 {
RyoheiHagimoto 0:56c5742b9e2b 110 unsigned edge = scn->last_edge - offset - (1 << ZBAR_FIXED) - ROUND;
RyoheiHagimoto 0:56c5742b9e2b 111 prec = ZBAR_FIXED - prec;
RyoheiHagimoto 0:56c5742b9e2b 112 if(prec > 0)
RyoheiHagimoto 0:56c5742b9e2b 113 return(edge >> prec);
RyoheiHagimoto 0:56c5742b9e2b 114 else if(!prec)
RyoheiHagimoto 0:56c5742b9e2b 115 return(edge);
RyoheiHagimoto 0:56c5742b9e2b 116 else
RyoheiHagimoto 0:56c5742b9e2b 117 return(edge << -prec);
RyoheiHagimoto 0:56c5742b9e2b 118 }
RyoheiHagimoto 0:56c5742b9e2b 119
RyoheiHagimoto 0:56c5742b9e2b 120 zbar_color_t zbar_scanner_get_color (const zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 121 {
RyoheiHagimoto 0:56c5742b9e2b 122 return((scn->y1_sign <= 0) ? ZBAR_SPACE : ZBAR_BAR);
RyoheiHagimoto 0:56c5742b9e2b 123 }
RyoheiHagimoto 0:56c5742b9e2b 124
RyoheiHagimoto 0:56c5742b9e2b 125 static inline unsigned calc_thresh (zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 126 {
RyoheiHagimoto 0:56c5742b9e2b 127 /* threshold 1st to improve noise rejection */
RyoheiHagimoto 0:56c5742b9e2b 128 unsigned thresh = scn->y1_thresh;
RyoheiHagimoto 0:56c5742b9e2b 129 if((thresh <= scn->y1_min_thresh) || !scn->width) {
RyoheiHagimoto 0:56c5742b9e2b 130 dprintf(1, " tmin=%d", scn->y1_min_thresh);
RyoheiHagimoto 0:56c5742b9e2b 131 return(scn->y1_min_thresh);
RyoheiHagimoto 0:56c5742b9e2b 132 }
RyoheiHagimoto 0:56c5742b9e2b 133 /* slowly return threshold to min */
RyoheiHagimoto 0:56c5742b9e2b 134 unsigned dx = (scn->x << ZBAR_FIXED) - scn->last_edge;
RyoheiHagimoto 0:56c5742b9e2b 135 unsigned long t = thresh * dx;
RyoheiHagimoto 0:56c5742b9e2b 136 t /= scn->width;
RyoheiHagimoto 0:56c5742b9e2b 137 t /= ZBAR_SCANNER_THRESH_FADE;
RyoheiHagimoto 0:56c5742b9e2b 138 dprintf(1, " thr=%d t=%ld x=%d last=%d.%d (%d)",
RyoheiHagimoto 0:56c5742b9e2b 139 thresh, t, scn->x, scn->last_edge >> ZBAR_FIXED,
RyoheiHagimoto 0:56c5742b9e2b 140 scn->last_edge & ((1 << ZBAR_FIXED) - 1), dx);
RyoheiHagimoto 0:56c5742b9e2b 141 if(thresh > t) {
RyoheiHagimoto 0:56c5742b9e2b 142 thresh -= t;
RyoheiHagimoto 0:56c5742b9e2b 143 if(thresh > scn->y1_min_thresh)
RyoheiHagimoto 0:56c5742b9e2b 144 return(thresh);
RyoheiHagimoto 0:56c5742b9e2b 145 }
RyoheiHagimoto 0:56c5742b9e2b 146 scn->y1_thresh = scn->y1_min_thresh;
RyoheiHagimoto 0:56c5742b9e2b 147 return(scn->y1_min_thresh);
RyoheiHagimoto 0:56c5742b9e2b 148 }
RyoheiHagimoto 0:56c5742b9e2b 149
RyoheiHagimoto 0:56c5742b9e2b 150 static inline zbar_symbol_type_t process_edge (zbar_scanner_t *scn,
RyoheiHagimoto 0:56c5742b9e2b 151 int y1)
RyoheiHagimoto 0:56c5742b9e2b 152 {
RyoheiHagimoto 0:56c5742b9e2b 153 if(!scn->y1_sign)
RyoheiHagimoto 0:56c5742b9e2b 154 scn->last_edge = scn->cur_edge = (1 << ZBAR_FIXED) + ROUND;
RyoheiHagimoto 0:56c5742b9e2b 155 else if(!scn->last_edge)
RyoheiHagimoto 0:56c5742b9e2b 156 scn->last_edge = scn->cur_edge;
RyoheiHagimoto 0:56c5742b9e2b 157
RyoheiHagimoto 0:56c5742b9e2b 158 scn->width = scn->cur_edge - scn->last_edge;
RyoheiHagimoto 0:56c5742b9e2b 159 dprintf(1, " sgn=%d cur=%d.%d w=%d (%s)\n",
RyoheiHagimoto 0:56c5742b9e2b 160 scn->y1_sign, scn->cur_edge >> ZBAR_FIXED,
RyoheiHagimoto 0:56c5742b9e2b 161 scn->cur_edge & ((1 << ZBAR_FIXED) - 1), scn->width,
RyoheiHagimoto 0:56c5742b9e2b 162 ((y1 > 0) ? "SPACE" : "BAR"));
RyoheiHagimoto 0:56c5742b9e2b 163 scn->last_edge = scn->cur_edge;
RyoheiHagimoto 0:56c5742b9e2b 164
RyoheiHagimoto 0:56c5742b9e2b 165 #if DEBUG_SVG > 1
RyoheiHagimoto 0:56c5742b9e2b 166 svg_path_moveto(SVG_ABS, scn->last_edge - (1 << ZBAR_FIXED) - ROUND, 0);
RyoheiHagimoto 0:56c5742b9e2b 167 #endif
RyoheiHagimoto 0:56c5742b9e2b 168
RyoheiHagimoto 0:56c5742b9e2b 169 /* pass to decoder */
RyoheiHagimoto 0:56c5742b9e2b 170 if(scn->decoder)
RyoheiHagimoto 0:56c5742b9e2b 171 return(zbar_decode_width(scn->decoder, scn->width));
RyoheiHagimoto 0:56c5742b9e2b 172 return(ZBAR_PARTIAL);
RyoheiHagimoto 0:56c5742b9e2b 173 }
RyoheiHagimoto 0:56c5742b9e2b 174
RyoheiHagimoto 0:56c5742b9e2b 175 inline zbar_symbol_type_t zbar_scanner_flush (zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 176 {
RyoheiHagimoto 0:56c5742b9e2b 177 if(!scn->y1_sign)
RyoheiHagimoto 0:56c5742b9e2b 178 return(ZBAR_NONE);
RyoheiHagimoto 0:56c5742b9e2b 179
RyoheiHagimoto 0:56c5742b9e2b 180 unsigned x = (scn->x << ZBAR_FIXED) + ROUND;
RyoheiHagimoto 0:56c5742b9e2b 181
RyoheiHagimoto 0:56c5742b9e2b 182 if(scn->cur_edge != x || scn->y1_sign > 0) {
RyoheiHagimoto 0:56c5742b9e2b 183 dprintf(1, "flush0:");
RyoheiHagimoto 0:56c5742b9e2b 184 zbar_symbol_type_t edge = process_edge(scn, -scn->y1_sign);
RyoheiHagimoto 0:56c5742b9e2b 185 scn->cur_edge = x;
RyoheiHagimoto 0:56c5742b9e2b 186 scn->y1_sign = -scn->y1_sign;
RyoheiHagimoto 0:56c5742b9e2b 187 return(edge);
RyoheiHagimoto 0:56c5742b9e2b 188 }
RyoheiHagimoto 0:56c5742b9e2b 189
RyoheiHagimoto 0:56c5742b9e2b 190 scn->y1_sign = scn->width = 0;
RyoheiHagimoto 0:56c5742b9e2b 191 if(scn->decoder)
RyoheiHagimoto 0:56c5742b9e2b 192 return(zbar_decode_width(scn->decoder, 0));
RyoheiHagimoto 0:56c5742b9e2b 193 return(ZBAR_PARTIAL);
RyoheiHagimoto 0:56c5742b9e2b 194 }
RyoheiHagimoto 0:56c5742b9e2b 195
RyoheiHagimoto 0:56c5742b9e2b 196 zbar_symbol_type_t zbar_scanner_new_scan (zbar_scanner_t *scn)
RyoheiHagimoto 0:56c5742b9e2b 197 {
RyoheiHagimoto 0:56c5742b9e2b 198 zbar_symbol_type_t edge = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 199 while(scn->y1_sign) {
RyoheiHagimoto 0:56c5742b9e2b 200 zbar_symbol_type_t tmp = zbar_scanner_flush(scn);
RyoheiHagimoto 0:56c5742b9e2b 201 if(tmp < 0 || tmp > edge)
RyoheiHagimoto 0:56c5742b9e2b 202 edge = tmp;
RyoheiHagimoto 0:56c5742b9e2b 203 }
RyoheiHagimoto 0:56c5742b9e2b 204
RyoheiHagimoto 0:56c5742b9e2b 205 /* reset scanner and associated decoder */
RyoheiHagimoto 0:56c5742b9e2b 206 memset(&scn->x, 0, sizeof(zbar_scanner_t) + (void*)scn - (void*)&scn->x);
RyoheiHagimoto 0:56c5742b9e2b 207 scn->y1_thresh = scn->y1_min_thresh;
RyoheiHagimoto 0:56c5742b9e2b 208 if(scn->decoder)
RyoheiHagimoto 0:56c5742b9e2b 209 zbar_decoder_new_scan(scn->decoder);
RyoheiHagimoto 0:56c5742b9e2b 210 return(edge);
RyoheiHagimoto 0:56c5742b9e2b 211 }
RyoheiHagimoto 0:56c5742b9e2b 212
RyoheiHagimoto 0:56c5742b9e2b 213 zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn,
RyoheiHagimoto 0:56c5742b9e2b 214 int y)
RyoheiHagimoto 0:56c5742b9e2b 215 {
RyoheiHagimoto 0:56c5742b9e2b 216 /* FIXME calc and clip to max y range... */
RyoheiHagimoto 0:56c5742b9e2b 217 /* retrieve short value history */
RyoheiHagimoto 0:56c5742b9e2b 218 register int x = scn->x;
RyoheiHagimoto 0:56c5742b9e2b 219 register int y0_1 = scn->y0[(x - 1) & 3];
RyoheiHagimoto 0:56c5742b9e2b 220 register int y0_0 = y0_1;
RyoheiHagimoto 0:56c5742b9e2b 221 if(x) {
RyoheiHagimoto 0:56c5742b9e2b 222 /* update weighted moving average */
RyoheiHagimoto 0:56c5742b9e2b 223 y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZBAR_FIXED;
RyoheiHagimoto 0:56c5742b9e2b 224 scn->y0[x & 3] = y0_0;
RyoheiHagimoto 0:56c5742b9e2b 225 }
RyoheiHagimoto 0:56c5742b9e2b 226 else
RyoheiHagimoto 0:56c5742b9e2b 227 y0_0 = y0_1 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y;
RyoheiHagimoto 0:56c5742b9e2b 228 register int y0_2 = scn->y0[(x - 2) & 3];
RyoheiHagimoto 0:56c5742b9e2b 229 register int y0_3 = scn->y0[(x - 3) & 3];
RyoheiHagimoto 0:56c5742b9e2b 230 /* 1st differential @ x-1 */
RyoheiHagimoto 0:56c5742b9e2b 231 register int y1_1 = y0_1 - y0_2;
RyoheiHagimoto 0:56c5742b9e2b 232 {
RyoheiHagimoto 0:56c5742b9e2b 233 register int y1_2 = y0_2 - y0_3;
RyoheiHagimoto 0:56c5742b9e2b 234 if((abs(y1_1) < abs(y1_2)) &&
RyoheiHagimoto 0:56c5742b9e2b 235 ((y1_1 >= 0) == (y1_2 >= 0)))
RyoheiHagimoto 0:56c5742b9e2b 236 y1_1 = y1_2;
RyoheiHagimoto 0:56c5742b9e2b 237 }
RyoheiHagimoto 0:56c5742b9e2b 238
RyoheiHagimoto 0:56c5742b9e2b 239 /* 2nd differentials @ x-1 & x-2 */
RyoheiHagimoto 0:56c5742b9e2b 240 register int y2_1 = y0_0 - (y0_1 * 2) + y0_2;
RyoheiHagimoto 0:56c5742b9e2b 241 register int y2_2 = y0_1 - (y0_2 * 2) + y0_3;
RyoheiHagimoto 0:56c5742b9e2b 242
RyoheiHagimoto 0:56c5742b9e2b 243 dprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d",
RyoheiHagimoto 0:56c5742b9e2b 244 x, y, y0_1, y1_1, y2_1);
RyoheiHagimoto 0:56c5742b9e2b 245
RyoheiHagimoto 0:56c5742b9e2b 246 zbar_symbol_type_t edge = ZBAR_NONE;
RyoheiHagimoto 0:56c5742b9e2b 247 /* 2nd zero-crossing is 1st local min/max - could be edge */
RyoheiHagimoto 0:56c5742b9e2b 248 if((!y2_1 ||
RyoheiHagimoto 0:56c5742b9e2b 249 ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) &&
RyoheiHagimoto 0:56c5742b9e2b 250 (calc_thresh(scn) <= abs(y1_1)))
RyoheiHagimoto 0:56c5742b9e2b 251 {
RyoheiHagimoto 0:56c5742b9e2b 252 /* check for 1st sign change */
RyoheiHagimoto 0:56c5742b9e2b 253 char y1_rev = (scn->y1_sign > 0) ? y1_1 < 0 : y1_1 > 0;
RyoheiHagimoto 0:56c5742b9e2b 254 if(y1_rev)
RyoheiHagimoto 0:56c5742b9e2b 255 /* intensity change reversal - finalize previous edge */
RyoheiHagimoto 0:56c5742b9e2b 256 edge = process_edge(scn, y1_1);
RyoheiHagimoto 0:56c5742b9e2b 257
RyoheiHagimoto 0:56c5742b9e2b 258 if(y1_rev || (abs(scn->y1_sign) < abs(y1_1))) {
RyoheiHagimoto 0:56c5742b9e2b 259 scn->y1_sign = y1_1;
RyoheiHagimoto 0:56c5742b9e2b 260
RyoheiHagimoto 0:56c5742b9e2b 261 /* adaptive thresholding */
RyoheiHagimoto 0:56c5742b9e2b 262 /* start at multiple of new min/max */
RyoheiHagimoto 0:56c5742b9e2b 263 scn->y1_thresh = (abs(y1_1) * THRESH_INIT + ROUND) >> ZBAR_FIXED;
RyoheiHagimoto 0:56c5742b9e2b 264 dprintf(1, "\tthr=%d", scn->y1_thresh);
RyoheiHagimoto 0:56c5742b9e2b 265 if(scn->y1_thresh < scn->y1_min_thresh)
RyoheiHagimoto 0:56c5742b9e2b 266 scn->y1_thresh = scn->y1_min_thresh;
RyoheiHagimoto 0:56c5742b9e2b 267
RyoheiHagimoto 0:56c5742b9e2b 268 /* update current edge */
RyoheiHagimoto 0:56c5742b9e2b 269 int d = y2_1 - y2_2;
RyoheiHagimoto 0:56c5742b9e2b 270 scn->cur_edge = 1 << ZBAR_FIXED;
RyoheiHagimoto 0:56c5742b9e2b 271 if(!d)
RyoheiHagimoto 0:56c5742b9e2b 272 scn->cur_edge >>= 1;
RyoheiHagimoto 0:56c5742b9e2b 273 else if(y2_1)
RyoheiHagimoto 0:56c5742b9e2b 274 /* interpolate zero crossing */
RyoheiHagimoto 0:56c5742b9e2b 275 scn->cur_edge -= ((y2_1 << ZBAR_FIXED) + 1) / d;
RyoheiHagimoto 0:56c5742b9e2b 276 scn->cur_edge += x << ZBAR_FIXED;
RyoheiHagimoto 0:56c5742b9e2b 277 dprintf(1, "\n");
RyoheiHagimoto 0:56c5742b9e2b 278 }
RyoheiHagimoto 0:56c5742b9e2b 279 }
RyoheiHagimoto 0:56c5742b9e2b 280 else
RyoheiHagimoto 0:56c5742b9e2b 281 dprintf(1, "\n");
RyoheiHagimoto 0:56c5742b9e2b 282 /* FIXME add fall-thru pass to decoder after heuristic "idle" period
RyoheiHagimoto 0:56c5742b9e2b 283 (eg, 6-8 * last width) */
RyoheiHagimoto 0:56c5742b9e2b 284 scn->x = x + 1;
RyoheiHagimoto 0:56c5742b9e2b 285 return(edge);
RyoheiHagimoto 0:56c5742b9e2b 286 }
RyoheiHagimoto 0:56c5742b9e2b 287
RyoheiHagimoto 0:56c5742b9e2b 288 /* undocumented API for drawing cutesy debug graphics */
RyoheiHagimoto 0:56c5742b9e2b 289 void zbar_scanner_get_state (const zbar_scanner_t *scn,
RyoheiHagimoto 0:56c5742b9e2b 290 unsigned *x,
RyoheiHagimoto 0:56c5742b9e2b 291 unsigned *cur_edge,
RyoheiHagimoto 0:56c5742b9e2b 292 unsigned *last_edge,
RyoheiHagimoto 0:56c5742b9e2b 293 int *y0,
RyoheiHagimoto 0:56c5742b9e2b 294 int *y1,
RyoheiHagimoto 0:56c5742b9e2b 295 int *y2,
RyoheiHagimoto 0:56c5742b9e2b 296 int *y1_thresh)
RyoheiHagimoto 0:56c5742b9e2b 297 {
RyoheiHagimoto 0:56c5742b9e2b 298 register int y0_0 = scn->y0[(scn->x - 1) & 3];
RyoheiHagimoto 0:56c5742b9e2b 299 register int y0_1 = scn->y0[(scn->x - 2) & 3];
RyoheiHagimoto 0:56c5742b9e2b 300 register int y0_2 = scn->y0[(scn->x - 3) & 3];
RyoheiHagimoto 0:56c5742b9e2b 301 if(x) *x = scn->x - 1;
RyoheiHagimoto 0:56c5742b9e2b 302 if(cur_edge) *cur_edge = scn->cur_edge;
RyoheiHagimoto 0:56c5742b9e2b 303 if(last_edge) *last_edge = scn->last_edge;
RyoheiHagimoto 0:56c5742b9e2b 304 if(y0) *y0 = y0_1;
RyoheiHagimoto 0:56c5742b9e2b 305 if(y1) *y1 = y0_1 - y0_2;
RyoheiHagimoto 0:56c5742b9e2b 306 if(y2) *y2 = y0_0 - (y0_1 * 2) + y0_2;
RyoheiHagimoto 0:56c5742b9e2b 307 /* NB not quite accurate (uses updated x) */
RyoheiHagimoto 0:56c5742b9e2b 308 zbar_scanner_t *mut_scn = (zbar_scanner_t*)scn;
RyoheiHagimoto 0:56c5742b9e2b 309 if(y1_thresh) *y1_thresh = calc_thresh(mut_scn);
RyoheiHagimoto 0:56c5742b9e2b 310 dprintf(1, "\n");
RyoheiHagimoto 0:56c5742b9e2b 311 }
RyoheiHagimoto 0:56c5742b9e2b 312