i25.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*------------------------------------------------------------------------
  2. * Copyright 2008-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 <string.h> /* memmove */
  25. #include <zbar.h>
  26. #include "decoder.h"
  27. #ifdef DEBUG_I25
  28. # define DEBUG_LEVEL (DEBUG_I25)
  29. #endif
  30. #include "debug.h"
  31. static inline unsigned char i25_decode1 (unsigned char enc,
  32. unsigned e,
  33. unsigned s)
  34. {
  35. unsigned char E = decode_e(e, s, 45);
  36. if(E > 7)
  37. return(0xff);
  38. enc <<= 1;
  39. if(E > 2)
  40. enc |= 1;
  41. return(enc);
  42. }
  43. static inline unsigned char i25_decode10 (zbar_decoder_t *dcode,
  44. unsigned char offset)
  45. {
  46. i25_decoder_t *dcode25 = &dcode->i25;
  47. dprintf(2, " s=%d", dcode25->s10);
  48. if(dcode25->s10 < 10)
  49. return(0xff);
  50. /* threshold bar width ratios */
  51. unsigned char enc = 0, par = 0;
  52. signed char i;
  53. for(i = 8; i >= 0; i -= 2) {
  54. unsigned char j = offset + ((dcode25->direction) ? i : 8 - i);
  55. enc = i25_decode1(enc, get_width(dcode, j), dcode25->s10);
  56. if(enc == 0xff)
  57. return(0xff);
  58. if(enc & 1)
  59. par++;
  60. }
  61. dprintf(2, " enc=%02x par=%x", enc, par);
  62. /* parity check */
  63. if(par != 2) {
  64. dprintf(2, " [bad parity]");
  65. return(0xff);
  66. }
  67. /* decode binary weights */
  68. enc &= 0xf;
  69. if(enc & 8) {
  70. if(enc == 12)
  71. enc = 0;
  72. else if(--enc > 9) {
  73. dprintf(2, " [invalid encoding]");
  74. return(0xff);
  75. }
  76. }
  77. dprintf(2, " => %x", enc);
  78. return(enc);
  79. }
  80. static inline signed char i25_decode_start (zbar_decoder_t *dcode)
  81. {
  82. i25_decoder_t *dcode25 = &dcode->i25;
  83. if(dcode25->s10 < 10)
  84. return(ZBAR_NONE);
  85. unsigned char enc = 0;
  86. unsigned char i = 10;
  87. enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
  88. enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
  89. enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10);
  90. if((get_color(dcode) == ZBAR_BAR)
  91. ? enc != 4
  92. : (enc = i25_decode1(enc, get_width(dcode, i++), dcode25->s10))) {
  93. dprintf(4, " i25: s=%d enc=%x [invalid]\n", dcode25->s10, enc);
  94. return(ZBAR_NONE);
  95. }
  96. /* check leading quiet zone - spec is 10n(?)
  97. * we require 5.25n for w=2n to 6.75n for w=3n
  98. * (FIXME should really factor in w:n ratio)
  99. */
  100. unsigned quiet = get_width(dcode, i++);
  101. if(quiet && quiet < dcode25->s10 * 3 / 8) {
  102. dprintf(3, " i25: s=%d enc=%x q=%d [invalid qz]\n",
  103. dcode25->s10, enc, quiet);
  104. return(ZBAR_NONE);
  105. }
  106. dcode25->direction = get_color(dcode);
  107. dcode25->element = 1;
  108. dcode25->character = 0;
  109. return(ZBAR_PARTIAL);
  110. }
  111. static inline signed char i25_decode_end (zbar_decoder_t *dcode)
  112. {
  113. i25_decoder_t *dcode25 = &dcode->i25;
  114. /* check trailing quiet zone */
  115. unsigned quiet = get_width(dcode, 0);
  116. if((quiet && quiet < dcode25->width * 3 / 8) ||
  117. decode_e(get_width(dcode, 1), dcode25->width, 45) > 2 ||
  118. decode_e(get_width(dcode, 2), dcode25->width, 45) > 2) {
  119. dprintf(3, " s=%d q=%d [invalid qz]\n", dcode25->width, quiet);
  120. return(ZBAR_NONE);
  121. }
  122. /* check exit condition */
  123. unsigned char E = decode_e(get_width(dcode, 3), dcode25->width, 45);
  124. if((!dcode25->direction)
  125. ? E - 3 > 4
  126. : (E > 2 ||
  127. decode_e(get_width(dcode, 4), dcode25->width, 45) > 2))
  128. return(ZBAR_NONE);
  129. if(dcode25->direction) {
  130. /* reverse buffer */
  131. dprintf(2, " (rev)");
  132. int i;
  133. for(i = 0; i < dcode25->character / 2; i++) {
  134. unsigned j = dcode25->character - 1 - i;
  135. char c = dcode->buf[i];
  136. dcode->buf[i] = dcode->buf[j];
  137. dcode->buf[j] = c;
  138. }
  139. }
  140. if(dcode25->character < CFG(*dcode25, ZBAR_CFG_MIN_LEN) ||
  141. (CFG(*dcode25, ZBAR_CFG_MAX_LEN) > 0 &&
  142. dcode25->character > CFG(*dcode25, ZBAR_CFG_MAX_LEN))) {
  143. dprintf(2, " [invalid len]\n");
  144. dcode->lock = 0;
  145. dcode25->character = -1;
  146. return(ZBAR_NONE);
  147. }
  148. dcode->buflen = dcode25->character;
  149. dcode->buf[dcode25->character] = '\0';
  150. dprintf(2, " [valid end]\n");
  151. dcode25->character = -1;
  152. return(ZBAR_I25);
  153. }
  154. zbar_symbol_type_t _zbar_decode_i25 (zbar_decoder_t *dcode)
  155. {
  156. i25_decoder_t *dcode25 = &dcode->i25;
  157. /* update latest character width */
  158. dcode25->s10 -= get_width(dcode, 10);
  159. dcode25->s10 += get_width(dcode, 0);
  160. if(dcode25->character < 0 &&
  161. !i25_decode_start(dcode))
  162. return(ZBAR_NONE);
  163. if(--dcode25->element == 6 - dcode25->direction)
  164. return(i25_decode_end(dcode));
  165. else if(dcode25->element)
  166. return(ZBAR_NONE);
  167. /* FIXME check current character width against previous */
  168. dcode25->width = dcode25->s10;
  169. dprintf(2, " i25[%c%02d+%x]",
  170. (dcode25->direction) ? '<' : '>',
  171. dcode25->character, dcode25->element);
  172. /* lock shared resources */
  173. if(!dcode25->character && get_lock(dcode, ZBAR_I25)) {
  174. dcode25->character = -1;
  175. dprintf(2, " [locked %d]\n", dcode->lock);
  176. return(ZBAR_PARTIAL);
  177. }
  178. unsigned char c = i25_decode10(dcode, 1);
  179. dprintf(2, " c=%x", c);
  180. if(c > 9 ||
  181. ((dcode25->character >= BUFFER_MIN) &&
  182. size_buf(dcode, dcode25->character + 2))) {
  183. dprintf(2, (c > 9) ? " [aborted]\n" : " [overflow]\n");
  184. dcode->lock = 0;
  185. dcode25->character = -1;
  186. return(ZBAR_NONE);
  187. }
  188. dcode->buf[dcode25->character++] = c + '0';
  189. c = i25_decode10(dcode, 0);
  190. dprintf(2, " c=%x", c);
  191. if(c > 9) {
  192. dprintf(2, " [aborted]\n");
  193. dcode->lock = 0;
  194. dcode25->character = -1;
  195. return(ZBAR_NONE);
  196. }
  197. else
  198. dprintf(2, "\n");
  199. dcode->buf[dcode25->character++] = c + '0';
  200. dcode25->element = 10;
  201. return((dcode25->character == 2) ? ZBAR_PARTIAL : ZBAR_NONE);
  202. }