ZKTeco live20R指纹采集识别适配谷歌浏览器

为解决谷歌浏览器不支持指纹采集器的问题,采用WebSocket技术实现浏览器与桌面应用间的通信,成功将指纹图像实时展示在网页上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近手头的软件项目需要用到指纹采集器,于是上某宝淘了下,发现成熟的指纹采集模块厂家不多。找了一家销量最高的。价格也挺便宜的。

大多数都有桌面版和IE浏览器插件,但是都没有谷歌浏览器版本的。郁闷!

项目是基于谷歌浏览器做的,但是谷歌浏览器不支持activeX控件。网上也有可以让activeX控件适配谷歌浏览器的方法,但是都不保证可用。本着网上没有就自己造的原则,我开始了适配之旅。

曲线救国,既然浏览器端不行那就走客户端,我的思路是这样的:

1、在桌面搭建websocket服务端,监听某个特定的端口的websocket连接 。服务端使用官方提供的客户端SDK来做采集指纹操作。采集到指纹后把数据转换成红色的指纹图片,然后把图片转成base64数据,传给客户端。

2、客户端,即谷歌浏览器端,通过websocket和服务端的服务进行连接,客户端连接服务后,服务端自动记录连接ID,通过该ID把base64格式图片数据发送到浏览器,浏览器把图片进行转换,变成图片显示。效果如下


以上为思路,说干就干,上代码前先把必须的websocket包安装一下,在vs2019里,项目-》引用,右键,管理NuGet程序包,搜索并安装SuperWebSocket.

下面是代码:

服务端主程序:

