Newer
Older
ICS / ICS / FingerPrintForm.cs
tanyue on 19 Mar 2023 11 KB 20230319 采集成功逻辑
using AForge.Video.DirectShow;
using libzkfpcsharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Sample;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using log4net.Repository.Hierarchy;

namespace ICS
{
    public partial class FingerPrintForm : Form
    {
        // 指纹采集设备
        IntPtr fingerPrintDevHandle = IntPtr.Zero;
        // 本窗口的句柄 用于显示指纹图像
        IntPtr formHandle = IntPtr.Zero;
        // 指纹数据库的句柄 用于判断执行指纹模板数据的相关API
        IntPtr dbHandle = IntPtr.Zero;

        // 采集线程工作标志位
        bool captureWorking = false;
        bool threadExit = false;

        // 小窗口显示指纹图像
        byte[] fpImgBuffer;
        // 已经采集的次数
        int RegisterCount = 0;
        // 需要采集测次数
        const int REGISTER_ROUND = 3;
        // 当前DB中保存的指纹ID
        int fingerId = 1;

        // 每次采集的指纹模板数据
        byte[][] regTmps;

        // 合并后的指纹模板数据
        byte[] regTmp;
        // 单次采集的指纹模板数据
        byte[] capTmp;

        // 单次采集的指纹模板数据长度 最长为2048个字节
        int cbCapTmp = 0;
        // 合并后的指纹模板数据长度
        int cbRegTmp = 0;

        // 指纹图像宽度和高度
        private int fpWidth = 0;
        private int fpHeight = 0;

        // 采集线程
        Thread captureThread = null;

        const int MESSAGE_CAPTURED_OK = 0x0400 + 6;

        public static log4net.ILog log = log4net.LogManager.GetLogger("ICS");

        public bool CaptureWorking { get => captureWorking; set => captureWorking = value; }
        public bool ThreadExit { get => threadExit; set => threadExit = value; }
        public int FingerId { get => fingerId; set => fingerId = value; }

        [DllImport("user32.dll", EntryPoint = "SendMessageA")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

        public FingerPrintForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 打开指纹采集设备
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public int OpenFingerDevice(int index)
        {
            fingerPrintDevHandle = zkfp2.OpenDevice(index);

            if (fingerPrintDevHandle == IntPtr.Zero)
            {
                // 指纹设备打开失败
                return -1;
            } else
            {
                dbHandle = zkfp2.DBInit();
                if (dbHandle == IntPtr.Zero)
                {
                    // 数据库初始化失败
                    return -2;
                } else
                {
                    fingerId = 1;
                    return 0;
                }
            }
        }

        /// <summary>
        /// 关闭指纹采集设备
        /// </summary>
        /// <param name="index"></param>

        public void CloseFingerDevice(int index)
        {
            // 关闭设备
            if (IntPtr.Zero!= fingerPrintDevHandle)
            {
                zkfp2.DBFree(dbHandle);
                dbHandle = IntPtr.Zero;

                zkfp2.CloseDevice(fingerPrintDevHandle);
                fingerPrintDevHandle= IntPtr.Zero;
            }
        }

        /// <summary>
        /// 开始采集指纹
        /// </summary>
        /// <param name="round"></param>
        public void StartCaptureFingerPrint()
        {
            if (IntPtr.Zero == fingerPrintDevHandle)
            {
                this.labelTips.Text = "设备还未初始化";
                JObject obj = new JObject
                {
                    { "command", "CaptureFingerPrint" },
                    { "success", "false" },
                    { "message", "device not initialized" }
                };
                Form1.SendMsgToClient("CapFingerPrint", JsonConvert.SerializeObject(obj));
                return;
            }

            this.labelTips.Text = "请用同一个手指按压3次";
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FingerPrintForm));
            this.picFingerPrint.Image = ((System.Drawing.Image)(resources.GetObject("picFingerPrint.Image")));

            // 读取参数中的指纹图像宽度和高度
            byte[] paramValue = new byte[4];
            int size = 4;
            zkfp2.GetParameters(fingerPrintDevHandle, 1, paramValue, ref size);
            zkfp2.ByteArray2Int(paramValue, ref fpWidth);

            zkfp2.GetParameters(fingerPrintDevHandle, 2, paramValue, ref size);
            zkfp2.ByteArray2Int(paramValue, ref fpHeight);

            // 生成指纹图像字节数组
            fpImgBuffer = new byte[fpWidth * fpHeight];
            regTmps = new byte[REGISTER_ROUND][];
            for (int i = 0; i < REGISTER_ROUND; i++)
            {
                regTmps[i] = new byte[2048];
            }
            regTmp = new byte[2048];
            capTmp = new byte[2048];
            this.RegisterCount = 0;

            // 开启采集线程
            captureThread = new Thread(new ThreadStart(DoCapture));
            ThreadExit = false;
            captureThread.IsBackground = true;
            captureThread.Start();

