From dd40aeaa7987a783eb8634cfe75ef640443cf91f Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Mon, 10 Jun 2019 16:56:57 +0200 Subject: [PATCH] examples: Add sendvirtimg.py script to send a print to virtual_imgdev With this script it is possible to test libfprint/fprintd without any hardware device. The image needs to be provides as a PNG with the alpha channel storing the print data. See the comment in the file on how the script can be used. --- examples/sendvirtimg.py | 111 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100755 examples/sendvirtimg.py diff --git a/examples/sendvirtimg.py b/examples/sendvirtimg.py new file mode 100755 index 0000000..eb5263b --- /dev/null +++ b/examples/sendvirtimg.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 + +# This script can be used together with the virtual_imgdev to simulate an +# image based fingerprint reader. +# +# To use, set the FP_VIRTUAL_IMAGE environment variable for both the +# libfprint using program (e.g. fprintd) and this script. +# +# Usually this would work by adding it into the systemd unit file. The +# best way of doing so is to create +# /etc/systemd/system/fprintd.service.d/fprintd-test.conf +# +# [Service] +# RuntimeDirectory=fprint +# Environment=FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock +# Environment=G_MESSAGES_DEBUG=all +# ReadWritePaths=$RUNTIME_DIR +# +# After that run: +# +# systemctl daemon-reload +# systemctl restart fprintd.service +# +# You may also need to disable selinux. +# +# Then run this script with e.g. +# FP_VIRTUAL_IMAGE=/run/fprint/virtimg_sock ./sendvirtimg.py prints/whorl.png + + + +import cairo +import sys +import os +import socket +import struct + +if len(sys.argv) != 2: + sys.stderr.write('You need to pass a PNG with an alpha channel!\n') + sys.exit(1) + +# Just copied from the C file, we could also use the introspection data for +# this. Also, most of them do *not* make any sense. +commands = { + 'retry' : struct.pack('ii', -1, 0), + 'retry-too-short' : struct.pack('ii', -1, 1), + 'retry-center-finger' : struct.pack('ii', -1, 2), + 'retry-remove-finger' : struct.pack('ii', -1, 3), + + 'error' : struct.pack('ii', -2, 0), + 'error-not-supported' : struct.pack('ii', -2, 1), + 'error-not-open' : struct.pack('ii', -2, 2), + 'error-already-open' : struct.pack('ii', -2, 3), + 'error-busy' : struct.pack('ii', -2, 4), + 'error-proto' : struct.pack('ii', -2, 5), + 'error-data-invalid' : struct.pack('ii', -2, 6), + 'error-data-not-found' : struct.pack('ii', -2, 7), + 'error-data-full' : struct.pack('ii', -2, 8), +} + + +if sys.argv[1] in commands: + command = commands[sys.argv[1]] +else: + png = cairo.ImageSurface.create_from_png(sys.argv[1]) + + # Cairo wants 4 byte aligned rows, so just add a few pixel if necessary + w = png.get_width() + h = png.get_height() + w = (w + 3) // 4 * 4 + h = (h + 3) // 4 * 4 + img = cairo.ImageSurface(cairo.Format.A8, w, h) + cr = cairo.Context(img) + + cr.set_source_rgba(1, 1, 1, 1) + cr.paint() + + cr.set_source_rgba(0, 0, 0, 0) + cr.set_operator(cairo.OPERATOR_SOURCE) + + cr.set_source_surface(png) + cr.paint() + + mem = img.get_data() + mem = mem.tobytes() + assert len(mem) == img.get_width() * img.get_height() + + command = struct.pack('ii', img.get_width(), img.get_height()) + command += mem + + + +def write_dbg_img(): + dbg_img_rgb = cairo.ImageSurface(cairo.Format.RGB24, img.get_width(), img.get_height()) + dbg_cr = cairo.Context(dbg_img_rgb) + dbg_cr.set_source_rgb(0, 0, 0) + dbg_cr.paint() + dbg_cr.set_source_rgb(1, 1, 1) + dbg_cr.mask_surface(img, 0, 0) + + dbg_img_rgb.write_to_png('/tmp/test.png') + +#write_dbg_img() + +# Send image through socket +sockaddr = os.environ['FP_VIRTUAL_IMAGE'] + +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +sock.connect(sockaddr) + +sock.sendall(command) +