A while ago, I got my hands on the executable file of the morphotop. The morphotop is a fingerprint reader that can read all of the fingerprints in your hand. After playing with it for a while, I managed to build a C++ library that can communicate with the device.
#include "BDS_Common.h"
#include "BDS_OS.h"
#include "BDS_Interface_XCS.h";
#include <iostream>
extern "C" __declspec(dllexport) int LoadLib(TCHAR *file, void ** o_pp_handle)
{
HINSTANCE h_lib = LoadLibrary(file);
*o_pp_handle = NULL;
if(h_lib == NULL)
return ERROR_LOADLIBRARY;
*o_pp_handle = h_lib;
return 0;
}
extern "C" __declspec(dllexport) int GProcAddress(void * i_p_handle,char * i_pc_method, void ** o_pp_procaddress) {
void * l_p_proc;
l_p_proc = GetProcAddress((HINSTANCE)i_p_handle,i_pc_method);
if(l_p_proc == NULL)
return ERROR_GETPROCADDRESS;
*o_pp_procaddress = l_p_proc;
return 0;
}
extern "C" __declspec(dllexport) int resolveInterface (TCHAR * i_pc_fullpath, int i_i_dllType,
interfaceFunction ** o_p_interfaceTable,
int * o_i_interfaceTable_count,
int * o_i_dllVersion) {
void * l_p_handle = 0;
int l_i_result;
int l_i_dllType;
void * l_pf_getInterface;
l_i_result = LoadLib(i_pc_fullpath,&l_p_handle);
if(l_i_result == 0) {
l_i_result = GProcAddress(l_p_handle,"getInterface", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_getInterface)l_pf_getInterface)
(&l_i_dllType,
o_i_dllVersion,
o_p_interfaceTable,
o_i_interfaceTable_count);
if (i_i_dllType != l_i_dllType) {
return ERROR_DLL_TYPE;
}
}
};
return l_i_result;
}
extern "C" __declspec(dllexport) int EnumerateUsableBiometricDevices (void * l_p_handle, int * const o_p_deviceCount) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_EnumerateUsableBiometricDevices", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_EnumerateUsableBiometricDevices)l_pf_getInterface)
(o_p_deviceCount);
}
return l_i_result;
}
extern "C" __declspec(dllexport) int OpenBioDevice (void * l_p_handle, const int i_i_deviceIndex,
int * o_p_deviceHandle,
void * const i_p_userData) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_OpenBiometricDevice", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_OpenBiometricDevice)l_pf_getInterface)
(i_i_deviceIndex,o_p_deviceHandle,i_p_userData);
}
return l_i_result;
}
extern "C" __declspec(dllexport) int CloseBioDevice (void * l_p_handle, const int i_i_deviceHandle) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_CloseBiometricDevice", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_CloseBiometricDevice)l_pf_getInterface)
(i_i_deviceHandle);
}
return l_i_result;
}
extern "C" __declspec(dllexport) int SetDetectionMode (void * l_p_handle, const int i_i_deviceHandle,
const int i_i_detectionMode, const int i_i_fingerNumber)
{
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_SetParametersForDetectionMode", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_SetParametersForDetectionMode)l_pf_getInterface)
(i_i_deviceHandle,
i_i_detectionMode,
i_i_fingerNumber);
}
return l_i_result;
}
extern "C" __declspec(dllexport) int GetDetectedImage (void * l_p_handle, const int i_i_deviceHandle,
const unsigned long i_l_timeout,
BDS_Image * const o_p_outputImage,
BDS_DetectionResults * const o_p_results) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_GetDetectedImage", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_GetDetectedImage)l_pf_getInterface)
(i_i_deviceHandle,
i_l_timeout, o_p_outputImage,o_p_results);
}
return l_i_result;
}
extern "C" __declspec(dllexport) BDS_Image * BDS_GetDirectImage (void * l_p_handle,const int i_i_deviceHandle,const unsigned long i_l_timeout
,BDS_Image * o_p_outputImage)
{
int l_i_result;
//o_p_outputImage=(BDS_Image*) new BDS_Image();
BDS_Image * o_p_outputImage2=(BDS_Image *) new BDS_Image();
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_GetDirectImage", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_GetDirectImage)l_pf_getInterface)
(i_i_deviceHandle,
i_l_timeout, o_p_outputImage2);
}
return o_p_outputImage2;
}
extern "C" __declspec(dllexport) int BDS_SetParametersForDirectMode (void * l_p_handle,const int i_i_deviceHandle,const int i_i_samplingMode)
{
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_SetParametersForDirectMode", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_SetParametersForDirectMode)l_pf_getInterface)
(i_i_deviceHandle,i_i_samplingMode );
}
return l_i_result;
}
extern "C" __declspec(dllexport) int AutoTest (void * l_p_handle,const int i_i_deviceIndex,
const BDS_TestParameters * const i_p_testParameters,
BDS_TestResults * const o_p_testResults) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_Autotest", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_Autotest)l_pf_getInterface)
(i_i_deviceIndex,
i_p_testParameters, o_p_testResults);
}
return l_i_result;
}
extern "C" __declspec(dllexport) int BDS_SetParametersForLiveMode (void * l_p_handle,
const int i_i_deviceHandle,
const int i_i_samplingMode) {
int l_i_result;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_SetParametersForLiveMode", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_SetParametersForLiveMode)l_pf_getInterface)
(i_i_deviceHandle,
i_i_samplingMode);
}
return l_i_result;
}
int ApplicationCallback(const int i_i_deviceHandle,BDS_Image * const i_p_currentImage,const unsigned char * const i_p_inputData,
unsigned char * const o_p_outputData,void * const o_p_userData){
return 0;
}
extern "C" __declspec(dllexport) int BDS_DefineLiveProcess (void * l_p_handle, const int i_i_deviceHandle,BDS_Callback c) {
int l_i_result;
void * l_pf_getInterface=(void*)new int(20);
//o_p_outputImage2=ApplicationCallback;
l_i_result = GProcAddress(l_p_handle,"BDS_DefineLiveProcess", &l_pf_getInterface);
std::cout<<l_i_result;
if(l_i_result == 0) {
l_i_result = ((pf_BDS_DefineLiveProcess)l_pf_getInterface)
(0,
c);
}
//free(l_pf_getInterface);
return l_i_result;
}
extern "C" __declspec(dllexport) int BDS_GetBiometricDeviceDescriptor (void * l_p_handle,const int i_i_deviceIndex,char * pointer){
int l_i_result;
BDS_DeviceDescriptor * o_p_deviceDescriptor =NULL;
void * l_pf_getInterface;
l_i_result = GProcAddress(l_p_handle,"BDS_GetBiometricDeviceDescriptor", &l_pf_getInterface);
if(l_i_result == 0) {
l_i_result = ((pf_BDS_GetBiometricDeviceDescriptor)l_pf_getInterface)
(i_i_deviceIndex,
o_p_deviceDescriptor);
pointer =o_p_deviceDescriptor->m_deviceSerial;
}
return l_i_result;
}
This code is outdated and I am sharing it in hopes that someone can benefit from it.
a also biult a c# wrapper that use the c++ library
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Morphotop
{
public unsafe partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//BDS_Callback callback = Callback;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct BDS_Image
{
public unsafe uint m_magic;
public unsafe uint m_version;
public unsafe uint m_width;
public unsafe uint m_height;
public unsafe uint m_flags;
public IntPtr m_image;
public unsafe uint m_count;
public unsafe uint m_checksum;
public unsafe fixed byte m_rfu[25];
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate int BDS_Callback(IntPtr i_i_deviceHandle,
BDS_Image* i_p_currentImage, IntPtr i_p_inputData,
IntPtr o_p_outputData, IntPtr i_p_userData);
public unsafe int CallbackPointer(IntPtr i_i_deviceHandle, BDS_Image* i_p_currentImage, IntPtr i_p_inputData,
IntPtr o_p_outputData, IntPtr i_p_userData)
{
try
{
uint size = i_p_currentImage->m_width * i_p_currentImage->m_height;
byte[] data = new byte[size];
byte[] height = new byte[i_p_currentImage->m_height];
byte[] width = new byte[i_p_currentImage->m_width];
IntPtr pointer = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(i_p_currentImage->m_image, data, 0, data.Length);
Marshal.FreeHGlobal(pointer);
SetPicture(pictureBox1, ConvertToBitmap(data, width.Length, height.Length));
}
catch
{
}
return 0;
}
private void SetPicture(PictureBox img, Bitmap bmp)
{
try
{
if (img.InvokeRequired)
{
img.Invoke(new MethodInvoker(
delegate()
{
pictureBox1.Image = bmp;
}));
}
else
{
pictureBox1.Image = bmp;
}
}
catch
{
}
}
public void Initialize()
{
// int res5 = OpenBioDevice(i_p_handle, 0, out device_handle, user_data);
}
private void Capture_Click(object sender, EventArgs e)
{
int p = BDS_SetParametersForDirectMode(i_p_handle, 1);
BDS_Image* resdet = BDS_GetDirectImage(i_p_handle, 0, 5000);
uint size = resdet->m_width * resdet->m_height;
byte[] data = new byte[size];
byte[] height = new byte[resdet->m_height];
byte[] width = new byte[resdet->m_width];
if (data.Length != null)
{
IntPtr pointer = Marshal.AllocHGlobal(data.Length);
try
{
Marshal.Copy(resdet->m_image, data, 0, data.Length);
Marshal.FreeHGlobal(pointer);
File.WriteAllBytes("test",data);
Bitmap bmp =ConvertToBitmap(data, width.Length, height.Length);
bmp.Save(Directory.GetCurrentDirectory()+"\\test.jpg");
pictureBox2.Image = bmp;
}
catch
{
}
}
}
private Bitmap ConvertToBitmap(byte[] image_data,int width,int height)
{
try
{
int Width = width;
int Height = height;
var b = new Bitmap(Width, Height, PixelFormat.Format8bppIndexed);
ColorPalette ncp = b.Palette;
for (int i = 0; i < 256; i++)
ncp.Entries[i] = Color.FromArgb(255, i, i, i);
b.Palette = ncp;
var BoundsRect = new Rectangle(0, 0, Width, Height);
BitmapData bmpData = b.LockBits(BoundsRect,
ImageLockMode.WriteOnly,
b.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = width * b.Height;
var rgbValues = new byte[bytes];
Marshal.Copy(image_data, 0, ptr, bytes);
b.UnlockBits(bmpData);
return b;
}
catch
{
return null;
}
}
private void Form1_Load(object sender, EventArgs e)
{
Initialize(textBox1);
}
private IntPtr i_p_handle;
public void Initialize(TextBox result)
{
i_p_handle = IntPtr.Zero;
IntPtr o_pp_procaddress = IntPtr.Zero;
IntPtr o_p_interfaceTable = IntPtr.Zero;
IntPtr o_i_interfaceTable_count = IntPtr.Zero;
IntPtr o_i_dllVersion = IntPtr.Zero;
IntPtr o_p_deviceCount = IntPtr.Zero;
IntPtr device_handle = IntPtr.Zero;
IntPtr img2 = IntPtr.Zero;
IntPtr r = IntPtr.Zero;
int user_data = 300;
int re = 0;
result.AppendText("Loading Library......." + Environment.NewLine);
re = LoadLib(Directory.GetCurrentDirectory() + "\\SDKServices.dll", out i_p_handle);
if (re == 0)
{
result.AppendText("Library Loaded No ERRORS" + Environment.NewLine);
result.AppendText("Resolving interface" + Environment.NewLine);
re = resolveInterface(Directory.GetCurrentDirectory() + "\\SDKServices.dll", o_pp_procaddress, out o_p_interfaceTable, out o_i_interfaceTable_count, out o_i_dllVersion);
if (re == 0)
{
result.AppendText("Interface resolved" + Environment.NewLine);
result.AppendText("Enumerating devices" + Environment.NewLine);
re = EnumerateUsableBiometricDevices(i_p_handle, out o_p_deviceCount);
OpenBioDevice(i_p_handle,0,out r,user_data);
SetupLiveMode(0,i_p_handle);
if (re == 0)
{
result.ForeColor = Color.Black;
result.AppendText("device enumerated" + Environment.NewLine);
}
else
{
result.AppendText("device could not be enumerated" + Environment.NewLine);
}
}
else
{
result.AppendText("Interface could not be resolved" + Environment.NewLine);
}
}
else
{
result.ForeColor = Color.Black;
result.AppendText("could not load library" + Environment.NewLine);
}
}
public void OpenDevice(TextBox result, IntPtr i_p_handle, IntPtr o_p_deviceHandle, int i_p_userData)
{
int resu = OpenBioDevice(i_p_handle, 0, out o_p_deviceHandle, i_p_userData);
if (resu == 0)
{
result.AppendText("Biometric Device Opened" + Environment.NewLine);
}
else
{
result.AppendText("Could not open Biometric device" + Environment.NewLine);
}
}
public void CloseDevice(TextBox result, IntPtr i_p_handle, int o_p_deviceHandle)
{
int resu = CloseBioDevice(i_p_handle, o_p_deviceHandle);
if (resu == 0)
{
result.ForeColor = Color.Black;
result.AppendText("Biometric Device Closed" + Environment.NewLine);
}
else
{
result.ForeColor = Color.Red;
result.AppendText("Could not close Biometric device" + Environment.NewLine);
}
}
public BDS_Callback callback1;
public void SetupLiveMode(int SamplingMode, IntPtr i_p_handle)
{
callback1 = new BDS_Callback(CallbackPointer);
int res = BDS_DefineLiveProcess(i_p_handle, SamplingMode, callback1);
}
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int LoadLib(String path, out IntPtr i_p_handle);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static int GProcAddress(IntPtr i_p_handle, string i_pc_method, out IntPtr o_pp_procaddress);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int resolveInterface(String path, IntPtr i_i_dllType, out IntPtr o_p_interfaceTable, out IntPtr o_i_interfaceTable_count, out IntPtr o_i_dllVersion);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int EnumerateUsableBiometricDevices(IntPtr path, out IntPtr o_p_deviceCount);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int OpenBioDevice(IntPtr path, int i_i_deviceIndex, out IntPtr o_p_deviceHandle, int i_p_userData);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int CloseBioDevice(IntPtr path, int i_i_deviceHandle);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int SetDetectionMode(IntPtr path, IntPtr i_i_deviceHandle, int i_i_detectionMode, int i_i_fingerNumber);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl)]
public extern unsafe static BDS_Image* BDS_GetDirectImage(IntPtr path, int i_i_deviceHandle, ulong i_l_timeout);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int BDS_SetParametersForDirectMode(IntPtr hadle, int sample);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int BDS_SetParametersForDirectMode(IntPtr path, IntPtr i_i_deviceHandle, int i_i_samplingMode);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int BDS_DefineLiveProcess(IntPtr l_p_handle, int a, BDS_Callback c);
[DllImport("SSB.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public extern static int BDS_DefineLiveProcess(int l_p_handle, BDS_Callback bds);
private void Close_Click(object sender, EventArgs e)
{
CloseDevice(textBox1, i_p_handle, 0);
}
IEnumerable<Rectangle> FindImageTiles(Bitmap compositeImage)
{
var result = new List<Rectangle>();
// Scan for a non-empty region that hasn't already been "captured"
for (var x = 0; x < compositeImage.Width; x++)
{
for (var y = 0; y < compositeImage.Height; y++)
{
// Only process the pixel if we don't have a rectangle that
// already contains this and if it's not empty
if (!result.Any(r => r.Contains(x, y))
&& compositeImage.GetPixel(x, y).A != 0)
{
// Now that we've found a point, create a rectangle
// surrounding that point, then expand outward until
// we have a bounding rectangle that doesn't intersect
// with the tile
var rect = new Rectangle(x - 1, y - 1, 2, 2);
bool foundBounds = false;
while (!foundBounds)
{
var xRange = Enumerable.Range(rect.Left, rect.Right)
.Where(px => px >= 0 && px < compositeImage.Width);
var yRange = Enumerable.Range(rect.Top, rect.Bottom)
.Where(py => py >= 0 && py < compositeImage.Height);
// Adjust the top
if (rect.Top >= 0
&& xRange
.Select(bx => compositeImage.GetPixel(bx, rect.Top))
.Any(p => p.A != 0))
{
rect.Y--;
rect.Height++;
}
else if (rect.Bottom < compositeImage.Height
&& xRange
.Select(bx => compositeImage.GetPixel(bx, rect.Bottom))
.Any(p => p.A != 0))
{
rect.Height++;
}
else if (rect.Left >= 0
&& yRange
.Select(by => compositeImage.GetPixel(rect.Left, by))
.Any(p => p.A != 0))
{
rect.X--;
rect.Width++;
}
else if (rect.Right < compositeImage.Width
&& yRange
.Select(by => compositeImage.GetPixel(rect.Right, by))
.Any(p => p.A != 0))
{
rect.Width++;
}
else
{
foundBounds = true;
}
}
result.Add(rect);
}
}
}
return result;
}
private void button1_Click(object sender, EventArgs e)
{
IEnumerable<Rectangle> rec = FindImageTiles((Bitmap)pictureBox2.Image);
Image img = pictureBox2.Image;
Graphics newGraphics = Graphics.FromImage(img);
foreach(Rectangle r in rec){
newGraphics.DrawRectangle(new Pen(Color.Black, 2), r);
}
}
}
}
you can find the entire project in here https://github.com/medsaid2001/morphotop-library
Top comments (0)