using libzkfpcsharp;
using Microsoft.Win32;
using SuperSocket.SocketBase.Config;
using SuperWebSocket;
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace FP_Service
{
    public partial class Form1 : Form
    {
        IntPtr mDevHandle = IntPtr.Zero;
        IntPtr FormHandle = IntPtr.Zero;
        string strBase64 = "";
        private bool isclose;
        bool bIsTimeToDie = false;
        byte[] FPBuffer;
        byte[][] RegTmps = new byte[3][];
        byte[] CapTmp = new byte[2048];
        int cbCapTmp = 2048;

        private int mfpWidth = 0;
        private int mfpHeight = 0;
        private WebSocketServer mWebSocketServer;
        private string mSessionID = "";
        const int MESSAGE_CAPTURED_OK = 0x0400 + 6;
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
        public Form1()
        {
            InitializeComponent();
        }
      
        private void Form1_Load(object sender, EventArgs e)
        {

            FormHandle = this.Handle;
            base.Left = Screen.GetBounds(this).Width - base.Width - 5;
            base.Top = Screen.GetBounds(this).Height - base.Height - 50;
            FirstAutoRun(true);//添加进系统服务,开机自启动。
            CheckAutoRun(Application.ExecutablePath, true);//添加进系统服务,开机自启动。
            int ret = zkfperrdef.ZKFP_ERR_OK;
            if ((ret = zkfp2.Init()) == zkfperrdef.ZKFP_ERR_OK)
            {
                int nCount = zkfp2.GetDeviceCount();
                if (nCount < 0)
                {
                    zkfp2.Terminate();
                    label1.Text="未发现指纹采集设备!";
                }
            }
            else
            {
                label1.Text = "初始化失败, 返回值为:" + ret;
            }
            //Setup();
            ServerConfig config = new ServerConfig{
                Ip = "127.0.0.1",
                Port = 8891,
                MaxConnectionNumber = 100,
                Name = "FPServer"
            };
            mWebSocketServer = new WebSocketServer();
            if (mWebSocketServer.Setup(config)) 
            { 
                label1.Text = "初始化服务成功。";
                mWebSocketServer.NewSessionConnected += MWebSocketServer_NewSessionConnected1;
            } 
            else {
                label1.Text = "初始化服务失败!"; 
            }
           if( mWebSocketServer.Start()) { label1.Text = "开启服务成功。";
              
            } else { label1.Text = "开启服务失败!"; }
         
            if (IntPtr.Zero == (mDevHandle = zkfp2.OpenDevice(0)))
            {
                label1.Text = "开启设备失败!";
                return;
            }
            else
            {
                for (int i = 0; i < 3; i++)
                {
                    RegTmps[i] = new byte[2048];
                }
                byte[] paramValue = new byte[4];
                int size = 4;
                zkfp2.GetParameters(mDevHandle, 1, paramValue, ref size);
                zkfp2.ByteArray2Int(paramValue, ref mfpWidth);

                size = 4;
                zkfp2.GetParameters(mDevHandle, 2, paramValue, ref size);
                zkfp2.ByteArray2Int(paramValue, ref mfpHeight);

                FPBuffer = new byte[mfpWidth * mfpHeight];

                Thread captureThread = new Thread(new ThreadStart(DoCapture));
                captureThread.IsBackground = true;
                captureThread.Start();
                bIsTimeToDie = false;
                label1.Text = "设备已连接";
            }

        }
    
        private void DoCapture()
        {
            while (!bIsTimeToDie)
            {
                cbCapTmp = 2048;
                int ret = zkfp2.AcquireFingerprint(mDevHandle, FPBuffer, CapTmp, ref cbCapTmp);
             
                if (ret == zkfp.ZKFP_ERR_OK)
                {
                    SendMessage(FormHandle, MESSAGE_CAPTURED_OK, IntPtr.Zero, IntPtr.Zero);
                }
                Thread.Sleep(200);
            }
        }
        private string ToBase64(Bitmap bmp)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                String strbaser64 = Convert.ToBase64String(arr);
                return strbaser64;
            }
            catch (Exception ex)
            {
                MessageBox.Show("转换失败:" + ex.Message);
                return "";
            }
        }
        private static Bitmap UpdateColor(Bitmap bitmap)
        {
            int width = bitmap.Width;
            int height = bitmap.Height;
            Bitmap newmap = new Bitmap(width, height);
            Color pixel;
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    pixel = bitmap.GetPixel(i, j); // 获取原图的像素点颜色值
                    int r, g, b, a;
                    r = pixel.R;
                    g = pixel.G;
                    b = pixel.B;
                    a = pixel.A;
                   

                    // 判断是否为白色背景
                    if ( b > 120|| r > 120 || g > 120)
                    {
                        newmap.SetPixel(i, j, Color.FromArgb(0,255, 255, 255));
                    }
                    else
                    {
                        newmap.SetPixel(i, j, Color.Red);
                    }
                }
            }
            return newmap;
        }
        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case MESSAGE_CAPTURED_OK:
                    {
                        MemoryStream ms = new MemoryStream();
                        BitmapFormat.GetBitmap(FPBuffer, mfpWidth, mfpHeight, ref ms);
                        Bitmap bmp = UpdateColor( new Bitmap(ms));
                        //Bitmap bmp =new Bitmap(ms);
                        strBase64 = ToBase64(bmp);
                        pictureBox2.Image = bmp;

                        foreach (WebSocketSession sendSession in mWebSocketServer.GetAllSessions())
                        {
                            if (sendSession.SessionID.Equals(mSessionID))
                            {
                                sendSession.Send(strBase64);
                                break;
                            }
                        }

                    }
                    break;

                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }

    
        private void MWebSocketServer_NewSessionConnected1(WebSocketSession session)
        {
            mSessionID = session.SessionID;//客户端连接成功保存ID至session
        }
     

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!isclose)
            {
                e.Cancel = true;
                base.Hide();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            isclose = true;
            this.Close();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                SetAutoRun(Application.ExecutablePath, false, true);
            }
            else
            {
                SetAutoRun(Application.ExecutablePath, true, true);
            }
        }
        public void SetAutoRun(string fileName, bool isAutoRun, bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                if (!File.Exists(fileName))
                {
                    throw new Exception("Not File!");
                }
                string name = fileName.Substring(fileName.LastIndexOf("\\") + 1);
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (isAutoRun)
                    {
                        if (reg.GetValue(name) == null)
                        {
                            reg.SetValue(name, fileName);
                        }
                        else if (!reg.GetValue(name).Equals(fileName))
                        {
                            reg.SetValue(name, fileName);
                        }
                    }
                    else
                    {
                        reg.DeleteValue(name);
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (isAutoRun)
                    {
                        if (reg.GetValue(name) == null)
                        {
                            reg.SetValue(name, fileName);
                        }
                        else if (!reg.GetValue(name).Equals(fileName))
                        {
                            reg.SetValue(name, fileName);
                        }
                    }
                    else
                    {
                        reg.DeleteValue(name);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }
        public void FirstAutoRun(bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                string name = "Run";
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\WC\\FPWebServer\\", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\WC\\FPWebServer\\");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        this.SetAutoRun(Application.ExecutablePath, true, true);
                        reg.SetValue(name, true);
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WC\\FPWebServer\\", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\WC\\FPWebServer\\");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        this.SetAutoRun(Application.ExecutablePath, true, false);
                        reg.SetValue(name, true);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }

        public void CheckAutoRun(string fileName, bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                if (!File.Exists(fileName))
                {
                    throw new Exception("Not File!");
                }
                string name = fileName.Substring(fileName.LastIndexOf("\\") + 1);
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        checkBox1.Checked = false;
                    }
                    else
                    {
                       checkBox1.Checked = true;
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        checkBox1.Checked = false;
                    }
                    else
                    {
                        checkBox1.Checked = true;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            mWebSocketServer.Stop();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int ret = zkfperrdef.ZKFP_ERR_OK;
            if ((ret = zkfp2.Init()) == zkfperrdef.ZKFP_ERR_OK)
            {
                int nCount = zkfp2.GetDeviceCount();
                if (nCount < 0)
                {
                    zkfp2.Terminate();
                    label1.Text = "未发现指纹采集设备!";
                }
            }
            else
            {
                label1.Text = "初始化失败, 返回值为:" + ret;
            }
        }

        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            if (base.Visible)
            {
                base.Hide();
                return;
            }
            base.Show();
        }
    }
}
using libzkfpcsharp;
using Microsoft.Win32;
using SuperSocket.SocketBase.Config;
using SuperWebSocket;
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace FP_Service
{
    public partial class Form1 : Form
    {
        IntPtr mDevHandle = IntPtr.Zero;
        IntPtr FormHandle = IntPtr.Zero;
        string strBase64 = "";
        private bool isclose;
        bool bIsTimeToDie = false;
        byte[] FPBuffer;
        byte[][] RegTmps = new byte[3][];
        byte[] CapTmp = new byte[2048];
        int cbCapTmp = 2048;

        private int mfpWidth = 0;
        private int mfpHeight = 0;
        private WebSocketServer mWebSocketServer;
        private string mSessionID = "";
        const int MESSAGE_CAPTURED_OK = 0x0400 + 6;
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
        public Form1()
        {
            InitializeComponent();
        }
      
        private void Form1_Load(object sender, EventArgs e)
        {

            FormHandle = this.Handle;
            base.Left = Screen.GetBounds(this).Width - base.Width - 5;
            base.Top = Screen.GetBounds(this).Height - base.Height - 50;
            FirstAutoRun(true);//添加进系统服务,开机自启动。
            CheckAutoRun(Application.ExecutablePath, true);//添加进系统服务,开机自启动。
            int ret = zkfperrdef.ZKFP_ERR_OK;
            if ((ret = zkfp2.Init()) == zkfperrdef.ZKFP_ERR_OK)
            {
                int nCount = zkfp2.GetDeviceCount();
                if (nCount < 0)
                {
                    zkfp2.Terminate();
                    label1.Text="未发现指纹采集设备!";
                }
            }
            else
            {
                label1.Text = "初始化失败, 返回值为:" + ret;
            }
            //Setup();
            ServerConfig config = new ServerConfig{
                Ip = "127.0.0.1",
                Port = 8891,
                MaxConnectionNumber = 100,
                Name = "FPServer"
            };
            mWebSocketServer = new WebSocketServer();
            if (mWebSocketServer.Setup(config)) 
            { 
                label1.Text = "初始化服务成功。";
                mWebSocketServer.NewSessionConnected += MWebSocketServer_NewSessionConnected1;
            } 
            else {
                label1.Text = "初始化服务失败!"; 
            }
           if( mWebSocketServer.Start()) { label1.Text = "开启服务成功。";
              
            } else { label1.Text = "开启服务失败!"; }
         
            if (IntPtr.Zero == (mDevHandle = zkfp2.OpenDevice(0)))
            {
                label1.Text = "开启设备失败!";
                return;
            }
            else
            {
                for (int i = 0; i < 3; i++)
                {
                    RegTmps[i] = new byte[2048];
                }
                byte[] paramValue = new byte[4];
                int size = 4;
                zkfp2.GetParameters(mDevHandle, 1, paramValue, ref size);
                zkfp2.ByteArray2Int(paramValue, ref mfpWidth);

                size = 4;
                zkfp2.GetParameters(mDevHandle, 2, paramValue, ref size);
                zkfp2.ByteArray2Int(paramValue, ref mfpHeight);

                FPBuffer = new byte[mfpWidth * mfpHeight];

                Thread captureThread = new Thread(new ThreadStart(DoCapture));
                captureThread.IsBackground = true;
                captureThread.Start();
                bIsTimeToDie = false;
                label1.Text = "设备已连接";
            }

        }
    
        private void DoCapture()
        {
            while (!bIsTimeToDie)
            {
                cbCapTmp = 2048;
                int ret = zkfp2.AcquireFingerprint(mDevHandle, FPBuffer, CapTmp, ref cbCapTmp);
             
                if (ret == zkfp.ZKFP_ERR_OK)
                {
                    SendMessage(FormHandle, MESSAGE_CAPTURED_OK, IntPtr.Zero, IntPtr.Zero);
                }
                Thread.Sleep(200);
            }
        }
        private string ToBase64(Bitmap bmp)
        {
            try
            {
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                String strbaser64 = Convert.ToBase64String(arr);
                return strbaser64;
            }
            catch (Exception ex)
            {
                MessageBox.Show("转换失败:" + ex.Message);
                return "";
            }
        }
        private static Bitmap UpdateColor(Bitmap bitmap)
        {
            int width = bitmap.Width;
            int height = bitmap.Height;
            Bitmap newmap = new Bitmap(width, height);
            Color pixel;
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    pixel = bitmap.GetPixel(i, j); // 获取原图的像素点颜色值
                    int r, g, b, a;
                    r = pixel.R;
                    g = pixel.G;
                    b = pixel.B;
                    a = pixel.A;
                   

                    // 判断是否为白色背景
                    if ( b > 120|| r > 120 || g > 120)
                    {
                        newmap.SetPixel(i, j, Color.FromArgb(0,255, 255, 255));
                    }
                    else
                    {
                        newmap.SetPixel(i, j, Color.Red);
                    }
                }
            }
            return newmap;
        }
        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case MESSAGE_CAPTURED_OK:
                    {
                        MemoryStream ms = new MemoryStream();
                        BitmapFormat.GetBitmap(FPBuffer, mfpWidth, mfpHeight, ref ms);
                        Bitmap bmp = UpdateColor( new Bitmap(ms));
                        //Bitmap bmp =new Bitmap(ms);
                        strBase64 = ToBase64(bmp);
                        pictureBox2.Image = bmp;

                        foreach (WebSocketSession sendSession in mWebSocketServer.GetAllSessions())
                        {
                            if (sendSession.SessionID.Equals(mSessionID))
                            {
                                sendSession.Send(strBase64);
                                break;
                            }
                        }

                    }
                    break;

                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }

    
        private void MWebSocketServer_NewSessionConnected1(WebSocketSession session)
        {
            mSessionID = session.SessionID;//客户端连接成功保存ID至session
        }
     

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!isclose)
            {
                e.Cancel = true;
                base.Hide();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            isclose = true;
            this.Close();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                SetAutoRun(Application.ExecutablePath, false, true);
            }
            else
            {
                SetAutoRun(Application.ExecutablePath, true, true);
            }
        }
        public void SetAutoRun(string fileName, bool isAutoRun, bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                if (!File.Exists(fileName))
                {
                    throw new Exception("Not File!");
                }
                string name = fileName.Substring(fileName.LastIndexOf("\\") + 1);
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (isAutoRun)
                    {
                        if (reg.GetValue(name) == null)
                        {
                            reg.SetValue(name, fileName);
                        }
                        else if (!reg.GetValue(name).Equals(fileName))
                        {
                            reg.SetValue(name, fileName);
                        }
                    }
                    else
                    {
                        reg.DeleteValue(name);
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (isAutoRun)
                    {
                        if (reg.GetValue(name) == null)
                        {
                            reg.SetValue(name, fileName);
                        }
                        else if (!reg.GetValue(name).Equals(fileName))
                        {
                            reg.SetValue(name, fileName);
                        }
                    }
                    else
                    {
                        reg.DeleteValue(name);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }
        public void FirstAutoRun(bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                string name = "Run";
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\WC\\FPWebServer\\", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\WC\\FPWebServer\\");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        this.SetAutoRun(Application.ExecutablePath, true, true);
                        reg.SetValue(name, true);
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\WC\\FPWebServer\\", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\WC\\FPWebServer\\");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        this.SetAutoRun(Application.ExecutablePath, true, false);
                        reg.SetValue(name, true);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }

        public void CheckAutoRun(string fileName, bool isCurrentUser)
        {
            RegistryKey reg = null;
            try
            {
                if (!File.Exists(fileName))
                {
                    throw new Exception("Not File!");
                }
                string name = fileName.Substring(fileName.LastIndexOf("\\") + 1);
                if (isCurrentUser)
                {
                    reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        checkBox1.Checked = false;
                    }
                    else
                    {
                       checkBox1.Checked = true;
                    }
                }
                else
                {
                    reg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                    if (reg == null)
                    {
                        reg = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                    }
                    if (reg.GetValue(name) == null)
                    {
                        checkBox1.Checked = false;
                    }
                    else
                    {
                        checkBox1.Checked = true;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.ToString());
            }
            finally
            {
                if (reg != null)
                {
                    reg.Close();
                }
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            mWebSocketServer.Stop();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            int ret = zkfperrdef.ZKFP_ERR_OK;
            if ((ret = zkfp2.Init()) == zkfperrdef.ZKFP_ERR_OK)
            {
                int nCount = zkfp2.GetDeviceCount();
                if (nCount < 0)
                {
                    zkfp2.Terminate();
                    label1.Text = "未发现指纹采集设备!";
                }
            }
            else
            {
                label1.Text = "初始化失败, 返回值为:" + ret;
            }
        }

        private void notifyIcon1_Click(object sender, EventArgs e)
        {
            if (base.Visible)
            {
                base.Hide();
                return;
            }
            base.Show();
        }
    }
}

