Skip to content
Advertisement

Get image from a fingerprint using Python and Ctypes

I’m trying to get an image from the fingerprint scanner Futronic FS88h, here is what I’ve been doing until now.

from ctypes import windll, wintypes
from os import device_encoding
import ctypes

lib = ctypes.WinDLL('ftrScanAPI.dll')

FTRHANDLE = ctypes.c_void_p

# classes

class FTRSCAN_DEVICE_INFO(ctypes.Structure):
    _fields_ = [
        ("dwStructSize", FTR_DWORD),
        ("byDeviceCompatibility", FTR_BYTE),
        ("wPixelSizeX", FTR_WORD),
        ("wPixelSizeY", FTR_WORD)
    ]
PFTRSCAN_DEVICE_INFO = ctypes.POINTER(FTRSCAN_DEVICE_INFO)

class FTRSCAN_FAKE_REPLICA_PARAMETERS(ctypes.Structure):
    _fields_ = [
        ("bCalculated", FTR_BOOL),
        ("nCalculatedSum1", ctypes.c_int),
        ("nCalculatedSumFuzzy", ctypes.c_int),
        ("nCalculatedSumEmpty", ctypes.c_int),
        ("nCalculatedSum2", ctypes.c_int),
        ("dblCalculatedTremor", ctypes.c_double),
        ("dblCalculatedValue", ctypes.c_double),
    ]
PFTRSCAN_FAKE_REPLICA_PARAMETERS = ctypes.POINTER(FTRSCAN_FAKE_REPLICA_PARAMETERS)
fake_replica = FTRSCAN_FAKE_REPLICA_PARAMETERS(0, 0, 0, 0, 0, 0, 0)

class FTRSCAN_FRAME_PARAMETERS(ctypes.Structure):
    _fields_ = [
        ("nContrastOnDose2", ctypes.c_int),
        ("nContrastOnDose4", ctypes.c_int),
        ("nDose", ctypes.c_int),
        ("nBrightnessOnDose1", ctypes.c_int),
        ("nBrightnessOnDose2", ctypes.c_int),
        ("nBrightnessOnDose3", ctypes.c_int),
        ("nBrightnessOnDose4", ctypes.c_int),
        ("FakeReplicaParams", FTRSCAN_FAKE_REPLICA_PARAMETERS),
    ]
PFTRSCAN_FRAME_PARAMETERS = ctypes.POINTER(FTRSCAN_FRAME_PARAMETERS)

if __name__ == "__main__":
    lib.ftrScanOpenDevice.argtypes = []
    lib.ftrScanOpenDevice.restype = FTRHANDLE
    h_device = lib.ftrScanOpenDevice()

    frame_parameters = FTRSCAN_FRAME_PARAMETERS(0, 0, 0, 0, 0, 0, 0, fake_replica, 0)
    lib.ftrScanIsFingerPresent.argtypes = [FTRHANDLE, PFTRSCAN_FRAME_PARAMETERS]
    lib.ftrScanIsFingerPresent.restype = FTR_BOOL
    if lib.ftrScanIsFingerPresent(h_device, ctypes.byref(frame_parameters)):
        print("nFinger parameters")
        print(f"1: {frame_parameters.nContrastOnDose2}")
        print(f"2: {frame_parameters.nContrastOnDose4}")
        print(f"3: {frame_parameters.nDose}")
        print(f"4: {frame_parameters.nBrightnessOnDose1}")
        print(f"5: {frame_parameters.nBrightnessOnDose2}")
        print(f"6: {frame_parameters.nBrightnessOnDose3}")
        print(f"7: {frame_parameters.nBrightnessOnDose4}n")

With this I’m able to check if the finger is present and it actually retrieves some info, but I need to get the image from the device and I’m not quite sure how to do it, I’ve been trying this:

    lib.ftrScanGetImage.argtypes = [FTRHANDLE]
    lib.ftrScanGetImage.restypes = wintypes.BOOL
    get_image = lib.ftrScanGetImage(h_device)
    print(get_image)

