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.
This commit is contained in:
Benjamin Berg 2019-06-10 16:56:57 +02:00
parent 2b6f22b84d
commit dd40aeaa79

111
examples/sendvirtimg.py Executable file
View file

@ -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)