服务端指纹数据转图片:

using System;
using System.Runtime.InteropServices;
using System.IO;

namespace FP_Service
{
    public class BitmapFormat
    {
        public struct BITMAPFILEHEADER
        {
            public ushort bfType;
            public int bfSize;
            public ushort bfReserved1;
            public ushort bfReserved2;
            public int bfOffBits;
        }

        public struct MASK
        {
            public byte redmask;
            public byte greenmask;
            public byte bluemask;
            public byte rgbReserved;
        }

        public struct BITMAPINFOHEADER
        {
            public int biSize;
            public int biWidth;
            public int biHeight;
            public ushort biPlanes;
            public ushort biBitCount;
            public int biCompression;
            public int biSizeImage;
            public int biXPelsPerMeter;
            public int biYPelsPerMeter;
            public int biClrUsed;
            public int biClrImportant;
        }

        /*******************************************
        * 函数名称:RotatePic       
        * 函数功能:旋转图片,目的是保存和显示的图片与按的指纹方向不同     
        * 函数入参:BmpBuf---旋转前的指纹字符串
        * 函数出参:ResBuf---旋转后的指纹字符串
        * 函数返回:无
        *********************************************/
        public static void RotatePic(byte[] BmpBuf, int width, int height, ref byte[] ResBuf)
        {
            int RowLoop = 0;
            int ColLoop = 0;
            int BmpBuflen = width * height;

            try
            {
                for (RowLoop = 0; RowLoop < BmpBuflen; )
                {
                    for (ColLoop = 0; ColLoop < width; ColLoop++)
                    {
                        ResBuf[RowLoop + ColLoop] = BmpBuf[BmpBuflen - RowLoop - width + ColLoop];
                    }

                    RowLoop = RowLoop + width;
                }
            }
            catch (Exception ex)
            {
                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
                //logger.Append();
            }
        }

