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);
}
}
}
}