zbar_symbol_type_t zbar_scan_y (zbar_scanner_t *scn, int y) { /* FIXME calc and clip to max y range... */ /* retrieve short value history */ register int x = scn->x; register int y0_1 = scn->y0[(x - 1) & 3]; register int y0_0 = y0_1; if(x) { /* update weighted moving average */ y0_0 += ((int)((y - y0_1) * EWMA_WEIGHT)) >> ZBAR_FIXED; scn->y0[x & 3] = y0_0; } else y0_0 = y0_1 = scn->y0[0] = scn->y0[1] = scn->y0[2] = scn->y0[3] = y; register int y0_2 = scn->y0[(x - 2) & 3]; register int y0_3 = scn->y0[(x - 3) & 3]; /* 1st differential @ x-1 */ register int y1_1 = y0_1 - y0_2; { register int y1_2 = y0_2 - y0_3; if((abs(y1_1) < abs(y1_2)) && ((y1_1 >= 0) == (y1_2 >= 0))) y1_1 = y1_2; } /* 2nd differentials @ x-1 & x-2 */ register int y2_1 = y0_0 - (y0_1 * 2) + y0_2; register int y2_2 = y0_1 - (y0_2 * 2) + y0_3; dprintf(1, "scan: x=%d y=%d y0=%d y1=%d y2=%d", x, y, y0_1, y1_1, y2_1); zbar_symbol_type_t edge = ZBAR_NONE; /* 2nd zero-crossing is 1st local min/max - could be edge */ if((!y2_1 || ((y2_1 > 0) ? y2_2 < 0 : y2_2 > 0)) && (calc_thresh(scn) <= abs(y1_1))) { /* check for 1st sign change */ char y1_rev = (scn->y1_sign > 0) ? y1_1 < 0 : y1_1 > 0; if(y1_rev) /* intensity change reversal - finalize previous edge */ edge = process_edge(scn, y1_1); if(y1_rev || (abs(scn->y1_sign) < abs(y1_1))) { scn->y1_sign = y1_1; /* adaptive thresholding */ /* start at multiple of new min/max */ scn->y1_thresh = (abs(y1_1) * THRESH_INIT + ROUND) >> ZBAR_FIXED; dprintf(1, "\tthr=%d", scn->y1_thresh); if(scn->y1_thresh < scn->y1_min_thresh) scn->y1_thresh = scn->y1_min_thresh; /* update current edge */ int d = y2_1 - y2_2; scn->cur_edge = 1 << ZBAR_FIXED; if(!d) scn->cur_edge >>= 1; else if(y2_1) /* interpolate zero crossing */ scn->cur_edge -= ((y2_1 << ZBAR_FIXED) + 1) / d; scn->cur_edge += x << ZBAR_FIXED; dprintf(1, "\n"); } } else dprintf(1, "\n"); /* FIXME add fall-thru pass to decoder after heuristic "idle" period (eg, 6-8 * last width) */ scn->x = x + 1; return(edge); }