From e31ddff4e82d89eb20a6165ab28ee72e0fe1d491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20H=C3=B6hnel?= Date: Sat, 21 Mar 2026 08:48:42 +0100 Subject: [PATCH] Add image enhancement function for upek-sensors --- libfprint/drivers/upeksonly.c | 4 +++ libfprint/drivers/upektc_img.c | 55 +++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/libfprint/drivers/upeksonly.c b/libfprint/drivers/upeksonly.c index e7ea3ce2..33244a74 100644 --- a/libfprint/drivers/upeksonly.c +++ b/libfprint/drivers/upeksonly.c @@ -1489,6 +1489,7 @@ fpi_device_upeksonly_class_init (FpiDeviceUpeksonlyClass *klass) dev_class->type = FP_DEVICE_TYPE_USB; dev_class->id_table = id_table; dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + dev_class->nr_enroll_stages = 10; dev_class->usb_discover = dev_discover; @@ -1546,6 +1547,9 @@ dev_init (FpImageDevice *dev) case UPEKSONLY_2016: self->img_width = IMG_WIDTH_2016; self->assembling_ctx.line_width = IMG_WIDTH_2016; + + /* The sensor resolution is too low for the normal threshold. */ + fpi_image_device_set_bz3_threshold (dev, 20); break; default: diff --git a/libfprint/drivers/upektc_img.c b/libfprint/drivers/upektc_img.c index f2c6edb8..0766c7a6 100644 --- a/libfprint/drivers/upektc_img.c +++ b/libfprint/drivers/upektc_img.c @@ -26,6 +26,54 @@ static void start_capture (FpImageDevice *dev); static void start_deactivation (FpImageDevice *dev); +/* Enhance image for better minutiae detection on small swipe sensors. + * Applies contrast stretching and 2x nearest-neighbor upscale. + * Returns a new FpImage; caller is responsible for the original. */ +static FpImage * +upektc_img_enhance (FpImage *orig) +{ + guint w = orig->width; + guint h = orig->height; + guint new_w = w * 2; + guint new_h = h * 2; + guchar *src = orig->data; + FpImage *enhanced; + guchar *dst; + guint i, x, y; + + /* Step 1: contrast stretch (histogram stretch to full 0-255 range) */ + guchar min_val = 255, max_val = 0; + + for (i = 0; i < w * h; i++) + { + if (src[i] < min_val) + min_val = src[i]; + if (src[i] > max_val) + max_val = src[i]; + } + + if (max_val > min_val) + { + guint range = max_val - min_val; + for (i = 0; i < w * h; i++) + src[i] = (guchar) (((guint) (src[i] - min_val) * 255) / range); + } + + /* Step 2: 2x nearest-neighbor upscale */ + enhanced = fp_image_new (new_w, new_h); + enhanced->flags = orig->flags; + dst = enhanced->data; + + for (y = 0; y < new_h; y++) + { + guint sy = y / 2; + for (x = 0; x < new_w; x++) + dst[y * new_w + x] = src[sy * w + x / 2]; + } + + return enhanced; +} + #define EP_IN (1 | FPI_USB_ENDPOINT_IN) #define EP_OUT (2 | FPI_USB_ENDPOINT_OUT) #define CTRL_TIMEOUT 4000 @@ -335,9 +383,13 @@ capture_read_data_cb (FpiUsbTransfer *transfer, FpDevice *device, fp_dbg ("Image size is %lu", (gulong) self->image_size); img = fp_image_new (img_class->img_width, img_class->img_height); - img->flags |= FPI_IMAGE_PARTIAL; memcpy (img->data, self->image_bits, self->image_size); + { + FpImage *enhanced = upektc_img_enhance (img); + g_object_unref (img); + img = enhanced; + } fpi_image_device_image_captured (dev, img); fpi_image_device_report_finger_status (dev, FALSE); @@ -770,6 +822,7 @@ fpi_device_upektc_img_class_init (FpiDeviceUpektcImgClass *klass) dev_class->type = FP_DEVICE_TYPE_USB; dev_class->id_table = id_table; dev_class->scan_type = FP_SCAN_TYPE_SWIPE; + dev_class->nr_enroll_stages = 10; dev_class->usb_discover = discover; img_class->img_open = dev_init;