            // 采集工作线程标志位
            CaptureWorking = true;
        }

        public void StopCaptureFingerPrint()
        {
            // 停止工作
            CaptureWorking = false;

            // 停止线程
            ThreadExit = true;

            // this.Hide();
        }

        /// <summary>
        /// 执行采集指纹动作
        /// </summary>
        private void DoCapture()
        {
            while (ThreadExit == false)
            {
                if (CaptureWorking == true)
                {
                    int ret = zkfp2.AcquireFingerprint(fingerPrintDevHandle, fpImgBuffer, capTmp, ref cbCapTmp);
                    if (ret == zkfp.ZKFP_ERR_OK)
                    {
                        SendMessage(formHandle, MESSAGE_CAPTURED_OK, IntPtr.Zero, IntPtr.Zero);
                    }
                    Thread.Sleep(200);
                }
            }
        }

        protected override void DefWndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case MESSAGE_CAPTURED_OK:
                    {
                        MemoryStream ms = new MemoryStream();
                        BitmapFormat.GetBitmap(fpImgBuffer, fpWidth, fpHeight, ref ms);
                        Bitmap bmp = new Bitmap(ms);
                        this.picFingerPrint.Image = bmp;

                        JObject obj = new JObject
                        {
                            { "command", "CaptureFingerPrint" },
                            { "image", "data:image/bmp;base64," + Form1.ToBase64(bmp) }
                        };

                        // 第一次采集
                        if (RegisterCount == 0)
                        {
                            Array.Copy(capTmp, regTmps[RegisterCount], cbCapTmp);

                            // 判断是否在数据库中有重复的指纹
                            // 仅在第一次采集时判断重复 后续会调用DBMatch判断是否与第一次采集的指纹为同一手指
                            int fid = 0;
                            int score = 0;
                            int identifyRet = zkfp2.DBIdentify(dbHandle, capTmp, ref fid, ref score);
                            if (identifyRet == 0 && fid > 0)
                            {
                                // 找到本次采集已经保存的指纹
                                obj.Add("success", "false");
                                obj.Add("message", "fingerPrint found");

                                this.labelTips.Text = "数据库中找到相同的手指" + fid + "\r\n请用不同手指再按压" + (REGISTER_ROUND - RegisterCount) + "次";
                            } 
                            else
                            {
                                // 数据库中没有找到 进行下一次采集
                                RegisterCount++;

                                obj.Add("success", "true");
                                obj.Add("pressLeft", REGISTER_ROUND - RegisterCount);

                                this.labelTips.Text = "请再按压" + (REGISTER_ROUND - RegisterCount) + "次";
                            }
                        } 
                        else
                        {
                            int matchRet = zkfp2.DBMatch(dbHandle, capTmp, regTmps[RegisterCount - 1]);
                            if (matchRet <= 0)
                            {
                                // 本次采集的指纹与上次采集的指纹不是同一个手指 提示
                                obj.Add("success", "false");
                                obj.Add("code", matchRet);
                                obj.Add("pressLeft", REGISTER_ROUND - RegisterCount);

                                this.labelTips.Text = "与上一次的手指不同\r\n请用同一手指再按压" + (REGISTER_ROUND - RegisterCount) + "次";
                            } else
                            {
                                Array.Copy(capTmp, regTmps[RegisterCount], cbCapTmp);
                                RegisterCount++;

                                obj.Add("success", "true");
                                obj.Add("pressLeft", REGISTER_ROUND - RegisterCount);

                                // 一枚指纹的3次采集结束 
                                if (RegisterCount >= REGISTER_ROUND)
                                {
                                    // 合并3次指纹
                                    int mergeRet = zkfp2.DBMerge(dbHandle, regTmps[0], regTmps[1], regTmps[2], regTmp, ref cbRegTmp);
                                    if (mergeRet == zkfperrdef.ZKFP_ERR_OK)
                                    {
                                        // 采集成功后将指纹保存到数据库中
                                        zkfp2.DBAdd(dbHandle, FingerId, regTmp);
                                        StopCaptureFingerPrint();

                                        FingerId++;

                                        obj.Add("tempLen", cbRegTmp);
                                        obj.Add("tempData", zkfp2.BlobToBase64(regTmp, cbRegTmp));

                                        this.labelTips.Text = "指纹采集成功";
                                        log.Info("指纹采集成功");
                                    }
                                    else
                                    {
                                        obj.Remove("success");
                                        obj.Add("success", "false");
                                        obj.Add("code", mergeRet);
                                    }
                                } else
                                {
                                    this.labelTips.Text = "请再按压" + (REGISTER_ROUND - RegisterCount) + "次";
                                }
                            }
                        }
                        
                        Form1.SendMsgToClient("CapFingerPrint", JsonConvert.SerializeObject(obj));
                        break;
                    }

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

        private void FingerPrintForm_Load(object sender, EventArgs e)
        {
            formHandle = this.Handle;
        }
    }
}