scanner.c 9.9 KB

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