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