DEV Community

medsaid2001
medsaid2001

Posted on

3 2

Morphotop Library

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;
} 
Enter fullscreen mode Exit fullscreen mode

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);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

you can find the entire project in here https://github.com/medsaid2001/morphotop-library

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Engage with a sea of insights in this enlightening article, highly esteemed within the encouraging DEV Community. Programmers of every skill level are invited to participate and enrich our shared knowledge.

A simple "thank you" can uplift someone's spirits. Express your appreciation in the comments section!

On DEV, sharing knowledge smooths our journey and strengthens our community bonds. Found this useful? A brief thank you to the author can mean a lot.

Okay