| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- 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;
- /// <summary>
- /// twainDSM 是否已安装
- /// </summary>
- private static bool twainDSMInstalled = true;
- /// <summary>
- /// 图片序号
- /// </summary>
- private static int imgIndex = 0;
- private static int preStatus = 0;
- /// <summary>
- /// 扫描仪状态
- /// </summary>
- private static ScannerState scannerState = ScannerState.Stop;
- /// <summary>
- /// 扫描仪当前状态
- /// </summary>
- public enum ScannerState { Stop, Running }
- /// <summary>
- /// 扫描任务
- /// </summary>
- private static ScanTask task;
- public static ScannerState State { get { return scannerState; } }
- /// <summary>
- /// 根据图片后缀获取图片格式
- /// </summary>
- /// <param name="suffix"></param>
- /// <returns></returns>
- 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 初始化扫描仪
- /// <summary>
- /// 初始化扫描仪
- /// </summary>
- 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
- /// <summary>
- /// 开始扫描
- /// </summary>
- /// <param name="scanTask"></param>
- 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;
- }
- }
- }
- /// <summary>
- /// 获取扫描仪资源
- /// </summary>
- /// <returns></returns>
- public static ScannerList GetScannerList()
- {
- ScannerList result = new ScannerList();
- if (twainDSMInstalled)
- {
- List<string> scannerSources = new List<string>();
- 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);
- }
- }
- }
- }
|