0

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;
}
  • How would you get the image in C? Get that working and port that, or at least show that code for help in porting it to Python. BTW, `ftrScanGetImage` takes more more parameters than `FTRHANDLE`. – Mark Tolonen Jun 07 '22 at 15:28
  • That's the thing, I haven't encounter any code in C and honestly I don't know C to actually do it, so that's why I'm confused. And yeah, it takes two other parameter, but dunno what I should pass on them. – Eduardo Aldana Jun 07 '22 at 15:41
  • The update isn't even referring to the same library. – Mark Tolonen Jun 07 '22 at 16:19
  • https://stackoverflow.com/search?q=%5Bpython%5D+%5Bctypes%5D+pass+buffer I don't think this is an easy task without C knowledge though. – Ulrich Eckhardt Jun 07 '22 at 16:36

1 Answers1

0

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)
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • Thank you very much, this stores the data in the buffer, though I'd like to create an image from that data, I've been trying to follow the example you showed, but I haven't find any good results, but it's an advance – Eduardo Aldana Jun 08 '22 at 16:16