Commit 061a4576 authored by Vasily Khoruzhick's avatar Vasily Khoruzhick

aeslib: improve frame-assembling routines

Some scanners provide hardware assistance in frame assemling, i.e.
horizontal and vertical offset to previous frame is provided. This
commit improves code to utilise that assistance. Sensors without
hardware assistance will use software algorithm, which was also
improved to do search in horizontal direction.
parent 82ae7c1c
...@@ -158,127 +158,268 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, ...@@ -158,127 +158,268 @@ void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
continue_write_regv(wdata); continue_write_regv(wdata);
} }
void aes_assemble_image(unsigned char *input, size_t width, size_t height, static inline unsigned char aes_get_pixel(struct aes_stripe *frame,
unsigned char *output) unsigned int x,
unsigned int y,
unsigned int frame_width,
unsigned int frame_height)
{ {
size_t row, column; unsigned char ret;
for (column = 0; column < width; column++) { ret = frame->data[x * (frame_height >> 1) + (y >> 1)];
for (row = 0; row < height; row += 2) { ret = y % 2 ? ret >> 4 : ret & 0xf;
output[width * row + column] = (*input & 0x0f) * 17; ret *= 17;
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
input++; return ret;
}
}
} }
/* find overlapping parts of frames */ static unsigned int calc_error(struct aes_stripe *first_frame,
static unsigned int find_overlap(unsigned char *first_frame, struct aes_stripe *second_frame,
unsigned char *second_frame, unsigned int *min_error, int dx,
unsigned int frame_width, unsigned int frame_height) int dy,
unsigned int frame_width,
unsigned int frame_height)
{ {
unsigned int dy; unsigned int width, height;
unsigned int not_overlapped_height = 0; unsigned int x1, y1, x2, y2, err, i, j;
/* 255 is highest brightness value for an 8bpp image */
*min_error = 255 * frame_width * frame_height; width = frame_width - (dx > 0 ? dx : -dx);
for (dy = 0; dy < frame_height; dy++) { height = frame_height - dy;
/* Calculating difference (error) between parts of frames */
unsigned int i; y1 = 0;
unsigned int error = 0; y2 = dy;
for (i = 0; i < frame_width * (frame_height - dy); i++) { i = 0;
/* Using ? operator to avoid abs function */ err = 0;
error += first_frame[i] > second_frame[i] ? do {
(first_frame[i] - second_frame[i]) : x1 = dx < 0 ? 0 : dx;
(second_frame[i] - first_frame[i]); x2 = dx < 0 ? -dx : 0;
} j = 0;
do {
unsigned char v1, v2;
v1 = aes_get_pixel(first_frame, x1, y1, frame_width, frame_height);
v2 = aes_get_pixel(second_frame, x2, y2, frame_width, frame_height);
err += v1 > v2 ? v1 - v2 : v2 - v1;
j++;
x1++;
x2++;
} while (j < width);
i++;
y1++;
y2++;
} while (i < height);
/* Normalize error */
err *= (frame_height * frame_width);
err /= (height * width);
if (err == 0)
return INT_MAX;
return err;
}
/* Normalize error */ /* This function is rather CPU-intensive. It's better to use hardware
error *= 15; * to detect movement direction when possible.
error /= i; */
if (error < *min_error) { static void find_overlap(struct aes_stripe *first_frame,
*min_error = error; struct aes_stripe *second_frame,
not_overlapped_height = dy; unsigned int *min_error,
unsigned int frame_width,
unsigned int frame_height)
{
int dx, dy;
unsigned int err;
*min_error = INT_MAX;
/* Seeking in horizontal and vertical dimensions,
* for horizontal dimension we'll check only 8 pixels
* in both directions. For vertical direction diff is
* rarely less than 2, so start with it.
*/
for (dy = 2; dy < frame_height; dy++) {
for (dx = -8; dx < 8; dx++) {
err = calc_error(first_frame, second_frame,
dx, dy, frame_width, frame_height);
if (err < *min_error) {
*min_error = err;
second_frame->delta_x = -dx;
second_frame->delta_y = dy;
}
} }
first_frame += frame_width;
} }
return not_overlapped_height;
} }
/* assemble a series of frames into a single image */ unsigned int aes_calc_delta(GSList *stripes, size_t num_stripes,
static unsigned int assemble(GSList *list_entry, size_t num_stripes,
unsigned int frame_width, unsigned int frame_height, unsigned int frame_width, unsigned int frame_height,
unsigned char *output, gboolean reverse, unsigned int *errors_sum) gboolean reverse)
{ {
uint8_t *assembled = output; GSList *list_entry = stripes;
int frame; GTimer *timer;
uint32_t image_height = frame_height; int frame = 1;
unsigned int min_error, frame_size = frame_width * frame_height; int height = 0;
*errors_sum = 0; struct aes_stripe *prev_stripe = list_entry->data;
unsigned int min_error;
if (reverse)
output += (num_stripes - 1) * frame_size; list_entry = g_slist_next(list_entry);
for (frame = 0; frame < num_stripes; frame++) {
aes_assemble_image(list_entry->data, frame_width, frame_height, output); timer = g_timer_new();
do {
if (reverse) struct aes_stripe *cur_stripe = list_entry->data;
output -= frame_size;
if (reverse) {
find_overlap(prev_stripe, cur_stripe, &min_error,
frame_width, frame_height);
prev_stripe->delta_y = -prev_stripe->delta_y;
prev_stripe->delta_x = -prev_stripe->delta_x;
}
else else
output += frame_size; find_overlap(cur_stripe, prev_stripe, &min_error,
frame_width, frame_height);
frame++;
height += prev_stripe->delta_y;
prev_stripe = cur_stripe;
list_entry = g_slist_next(list_entry); list_entry = g_slist_next(list_entry);
} while (frame < num_stripes);
if (height < 0)
height = -height;
height += frame_height;
g_timer_stop(timer);
fp_dbg("calc delta completed in %f secs", g_timer_elapsed(timer, NULL));
g_timer_destroy(timer);
return height;
}
static inline void aes_blit_stripe(struct fp_img *img,
struct aes_stripe *stripe,
int x, int y, unsigned int frame_width,
unsigned int frame_height)
{
unsigned int ix, iy;
unsigned int fx, fy;
unsigned int width, height;
/* Find intersection */
if (x < 0) {
width = frame_width + x;
ix = 0;
fx = -x;
} else {
ix = x;
fx = 0;
width = frame_width;
} }
if ((ix + width) > img->width)
width = img->width - ix;
/* Detecting where frames overlaped */ if (y < 0) {
output = assembled; iy = 0;
for (frame = 1; frame < num_stripes; frame++) { fy = -y;
int not_overlapped; height = frame_height + y;
} else {
output += frame_size; iy = y;
not_overlapped = find_overlap(assembled, output, &min_error, fy = 0;
frame_width, frame_height); height = frame_height;
*errors_sum += min_error; }
image_height += not_overlapped;
assembled += frame_width * not_overlapped; if (fx > frame_width)
memcpy(assembled, output, frame_size); return;
if (fy > frame_height)
return;
if (ix > img->width)
return;
if (iy > img->height)
return;
if ((iy + height) > img->height)
height = img->height - iy;
for (; fy < height; fy++, iy++) {
if (x < 0) {
ix = 0;
fx = -x;
} else {
ix = x;
fx = 0;
}
for (; fx < width; fx++, ix++) {
img->data[ix + (iy * img->width)] = aes_get_pixel(stripe, fx, fy, frame_width, frame_height);
}
} }
return image_height;
} }
struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len,
unsigned int frame_width, unsigned int frame_height) unsigned int frame_width, unsigned int frame_height, unsigned int img_width)
{ {
size_t final_size; GSList *stripe;
struct fp_img *img; struct fp_img *img;
unsigned int frame_size = frame_width * frame_height; int height = 0;
unsigned int errors_sum, r_errors_sum; int i, y, x;
gboolean reverse = FALSE;
struct aes_stripe *aes_stripe;
BUG_ON(stripes_len == 0); BUG_ON(stripes_len == 0);
BUG_ON(img_width < frame_width);
/* create buffer big enough for max image */ /* Calculate height */
img = fpi_img_new(stripes_len * frame_size); i = 0;
stripe = stripes;
img->flags = FP_IMG_COLORS_INVERTED; /* No offset for 1st image */
img->height = assemble(stripes, stripes_len, aes_stripe = stripe->data;
frame_width, frame_height, aes_stripe->delta_x = 0;
img->data, FALSE, &errors_sum); aes_stripe->delta_y = 0;
img->height = assemble(stripes, stripes_len, do {
frame_width, frame_height, aes_stripe = stripe->data;
img->data, TRUE, &r_errors_sum);
height += aes_stripe->delta_y;
if (r_errors_sum > errors_sum) { i++;
img->height = assemble(stripes, stripes_len, stripe = g_slist_next(stripe);
frame_width, frame_height, } while (i < stripes_len);
img->data, FALSE, &errors_sum);
img->flags |= FP_IMG_V_FLIPPED | FP_IMG_H_FLIPPED; fp_dbg("height is %d", height);
fp_dbg("normal scan direction");
} else { if (height < 0) {
fp_dbg("reversed scan direction"); reverse = TRUE;
height = -height;
} }
/* now that overlap has been removed, resize output image buffer */ /* For last frame */
final_size = img->height * frame_width; height += frame_height;
img = fpi_img_resize(img, final_size);
img->width = frame_width; /* Create buffer big enough for max image */
img = fpi_img_new(img_width * height);
img->flags = FP_IMG_COLORS_INVERTED;
img->width = img_width;
img->height = height;
/* Assemble stripes */
i = 0;
stripe = stripes;
y = reverse ? (height - frame_height) : 0;
x = (img_width - frame_width) / 2;
do {
aes_stripe = stripe->data;
y += aes_stripe->delta_y;
x += aes_stripe->delta_x;
aes_blit_stripe(img, aes_stripe, x, y, frame_width, frame_height);
stripe = g_slist_next(stripe);
i++;
} while (i < stripes_len);
return img; return img;
} }
...@@ -27,17 +27,24 @@ struct aes_regwrite { ...@@ -27,17 +27,24 @@ struct aes_regwrite {
unsigned char value; unsigned char value;
}; };
struct aes_stripe {
int delta_x;
int delta_y;
unsigned char data[0];
};
typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result, typedef void (*aes_write_regv_cb)(struct fp_img_dev *dev, int result,
void *user_data); void *user_data);
void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs, void aes_write_regv(struct fp_img_dev *dev, const struct aes_regwrite *regs,
unsigned int num_regs, aes_write_regv_cb callback, void *user_data); unsigned int num_regs, aes_write_regv_cb callback, void *user_data);
void aes_assemble_image(unsigned char *input, size_t width, size_t height, unsigned int aes_calc_delta(GSList *stripes, size_t stripes_len,
unsigned char *output); unsigned int frame_width, unsigned int frame_height,
gboolean reverse);
struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len, struct fp_img *aes_assemble(GSList *stripes, size_t stripes_len,
unsigned int frame_width, unsigned int frame_height); unsigned int frame_width, unsigned int frame_height, unsigned int img_width);
#endif #endif
...@@ -609,13 +609,24 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) ...@@ -609,13 +609,24 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
/* stop capturing if MAX_FRAMES is reached */ /* stop capturing if MAX_FRAMES is reached */
if (aesdev->blanks_count > 10 || g_slist_length(aesdev->strips) >= MAX_FRAMES) { if (aesdev->blanks_count > 10 || g_slist_length(aesdev->strips) >= MAX_FRAMES) {
struct fp_img *img; struct fp_img *img;
unsigned int height, rev_height;
fp_dbg("sending stop capture.... blanks=%d frames=%d", aesdev->blanks_count, g_slist_length(aesdev->strips)); fp_dbg("sending stop capture.... blanks=%d frames=%d", aesdev->blanks_count, g_slist_length(aesdev->strips));
/* send stop capture bits */ /* send stop capture bits */
aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL); aes_write_regv(dev, capture_stop, G_N_ELEMENTS(capture_stop), stub_capture_stop_cb, NULL);
aesdev->strips = g_slist_reverse(aesdev->strips); aesdev->strips = g_slist_reverse(aesdev->strips);
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, TRUE);
fp_dbg("heights: %d rev: %d", height, rev_height);
if (rev_height < height) {
fp_dbg("Reversed direction");
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
}
img = aes_assemble(aesdev->strips, aesdev->strips_len, img = aes_assemble(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT); FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
g_slist_free_full(aesdev->strips, g_free); g_slist_free_full(aesdev->strips, g_free);
aesdev->strips = NULL; aesdev->strips = NULL;
aesdev->strips_len = 0; aesdev->strips_len = 0;
...@@ -829,13 +840,9 @@ struct fp_img_driver aes1610_driver = { ...@@ -829,13 +840,9 @@ struct fp_img_driver aes1610_driver = {
}, },
.flags = 0, .flags = 0,
.img_height = -1, .img_height = -1,
.img_width = 128, .img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
/* temporarily lowered until we sort out image processing code .bz3_threshold = 50,
* binarized scan quality is good, minutiae detection is accurate,
* it's just that we get fewer minutiae than other scanners (less scanning
* area) */
.bz3_threshold = 10,
.open = dev_init, .open = dev_init,
.close = dev_deinit, .close = dev_deinit,
......
...@@ -49,7 +49,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) ...@@ -49,7 +49,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
dev->priv = aesdev = g_malloc0(sizeof(struct aesX660_dev)); dev->priv = aesdev = g_malloc0(sizeof(struct aesX660_dev));
aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE); aesdev->buffer = g_malloc0(AES1660_FRAME_SIZE + AESX660_HEADER_SIZE);
aesdev->h_scale_factor = SCALE_FACTOR;
aesdev->init_seqs[0] = aes1660_init_1; aesdev->init_seqs[0] = aes1660_init_1;
aesdev->init_seqs_len[0] = array_n_elements(aes1660_init_1); aesdev->init_seqs_len[0] = array_n_elements(aes1660_init_1);
aesdev->init_seqs[1] = aes1660_init_2; aesdev->init_seqs[1] = aes1660_init_2;
...@@ -102,7 +101,8 @@ struct fp_img_driver aes1660_driver = { ...@@ -102,7 +101,8 @@ struct fp_img_driver aes1660_driver = {
}, },
.flags = 0, .flags = 0,
.img_height = -1, .img_height = -1,
.img_width = FRAME_WIDTH * SCALE_FACTOR, .img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.bz3_threshold = 70,
.open = dev_init, .open = dev_init,
.close = dev_deinit, .close = dev_deinit,
......
...@@ -481,10 +481,21 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) ...@@ -481,10 +481,21 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
aesdev->no_finger_cnt++; aesdev->no_finger_cnt++;
if (aesdev->no_finger_cnt == 3) { if (aesdev->no_finger_cnt == 3) {
struct fp_img *img; struct fp_img *img;
unsigned int height, rev_height;
aesdev->strips = g_slist_reverse(aesdev->strips); aesdev->strips = g_slist_reverse(aesdev->strips);
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
rev_height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, TRUE);
fp_dbg("heights: %d rev: %d", height, rev_height);
if (rev_height < height) {
fp_dbg("Reversed direction");
height = aes_calc_delta(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT, FALSE);
}
img = aes_assemble(aesdev->strips, aesdev->strips_len, img = aes_assemble(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT); FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
g_slist_free_full(aesdev->strips, g_free); g_slist_free_full(aesdev->strips, g_free);
aesdev->strips = NULL; aesdev->strips = NULL;
aesdev->strips_len = 0; aesdev->strips_len = 0;
...@@ -498,10 +509,13 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer) ...@@ -498,10 +509,13 @@ static void capture_read_strip_cb(struct libusb_transfer *transfer)
} else { } else {
/* obtain next strip */ /* obtain next strip */
/* FIXME: would preallocating strip buffers be a decent optimization? */ /* FIXME: would preallocating strip buffers be a decent optimization? */
stripdata = g_malloc(192 * 8); struct aes_stripe *stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe));
stripe->delta_x = 0;
stripe->delta_y = 0;
stripdata = stripe->data;
memcpy(stripdata, data + 1, 192*8); memcpy(stripdata, data + 1, 192*8);
aesdev->no_finger_cnt = 0; aesdev->no_finger_cnt = 0;
aesdev->strips = g_slist_prepend(aesdev->strips, stripdata); aesdev->strips = g_slist_prepend(aesdev->strips, stripe);
aesdev->strips_len++; aesdev->strips_len++;
fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP); fpi_ssm_jump_to_state(ssm, CAPTURE_REQUEST_STRIP);
...@@ -867,7 +881,7 @@ struct fp_img_driver aes2501_driver = { ...@@ -867,7 +881,7 @@ struct fp_img_driver aes2501_driver = {
}, },
.flags = 0, .flags = 0,
.img_height = -1, .img_height = -1,
.img_width = 192, .img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.open = dev_init, .open = dev_init,
.close = dev_deinit, .close = dev_deinit,
......
...@@ -204,6 +204,7 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data) ...@@ -204,6 +204,7 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data)
unsigned char *stripdata; unsigned char *stripdata;
struct fp_img_dev *dev = ssm->priv; struct fp_img_dev *dev = ssm->priv;
struct aes2550_dev *aesdev = dev->priv; struct aes2550_dev *aesdev = dev->priv;
struct aes_stripe *stripe;
int len; int len;
if (data[0] != AES2550_EDATA_MAGIC) { if (data[0] != AES2550_EDATA_MAGIC) {
...@@ -214,11 +215,16 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data) ...@@ -214,11 +215,16 @@ static int process_strip_data(struct fpi_ssm *ssm, unsigned char *data)
if (len != (AES2550_STRIP_SIZE - 3)) { if (len != (AES2550_STRIP_SIZE - 3)) {
fp_dbg("Bogus frame len: %.4x\n", len); fp_dbg("Bogus frame len: %.4x\n", len);
} }
stripdata = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2); /* 4 bits per pixel */ stripe = g_malloc(FRAME_WIDTH * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe)); /* 4 bits per pixel */
stripe->delta_x = (int8_t)data[6];
stripe->delta_y = -(int8_t)data[7];
stripdata = stripe->data;
memcpy(stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2); memcpy(stripdata, data + 33, FRAME_WIDTH * FRAME_HEIGHT / 2);
aesdev->strips = g_slist_prepend(aesdev->strips, stripdata); aesdev->strips = g_slist_prepend(aesdev->strips, stripe);
aesdev->strips_len++; aesdev->strips_len++;
fp_dbg("deltas: %dx%d", stripe->delta_x, stripe->delta_y);
return 0; return 0;
} }
...@@ -242,12 +248,13 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer) ...@@ -242,12 +248,13 @@ static void capture_set_idle_reqs_cb(struct libusb_transfer *transfer)
struct aes2550_dev *aesdev = dev->priv; struct aes2550_dev *aesdev = dev->priv;
if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) && if ((transfer->status == LIBUSB_TRANSFER_COMPLETED) &&
(transfer->length == transfer->actual_length)) { (transfer->length == transfer->actual_length) &&
aesdev->strips_len) {
struct fp_img *img; struct fp_img *img;
aesdev->strips = g_slist_reverse(aesdev->strips); aesdev->strips = g_slist_reverse(aesdev->strips);
img = aes_assemble(aesdev->strips, aesdev->strips_len, img = aes_assemble(aesdev->strips, aesdev->strips_len,
FRAME_WIDTH, FRAME_HEIGHT); FRAME_WIDTH, FRAME_HEIGHT, FRAME_WIDTH + FRAME_WIDTH / 2);
g_slist_free_full(aesdev->strips, g_free); g_slist_free_full(aesdev->strips, g_free);
aesdev->strips = NULL; aesdev->strips = NULL;
aesdev->strips_len = 0; aesdev->strips_len = 0;
...@@ -637,7 +644,7 @@ struct fp_img_driver aes2550_driver = { ...@@ -637,7 +644,7 @@ struct fp_img_driver aes2550_driver = {
}, },
.flags = 0, .flags = 0,
.img_height = -1, .img_height = -1,
.img_width = 192, .img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.open = dev_init, .open = dev_init,
.close = dev_deinit, .close = dev_deinit,
......
...@@ -49,7 +49,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data) ...@@ -49,7 +49,6 @@ static int dev_init(struct fp_img_dev *dev, unsigned long driver_data)
dev->priv = aesdev = g_malloc0(sizeof(struct aesX660_dev)); dev->priv = aesdev = g_malloc0(sizeof(struct aesX660_dev));
aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE); aesdev->buffer = g_malloc0(AES2660_FRAME_SIZE + AESX660_HEADER_SIZE);
/* No scaling for AES2660 */ /* No scaling for AES2660 */
aesdev->h_scale_factor = 1;
aesdev->init_seqs[0] = aes2660_init_1; aesdev->init_seqs[0] = aes2660_init_1;
aesdev->init_seqs_len[0] = array_n_elements(aes2660_init_1); aesdev->init_seqs_len[0] = array_n_elements(aes2660_init_1);
aesdev->init_seqs[1] = aes2660_init_2; aesdev->init_seqs[1] = aes2660_init_2;
...@@ -103,7 +102,7 @@ struct fp_img_driver aes2660_driver = { ...@@ -103,7 +102,7 @@ struct fp_img_driver aes2660_driver = {
}, },
.flags = 0, .flags = 0,
.img_height = -1, .img_height = -1,
.img_width = FRAME_WIDTH, .img_width = FRAME_WIDTH + FRAME_WIDTH / 2,
.open = dev_init, .open = dev_init,
.close = dev_deinit, .close = dev_deinit,
......
...@@ -52,6 +52,20 @@ ...@@ -52,6 +52,20 @@
static void do_capture(struct fp_img_dev *dev); static void do_capture(struct fp_img_dev *dev);
static void aes3k_assemble_image(unsigned char *input, size_t width, size_t height,
unsigned char *output)
{
size_t row, column;
for (column = 0; column < width; column++) {
for (row = 0; row < height; row += 2) {
output[width * row + column] = (*input & 0x0f) * 17;
output[width * (row + 1) + column] = ((*input & 0xf0) >> 4) * 17;
input++;
}
}
}
static void img_cb(struct libusb_transfer *transfer) static void img_cb(struct libusb_transfer *transfer)
{ {
struct fp_img_dev *dev = transfer->user_data; struct fp_img_dev *dev = transfer->user_data;
...@@ -80,7 +94,7 @@ static void img_cb(struct libusb_transfer *transfer) ...@@ -80,7 +94,7 @@ static void img_cb(struct libusb_transfer *transfer)
for (i = 0; i < aesdev->frame_number; i++) { for (i = 0; i < aesdev->frame_number; i++) {
fp_dbg("frame header byte %02x", *ptr); fp_dbg("frame header byte %02x", *ptr);
ptr++; ptr++;
aes_assemble_image(ptr, aesdev->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * aesdev->frame_width * AES3K_FRAME_HEIGHT)); aes3k_assemble_image(ptr, aesdev->frame_width, AES3K_FRAME_HEIGHT, tmp->data + (i * aesdev->frame_width * AES3K_FRAME_HEIGHT));
ptr += aesdev->frame_size; ptr += aesdev->frame_size;
} }
......
...@@ -273,19 +273,25 @@ enum capture_states { ...@@ -273,19 +273,25 @@ enum capture_states {
/* Returns number of processed bytes */ /* Returns number of processed bytes */
static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data) static int process_stripe_data(struct fpi_ssm *ssm, unsigned char *data)
{ {
struct aes_stripe *stripe;
unsigned char *stripdata; unsigned char *stripdata;
struct fp_img_dev *dev = ssm->priv; struct fp_img_dev *dev = ssm->priv;
struct aesX660_dev *aesdev = dev->priv; struct aesX660_dev *aesdev = dev->priv;
stripdata = g_malloc(aesdev->frame_width * FRAME_HEIGHT / 2); /* 4 bits per pixel */ stripe = g_malloc(aesdev->frame_width * FRAME_HEIGHT / 2 + sizeof(struct aes_stripe)); /* 4 bpp */
stripdata = stripe->data;
fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET], fp_dbg("Processing frame %.2x %.2x", data[AESX660_IMAGE_OK_OFFSET],
data[AESX660_LAST_FRAME_OFFSET]); data[AESX660_LAST_FRAME_OFFSET]);