934 lines
27 KiB
Diff
934 lines
27 KiB
Diff
From 0063288d48791b181d794615e5694f9d3c8c1007 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
|
Date: Wed, 11 Dec 2019 19:55:47 +0100
|
|
Subject: [PATCH 107/181] fp-image, fp-print: Move private methods to own code
|
|
units
|
|
|
|
---
|
|
libfprint/fp-image.c | 128 +-----------------
|
|
libfprint/fp-print-private.h | 46 +++++++
|
|
libfprint/fp-print.c | 247 +---------------------------------
|
|
libfprint/fpi-image.c | 150 +++++++++++++++++++++
|
|
libfprint/fpi-print.c | 249 +++++++++++++++++++++++++++++++++++
|
|
libfprint/meson.build | 2 +
|
|
6 files changed, 452 insertions(+), 370 deletions(-)
|
|
create mode 100644 libfprint/fp-print-private.h
|
|
create mode 100644 libfprint/fpi-image.c
|
|
create mode 100644 libfprint/fpi-print.c
|
|
|
|
diff --git a/libfprint/fp-image.c b/libfprint/fp-image.c
|
|
index 16837a8..ac70d68 100644
|
|
--- a/libfprint/fp-image.c
|
|
+++ b/libfprint/fp-image.c
|
|
@@ -18,15 +18,13 @@
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
+#define FP_COMPONENT "image"
|
|
+
|
|
#include "fpi-image.h"
|
|
#include "fpi-log.h"
|
|
|
|
#include <nbis.h>
|
|
|
|
-#if HAVE_PIXMAN
|
|
-#include <pixman.h>
|
|
-#endif
|
|
-
|
|
/**
|
|
* SECTION: fp-image
|
|
* @title: FpImage
|
|
@@ -36,15 +34,6 @@
|
|
* this object allows accessing this data.
|
|
*/
|
|
|
|
-/**
|
|
- * SECTION: fpi-image
|
|
- * @title: Internal FpImage
|
|
- * @short_description: Internal image handling routines
|
|
- *
|
|
- * Internal image handling routines. Also see the public <ulink
|
|
- * url="libfprint-FpImage.html">FpImage routines</ulink>.
|
|
- */
|
|
-
|
|
G_DEFINE_TYPE (FpImage, fp_image, G_TYPE_OBJECT)
|
|
|
|
enum {
|
|
@@ -479,78 +468,6 @@ fp_image_detect_minutiae_finish (FpImage *self,
|
|
return g_task_propagate_boolean (G_TASK (result), error);
|
|
}
|
|
|
|
-
|
|
-
|
|
-/**
|
|
- * fpi_std_sq_dev:
|
|
- * @buf: buffer (usually bitmap, one byte per pixel)
|
|
- * @size: size of @buffer
|
|
- *
|
|
- * Calculates the squared standard deviation of the individual
|
|
- * pixels in the buffer, as per the following formula:
|
|
- * |[<!-- -->
|
|
- * mean = sum (buf[0..size]) / size
|
|
- * sq_dev = sum ((buf[0.size] - mean) ^ 2)
|
|
- * ]|
|
|
- * This function is usually used to determine whether image
|
|
- * is empty.
|
|
- *
|
|
- * Returns: the squared standard deviation for @buffer
|
|
- */
|
|
-gint
|
|
-fpi_std_sq_dev (const guint8 *buf,
|
|
- gint size)
|
|
-{
|
|
- guint64 res = 0, mean = 0;
|
|
- gint i;
|
|
-
|
|
- for (i = 0; i < size; i++)
|
|
- mean += buf[i];
|
|
-
|
|
- mean /= size;
|
|
-
|
|
- for (i = 0; i < size; i++)
|
|
- {
|
|
- int dev = (int) buf[i] - mean;
|
|
- res += dev * dev;
|
|
- }
|
|
-
|
|
- return res / size;
|
|
-}
|
|
-
|
|
-/**
|
|
- * fpi_mean_sq_diff_norm:
|
|
- * @buf1: buffer (usually bitmap, one byte per pixel)
|
|
- * @buf2: buffer (usually bitmap, one byte per pixel)
|
|
- * @size: buffer size of smallest buffer
|
|
- *
|
|
- * This function calculates the normalized mean square difference of
|
|
- * two buffers, usually two lines, as per the following formula:
|
|
- * |[<!-- -->
|
|
- * sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size
|
|
- * ]|
|
|
- *
|
|
- * This functions is usually used to get numerical difference
|
|
- * between two images.
|
|
- *
|
|
- * Returns: the normalized mean squared difference between @buf1 and @buf2
|
|
- */
|
|
-gint
|
|
-fpi_mean_sq_diff_norm (const guint8 *buf1,
|
|
- const guint8 *buf2,
|
|
- gint size)
|
|
-{
|
|
- int res = 0, i;
|
|
-
|
|
- for (i = 0; i < size; i++)
|
|
- {
|
|
- int dev = (int) buf1[i] - (int) buf2[i];
|
|
- res += dev * dev;
|
|
- }
|
|
-
|
|
- return res / size;
|
|
-}
|
|
-
|
|
/**
|
|
* fp_minutia_get_coords:
|
|
* @min: A #FpMinutia
|
|
@@ -568,44 +485,3 @@ fp_minutia_get_coords (FpMinutia *min, gint *x, gint *y)
|
|
if (y)
|
|
*y = min->y;
|
|
}
|
|
-
|
|
-#if HAVE_PIXMAN
|
|
-FpImage *
|
|
-fpi_image_resize (FpImage *orig_img,
|
|
- guint w_factor,
|
|
- guint h_factor)
|
|
-{
|
|
- int new_width = orig_img->width * w_factor;
|
|
- int new_height = orig_img->height * h_factor;
|
|
- pixman_image_t *orig, *resized;
|
|
- pixman_transform_t transform;
|
|
- FpImage *newimg;
|
|
-
|
|
- orig = pixman_image_create_bits (PIXMAN_a8, orig_img->width, orig_img->height, (uint32_t *) orig_img->data, orig_img->width);
|
|
- resized = pixman_image_create_bits (PIXMAN_a8, new_width, new_height, NULL, new_width);
|
|
-
|
|
- pixman_transform_init_identity (&transform);
|
|
- pixman_transform_scale (NULL, &transform, pixman_int_to_fixed (w_factor), pixman_int_to_fixed (h_factor));
|
|
- pixman_image_set_transform (orig, &transform);
|
|
- pixman_image_set_filter (orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
|
- pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
- orig, /* src */
|
|
- NULL, /* mask */
|
|
- resized, /* dst */
|
|
- 0, 0, /* src x y */
|
|
- 0, 0, /* mask x y */
|
|
- 0, 0, /* dst x y */
|
|
- new_width, new_height /* width height */
|
|
- );
|
|
-
|
|
- newimg = fp_image_new (new_width, new_height);
|
|
- newimg->flags = orig_img->flags;
|
|
-
|
|
- memcpy (newimg->data, pixman_image_get_data (resized), new_width * new_height);
|
|
-
|
|
- pixman_image_unref (orig);
|
|
- pixman_image_unref (resized);
|
|
-
|
|
- return newimg;
|
|
-}
|
|
-#endif
|
|
diff --git a/libfprint/fp-print-private.h b/libfprint/fp-print-private.h
|
|
new file mode 100644
|
|
index 0000000..f5822b3
|
|
--- /dev/null
|
|
+++ b/libfprint/fp-print-private.h
|
|
@@ -0,0 +1,46 @@
|
|
+/*
|
|
+ * FPrint Print handling
|
|
+ * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
|
+ * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#include "fpi-print.h"
|
|
+#include "fpi-image.h"
|
|
+
|
|
+#include <nbis.h>
|
|
+
|
|
+struct _FpPrint
|
|
+{
|
|
+ GInitiallyUnowned parent_instance;
|
|
+
|
|
+ FpPrintType type;
|
|
+
|
|
+ gchar *driver;
|
|
+ gchar *device_id;
|
|
+ gboolean device_stored;
|
|
+
|
|
+ FpImage *image;
|
|
+
|
|
+ /* Metadata */
|
|
+ FpFinger finger;
|
|
+ gchar *username;
|
|
+ gchar *description;
|
|
+ GDate *enroll_date;
|
|
+
|
|
+ GVariant *data;
|
|
+ GPtrArray *prints;
|
|
+};
|
|
diff --git a/libfprint/fp-print.c b/libfprint/fp-print.c
|
|
index f724c77..30fdf1a 100644
|
|
--- a/libfprint/fp-print.c
|
|
+++ b/libfprint/fp-print.c
|
|
@@ -18,12 +18,10 @@
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
-#include "fpi-print.h"
|
|
-#include "fpi-image.h"
|
|
-#include "fpi-log.h"
|
|
-#include "fpi-device.h"
|
|
+#define FP_COMPONENT "print"
|
|
|
|
-#include <nbis.h>
|
|
+#include "fp-print-private.h"
|
|
+#include "fpi-log.h"
|
|
|
|
/**
|
|
* SECTION: fp-print
|
|
@@ -42,28 +40,6 @@
|
|
* #FpPrint routines.
|
|
*/
|
|
|
|
-struct _FpPrint
|
|
-{
|
|
- GInitiallyUnowned parent_instance;
|
|
-
|
|
- FpPrintType type;
|
|
-
|
|
- gchar *driver;
|
|
- gchar *device_id;
|
|
- gboolean device_stored;
|
|
-
|
|
- FpImage *image;
|
|
-
|
|
- /* Metadata */
|
|
- FpFinger finger;
|
|
- gchar *username;
|
|
- gchar *description;
|
|
- GDate *enroll_date;
|
|
-
|
|
- GVariant *data;
|
|
- GPtrArray *prints;
|
|
-};
|
|
-
|
|
G_DEFINE_TYPE (FpPrint, fp_print, G_TYPE_INITIALLY_UNOWNED)
|
|
|
|
enum {
|
|
@@ -540,223 +516,6 @@ fp_print_set_enroll_date (FpPrint *print,
|
|
g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_ENROLL_DATE]);
|
|
}
|
|
|
|
-
|
|
-
|
|
-/**
|
|
- * fpi_print_add_print:
|
|
- * @print: A #FpPrint
|
|
- * @add: Print to append to @print
|
|
- *
|
|
- * Appends the single #FP_PRINT_NBIS print from @add to the collection of
|
|
- * prints in @print. Both print objects need to be of type #FP_PRINT_NBIS
|
|
- * for this to work.
|
|
- */
|
|
-void
|
|
-fpi_print_add_print (FpPrint *print, FpPrint *add)
|
|
-{
|
|
- g_return_if_fail (print->type == FP_PRINT_NBIS);
|
|
- g_return_if_fail (add->type == FP_PRINT_NBIS);
|
|
-
|
|
- g_assert (add->prints->len == 1);
|
|
- g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
|
-}
|
|
-
|
|
-/**
|
|
- * fpi_print_set_type:
|
|
- * @print: A #FpPrint
|
|
- * @type: The newly type of the print data
|
|
- *
|
|
- * This function can only be called exactly once. Drivers should
|
|
- * call it after creating a new print, or to initialize the template
|
|
- * print passed during enrollment.
|
|
- */
|
|
-void
|
|
-fpi_print_set_type (FpPrint *print,
|
|
- FpPrintType type)
|
|
-{
|
|
- g_return_if_fail (FP_IS_PRINT (print));
|
|
- /* We only allow setting this once! */
|
|
- g_return_if_fail (print->type == FP_PRINT_UNDEFINED);
|
|
-
|
|
- print->type = type;
|
|
- if (print->type == FP_PRINT_NBIS)
|
|
- {
|
|
- g_assert_null (print->prints);
|
|
- print->prints = g_ptr_array_new_with_free_func (g_free);
|
|
- }
|
|
- g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_FPI_TYPE]);
|
|
-}
|
|
-
|
|
-/**
|
|
- * fpi_print_set_device_stored:
|
|
- * @print: A #FpPrint
|
|
- * @device_stored: Whether the print is stored on the device or not
|
|
- *
|
|
- * Drivers must set this to %TRUE for any print that is really a handle
|
|
- * for data that is stored on the device itself.
|
|
- */
|
|
-void
|
|
-fpi_print_set_device_stored (FpPrint *print,
|
|
- gboolean device_stored)
|
|
-{
|
|
- g_return_if_fail (FP_IS_PRINT (print));
|
|
-
|
|
- print->device_stored = device_stored;
|
|
- g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_DEVICE_STORED]);
|
|
-}
|
|
-
|
|
-/* XXX: This is the old version, but wouldn't it be smarter to instead
|
|
- * use the highest quality mintutiae? Possibly just using bz_prune from
|
|
- * upstream? */
|
|
-static void
|
|
-minutiae_to_xyt (struct fp_minutiae *minutiae,
|
|
- int bwidth,
|
|
- int bheight,
|
|
- struct xyt_struct *xyt)
|
|
-{
|
|
- int i;
|
|
- struct fp_minutia *minutia;
|
|
- struct minutiae_struct c[MAX_FILE_MINUTIAE];
|
|
-
|
|
- /* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
|
|
- int nmin = min (minutiae->num, MAX_BOZORTH_MINUTIAE);
|
|
-
|
|
- for (i = 0; i < nmin; i++)
|
|
- {
|
|
- minutia = minutiae->list[i];
|
|
-
|
|
- lfs2nist_minutia_XYT (&c[i].col[0], &c[i].col[1], &c[i].col[2],
|
|
- minutia, bwidth, bheight);
|
|
- c[i].col[3] = sround (minutia->reliability * 100.0);
|
|
-
|
|
- if (c[i].col[2] > 180)
|
|
- c[i].col[2] -= 360;
|
|
- }
|
|
-
|
|
- qsort ((void *) &c, (size_t) nmin, sizeof (struct minutiae_struct),
|
|
- sort_x_y);
|
|
-
|
|
- for (i = 0; i < nmin; i++)
|
|
- {
|
|
- xyt->xcol[i] = c[i].col[0];
|
|
- xyt->ycol[i] = c[i].col[1];
|
|
- xyt->thetacol[i] = c[i].col[2];
|
|
- }
|
|
- xyt->nrows = nmin;
|
|
-}
|
|
-
|
|
-/**
|
|
- * fpi_print_add_from_image:
|
|
- * @print: A #FpPrint
|
|
- * @image: A #FpImage
|
|
- * @error: Return location for error
|
|
- *
|
|
- * Extracts the minutiae from the given image and adds it to @print of
|
|
- * type #FP_PRINT_NBIS.
|
|
- *
|
|
- * The @image will be kept so that API users can get retrieve it e.g.
|
|
- * for debugging purposes.
|
|
- *
|
|
- * Returns: %TRUE on success
|
|
- */
|
|
-gboolean
|
|
-fpi_print_add_from_image (FpPrint *print,
|
|
- FpImage *image,
|
|
- GError **error)
|
|
-{
|
|
- GPtrArray *minutiae;
|
|
- struct fp_minutiae _minutiae;
|
|
- struct xyt_struct *xyt;
|
|
-
|
|
- if (print->type != FP_PRINT_NBIS || !image)
|
|
- {
|
|
- g_set_error (error,
|
|
- G_IO_ERROR,
|
|
- G_IO_ERROR_INVALID_DATA,
|
|
- "Cannot add print data from image!");
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- minutiae = fp_image_get_minutiae (image);
|
|
- if (!minutiae || minutiae->len == 0)
|
|
- {
|
|
- g_set_error (error,
|
|
- G_IO_ERROR,
|
|
- G_IO_ERROR_INVALID_DATA,
|
|
- "No minutiae found in image or not yet detected!");
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- _minutiae.num = minutiae->len;
|
|
- _minutiae.list = (struct fp_minutia **) minutiae->pdata;
|
|
- _minutiae.alloc = minutiae->len;
|
|
-
|
|
- xyt = g_new0 (struct xyt_struct, 1);
|
|
- minutiae_to_xyt (&_minutiae, image->width, image->height, xyt);
|
|
- g_ptr_array_add (print->prints, xyt);
|
|
-
|
|
- g_clear_object (&print->image);
|
|
- print->image = g_object_ref (image);
|
|
- g_object_notify_by_pspec (G_OBJECT (print), properties[PROP_IMAGE]);
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-/**
|
|
- * fpi_print_bz3_match:
|
|
- * @template: A #FpPrint containing one or more prints
|
|
- * @print: A newly scanned #FpPrint to test
|
|
- * @bz3_threshold: The BZ3 match threshold
|
|
- * @error: Return location for error
|
|
- *
|
|
- * Match the newly scanned @print (containing exactly one print) against the
|
|
- * prints contained in @template which will have been stored during enrollment.
|
|
- *
|
|
- * Both @template and @print need to be of type #FP_PRINT_NBIS for this to
|
|
- * work.
|
|
- *
|
|
- * Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
|
- */
|
|
-FpiMatchResult
|
|
-fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
|
|
-{
|
|
- struct xyt_struct *pstruct;
|
|
- gint probe_len;
|
|
- gint i;
|
|
-
|
|
- /* XXX: Use a different error type? */
|
|
- if (template->type != FP_PRINT_NBIS || print->type != FP_PRINT_NBIS)
|
|
- {
|
|
- *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
|
- "It is only possible to match NBIS type print data");
|
|
- return FPI_MATCH_ERROR;
|
|
- }
|
|
-
|
|
- if (print->prints->len != 1)
|
|
- {
|
|
- *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
- "New print contains more than one print!");
|
|
- return FPI_MATCH_ERROR;
|
|
- }
|
|
-
|
|
- pstruct = g_ptr_array_index (print->prints, 0);
|
|
- probe_len = bozorth_probe_init (pstruct);
|
|
-
|
|
- for (i = 0; i < template->prints->len; i++)
|
|
- {
|
|
- struct xyt_struct *gstruct;
|
|
- gint score;
|
|
- gstruct = g_ptr_array_index (template->prints, i);
|
|
- score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
|
- fp_dbg ("score %d", score);
|
|
-
|
|
- if (score >= bz3_threshold)
|
|
- return FPI_MATCH_SUCCESS;
|
|
- }
|
|
-
|
|
- return FPI_MATCH_FAIL;
|
|
-}
|
|
-
|
|
/**
|
|
* fp_print_compatible:
|
|
* @self: A #FpPrint
|
|
diff --git a/libfprint/fpi-image.c b/libfprint/fpi-image.c
|
|
new file mode 100644
|
|
index 0000000..8344037
|
|
--- /dev/null
|
|
+++ b/libfprint/fpi-image.c
|
|
@@ -0,0 +1,150 @@
|
|
+/*
|
|
+ * FPrint Image - Private APIs
|
|
+ * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
|
+ * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#define FP_COMPONENT "image"
|
|
+
|
|
+#include "fpi-image.h"
|
|
+#include "fpi-log.h"
|
|
+
|
|
+#include <nbis.h>
|
|
+
|
|
+#if HAVE_PIXMAN
|
|
+#include <pixman.h>
|
|
+#endif
|
|
+
|
|
+/**
|
|
+ * SECTION: fpi-image
|
|
+ * @title: Internal FpImage
|
|
+ * @short_description: Internal image handling routines
|
|
+ *
|
|
+ * Internal image handling routines. Also see the public <ulink
|
|
+ * url="libfprint-FpImage.html">FpImage routines</ulink>.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * fpi_std_sq_dev:
|
|
+ * @buf: buffer (usually bitmap, one byte per pixel)
|
|
+ * @size: size of @buffer
|
|
+ *
|
|
+ * Calculates the squared standard deviation of the individual
|
|
+ * pixels in the buffer, as per the following formula:
|
|
+ * |[<!-- -->
|
|
+ * mean = sum (buf[0..size]) / size
|
|
+ * sq_dev = sum ((buf[0.size] - mean) ^ 2)
|
|
+ * ]|
|
|
+ * This function is usually used to determine whether image
|
|
+ * is empty.
|
|
+ *
|
|
+ * Returns: the squared standard deviation for @buffer
|
|
+ */
|
|
+gint
|
|
+fpi_std_sq_dev (const guint8 *buf,
|
|
+ gint size)
|
|
+{
|
|
+ guint64 res = 0, mean = 0;
|
|
+ gint i;
|
|
+
|
|
+ for (i = 0; i < size; i++)
|
|
+ mean += buf[i];
|
|
+
|
|
+ mean /= size;
|
|
+
|
|
+ for (i = 0; i < size; i++)
|
|
+ {
|
|
+ int dev = (int) buf[i] - mean;
|
|
+ res += dev * dev;
|
|
+ }
|
|
+
|
|
+ return res / size;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * fpi_mean_sq_diff_norm:
|
|
+ * @buf1: buffer (usually bitmap, one byte per pixel)
|
|
+ * @buf2: buffer (usually bitmap, one byte per pixel)
|
|
+ * @size: buffer size of smallest buffer
|
|
+ *
|
|
+ * This function calculates the normalized mean square difference of
|
|
+ * two buffers, usually two lines, as per the following formula:
|
|
+ * |[<!-- -->
|
|
+ * sq_diff = sum ((buf1[0..size] - buf2[0..size]) ^ 2) / size
|
|
+ * ]|
|
|
+ *
|
|
+ * This functions is usually used to get numerical difference
|
|
+ * between two images.
|
|
+ *
|
|
+ * Returns: the normalized mean squared difference between @buf1 and @buf2
|
|
+ */
|
|
+gint
|
|
+fpi_mean_sq_diff_norm (const guint8 *buf1,
|
|
+ const guint8 *buf2,
|
|
+ gint size)
|
|
+{
|
|
+ int res = 0, i;
|
|
+
|
|
+ for (i = 0; i < size; i++)
|
|
+ {
|
|
+ int dev = (int) buf1[i] - (int) buf2[i];
|
|
+ res += dev * dev;
|
|
+ }
|
|
+
|
|
+ return res / size;
|
|
+}
|
|
+
|
|
+#if HAVE_PIXMAN
|
|
+FpImage *
|
|
+fpi_image_resize (FpImage *orig_img,
|
|
+ guint w_factor,
|
|
+ guint h_factor)
|
|
+{
|
|
+ int new_width = orig_img->width * w_factor;
|
|
+ int new_height = orig_img->height * h_factor;
|
|
+ pixman_image_t *orig, *resized;
|
|
+ pixman_transform_t transform;
|
|
+ FpImage *newimg;
|
|
+
|
|
+ orig = pixman_image_create_bits (PIXMAN_a8, orig_img->width, orig_img->height, (uint32_t *) orig_img->data, orig_img->width);
|
|
+ resized = pixman_image_create_bits (PIXMAN_a8, new_width, new_height, NULL, new_width);
|
|
+
|
|
+ pixman_transform_init_identity (&transform);
|
|
+ pixman_transform_scale (NULL, &transform, pixman_int_to_fixed (w_factor), pixman_int_to_fixed (h_factor));
|
|
+ pixman_image_set_transform (orig, &transform);
|
|
+ pixman_image_set_filter (orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
|
|
+ pixman_image_composite32 (PIXMAN_OP_SRC,
|
|
+ orig, /* src */
|
|
+ NULL, /* mask */
|
|
+ resized, /* dst */
|
|
+ 0, 0, /* src x y */
|
|
+ 0, 0, /* mask x y */
|
|
+ 0, 0, /* dst x y */
|
|
+ new_width, new_height /* width height */
|
|
+ );
|
|
+
|
|
+ newimg = fp_image_new (new_width, new_height);
|
|
+ newimg->flags = orig_img->flags;
|
|
+
|
|
+ memcpy (newimg->data, pixman_image_get_data (resized), new_width * new_height);
|
|
+
|
|
+ pixman_image_unref (orig);
|
|
+ pixman_image_unref (resized);
|
|
+
|
|
+ return newimg;
|
|
+}
|
|
+#endif
|
|
diff --git a/libfprint/fpi-print.c b/libfprint/fpi-print.c
|
|
new file mode 100644
|
|
index 0000000..a407dd9
|
|
--- /dev/null
|
|
+++ b/libfprint/fpi-print.c
|
|
@@ -0,0 +1,249 @@
|
|
+/*
|
|
+ * FPrint Print handling - Private APIs
|
|
+ * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
|
+ * Copyright (C) 2019 Benjamin Berg <bberg@redhat.com>
|
|
+ *
|
|
+ * This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU Lesser General Public
|
|
+ * License as published by the Free Software Foundation; either
|
|
+ * version 2.1 of the License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ * Lesser General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU Lesser General Public
|
|
+ * License along with this library; if not, write to the Free Software
|
|
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
+ */
|
|
+
|
|
+#define FP_COMPONENT "print"
|
|
+#include "fpi-log.h"
|
|
+
|
|
+#include "fp-print-private.h"
|
|
+#include "fpi-device.h"
|
|
+
|
|
+/**
|
|
+ * SECTION: fpi-print
|
|
+ * @title: Internal FpPrint
|
|
+ * @short_description: Internal fingerprint handling routines
|
|
+ *
|
|
+ * Interaction with prints and their storage. See also the public
|
|
+ * #FpPrint routines.
|
|
+ */
|
|
+
|
|
+/**
|
|
+ * fpi_print_add_print:
|
|
+ * @print: A #FpPrint
|
|
+ * @add: Print to append to @print
|
|
+ *
|
|
+ * Appends the single #FP_PRINT_NBIS print from @add to the collection of
|
|
+ * prints in @print. Both print objects need to be of type #FP_PRINT_NBIS
|
|
+ * for this to work.
|
|
+ */
|
|
+void
|
|
+fpi_print_add_print (FpPrint *print, FpPrint *add)
|
|
+{
|
|
+ g_return_if_fail (print->type == FP_PRINT_NBIS);
|
|
+ g_return_if_fail (add->type == FP_PRINT_NBIS);
|
|
+
|
|
+ g_assert (add->prints->len == 1);
|
|
+ g_ptr_array_add (print->prints, g_memdup (add->prints->pdata[0], sizeof (struct xyt_struct)));
|
|
+}
|
|
+
|
|
+/**
|
|
+ * fpi_print_set_type:
|
|
+ * @print: A #FpPrint
|
|
+ * @type: The newly type of the print data
|
|
+ *
|
|
+ * This function can only be called exactly once. Drivers should
|
|
+ * call it after creating a new print, or to initialize the template
|
|
+ * print passed during enrollment.
|
|
+ */
|
|
+void
|
|
+fpi_print_set_type (FpPrint *print,
|
|
+ FpPrintType type)
|
|
+{
|
|
+ g_return_if_fail (FP_IS_PRINT (print));
|
|
+ /* We only allow setting this once! */
|
|
+ g_return_if_fail (print->type == FP_PRINT_UNDEFINED);
|
|
+
|
|
+ print->type = type;
|
|
+ if (print->type == FP_PRINT_NBIS)
|
|
+ {
|
|
+ g_assert_null (print->prints);
|
|
+ print->prints = g_ptr_array_new_with_free_func (g_free);
|
|
+ }
|
|
+ g_object_notify (G_OBJECT (print), "fp-type");
|
|
+}
|
|
+
|
|
+/**
|
|
+ * fpi_print_set_device_stored:
|
|
+ * @print: A #FpPrint
|
|
+ * @device_stored: Whether the print is stored on the device or not
|
|
+ *
|
|
+ * Drivers must set this to %TRUE for any print that is really a handle
|
|
+ * for data that is stored on the device itself.
|
|
+ */
|
|
+void
|
|
+fpi_print_set_device_stored (FpPrint *print,
|
|
+ gboolean device_stored)
|
|
+{
|
|
+ g_return_if_fail (FP_IS_PRINT (print));
|
|
+
|
|
+ print->device_stored = device_stored;
|
|
+ g_object_notify (G_OBJECT (print), "device-stored");
|
|
+}
|
|
+
|
|
+/* XXX: This is the old version, but wouldn't it be smarter to instead
|
|
+ * use the highest quality mintutiae? Possibly just using bz_prune from
|
|
+ * upstream? */
|
|
+static void
|
|
+minutiae_to_xyt (struct fp_minutiae *minutiae,
|
|
+ int bwidth,
|
|
+ int bheight,
|
|
+ struct xyt_struct *xyt)
|
|
+{
|
|
+ int i;
|
|
+ struct fp_minutia *minutia;
|
|
+ struct minutiae_struct c[MAX_FILE_MINUTIAE];
|
|
+
|
|
+ /* struct xyt_struct uses arrays of MAX_BOZORTH_MINUTIAE (200) */
|
|
+ int nmin = min (minutiae->num, MAX_BOZORTH_MINUTIAE);
|
|
+
|
|
+ for (i = 0; i < nmin; i++)
|
|
+ {
|
|
+ minutia = minutiae->list[i];
|
|
+
|
|
+ lfs2nist_minutia_XYT (&c[i].col[0], &c[i].col[1], &c[i].col[2],
|
|
+ minutia, bwidth, bheight);
|
|
+ c[i].col[3] = sround (minutia->reliability * 100.0);
|
|
+
|
|
+ if (c[i].col[2] > 180)
|
|
+ c[i].col[2] -= 360;
|
|
+ }
|
|
+
|
|
+ qsort ((void *) &c, (size_t) nmin, sizeof (struct minutiae_struct),
|
|
+ sort_x_y);
|
|
+
|
|
+ for (i = 0; i < nmin; i++)
|
|
+ {
|
|
+ xyt->xcol[i] = c[i].col[0];
|
|
+ xyt->ycol[i] = c[i].col[1];
|
|
+ xyt->thetacol[i] = c[i].col[2];
|
|
+ }
|
|
+ xyt->nrows = nmin;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * fpi_print_add_from_image:
|
|
+ * @print: A #FpPrint
|
|
+ * @image: A #FpImage
|
|
+ * @error: Return location for error
|
|
+ *
|
|
+ * Extracts the minutiae from the given image and adds it to @print of
|
|
+ * type #FP_PRINT_NBIS.
|
|
+ *
|
|
+ * The @image will be kept so that API users can get retrieve it e.g.
|
|
+ * for debugging purposes.
|
|
+ *
|
|
+ * Returns: %TRUE on success
|
|
+ */
|
|
+gboolean
|
|
+fpi_print_add_from_image (FpPrint *print,
|
|
+ FpImage *image,
|
|
+ GError **error)
|
|
+{
|
|
+ GPtrArray *minutiae;
|
|
+ struct fp_minutiae _minutiae;
|
|
+ struct xyt_struct *xyt;
|
|
+
|
|
+ if (print->type != FP_PRINT_NBIS || !image)
|
|
+ {
|
|
+ g_set_error (error,
|
|
+ G_IO_ERROR,
|
|
+ G_IO_ERROR_INVALID_DATA,
|
|
+ "Cannot add print data from image!");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ minutiae = fp_image_get_minutiae (image);
|
|
+ if (!minutiae || minutiae->len == 0)
|
|
+ {
|
|
+ g_set_error (error,
|
|
+ G_IO_ERROR,
|
|
+ G_IO_ERROR_INVALID_DATA,
|
|
+ "No minutiae found in image or not yet detected!");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ _minutiae.num = minutiae->len;
|
|
+ _minutiae.list = (struct fp_minutia **) minutiae->pdata;
|
|
+ _minutiae.alloc = minutiae->len;
|
|
+
|
|
+ xyt = g_new0 (struct xyt_struct, 1);
|
|
+ minutiae_to_xyt (&_minutiae, image->width, image->height, xyt);
|
|
+ g_ptr_array_add (print->prints, xyt);
|
|
+
|
|
+ g_clear_object (&print->image);
|
|
+ print->image = g_object_ref (image);
|
|
+ g_object_notify (G_OBJECT (print), "image");
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * fpi_print_bz3_match:
|
|
+ * @template: A #FpPrint containing one or more prints
|
|
+ * @print: A newly scanned #FpPrint to test
|
|
+ * @bz3_threshold: The BZ3 match threshold
|
|
+ * @error: Return location for error
|
|
+ *
|
|
+ * Match the newly scanned @print (containing exactly one print) against the
|
|
+ * prints contained in @template which will have been stored during enrollment.
|
|
+ *
|
|
+ * Both @template and @print need to be of type #FP_PRINT_NBIS for this to
|
|
+ * work.
|
|
+ *
|
|
+ * Returns: Whether the prints match, @error will be set if #FPI_MATCH_ERROR is returned
|
|
+ */
|
|
+FpiMatchResult
|
|
+fpi_print_bz3_match (FpPrint *template, FpPrint *print, gint bz3_threshold, GError **error)
|
|
+{
|
|
+ struct xyt_struct *pstruct;
|
|
+ gint probe_len;
|
|
+ gint i;
|
|
+
|
|
+ /* XXX: Use a different error type? */
|
|
+ if (template->type != FP_PRINT_NBIS || print->type != FP_PRINT_NBIS)
|
|
+ {
|
|
+ *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_NOT_SUPPORTED,
|
|
+ "It is only possible to match NBIS type print data");
|
|
+ return FPI_MATCH_ERROR;
|
|
+ }
|
|
+
|
|
+ if (print->prints->len != 1)
|
|
+ {
|
|
+ *error = fpi_device_error_new_msg (FP_DEVICE_ERROR_GENERAL,
|
|
+ "New print contains more than one print!");
|
|
+ return FPI_MATCH_ERROR;
|
|
+ }
|
|
+
|
|
+ pstruct = g_ptr_array_index (print->prints, 0);
|
|
+ probe_len = bozorth_probe_init (pstruct);
|
|
+
|
|
+ for (i = 0; i < template->prints->len; i++)
|
|
+ {
|
|
+ struct xyt_struct *gstruct;
|
|
+ gint score;
|
|
+ gstruct = g_ptr_array_index (template->prints, i);
|
|
+ score = bozorth_to_gallery (probe_len, pstruct, gstruct);
|
|
+ fp_dbg ("score %d", score);
|
|
+
|
|
+ if (score >= bz3_threshold)
|
|
+ return FPI_MATCH_SUCCESS;
|
|
+ }
|
|
+
|
|
+ return FPI_MATCH_FAIL;
|
|
+}
|
|
diff --git a/libfprint/meson.build b/libfprint/meson.build
|
|
index 9eb4849..8cb8609 100644
|
|
--- a/libfprint/meson.build
|
|
+++ b/libfprint/meson.build
|
|
@@ -9,7 +9,9 @@ libfprint_sources = [
|
|
libfprint_private_sources = [
|
|
'fpi-assembling.c',
|
|
'fpi-device.c',
|
|
+ 'fpi-image.c',
|
|
'fpi-image-device.c',
|
|
+ 'fpi-print.c',
|
|
'fpi-ssm.c',
|
|
'fpi-usb-transfer.c',
|
|
'fpi-byte-reader.c',
|
|
--
|
|
2.24.1
|
|
|