using DaJiaoYan.Models; using DaJiaoYan.Utils; using DaJiaoYan.Variables; using NTwain; using NTwain.Data; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; using static DaJiaoYan.Models.ScanTask; namespace DaJiaoYan.Services { internal class Scan { public delegate void DeleLoadDriver(bool ok); public static DeleLoadDriver DelegateLoadDriver; public delegate void DeleChangeScannerName(string name); public static DeleChangeScannerName DelegateChangeScannerName; public delegate void DeleChangeScannerStatus(string status, Color color); public static DeleChangeScannerStatus DelegateChangeScannerStatus; public static IntPtr OwnerFormHandle; //private Form form; //private IntPtr Control.Handle; private static TwainSession _twain; /// /// twainDSM 是否已安装 /// private static bool twainDSMInstalled = true; /// /// 图片序号 /// private static int imgIndex = 0; private static int preStatus = 0; /// /// 扫描仪状态 /// private static ScannerState scannerState = ScannerState.Stop; /// /// 扫描仪当前状态 /// public enum ScannerState { Stop, Running } /// /// 扫描任务 /// private static ScanTask task; public static ScannerState State { get { return scannerState; } } /// /// 根据图片后缀获取图片格式 /// /// /// private static ImageFormat GetImageFormat(string suffix) { ImageFormat imageFormat; switch (suffix.ToLower()) { case "bmp": imageFormat = ImageFormat.Bmp; break; case "jpg": imageFormat = ImageFormat.Jpeg; break; case "jpeg": imageFormat = ImageFormat.Jpeg; break; default: imageFormat = ImageFormat.Png; break; } return imageFormat; } #region 初始化扫描仪 /// /// 初始化扫描仪 /// public static void SetupTwain() { var appId = TWIdentity.CreateFromAssembly(DataGroups.Image, Assembly.GetExecutingAssembly()); _twain = new TwainSession(appId); _twain.StateChanged += (s, e) => { if (preStatus >= 4 && _twain.State < 4) { ChangeScannerState(ScannerState.Stop); } preStatus = _twain.State; }; _twain.TransferError += (s, e) => { // 扫描错误 //Services.Agent.ScanTaskError(); task.OnScannerError?.Invoke(); //Log.WriteLine("Got xfer error on thread " + Thread.CurrentThread.ManagedThreadId); }; _twain.DataTransferred += (s, e) => { // 文件扫描完成 //scannerState = ScannerState.Running; ChangeScannerState(ScannerState.Running); //Log.WriteLine("Transferred data event on thread " + Thread.CurrentThread.ManagedThreadId); // example on getting ext image info var infos = e.GetExtImageInfo(ExtendedImageInfo.Camera).Where(it => it.ReturnCode == ReturnCode.Success); foreach (var it in infos) { var values = it.ReadValues(); //Log.WriteLine(string.Format("{0} = {1}", it.InfoID, values.FirstOrDefault())); break; } string name = string.Format("{0}_{1}.{2}", DateTime.Now.ToString("yyyyMMdd_HHmmss_fff"), string.Format("{0:d7}", ++imgIndex), task.ImageSuffix); string fileName = Path.Combine(task.Path, name); if (e.NativeData != IntPtr.Zero) { // 扫描流 using (var stream = e.GetNativeImageStream()) { if (stream != null) { using (Bitmap bmp = new Bitmap(stream)) { bmp?.Save(fileName, GetImageFormat(task.ImageSuffix)); } } } } else if (!string.IsNullOrEmpty(e.FileDataPath)) { using (Bitmap bmp = new Bitmap(e.FileDataPath)) { bmp?.Save(fileName, GetImageFormat(task.ImageSuffix)); } //var bmp = new Bitmap(e.FileDataPath); //; // 已存为文件 //File.Copy(e.FileDataPath, fileName); } //Services.Agent.SendImage(fileName); Task.Run(() => { //await Task.Delay(100); task.OnDeleScanFileCompleted?.Invoke(fileName, imgIndex); }); if (_twain.State == 4) { //scannerState = ScannerState.Stop; ChangeScannerState(ScannerState.Stop); } }; _twain.SourceDisabled += (s, e) => { // 扫描任务完成 ChangeScannerState(ScannerState.Stop); task.OnScanTaskCompleted?.Invoke(); }; _twain.TransferReady += (s, e) => { // 扫描仪可用 //Log.WriteLine("Transferr ready event on thread " + Thread.CurrentThread.ManagedThreadId); }; // either set sync context and don't worry about threads during events, // or don't and use control.invoke during the events yourself _twain.SynchronizationContext = SynchronizationContext.Current; if (_twain.State < 3) { try { // use this for internal msg loop _twain.Open(); } catch { twainDSMInstalled = false; } } } private static void Twain_DeviceEvent(object sender, DeviceEventArgs e) { throw new NotImplementedException(); } #endregion /// /// 开始扫描 /// /// public static void Start(ScanTask scanTask) { void SendResult(bool status, string msg) { scanTask.OnScanBegin?.Invoke(status, msg); ChangeScannerState(status ? ScannerState.Running : ScannerState.Stop); } task = scanTask; if (!twainDSMInstalled) { SendResult(false, Const.ERR_NO_ANY_TWAIN_DRIVER); Log.WriteLine("未加载扫描仪驱动!"); return; } else if (string.IsNullOrEmpty(task.Path)) { SendResult(false, Const.ERR_NO_IMAGE_PATH); return; } else { if (!Directory.Exists(scanTask.Path)) { Directory.CreateDirectory(scanTask.Path); } if (_twain.State < 3) { if (_twain.Open() != ReturnCode.Success) { SendResult(false, Const.ERR_SCANNER_NOT_AVALIABLE); return; } } if (_twain.CurrentSource == null || !_twain.CurrentSource.Name.Equals(task.Scanner)) { if (_twain.OpenSource(task.Scanner) != ReturnCode.Success) { SendResult(false, Const.ERR_SCANNER_NOT_AVALIABLE); return; } } if (_twain.State != 4) { SendResult(false, Const.ERR_SCANNER_NOT_AVALIABLE); return; } else { //单双面(强制双面) //var duplexEnabled = BoolType.True; var ds = _twain.CurrentSource; //if (!ds.IsOpen) //{ // ds.Open(); //} var dsc = ds.Capabilities; DelegateChangeScannerName?.Invoke(scanTask.Scanner); dsc.CapDuplexEnabled.SetValue(BoolType.True); //var pixelType = PixelType.RGB; if (task.Colorful) { //图片类型(强制彩色) dsc.ICapPixelType.SetValue(PixelType.RGB); } else { // 扫描灰度图 dsc.ICapPixelType.SetValue(PixelType.Gray); } //旋转(强制不旋转) //var rotation = 0; dsc.ICapRotation.SetValue(0); //分辨率 dsc.ICapXResolution.SetValue(task.ImageDpi); dsc.ICapYResolution.SetValue(task.ImageDpi); //使用Twain源的进度指示器? (当ShowUI == FALSE才有效) dsc.CapIndicators.SetValue(BoolType.False); // 自动尺寸 dsc.ICapAutoSize.SetValue(AutoSize.Auto); // 自动旋转 dsc.ICapAutomaticRotate.SetValue(BoolType.False); //dsc.CapDuplexEnabled.SetValue(BoolType.True); ////dsc.ICapImageFileFormat.SetValue(FileFormat.Png); //dsc.CapAutoScan.SetValue(BoolType.False); dsc.ICapXferMech.SetValue(XferMech.Native); ////_twain.CurrentSource.Capabilities.CapXferCount.SetValue(1); ////var pixelType = PixelType.RGB; //if (task.Colorful) //{ // //图片类型(强制彩色) // dsc.ICapPixelType.SetValue(PixelType.RGB); //} //else //{ // // 扫描灰度图 // dsc.ICapPixelType.SetValue(PixelType.Gray); //} ////旋转(强制不旋转) ////var rotation = 0; //dsc.ICapRotation.SetValue(0); ////_twain.CurrentSource.Capabilities.If ////分辨率 //dsc.ICapXResolution.SetValue(task.ImageDpi); //dsc.ICapYResolution.SetValue(task.ImageDpi); //dsc.CapIndicators.SetValue(BoolType.False); //// 自动尺寸 //dsc.ICapAutoSize.SetValue(AutoSize.Auto); //// 自动旋转 //dsc.ICapAutomaticRotate.SetValue(BoolType.False); // 连续扫描的张数 if (task.CapXferCount > 0) { dsc.CapXferCount.SetValue(task.CapXferCount); } else { dsc.CapXferCount.SetValue(-1); } //dsc.ICapImageMerge.SetValue(ImageMerge.None); imgIndex = 0; //scannerState = ScannerState.Running; ChangeScannerState(ScannerState.Running); //使用Twain源的进度指示器? (当ShowUI == FALSE才有效) ds.Enable(SourceEnableMode.NoUI, false, OwnerFormHandle); //if (_twain.CurrentSource.Capabilities.CapUIControllable.IsSupported)//.SupportedCaps.Contains(CapabilityId.CapUIControllable)) //{ // // hide scanner ui if possible // _twain.CurrentSource.Enable(SourceEnableMode.ShowUI, false, OwnerFormHandle); // //if (_twain.CurrentSource.Enable(SourceEnableMode.NoUI, true, OwnerFormHandle) == ReturnCode.Success) // //{ // // //btnAppendScan.Enabled = false; // //} //} //else //{ // _twain.CurrentSource.Enable(SourceEnableMode.ShowUI, false, OwnerFormHandle); // //if (_twain.CurrentSource.Enable(SourceEnableMode.ShowUI, false, OwnerFormHandle) == ReturnCode.Success) // //{ // // //btnOverWriteScan.Enabled = false; // //} //} Log.WriteLine(Json.Encode("开始扫描!")); SendResult(true, ""); return; } } } /// /// 获取扫描仪资源 /// /// public static ScannerList GetScannerList() { ScannerList result = new ScannerList(); if (twainDSMInstalled) { List scannerSources = new List(); if (_twain == null) { SetupTwain(); } if (_twain != null) { foreach (var src in _twain) { scannerSources.Add(src.Name); } result.Resources = scannerSources.ToArray(); if (_twain.CurrentSource != null) { result.Selected = _twain.CurrentSource.Name; DelegateChangeScannerName?.Invoke(result.Selected); } else { DelegateChangeScannerName?.Invoke("未选择扫描仪"); } } DelegateLoadDriver?.Invoke(true); } else { DelegateLoadDriver?.Invoke(false); Log.WriteLine("未能正确加载扫描仪驱动。"); } return result; } private static void ChangeScannerState(ScannerState state) { scannerState = state; if (state == ScannerState.Running) { DelegateChangeScannerStatus("扫描中", Color.Green); } else if (state == ScannerState.Stop) { DelegateChangeScannerStatus("未扫描", Color.Red); } } } }