const zbar_symbol_set_t* zbar_processor_get_results (const zbar_processor_t *proc) { zbar_processor_t *ncproc = (zbar_processor_t*)proc; proc_enter(ncproc); const zbar_symbol_set_t *syms = proc->syms; if(syms) zbar_symbol_set_ref(syms, 1); proc_leave(ncproc); return(syms); }
JNIEXPORT jlong JNICALL Java_net_sourceforge_zbar_Image_getSymbols (JNIEnv *env, jobject obj, jlong peer) { const zbar_symbol_set_t *zsyms = zbar_image_get_symbols(PEER_CAST(peer)); if(zsyms) { zbar_symbol_set_ref(zsyms, 1); stats.SymbolSet_create++; } return((intptr_t)zsyms); }
void _zbar_symbol_free (zbar_symbol_t *sym) { if(sym->syms) { zbar_symbol_set_ref(sym->syms, -1); sym->syms = NULL; } if(sym->pts) free(sym->pts); if(sym->data_alloc && sym->data) free(sym->data); free(sym); }
zbarSymbolSet* zbarSymbolSet_FromSymbolSet(const zbar_symbol_set_t *zsyms) { zbarSymbolSet *self = PyObject_New(zbarSymbolSet, &zbarSymbolSet_Type); if(!self) return(NULL); if(zsyms) { zbar_symbol_set_t *ncsyms = (zbar_symbol_set_t*)zsyms; zbar_symbol_set_ref(ncsyms, 1); } self->zsyms = zsyms; return(self); }
int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img) { /* timestamp image * FIXME prefer video timestamp */ #if _POSIX_TIMERS > 0 struct timespec abstime; clock_gettime(CLOCK_REALTIME, &abstime); iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_nsec / 500000) + 1) / 2; #else struct timeval abstime; gettimeofday(&abstime, NULL); iscn->time = (abstime.tv_sec * 1000) + ((abstime.tv_usec / 500) + 1) / 2; #endif #ifdef ENABLE_QRCODE _zbar_qr_reset(iscn->qr); #endif /* get grayscale image, convert if necessary */ if(img->format != fourcc('Y','8','0','0') && img->format != fourcc('G','R','E','Y')){ printf("ERROR: zbar unsupported format: %x ", img->format); return(-1); } iscn->img = img; /* recycle previous scanner and image results */ zbar_image_scanner_recycle_image(iscn, img); zbar_symbol_set_t *syms = iscn->syms; if(!syms) { syms = iscn->syms = _zbar_symbol_set_create(); STAT(syms_new); zbar_symbol_set_ref(syms, 1); } else zbar_symbol_set_ref(syms, 2); img->syms = syms; unsigned w = img->width; unsigned h = img->height; const uint8_t *data = img->data; zbar_image_write_png(img, "debug.png"); svg_open("debug.svg", 0, 0, w, h); svg_image("debug.png", w, h); zbar_scanner_t *scn = iscn->scn; int density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { svg_group_start("scanner", 0, 1, 1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; iscn->dy = 0; int border = (((h - 1) % density) + 1) / 2; if(border > h / 2) border = h / 2; movedelta(0, border); iscn->v = y; zbar_scanner_new_scan(scn); while(y < h) { zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; iscn->umin = 0; while(x < w) { uint8_t d = *p; movedelta(1, 0); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(-1, density); iscn->v = y; if(y >= h) break; zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; iscn->umin = w; while(x >= 0) { uint8_t d = *p; movedelta(-1, 0); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(1, density); iscn->v = y; } svg_group_end(); } iscn->dx = 0; density = CFG(iscn, ZBAR_CFG_X_DENSITY); if(density > 0) { svg_group_start("scanner", 90, 1, -1, 0, 0); const uint8_t *p = data; int x = 0, y = 0; int border = (((w - 1) % density) + 1) / 2; if(border > w / 2) border = w / 2; movedelta(border, 0); iscn->v = x; while(x < w) { zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; iscn->umin = 0; while(y < h) { uint8_t d = *p; movedelta(0, 1); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(density, -1); iscn->v = x; if(x >= w) break; zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; iscn->umin = h; while(y >= 0) { uint8_t d = *p; movedelta(0, -1); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(density, 1); iscn->v = x; } svg_group_end(); } iscn->dy = 0; iscn->img = NULL; #ifdef ENABLE_QRCODE _zbar_qr_decode(iscn->qr, iscn, img); #endif /* FIXME tmp hack to filter bad EAN results */ if(syms->nsyms && !iscn->enable_cache && (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)) { zbar_symbol_t **symp = &syms->head, *sym; while((sym = *symp)) { if(sym->type < ZBAR_I25 && sym->type > ZBAR_PARTIAL && sym->quality < 3) { /* recycle */ *symp = sym->next; syms->nsyms--; sym->next = NULL; _zbar_image_scanner_recycle_syms(iscn, sym); } else symp = &sym->next; } } if(syms->nsyms && iscn->handler) iscn->handler(img, iscn->userdata); svg_close(); return(syms->nsyms); }
inline int zbar_window_redraw (zbar_window_t *w) { if(window_lock(w)) return(-1); if(!w->display || _zbar_window_begin(w)) { (void)window_unlock(w); return(-1); } int rc = 0; zbar_image_t *img = w->image; if(w->init && w->draw_image && img) { int format_change = (w->src_format != img->format && w->format != img->format); if(format_change) { _zbar_best_format(img->format, &w->format, w->formats); if(!w->format) rc = err_capture_int(w, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no conversion from %x to supported formats", img->format); w->src_format = img->format; } if(!rc && (format_change || !w->scaled_size.x || !w->dst_width)) { zprintf(24, "init: src=%.4s(%08lx) %dx%d dst=%.4s(%08lx) %dx%d\n", (char*)&w->src_format, w->src_format, w->src_width, w->src_height, (char*)&w->format, w->format, w->dst_width, w->dst_height); if(!w->dst_width) { w->src_width = img->width; w->src_height = img->height; } point_t size = { w->width, w->height }; if(size.x > w->max_width) size.x = w->max_width; if(size.y > w->max_height) size.y = w->max_height; if(size.x * w->src_height < size.y * w->src_width) { w->scale_num = size.x; w->scale_den = w->src_width; } else { w->scale_num = size.y; w->scale_den = w->src_height; } rc = w->init(w, img, format_change); if(!rc) { size.x = w->src_width; size.y = w->src_height; w->scaled_size = size = window_scale_pt(w, size); w->scaled_offset.x = ((int)w->width - size.x) / 2; w->scaled_offset.y = ((int)w->height - size.y) / 2; zprintf(24, "scale: src=%dx%d win=%dx%d by %d/%d => %dx%d @%d,%d\n", w->src_width, w->src_height, w->width, w->height, w->scale_num, w->scale_den, size.x, size.y, w->scaled_offset.x, w->scaled_offset.y); } else { /* unable to display this image */ _zbar_image_refcnt(img, -1); w->image = img = NULL; } } if(!rc && (img->format != w->format || img->width != w->dst_width || img->height != w->dst_height)) { /* save *converted* image for redraw */ zprintf(48, "convert: %.4s(%08lx) %dx%d => %.4s(%08lx) %dx%d\n", (char*)&img->format, img->format, img->width, img->height, (char*)&w->format, w->format, w->dst_width, w->dst_height); w->image = zbar_image_convert_resize(img, w->format, w->dst_width, w->dst_height); w->image->syms = img->syms; if(img->syms) zbar_symbol_set_ref(img->syms, 1); zbar_image_destroy(img); img = w->image; } if(!rc) { rc = w->draw_image(w, img); point_t org = w->scaled_offset; if(org.x > 0) { point_t p = { 0, org.y }; point_t s = { org.x, w->scaled_size.y }; _zbar_window_fill_rect(w, 0, p, s); s.x = w->width - w->scaled_size.x - s.x; if(s.x > 0) { p.x = w->width - s.x; _zbar_window_fill_rect(w, 0, p, s); } } if(org.y > 0) { point_t p = { 0, 0 }; point_t s = { w->width, org.y }; _zbar_window_fill_rect(w, 0, p, s); s.y = w->height - w->scaled_size.y - s.y; if(s.y > 0) { p.y = w->height - s.y; _zbar_window_fill_rect(w, 0, p, s); } } } if(!rc) rc = window_draw_overlay(w); } else rc = 1; if(rc) rc = _zbar_window_draw_logo(w); _zbar_window_end(w); (void)window_unlock(w); return(rc); }
int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img) { zbar_symbol_set_t *syms; const uint8_t *data; zbar_scanner_t *scn = iscn->scn; unsigned w, h, cx1, cy1; int density; /* timestamp image * FIXME prefer video timestamp */ iscn->time = _zbar_timer_now(); #ifdef ENABLE_QRCODE _zbar_qr_reset(iscn->qr); #endif /* image must be in grayscale format */ if(img->format != fourcc('Y','8','0','0') && img->format != fourcc('G','R','E','Y')) return(-1); iscn->img = img; /* recycle previous scanner and image results */ zbar_image_scanner_recycle_image(iscn, img); syms = iscn->syms; if(!syms) { syms = iscn->syms = _zbar_symbol_set_create(); STAT(syms_new); zbar_symbol_set_ref(syms, 1); } else zbar_symbol_set_ref(syms, 2); img->syms = syms; w = img->width; h = img->height; cx1 = img->crop_x + img->crop_w; assert(cx1 <= w); cy1 = img->crop_y + img->crop_h; assert(cy1 <= h); data = img->data; zbar_image_write_png(img, "debug.png"); svg_open("debug.svg", 0, 0, w, h); svg_image("debug.png", w, h); zbar_scanner_new_scan(scn); density = CFG(iscn, ZBAR_CFG_Y_DENSITY); if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; int border = (((img->crop_h - 1) % density) + 1) / 2; if(border > img->crop_h / 2) border = img->crop_h / 2; border += img->crop_y; assert(border <= h); svg_group_start("scanner", 0, 1, 1, 0, 0); iscn->dy = 0; movedelta(img->crop_x, border); iscn->v = y; while(y < cy1) { int cx0 = img->crop_x;; zprintf(128, "img_x+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, y + 0.5); iscn->dx = iscn->du = 1; iscn->umin = cx0; while(x < cx1) { uint8_t d = *p; movedelta(1, 0); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(-1, density); iscn->v = y; if(y >= cy1) break; zprintf(128, "img_x-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, w, y + 0.5); iscn->dx = iscn->du = -1; iscn->umin = cx1; while(x >= cx0) { uint8_t d = *p; movedelta(-1, 0); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(1, density); iscn->v = y; } svg_group_end(); } iscn->dx = 0; density = CFG(iscn, ZBAR_CFG_X_DENSITY); if(density > 0) { const uint8_t *p = data; int x = 0, y = 0; int border = (((img->crop_w - 1) % density) + 1) / 2; if(border > img->crop_w / 2) border = img->crop_w / 2; border += img->crop_x; assert(border <= w); svg_group_start("scanner", 90, 1, -1, 0, 0); movedelta(border, img->crop_y); iscn->v = x; while(x < cx1) { int cy0 = img->crop_y; zprintf(128, "img_y+: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", 1. / 32, 0, x + 0.5); iscn->dy = iscn->du = 1; iscn->umin = cy0; while(y < cy1) { uint8_t d = *p; movedelta(0, 1); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(density, -1); iscn->v = x; if(x >= cx1) break; zprintf(128, "img_y-: %04d,%04d @%p\n", x, y, p); svg_path_start("vedge", -1. / 32, h, x + 0.5); iscn->dy = iscn->du = -1; iscn->umin = cy1; while(y >= cy0) { uint8_t d = *p; movedelta(0, -1); zbar_scan_y(scn, d); } ASSERT_POS; quiet_border(iscn); svg_path_end(); movedelta(density, 1); iscn->v = x; } svg_group_end(); } iscn->dy = 0; iscn->img = NULL; #ifdef ENABLE_QRCODE _zbar_qr_decode(iscn->qr, iscn, img); #endif /* FIXME tmp hack to filter bad EAN results */ /* FIXME tmp hack to merge simple case EAN add-ons */ char filter = (!iscn->enable_cache && (density == 1 || CFG(iscn, ZBAR_CFG_Y_DENSITY) == 1)); int nean = 0, naddon = 0; if(syms->nsyms) { zbar_symbol_t **symp; for(symp = &syms->head; *symp; ) { zbar_symbol_t *sym = *symp; if(sym->cache_count <= 0 && ((sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) || sym->type == ZBAR_DATABAR || sym->type == ZBAR_DATABAR_EXP || sym->type == ZBAR_CODABAR)) { if((sym->type == ZBAR_CODABAR || filter) && sym->quality < 4) { if(iscn->enable_cache) { /* revert cache update */ zbar_symbol_t *entry = cache_lookup(iscn, sym); if(entry) entry->cache_count--; else assert(0); } /* recycle */ *symp = sym->next; syms->nsyms--; sym->next = NULL; _zbar_image_scanner_recycle_syms(iscn, sym); continue; } else if(sym->type < ZBAR_COMPOSITE && sym->type != ZBAR_ISBN10) { if(sym->type > ZBAR_EAN5) nean++; else naddon++; } } symp = &sym->next; } if(nean == 1 && naddon == 1 && iscn->ean_config) { /* create container symbol for composite result */ zbar_symbol_t *ean = NULL, *addon = NULL; for(symp = &syms->head; *symp; ) { zbar_symbol_t *sym = *symp; if(sym->type < ZBAR_COMPOSITE && sym->type > ZBAR_PARTIAL) { /* move to composite */ *symp = sym->next; syms->nsyms--; sym->next = NULL; if(sym->type <= ZBAR_EAN5) addon = sym; else ean = sym; } else symp = &sym->next; } assert(ean); assert(addon); int datalen = ean->datalen + addon->datalen + 1; zbar_symbol_t *ean_sym = _zbar_image_scanner_alloc_sym(iscn, ZBAR_COMPOSITE, datalen); ean_sym->orient = ean->orient; ean_sym->syms = _zbar_symbol_set_create(); memcpy(ean_sym->data, ean->data, ean->datalen); memcpy(ean_sym->data + ean->datalen, addon->data, addon->datalen + 1); ean_sym->syms->head = ean; ean->next = addon; ean_sym->syms->nsyms = 2; _zbar_image_scanner_add_sym(iscn, ean_sym); } } if(syms->nsyms && iscn->handler) iscn->handler(img, iscn->userdata); svg_close(); return(syms->nsyms); }
/* API lock is already held */ int _zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { uint32_t force_fmt = proc->force_output; int nsyms, rc; if(img) { zbar_image_t *tmp; uint32_t format = zbar_image_get_format(img); zprintf(16, "processing: %.4s(%08lx) %dx%d @%p\n", (char*)&format, format, zbar_image_get_width(img), zbar_image_get_height(img), zbar_image_get_data(img)); /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ tmp = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!tmp) goto error; if(proc->syms) { zbar_symbol_set_ref(proc->syms, -1); proc->syms = NULL; } zbar_image_scanner_recycle_image(proc->scanner, img); nsyms = zbar_scan_image(proc->scanner, tmp); _zbar_image_swap_symbols(img, tmp); zbar_image_destroy(tmp); tmp = NULL; if(nsyms < 0) goto error; proc->syms = zbar_image_scanner_get_results(proc->scanner); if(proc->syms) zbar_symbol_set_ref(proc->syms, 1); if(_zbar_verbosity >= 8) { const zbar_symbol_t *sym = zbar_image_first_symbol(img); while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); zprintf(8, "%s%s: %s (%d pts) (q=%d) (%s)\n", zbar_get_symbol_name(type), zbar_get_addon_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), zbar_symbol_get_quality(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zbar_symbol_next(sym); } } if(nsyms) { /* FIXME only call after filtering */ _zbar_mutex_lock(&proc->mutex); _zbar_processor_notify(proc, EVENT_OUTPUT); _zbar_mutex_unlock(&proc->mutex); if(proc->handler) proc->handler(img, proc->userdata); } if(force_fmt) { zbar_symbol_set_t *syms = img->syms; img = zbar_image_convert(img, force_fmt); if(!img) goto error; img->syms = syms; zbar_symbol_set_ref(syms, 1); } } /* display to window if enabled */ rc = 0; if(force_fmt && img) zbar_image_destroy(img); return(rc); error: return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); }