        /*******************************************
        * 函数名称:StructToBytes       
        * 函数功能:将结构体转化成无符号字符串数组     
        * 函数入参:StructObj---被转化的结构体
        *           Size---被转化的结构体的大小
        * 函数出参:无
        * 函数返回:结构体转化后的数组
        *********************************************/
        public static byte[] StructToBytes(object StructObj, int Size)
        {
            int StructSize = Marshal.SizeOf(StructObj);
            byte[] GetBytes = new byte[StructSize];

            try
            {
                IntPtr StructPtr = Marshal.AllocHGlobal(StructSize);
                Marshal.StructureToPtr(StructObj, StructPtr, false);
                Marshal.Copy(StructPtr, GetBytes, 0, StructSize);
                Marshal.FreeHGlobal(StructPtr);

                if (Size == 14)
                {
                    byte[] NewBytes = new byte[Size];
                    int Count = 0;
                    int Loop = 0;

                    for (Loop = 0; Loop < StructSize; Loop++)
                    {
                        if (Loop != 2 && Loop != 3)
                        {
                            NewBytes[Count] = GetBytes[Loop];
                            Count++;
                        }
                    }

                    return NewBytes;
                }
                else
                {
                    return GetBytes;
                }
            }
            catch (Exception ex)
            {
                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
                //logger.Append();

                return GetBytes;
            }
        }

