Home > OS >  Get image from a fingerprint using Python and Ctypes
Get image from a fingerprint using Python and Ctypes

Time:06-09

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;
}

CodePudding user response:

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)
  • Related