But this only returns a bool, I’d love to know how to get the image or some data that I can convert into a image. This is the .dll that I’m using.

ftrScanAPI.h

I’ve found this piece of code that gets the image, however, I don’t know how I should port it to Python, here’s the piece of code from this question.

int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);

int main(int argc, char** argv) {
    unsigned char *rawData; // Removed the NULL assignment
    char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";

    // Set the size of rawData - loadImageSize() sets the value of the ImageSize class variable.
    loadImageSize();
    rawData = (unsigned char *) malloc(ImageSize.nImageSize);

    getRawImage(rawData);
    // This works now
    writeJPEGBFile(rawData, filename);
    free(rawData);
    return 0;
}

int getRawImage(unsigned char *pBuffer) {
    void *hDevice;

    hDevice = scanOpenDevice();
    // Removed code for simplification
    scanGetFrame(hDevice, pBuffer, NULL)
    scanCloseDevice(hDevice);
    return 0;
}

int writeJPEGBFile(unsigned char *idata, char *ofile) {
    // JPEG code goes here
    return 0;
}

Advertisement

Answer

There’s a C# example here. Using it as a reference:

# Relevant definitions from the library header:

# #define FTR_API_PREFIX
# #define FTR_API __stdcall
#
# typedef void* FTRHANDLE;
# typedef void* FTR_PVOID;
# typedef int   FTR_BOOL;
#
# typedef struct
# {
#     int nWidth;
#     int nHeight;
#     int nImageSize;
# } FTRSCAN_IMAGE_SIZE, *PFTRSCAN_IMAGE_SIZE;
#
# FTR_API_PREFIX FTRHANDLE FTR_API ftrScanOpenDevice();
# FTR_API_PREFIX void FTR_API ftrScanCloseDevice( FTRHANDLE ftrHandle );
# FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetImageSize( FTRHANDLE ftrHandle, PFTRSCAN_IMAGE_SIZE pImageSize );
# FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetImage( FTRHANDLE ftrHandle, int nDose, FTR_PVOID pBuffer );

import ctypes as ct

# A type-safe handle
class FTRHANDLE(ct.c_void_p):
    pass

class FTRSCAN_IMAGE_SIZE(ct.Structure):
    _fields_ = (('nWidth', ct.c_int),
                ('nHeight', ct.c_int),
                ('nImageSize', ct.c_int))

PFTRSCAN_IMAGE_SIZE = ct.POINTER(FTRSCAN_IMAGE_SIZE)

lib = ct.WinDLL('./ftrScanAPI')  # due to __stdcall, only matters if 32-bit Python and DLL
lib.ftrScanOpenDevice.argtypes = ()
lib.ftrScanOpenDevice.restype = FTRHANDLE
lib.ftrScanCloseDevice.argtypes = FTRHANDLE,
lib.ftrScanCloseDevice.restype = None
lib.ftrScanGetImageSize.argtypes = FTRHANDLE, PFTRSCAN_IMAGE_SIZE
lib.ftrScanGetImageSize.restype = ct.c_int
lib.ftrScanGetImage.argtypes = FTRHANDLE, ct.c_int, ct.c_void_p
lib.ftrScanGetImage.restype = ct.c_int

handle = lib.ftrScanOpenDevice()
try:
    size = FTRSCAN_IMAGE_SIZE() # allocate output parameter storage
    if not lib.ftrScanGetImageSize(handle, ct.byref(size)):
        raise RuntimeError('get size failed')
    NDos = 4 # I don't know what this parameter means, from C# example
    buffer = ct.create_string_buffer(size.nImageSize) # storage for image
    if not lib.ftrScanGetImage(handle, NDos, buffer):
        raise RuntimeError('get image failed')
    # buffer contains the image data now
finally:
    lib.ftrScanCloseDevice(handle)
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement