lib: Document assembling functions

This commit is contained in:
Vasily Khoruzhick 2018-12-02 11:02:12 -08:00 committed by Bastien Nocera
parent c9733d27df
commit 2088a6177f
2 changed files with 112 additions and 16 deletions

View file

@ -163,6 +163,22 @@ static unsigned int do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
return total_error / num_stripes; return total_error / num_stripes;
} }
/**
* fpi_do_movement_estimation:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @stripes: a singly-linked list of #fpi_frame
* @num_stripes: number of items in @stripes to process
*
* fpi_do_movement_estimation() estimates the movement between adjacent
* frames, populating @delta_x and @delta_y values for each #fpi_frame.
*
* This function is used for devices that don't do movement estimation
* in hardware. If hardware movement estimation is supported, the driver
* should populate @delta_x and @delta_y instead.
*
* Note that @num_stripes might be shorter than the length of the list,
* if some stripes should be skipped.
*/
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t num_stripes) GSList *stripes, size_t num_stripes)
{ {
@ -236,8 +252,22 @@ static inline void aes_blit_stripe(struct fpi_frame_asmbl_ctx *ctx,
} }
} }
/**
* fpi_assemble_frames:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @stripes: linked list of #fpi_frame
* @num_stripes: number of items in @stripes to process
*
* fpi_assemble_frames() assembles individual frames into a single image.
* It expects @delta_x and @delta_y of #fpi_frame to be populated.
*
* Note that @num_stripes might be shorter than the length of the list,
* if some stripes should be skipped.
*
* Returns: a newly allocated #fp_img.
*/
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len) GSList *stripes, size_t num_stripes)
{ {
GSList *stripe; GSList *stripe;
struct fp_img *img; struct fp_img *img;
@ -246,7 +276,8 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
gboolean reverse = FALSE; gboolean reverse = FALSE;
struct fpi_frame *fpi_frame; struct fpi_frame *fpi_frame;
BUG_ON(stripes_len == 0); //FIXME g_return_if_fail
BUG_ON(num_stripes == 0);
BUG_ON(ctx->image_width < ctx->frame_width); BUG_ON(ctx->image_width < ctx->frame_width);
/* Calculate height */ /* Calculate height */
@ -263,7 +294,7 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
height += fpi_frame->delta_y; height += fpi_frame->delta_y;
i++; i++;
stripe = g_slist_next(stripe); stripe = g_slist_next(stripe);
} while (i < stripes_len); } while (i < num_stripes);
fp_dbg("height is %d", height); fp_dbg("height is %d", height);
@ -305,7 +336,7 @@ struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
stripe = g_slist_next(stripe); stripe = g_slist_next(stripe);
i++; i++;
} while (i < stripes_len); } while (i < num_stripes);
return img; return img;
} }
@ -361,32 +392,45 @@ static void interpolate_lines(struct fpi_line_asmbl_ctx *ctx,
} }
} }
/* Rescale image to account for variable swiping speed */ /**
* fpi_assemble_lines:
* @ctx: #fpi_frame_asmbl_ctx - frame assembling context
* @lines: linked list of lines
* @num_lines: number of items in @lines to process
*
* #fpi_assemble_lines assembles individual lines into a single image.
* It also rescales image to account variable swiping speed.
*
* Note that @num_lines might be shorter than the length of the list,
* if some lines should be skipped.
*
* Returns: a newly allocated #fp_img.
*/
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx, struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
GSList *lines, size_t lines_len) GSList *lines, size_t num_lines)
{ {
/* Number of output lines per distance between two scanners */ /* Number of output lines per distance between two scanners */
int i; int i;
GSList *row1, *row2; GSList *row1, *row2;
float y = 0.0; float y = 0.0;
int line_ind = 0; int line_ind = 0;
int *offsets = (int *)g_malloc0((lines_len / 2) * sizeof(int)); int *offsets = (int *)g_malloc0((num_lines / 2) * sizeof(int));
unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height); unsigned char *output = g_malloc0(ctx->line_width * ctx->max_height);
struct fp_img *img; struct fp_img *img;
g_return_val_if_fail (lines != NULL, NULL); g_return_val_if_fail (lines != NULL, NULL);
g_return_val_if_fail (lines_len > 0, NULL); g_return_val_if_fail (num_lines > 0, NULL);
fp_dbg("%"G_GINT64_FORMAT, g_get_real_time()); fp_dbg("%"G_GINT64_FORMAT, g_get_real_time());
row1 = lines; row1 = lines;
for (i = 0; (i < lines_len - 1) && row1; i += 2) { for (i = 0; (i < num_lines - 1) && row1; i += 2) {
int bestmatch = i; int bestmatch = i;
int bestdiff = 0; int bestdiff = 0;
int j, firstrow, lastrow; int j, firstrow, lastrow;
firstrow = i + 1; firstrow = i + 1;
lastrow = MIN(i + ctx->max_search_offset, lines_len - 1); lastrow = MIN(i + ctx->max_search_offset, num_lines - 1);
row2 = g_slist_next(row1); row2 = g_slist_next(row1);
for (j = firstrow; j <= lastrow; j++) { for (j = firstrow; j <= lastrow; j++) {
@ -406,13 +450,13 @@ struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
row1 = g_slist_next(row1); row1 = g_slist_next(row1);
} }
median_filter(offsets, (lines_len / 2) - 1, ctx->median_filter_size); median_filter(offsets, (num_lines / 2) - 1, ctx->median_filter_size);
fp_dbg("offsets_filtered: %"G_GINT64_FORMAT, g_get_real_time()); fp_dbg("offsets_filtered: %"G_GINT64_FORMAT, g_get_real_time());
for (i = 0; i <= (lines_len / 2) - 1; i++) for (i = 0; i <= (num_lines / 2) - 1; i++)
fp_dbg("%d", offsets[i]); fp_dbg("%d", offsets[i]);
row1 = lines; row1 = lines;
for (i = 0; i < lines_len - 1; i++, row1 = g_slist_next(row1)) { for (i = 0; i < num_lines - 1; i++, row1 = g_slist_next(row1)) {
int offset = offsets[i/2]; int offset = offsets[i/2];
if (offset > 0) { if (offset > 0) {
float ynext = y + (float)ctx->resolution / offset; float ynext = y + (float)ctx->resolution / offset;

View file

@ -22,12 +22,36 @@
#include <fprint.h> #include <fprint.h>
/**
* fpi_frame:
* @delta_x: X offset of the frame
* @delta_y: Y offset of the frame
* @data: bitmap
*
* #fpi_frame is used to store frames for swipe sensors. Drivers should
* populate delta_x and delta_y if the device supports hardware movement
* estimation.
*/
struct fpi_frame { struct fpi_frame {
int delta_x; int delta_x;
int delta_y; int delta_y;
unsigned char data[0]; unsigned char data[0];
}; };
/**
* fpi_frame_asmbl_ctx:
* @frame_width: width of the frame
* @frame_height: height of the frame
* @image_width: resulting image width
* @get_pixel: pixel accessor, returns pixel brightness at x,y of frame
*
* #fpi_frame_asmbl_ctx is a structure holding the context for frame
* assembling routines.
*
* Drivers should define their own #fpi_frame_asmbl_ctx depending on
* hardware parameters of scanner. @image_width is usually 25% wider than
* @frame_width to take horizontal movement into account.
*/
struct fpi_frame_asmbl_ctx { struct fpi_frame_asmbl_ctx {
unsigned int frame_width; unsigned int frame_width;
unsigned int frame_height; unsigned int frame_height;
@ -39,11 +63,39 @@ struct fpi_frame_asmbl_ctx {
}; };
void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx, void fpi_do_movement_estimation(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len); GSList *stripes, size_t num_stripes);
struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx, struct fp_img *fpi_assemble_frames(struct fpi_frame_asmbl_ctx *ctx,
GSList *stripes, size_t stripes_len); GSList *stripes, size_t num_stripes);
/**
* fpi_line_asmbl_ctx:
* @line_width: width of line
* @max_height: maximal height of assembled image
* @resolution: scale factor used for line assembling routines.
* @median_filter_size: size of median filter for movement estimation
* @max_search_offset: the number of lines to search for the next line
* @get_deviation: pointer to a function that returns the numerical difference
* between two lines
* @get_pixel: pixel accessor, returns pixel brightness at x of line
*
* #fpi_line_asmbl_ctx is a structure holding the context for line assembling
* routines.
*
* Drivers should define their own #fpi_line_asmbl_ctx depending on
* the hardware parameters of the scanner. Swipe scanners of this type usually
* return two lines, the second line is often narrower than first and is used
* for movement estimation.
*
* The @max_search_offset value indicates how many lines forward the assembling
* routines should look while searching for next line. This value depends on
* how fast the hardware sends frames.
*
* The function pointed to by @get_deviation should return the numerical difference
* between two lines. Higher values means lines are more different. If the reader
* returns two lines at a time, this function should be used to estimate the
* difference between pairs of lines.
*/
struct fpi_line_asmbl_ctx { struct fpi_line_asmbl_ctx {
unsigned int line_width; unsigned int line_width;
unsigned int max_height; unsigned int max_height;
@ -58,6 +110,6 @@ struct fpi_line_asmbl_ctx {
}; };
struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx, struct fp_img *fpi_assemble_lines(struct fpi_line_asmbl_ctx *ctx,
GSList *lines, size_t lines_len); GSList *lines, size_t num_lines);
#endif #endif