        /*******************************************
        * 函数名称:GetBitmap       
        * 函数功能:将传进来的数据保存为图片     
        * 函数入参:buffer---图片数据
        *           nWidth---图片的宽度
        *           nHeight---图片的高度
        * 函数出参:无
        * 函数返回:无
        *********************************************/
        public static void GetBitmap(byte[] buffer, int nWidth, int nHeight, ref MemoryStream ms)
        {
            int ColorIndex = 0;
            ushort m_nBitCount = 8;
            int m_nColorTableEntries = 256;
            byte[] ResBuf = new byte[nWidth * nHeight*2];

            try
            {
                BITMAPFILEHEADER BmpHeader = new BITMAPFILEHEADER();
                BITMAPINFOHEADER BmpInfoHeader = new BITMAPINFOHEADER();
                MASK[] ColorMask = new MASK[m_nColorTableEntries];

                int w = (((nWidth + 3) / 4) * 4);

                //图片头信息
                BmpInfoHeader.biSize = Marshal.SizeOf(BmpInfoHeader);
                BmpInfoHeader.biWidth = nWidth;
                BmpInfoHeader.biHeight = nHeight;
                BmpInfoHeader.biPlanes = 1;
                BmpInfoHeader.biBitCount = m_nBitCount;
                BmpInfoHeader.biCompression = 0;
                BmpInfoHeader.biSizeImage = 0;
                BmpInfoHeader.biXPelsPerMeter = 0;
                BmpInfoHeader.biYPelsPerMeter = 0;
                BmpInfoHeader.biClrUsed = m_nColorTableEntries;
                BmpInfoHeader.biClrImportant = m_nColorTableEntries;

                //文件头信息
                BmpHeader.bfType = 0x4D42;
                BmpHeader.bfOffBits = 14 + Marshal.SizeOf(BmpInfoHeader) + BmpInfoHeader.biClrUsed * 4;
                BmpHeader.bfSize = BmpHeader.bfOffBits + ((((w * BmpInfoHeader.biBitCount + 31) / 32) * 4) * BmpInfoHeader.biHeight);
                BmpHeader.bfReserved1 = 0;
                BmpHeader.bfReserved2 = 0;

                ms.Write(StructToBytes(BmpHeader, 14), 0, 14);
                ms.Write(StructToBytes(BmpInfoHeader, Marshal.SizeOf(BmpInfoHeader)), 0, Marshal.SizeOf(BmpInfoHeader));

                //调试板信息
                for (ColorIndex = 0; ColorIndex < m_nColorTableEntries; ColorIndex++)
                {
                   
                    ColorMask[ColorIndex].redmask = (byte)ColorIndex;;
                    ColorMask[ColorIndex].greenmask = (byte)ColorIndex;
                    ColorMask[ColorIndex].bluemask = (byte)ColorIndex;
                    //ColorMask[ColorIndex].greenmask = (byte)ColorIndex;
                    //ColorMask[ColorIndex].bluemask = (byte)ColorIndex;
                    ColorMask[ColorIndex].rgbReserved = 0;

                    ms.Write(StructToBytes(ColorMask[ColorIndex], Marshal.SizeOf(ColorMask[ColorIndex])), 0, Marshal.SizeOf(ColorMask[ColorIndex]));
                }

                //图片旋转,解决指纹图片倒立的问题
                RotatePic(buffer, nWidth, nHeight, ref ResBuf);

                byte[] filter = null;
                if (w - nWidth > 0)
                {
                    filter = new byte[w - nWidth];
                }
                for (int i = 0; i < nHeight; i++)
                {
                    ms.Write(ResBuf, i * nWidth, nWidth);
                    if (w - nWidth > 0)
                    {
                        ms.Write(ResBuf, 0, w - nWidth);
                    }
                }
            }
            catch (Exception ex)
            {
               // ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
               // logger.Append();
            }
        }

