From 589e44dad3f8e56fb765e13ce4e34e1dba1060fa Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 17 Nov 2012 15:32:25 +0300 Subject: [PATCH 2/9] aes: unify image processing code for AuthenTec devices Move overlap detection and assembling code into aeslib to prevent code duplication --- libfprint/aeslib.c | 111 +++++++++++++++++++++++++++++++++++ libfprint/aeslib.h | 3 + libfprint/drivers/aes1610.c | 139 ++++---------------------------------------- libfprint/drivers/aes2501.c | 125 ++++----------------------------------- libfprint/drivers/aes2550.c | 125 ++++----------------------------------- 5 files changed, 147 insertions(+), 356 deletions(-) diff --git a/libfprint/aeslib.c b/libfprint/aeslib.c index da9be01..0b01d31 100644 --- a/libfprint/aeslib.c +++ b/libfprint/aeslib.c @@ -20,6 +20,7 @@ #define FP_COMPONENT "aeslib" #include +#include #include #include @@ -171,3 +172,113 @@ void aes_assemble_image(unsigned char *input, size_t width, size_t height, } } +/* find overlapping parts of frames */ +static unsigned int find_overlap(unsigned char *first_frame, + unsigned char *second_frame, unsigned int *min_error, + unsigned int frame_width, unsigned int frame_height) +{ + unsigned int dy; + unsigned int not_overlapped_height = 0; + /* 255 is highest brightness value for an 8bpp image */ + *min_error = 255 * frame_width * frame_height; + for (dy = 0; dy < frame_height; dy++) { + /* Calculating difference (error) between parts of frames */ + unsigned int i; + unsigned int error = 0; + for (i = 0; i < frame_width * (frame_height - dy); i++) { + /* Using ? operator to avoid abs function */ + error += first_frame[i] > second_frame[i] ? + (first_frame[i] - second_frame[i]) : + (second_frame[i] - first_frame[i]); + } + + /* Normalize error */ + error *= 15; + error /= i; + if (error < *min_error) { + *min_error = error; + not_overlapped_height = dy; + } + first_frame += frame_width; + } + + return not_overlapped_height; +} + +/* assemble a series of frames into a single image */ +static unsigned int assemble(GSList *list_entry, size_t num_stripes, + unsigned int frame_width, unsigned int frame_height, + unsigned char *output, gboolean reverse, unsigned int *errors_sum) +{ + uint8_t *assembled = output; + int frame; + uint32_t image_height = frame_height; + unsigned int min_error, frame_size = frame_width * frame_height; + *errors_sum = 0; + + if (reverse) + output += (num_stripes - 1) * frame_size; + for (frame = 0; frame < num_stripes; frame++) { + aes_assemble_image(list_entry->data, frame_width, frame_height, output); + + if (reverse) + output -= frame_size; + else + output += frame_size; + list_entry = g_slist_next(list_entry); + } + + /* Detecting where frames overlaped */ + output = assembled; + for (frame = 1; frame < num_stripes; frame++) { + int not_overlapped; + + output += frame_size; + not_overlapped = find_overlap(assembled, output, &min_error, + frame_width, frame_height); + *errors_sum += min_error; + image_height += not_overlapped; + assembled += frame_width * not_overlapped; + memcpy(assembled, output, frame_size); + } + return image_height; +} + +struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, + unsigned int frame_width, unsigned int frame_height) +{ + size_t final_size; + struct fp_img *img; + unsigned int frame_size = frame_width * frame_height; + unsigned int errors_sum, r_errors_sum; + + BUG_ON(stripes_len == 0); + + /* create buffer big enough for max image */ + img = fpi_img_new(stripes_len * frame_size); + + img->flags = FP_IMG_COLORS_INVERTED; + img->height = assemble(stripes, stripes_len, + frame_width, frame_height, + img->data, FALSE, &errors_sum); + img->height = assemble(stripes, stripes_len, + frame_width, frame_height, + img->data, TRUE, &r_errors_sum); + + if (r_errors_sum > errors_sum) { + img->height = assemble(stripes, stripes_len, + frame_width, frame_height, + img->data, FALSE, &errors_sum); + img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; + fp_dbg("normal scan direction"); + } else { + fp_dbg("reversed scan direction"); + } + + /* now that overlap has been removed, resize output image buffer */ + final_size = img->height * frame_width; + img = fpi_img_resize(img, final_size); + img->width = frame_width; + + return img; +} diff --git a/libfprint/aeslib.h b/libfprint/aeslib.h index 3c65dae..e366262 100644 --- a/libfprint/aeslib.h +++ b/libfprint/aeslib.h @@ -36,5 +36,8 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, void aes_assemble_image(unsigned char *input, size_t width, size_t height, unsigned char *output); +struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, + unsigned int frame_width, unsigned int frame_height); + #endif diff --git a/libfprint/drivers/aes1610.c b/libfprint/drivers/aes1610.c index 96e87b3..a4847fb 100644 --- a/libfprint/drivers/aes1610.c +++ b/libfprint/drivers/aes1610.c @@ -4,6 +4,7 @@ * Copyright (C) 2007 Cyrille Bagard * Copyright (C) 2007 Vasily Khoruzhick * Copyright (C) 2009 Guido Grazioli + * Copyright (C) 2012 Vasily Khoruzhick * * Based on code from libfprint aes2501 driver. * @@ -147,131 +148,6 @@ static void generic_read_ignore_data(struct fpi_ssm *ssm, size_t bytes) } } -/****** IMAGE PROCESSING ******/ - -/* find overlapping parts of frames */ -static unsigned int find_overlap(unsigned char *first_frame, - unsigned char *second_frame, unsigned int *min_error) -{ - unsigned int dy; - unsigned int not_overlapped_height = 0; - *min_error = 255 * FRAME_SIZE; - for (dy = 0; dy < FRAME_HEIGHT; dy++) { - /* Calculating difference (error) between parts of frames */ - unsigned int i; - unsigned int error = 0; - for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) { - /* Using ? operator to avoid abs function */ - error += first_frame[i] > second_frame[i] ? - (first_frame[i] - second_frame[i]) : - (second_frame[i] - first_frame[i]); - } - - /* Normalize error */ - error *= 15; - error /= i; - if (error < *min_error) { - *min_error = error; - not_overlapped_height = dy; - } - first_frame += FRAME_WIDTH; - } - - return not_overlapped_height; -} - -/* assemble a series of frames into a single image */ -static unsigned int assemble(struct aes1610_dev *aesdev, unsigned char *output, - gboolean reverse, unsigned int *errors_sum) -{ - uint8_t *assembled = output; - int frame; - uint32_t image_height = FRAME_HEIGHT; - unsigned int min_error; - size_t num_strips = aesdev->strips_len; - GSList *list_entry = aesdev->strips; - *errors_sum = 0; - - if (num_strips < 1) - return 0; - - /* Rotating given data by 90 degrees - * Taken from document describing aes1610 image format - * TODO: move reversing detection here */ - - if (reverse) - output += (num_strips - 1) * FRAME_SIZE; - for (frame = 0; frame < num_strips; frame++) { - aes_assemble_image(list_entry->data, FRAME_WIDTH, FRAME_HEIGHT, output); - - if (reverse) - output -= FRAME_SIZE; - else - output += FRAME_SIZE; - list_entry = g_slist_next(list_entry); - } - - /* Detecting where frames overlaped */ - output = assembled; - for (frame = 1; frame < num_strips; frame++) { - int not_overlapped; - - output += FRAME_SIZE; - not_overlapped = find_overlap(assembled, output, &min_error); - *errors_sum += min_error; - image_height += not_overlapped; - assembled += FRAME_WIDTH * not_overlapped; - memcpy(assembled, output, FRAME_SIZE); - } - return image_height; -} - -static void assemble_and_submit_image(struct fp_img_dev *dev) -{ - struct aes1610_dev *aesdev = dev->priv; - size_t final_size; - struct fp_img *img; - unsigned int errors_sum, r_errors_sum; - - fp_dbg(""); - - BUG_ON(aesdev->strips_len == 0); - - /* reverse list */ - aesdev->strips = g_slist_reverse(aesdev->strips); - - /* create buffer big enough for max image */ - img = fpi_img_new(aesdev->strips_len * FRAME_SIZE); - - img->flags = FP_IMG_COLORS_INVERTED; - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->height = assemble(aesdev, img->data, TRUE, &r_errors_sum); - - if (r_errors_sum > errors_sum) { - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - fp_dbg("normal scan direction"); - } else { - fp_dbg("reversed scan direction"); - } - - /* now that overlap has been removed, resize output image buffer */ - final_size = img->height * FRAME_WIDTH; - img = fpi_img_resize(img, final_size); - /* FIXME: ugly workaround */ - if (img->height < 12) - img->height = 12; - fpi_imgdev_image_captured(dev, img); - - /* free strips and strip list */ - g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; - aesdev->blanks_count = 0; -} - - /****** FINGER PRESENCE DETECTION ******/ @@ -732,11 +608,20 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) /* stop capturing if MAX_FRAMES is reached */ if (aesdev->blanks_count > 10 || g_slist_length(aesdev->strips) >= MAX_FRAMES) { + struct fp_img *img; + fp_dbg("sending stop capture.... blanks=%d frames=%d", aesdev->blanks_count, g_slist_length(aesdev->strips)); /* send stop capture bits */ aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL); - /* assemble image and submit it to library */ - assemble_and_submit_image(dev); + aesdev->strips = g_slist_reverse(aesdev->strips); + img = aes_assemble(aesdev->strips, aesdev->strips_len, + FRAME_WIDTH, FRAME_HEIGHT); + g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); + g_slist_free(aesdev->strips); + aesdev->strips = NULL; + aesdev->strips_len = 0; + aesdev->blanks_count = 0; + fpi_imgdev_image_captured(dev, img); fpi_imgdev_report_finger_status(dev, FALSE); /* marking machine complete will re-trigger finger detection loop */ fpi_ssm_mark_completed(ssm); diff --git a/libfprint/drivers/aes2501.c b/libfprint/drivers/aes2501.c index 246d45e..f4912b7 100644 --- a/libfprint/drivers/aes2501.c +++ b/libfprint/drivers/aes2501.c @@ -248,119 +248,6 @@ static int sum_histogram_values(unsigned char *data, uint8_t threshold) return r; } -/* find overlapping parts of frames */ -static unsigned int find_overlap(unsigned char *first_frame, - unsigned char *second_frame, unsigned int *min_error) -{ - unsigned int dy; - unsigned int not_overlapped_height = 0; - *min_error = 255 * FRAME_SIZE; - for (dy = 0; dy < FRAME_HEIGHT; dy++) { - /* Calculating difference (error) between parts of frames */ - unsigned int i; - unsigned int error = 0; - for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) { - /* Using ? operator to avoid abs function */ - error += first_frame[i] > second_frame[i] ? - (first_frame[i] - second_frame[i]) : - (second_frame[i] - first_frame[i]); - } - - /* Normalize error */ - error *= 15; - error /= i; - if (error < *min_error) { - *min_error = error; - not_overlapped_height = dy; - } - first_frame += FRAME_WIDTH; - } - - return not_overlapped_height; -} - -/* assemble a series of frames into a single image */ -static unsigned int assemble(struct aes2501_dev *aesdev, unsigned char *output, - gboolean reverse, unsigned int *errors_sum) -{ - uint8_t *assembled = output; - int frame; - uint32_t image_height = FRAME_HEIGHT; - unsigned int min_error; - size_t num_strips = aesdev->strips_len; - GSList *list_entry = aesdev->strips; - *errors_sum = 0; - - /* Rotating given data by 90 degrees - * Taken from document describing aes2501 image format - * TODO: move reversing detection here */ - - if (reverse) - output += (num_strips - 1) * FRAME_SIZE; - for (frame = 0; frame < num_strips; frame++) { - aes_assemble_image(list_entry->data, FRAME_WIDTH, FRAME_HEIGHT, output); - - if (reverse) - output -= FRAME_SIZE; - else - output += FRAME_SIZE; - list_entry = g_slist_next(list_entry); - } - - /* Detecting where frames overlaped */ - output = assembled; - for (frame = 1; frame < num_strips; frame++) { - int not_overlapped; - - output += FRAME_SIZE; - not_overlapped = find_overlap(assembled, output, &min_error); - *errors_sum += min_error; - image_height += not_overlapped; - assembled += FRAME_WIDTH * not_overlapped; - memcpy(assembled, output, FRAME_SIZE); - } - return image_height; -} - -static void assemble_and_submit_image(struct fp_img_dev *dev) -{ - struct aes2501_dev *aesdev = dev->priv; - size_t final_size; - struct fp_img *img; - unsigned int errors_sum, r_errors_sum; - - BUG_ON(aesdev->strips_len == 0); - - /* reverse list */ - aesdev->strips = g_slist_reverse(aesdev->strips); - - /* create buffer big enough for max image */ - img = fpi_img_new(aesdev->strips_len * FRAME_SIZE); - - img->flags = FP_IMG_COLORS_INVERTED; - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->height = assemble(aesdev, img->data, TRUE, &r_errors_sum); - - if (r_errors_sum > errors_sum) { - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - fp_dbg("normal scan direction"); - } else { - fp_dbg("reversed scan direction"); - } - - /* now that overlap has been removed, resize output image buffer */ - final_size = img->height * FRAME_WIDTH; - img = fpi_img_resize(img, final_size); - fpi_imgdev_image_captured(dev, img); - - /* free strips and strip list */ - g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); - g_slist_free(aesdev->strips); - aesdev->strips = NULL; -} - - /****** FINGER PRESENCE DETECTION ******/ static const struct aes_regwrite finger_det_reqs[] = { @@ -593,8 +480,16 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) if (sum == 0) { aesdev->no_finger_cnt++; if (aesdev->no_finger_cnt == 3) { - /* assemble image and submit it to library */ - assemble_and_submit_image(dev); + struct fp_img *img; + + aesdev->strips = g_slist_reverse(aesdev->strips); + img = aes_assemble(aesdev->strips, aesdev->strips_len, + FRAME_WIDTH, FRAME_HEIGHT); + g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); + g_slist_free(aesdev->strips); + aesdev->strips = NULL; + aesdev->strips_len = 0; + fpi_imgdev_image_captured(dev, img); fpi_imgdev_report_finger_status(dev, FALSE); /* marking machine complete will re-trigger finger detection loop */ fpi_ssm_mark_completed(ssm); diff --git a/libfprint/drivers/aes2550.c b/libfprint/drivers/aes2550.c index 9c2eb69..30b6dc6 100644 --- a/libfprint/drivers/aes2550.c +++ b/libfprint/drivers/aes2550.c @@ -64,119 +64,6 @@ struct aes2550_dev { int heartbeat_cnt; }; -/****** IMAGE PROCESSING ******/ - -/* find overlapping parts of frames */ -static unsigned int find_overlap(unsigned char *first_frame, - unsigned char *second_frame, unsigned int *min_error) -{ - unsigned int dy; - unsigned int not_overlapped_height = 0; - /* 255 is highest brightness value for an 8bpp image */ - *min_error = 255 * FRAME_SIZE; - for (dy = 0; dy < FRAME_HEIGHT; dy++) { - /* Calculating difference (error) between parts of frames */ - unsigned int i; - unsigned int error = 0; - for (i = 0; i < FRAME_WIDTH * (FRAME_HEIGHT - dy); i++) { - /* Using ? operator to avoid abs function */ - error += first_frame[i] > second_frame[i] ? - (first_frame[i] - second_frame[i]) : - (second_frame[i] - first_frame[i]); - } - - /* Normalize error */ - error *= 15; - error /= i; - if (error < *min_error) { - *min_error = error; - not_overlapped_height = dy; - } - first_frame += FRAME_WIDTH; - } - - return not_overlapped_height; -} - -/* assemble a series of frames into a single image */ -static unsigned int assemble(struct aes2550_dev *aesdev, unsigned char *output, - gboolean reverse, unsigned int *errors_sum) -{ - uint8_t *assembled = output; - int frame; - uint32_t image_height = FRAME_HEIGHT; - unsigned int min_error; - size_t num_strips = aesdev->strips_len; - GSList *list_entry = aesdev->strips; - *errors_sum = 0; - - if (reverse) - output += (num_strips - 1) * FRAME_SIZE; - for (frame = 0; frame < num_strips; frame++) { - aes_assemble_image(list_entry->data, FRAME_WIDTH, FRAME_HEIGHT, output); - - if (reverse) - output -= FRAME_SIZE; - else - output += FRAME_SIZE; - list_entry = g_slist_next(list_entry); - } - - /* Detecting where frames overlaped */ - output = assembled; - for (frame = 1; frame < num_strips; frame++) { - int not_overlapped; - - output += FRAME_SIZE; - not_overlapped = find_overlap(assembled, output, &min_error); - *errors_sum += min_error; - image_height += not_overlapped; - assembled += FRAME_WIDTH * not_overlapped; - memcpy(assembled, output, FRAME_SIZE); - } - return image_height; -} - -static void assemble_and_submit_image(struct fp_img_dev *dev) -{ - struct aes2550_dev *aesdev = dev->priv; - size_t final_size; - struct fp_img *img; - unsigned int errors_sum, r_errors_sum; - - BUG_ON(aesdev->strips_len == 0); - - /* reverse list */ - aesdev->strips = g_slist_reverse(aesdev->strips); - - /* create buffer big enough for max image */ - img = fpi_img_new(aesdev->strips_len * FRAME_SIZE); - - img->flags = FP_IMG_COLORS_INVERTED; - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->height = assemble(aesdev, img->data, TRUE, &r_errors_sum); - - if (r_errors_sum > errors_sum) { - img->height = assemble(aesdev, img->data, FALSE, &errors_sum); - img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; - fp_dbg("normal scan direction"); - } else { - fp_dbg("reversed scan direction"); - } - - /* now that overlap has been removed, resize output image buffer */ - final_size = img->height * FRAME_WIDTH; - img = fpi_img_resize(img, final_size); - fpi_imgdev_image_captured(dev, img); - - /* free strips and strip list */ - g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); - g_slist_free(aesdev->strips); - aesdev->strips = NULL; - aesdev->strips_len = 0; -} - - /****** FINGER PRESENCE DETECTION ******/ static unsigned char finger_det_reqs[] = { @@ -356,10 +243,20 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer) { struct fpi_ssm *ssm = transfer->user_data; struct fp_img_dev *dev = ssm->priv; + struct aes2550_dev *aesdev = dev->priv; if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && (transfer->length == transfer->actual_length)) { - assemble_and_submit_image(dev); + struct fp_img *img; + + aesdev->strips = g_slist_reverse(aesdev->strips); + img = aes_assemble(aesdev->strips, aesdev->strips_len, + FRAME_WIDTH, FRAME_HEIGHT); + g_slist_foreach(aesdev->strips, (GFunc) g_free, NULL); + g_slist_free(aesdev->strips); + aesdev->strips = NULL; + aesdev->strips_len = 0; + fpi_imgdev_image_captured(dev, img); fpi_imgdev_report_finger_status(dev, FALSE); /* marking machine complete will re-trigger finger detection loop */ fpi_ssm_mark_completed(ssm); -- 1.8.0