        /*******************************************
        * 函数名称:WriteBitmap       
        * 函数功能:将传进来的数据保存为图片     
        * 函数入参:buffer---图片数据
        *           nWidth---图片的宽度
        *           nHeight---图片的高度
        * 函数出参:无
        * 函数返回:无
        *********************************************/
        public static void WriteBitmap(byte[] buffer, int nWidth, int nHeight)
        {
            int ColorIndex = 0;
            ushort m_nBitCount = 8;
            int m_nColorTableEntries = 256;
            byte[] ResBuf = new byte[nWidth * nHeight];

            try
            {

                BITMAPFILEHEADER BmpHeader = new BITMAPFILEHEADER();
                BITMAPINFOHEADER BmpInfoHeader = new BITMAPINFOHEADER();
                MASK[] ColorMask = new MASK[m_nColorTableEntries];
                int w = (((nWidth + 3) / 4) * 4);
                //图片头信息
                BmpInfoHeader.biSize = Marshal.SizeOf(BmpInfoHeader);
                BmpInfoHeader.biWidth = nWidth;
                BmpInfoHeader.biHeight = nHeight;
                BmpInfoHeader.biPlanes = 1;
                BmpInfoHeader.biBitCount = m_nBitCount;
                BmpInfoHeader.biCompression = 0;
                BmpInfoHeader.biSizeImage = 0;
                BmpInfoHeader.biXPelsPerMeter = 0;
                BmpInfoHeader.biYPelsPerMeter = 0;
                BmpInfoHeader.biClrUsed = m_nColorTableEntries;
                BmpInfoHeader.biClrImportant = m_nColorTableEntries;

                //文件头信息
                BmpHeader.bfType = 0x4D42;
                BmpHeader.bfOffBits = 14 + Marshal.SizeOf(BmpInfoHeader) + BmpInfoHeader.biClrUsed * 4;
                BmpHeader.bfSize = BmpHeader.bfOffBits + ((((w * BmpInfoHeader.biBitCount + 31) / 32) * 4) * BmpInfoHeader.biHeight);
                BmpHeader.bfReserved1 = 0;
                BmpHeader.bfReserved2 = 0;

                Stream FileStream = File.Open("finger.bmp", FileMode.Create, FileAccess.Write);
                BinaryWriter TmpBinaryWriter = new BinaryWriter(FileStream);

                TmpBinaryWriter.Write(StructToBytes(BmpHeader, 14));
                TmpBinaryWriter.Write(StructToBytes(BmpInfoHeader, Marshal.SizeOf(BmpInfoHeader)));

                //调试板信息
                for (ColorIndex = 0; ColorIndex < m_nColorTableEntries; ColorIndex++)
                {
                    ColorMask[ColorIndex].redmask = (byte)ColorIndex;
                    ColorMask[ColorIndex].greenmask = (byte)ColorIndex;
                    ColorMask[ColorIndex].bluemask = (byte)ColorIndex;
                    ColorMask[ColorIndex].rgbReserved = 0;

                    TmpBinaryWriter.Write(StructToBytes(ColorMask[ColorIndex], Marshal.SizeOf(ColorMask[ColorIndex])));
                }

                //图片旋转,解决指纹图片倒立的问题
                RotatePic(buffer, nWidth, nHeight, ref ResBuf);

                //写图片
                //TmpBinaryWriter.Write(ResBuf);
                byte[] filter = null;
                if (w - nWidth > 0)
                {
                    filter = new byte[w - nWidth];
                }
                for (int i = 0; i < nHeight; i++)
                {
                    TmpBinaryWriter.Write(ResBuf, i * nWidth, nWidth);
                    if (w - nWidth > 0)
                    {
                        TmpBinaryWriter.Write(ResBuf, 0, w - nWidth);
                    }
                }

                FileStream.Close();
                TmpBinaryWriter.Close();
            }
            catch (Exception ex)
            {
                //ZKCE.SysException.ZKCELogger logger = new ZKCE.SysException.ZKCELogger(ex);
                //logger.Append();
            }
        }
    }
}

客户端,浏览器端代码:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>fp</title>
  <meta name="description" content="fp">

  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">

  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">

  <link rel="stylesheet" href="css/signature-pad.css">
  <script src="/jquery.min.js" type="text/javascript"></script>
</head>
<body onselectstart="return false">


    <div id="signature-pad" class="signature-pad">
        <div>

        </div>
        <div class="signature-pad--body">
            <table width="100%" border="0" cellspacing="0">
                <tr align="center">
                    <td width="100%"><img src="https://img-blog.csdnimg.cn/2022010611375296516.png" alt="" width="256" height="288" id="imgDiv" align="middle" /></td>
                </tr>
            </table>
        </div>
      
    </div>
    <script type="text/javascript">
        var ws;
        $(document).ready(function () {

            // test if the browser supports web sockets
            if ("WebSocket" in window) {
                connect("ws://127.0.0.1:8891/");
            } else {
                $('#es').val('浏览器不支持此指纹仪!');
            };

            // function to send data on the web socket
            function ws_send(str) {
                try {
                    ws.send(str);
                } catch (err) {
                    $('#es').val('error');
                }
            }

            // connect to the specified host
            function connect(host) {

                $('#es').val('Connecting to " + host + " ...');
                try {
                    ws = new WebSocket(host); // create the web socket
                } catch (err) {
                    $('#es').val('error');
                }

                ws.onopen = function () {
                   // $('#es').val('设备连接成功!');
                };

                ws.onmessage = function (evt) {

                    var obj = evt.data;
                 
                    var img = document.getElementById("imgDiv");
                    img.src = "data:image/png;base64," + obj;

                };

                ws.onclose = function () {
                   // document.getElementById("es").value = "Closed!";
                };
            };

        });

    </script>

</body>
</html>

以上就是全部代码,服务端运行后会自动注册服务到系统,下次开机可自启动,如果不想可在程序里关闭。(指纹识别采集的数据转图片后是黑色的,实际需要红色的,在这里通过判断图片像素点的色纸批量修改黑色到红色)。


我是一个为了做产品啥都学的程序员,希望这些文字能给你些许的帮助。

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值