我正在编写一个需要在.net(c#
版本4.0
,Visual Studio 2010中进行扫描的应用程序。我正在使用TWAIN
API进行扫描,我的布局功能有问题。以下代码在Microtek i800
,CanoScan 9000F
和Microtek Artix Scan F2
上完全正常,但是当我针对Epson Perfection V700运行它时,会发生一些非常奇怪的事情。
即使我将布局的左边距设置为0
,图像的左边缘也会被切断。我尝试将其设置为负值,但这没有任何区别。似乎有一些奇怪的东西,它迫使它成为一个电影大小(也许是因为我正在开灯)。如果我使用扫描仪附带的工具,它允许我选择包含两个边缘的区域(并打开灯),因此必须可以。此外,顶部和底部坐标工作得非常好。
所以我的问题是......
有谁知道我可以扫描整个宽度的任何方式?在TWAIN中是否有其他设置我可以先设置让它忘记纸张尺寸? (我尝试将PaperDetectable设置为false,但没有区别。)
另一件事:如果我没有设置布局,它仍会切断边缘的图片(只是不是顶部和底部),但是如果我也没有设置指示灯(或者我没有设置灯亮,但我设置了尺寸)它做了我所期望的:专门从最左边扫描整个画面(但问题是,我真的需要光线和整个扫描宽度 - 当然不是'太多了,不能问......)。
这是代码(它是1表格窗体应用程序的代码,后面有一个按钮):
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Windows.Forms;
namespace TwainLayoutWindowsFormsApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
TwainIdentity appid = null;
TwainIdentity scanner = null;
bool enabled = false;
try
{
appid = InitializeTwain(Handle);
scanner = GetSource(appid, "EPSON Perfection V700/V750");
Open(appid, scanner);
SetLightOn(appid, scanner);
SetLayout(appid, scanner);
Enable(appid, scanner, Handle);
enabled = true;
var bmps = Scan(appid, scanner);
Disable(appid, scanner);
enabled = false;
bmps.First().Save(@"c:\users\public\scan.bmp", ImageFormat.Bmp);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
if (appid != null && scanner != null)
{
if (enabled)
{
try
{
Disable(appid, scanner);
}
catch(InvalidOperationException)
{
}
}
Close(appid, scanner);
}
}
}
private static void SetLayout(TwainIdentity appid,
TwainIdentity scanner)
{
TwainImageLayout layout = new TwainImageLayout();
var rc = NativeMethods.DSilayout(appid,
scanner,
TwainDataGroups.Image,
TwainDataArgumentType.ImageLayout,
TwainMessage.Get,
layout);
// 1 inch from the top and 0 from the left
layout.Frame.Top = new TwainFix32();
layout.Frame.Top.Whole = 1;
layout.Frame.Left = new TwainFix32();
layout.Frame.Left.Whole = 0;
layout.Frame.Right = new TwainFix32();
layout.Frame.Right.Whole = 6;
layout.Frame.Bottom = new TwainFix32();
layout.Frame.Bottom.Whole = 3;
layout.FrameNumber = 1;
layout.PageNumber = 1;
layout.DocumentNumber = 1;
rc = NativeMethods.DSilayout(appid,
scanner,
TwainDataGroups.Image,
TwainDataArgumentType.ImageLayout,
TwainMessage.Set,
layout);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Failed to set layout");
var s = new TwainStatus();
rc = NativeMethods.DSstatus(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.Status,
TwainMessage.Get, s);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Failed to get layout");
}
private IEnumerable<Bitmap> Scan(TwainIdentity appid,
TwainIdentity scanner)
{
var pictures = new List<Bitmap>();
TwainReturnCode rc;
IntPtr hbitmap;
var pxfr = new TwainPendingXfers();
do
{
pxfr.Count = 10;
hbitmap = IntPtr.Zero;
var iinf = new TwainImageInfo();
rc = NativeMethods.DSiinf(appid,
scanner,
TwainDataGroups.Image,
TwainDataArgumentType.ImageInfo,
TwainMessage.Get,
iinf);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Could not INF");
rc = NativeMethods.DSixfer(appid,
scanner,
TwainDataGroups.Image,
TwainDataArgumentType.ImageNativeXfer,
TwainMessage.Get,
ref hbitmap);
if (rc != TwainReturnCode.XferDone)
throw new InvalidOperationException("Could DSI XFER");
rc = NativeMethods.DSpxfer(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.PendingXfers,
TwainMessage.EndXfer,
pxfr);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Could DSP XFER");
var bmp = TwainBitmapConvertor.ToBitmap(hbitmap);
pictures.Add(bmp);
}
while (pxfr.Count != 0);
NativeMethods.DSpxfer(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.PendingXfers,
TwainMessage.StopFeeder,
pxfr);
return pictures;
}
private static void Enable(TwainIdentity appid,
TwainIdentity scanner,
IntPtr hwnd)
{
var guif = new TwainUserInterface();
guif.ShowUI = 0;
guif.ModalUI = 1;
guif.ParentHand = hwnd;
var rc = NativeMethods.DSuserif(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.UserInterface,
TwainMessage.EnableDS,
guif);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Could not enable");
}
private static void Disable(TwainIdentity appid, TwainIdentity scanner)
{
var guif = new TwainUserInterface();
var rc = NativeMethods.DSuserif(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.UserInterface,
TwainMessage.DisableDS,
guif);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Could not disable");
}
private static void SetLightOn(TwainIdentity appid, TwainIdentity scanner)
{
using (var capability = new TwainCapability(TwainCapabilityType.Lightpath, 1))
{
var rc = NativeMethods.DScap(appid,
scanner,
TwainDataGroups.Control,
TwainDataArgumentType.Capability,
TwainMessage.Set,
capability);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Failed to set light");
}
}
private static void Close(TwainIdentity appid, TwainIdentity scanner)
{
NativeMethods.DSMident(appid,
IntPtr.Zero,
TwainDataGroups.Control,
TwainDataArgumentType.Identity,
TwainMessage.CloseDS,
scanner);
}
private static void Open(TwainIdentity appid, TwainIdentity scanner)
{
var rc = NativeMethods.DSMident(appid,
IntPtr.Zero,
TwainDataGroups.Control,
TwainDataArgumentType.Identity,
TwainMessage.OpenDS,
scanner);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Failed to open");
}
private static TwainIdentity InitializeTwain(IntPtr hwndp)
{
var appid = new TwainIdentity();
appid.Version.MajorNum = 1;
appid.Version.MinorNum = 0;
appid.Version.Language = 13;
appid.Version.Country = 1;
appid.Version.Info = "Test";
appid.Id = IntPtr.Zero;
appid.ProtocolMajor = 1;
appid.ProtocolMinor = 9;
appid.SupportedGroups = (int)(TwainDataGroups.Image | TwainDataGroups.Control);
appid.Manufacturer = "Test Manufacturer";
appid.ProductFamily = "Test Family";
appid.ProductName = "Test Product";
var rc = NativeMethods.DSMparent(appid,
IntPtr.Zero,
TwainDataGroups.Control,
TwainDataArgumentType.Parent,
TwainMessage.OpenDSM,
ref hwndp);
if (rc != TwainReturnCode.Success)
throw new InvalidOperationException("Could Not DSMParent");
return appid;
}
private static TwainIdentity GetSource(TwainIdentity appid, string name)
{
var device = new TwainIdentity { Id = IntPtr.Zero };
var rc = NativeMethods.DSMentry(appid,
IntPtr.Zero,
TwainDataGroups.Control,
TwainDataArgumentType.Identity,
TwainMessage.GetFirst,
device);
if (rc != TwainReturnCode.EndOfList &&
device.ProductName.Equals(name,
StringComparison.OrdinalIgnoreCase))
{
return device;
}
while (rc != TwainReturnCode.EndOfList)
{
device = new TwainIdentity { Id = IntPtr.Zero };
rc = NativeMethods.DSMentry(appid,
IntPtr.Zero,
TwainDataGroups.Control,
TwainDataArgumentType.Identity,
TwainMessage.GetNext,
device);
if (rc != TwainReturnCode.EndOfList &&
device.ProductName.Equals(name,
StringComparison.OrdinalIgnoreCase))
{
return device;
}
}
throw new InvalidOperationException("Could not find device");
}
}
}
为了完整性,这里是我用来将HBITMAP转换为System.Drawing.Bitmap的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Globalization;
namespace TwainLayoutWindowsFormsApplication
{
internal static class TwainBitmapConvertor
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
private class BitmapInfoHeader
{
public int Size;
public int Width;
public int Height;
public short Planes;
public short BitCount;
public int Compression;
public int SizeImage;
public int XPelsPerMeter;
public int YPelsPerMeter;
public int ClrUsed;
public int ClrImportant;
}
internal static Bitmap ToBitmap(IntPtr dibHandle)
{
var bitmapPointer = NativeMethods.GlobalLock(dibHandle);
var bitmapInfo = new BitmapInfoHeader();
Marshal.PtrToStructure(bitmapPointer, bitmapInfo);
var rectangle = new Rectangle();
rectangle.X = rectangle.Y = 0;
rectangle.Width = bitmapInfo.Width;
rectangle.Height = bitmapInfo.Height;
if (bitmapInfo.SizeImage == 0)
{
bitmapInfo.SizeImage =
((((bitmapInfo.Width * bitmapInfo.BitCount) + 31) & ~31) >> 3)
* bitmapInfo.Height;
}
// The following code only works on x86
if (Marshal.SizeOf(typeof(IntPtr)) != 4)
throw new NotSupportedException("Only x86 is supported");
int pixelInfoPointer = bitmapInfo.ClrUsed;
if ((pixelInfoPointer == 0) && (bitmapInfo.BitCount <= 8))
{
pixelInfoPointer = 1 << bitmapInfo.BitCount;
}
pixelInfoPointer = (pixelInfoPointer * 4) + bitmapInfo.Size
+ bitmapPointer.ToInt32();
IntPtr pixelInfoIntPointer = new IntPtr(pixelInfoPointer);
var bitmap = new Bitmap(rectangle.Width, rectangle.Height);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
IntPtr hdc = graphics.GetHdc();
try
{
NativeMethods.SetDIBitsToDevice(hdc,
0, 0, rectangle.Width, rectangle.Height, 0, 0, 0,
rectangle.Height, pixelInfoIntPointer, bitmapPointer, 0);
}
finally
{
graphics.ReleaseHdc(hdc);
}
}
bitmap.SetResolution(PpmToDpi(bitmapInfo.XPelsPerMeter),
PpmToDpi(bitmapInfo.YPelsPerMeter));
NativeMethods.GlobalUnlock(dibHandle);
NativeMethods.GlobalFree(dibHandle);
return bitmap;
}
private static float PpmToDpi(double pixelsPerMeter)
{
double pixelsPerMillimeter = (double)pixelsPerMeter / 1000.0;
double dotsPerInch = pixelsPerMillimeter * 25.4;
return (float)Math.Round(dotsPerInch, 2);
}
}
}
以下是p / invokes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace TwainLayoutWindowsFormsApplication
{
internal static class NativeMethods
{
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalAlloc(int flags, int size);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalLock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern bool GlobalUnlock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GlobalFree(IntPtr handle);
[DllImport("gdi32.dll", ExactSpelling = true)]
public static extern int SetDIBitsToDevice(IntPtr hdc, int xdst, int ydst, int width, int height,
int xsrc, int ysrc, int start, int lines, IntPtr bitsptr, IntPtr bmiptr, int color);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMparent([In, Out] TwainIdentity origin, IntPtr zeroptr, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, ref IntPtr refptr);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMident([In, Out] TwainIdentity origin, IntPtr zeroptr, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainIdentity idds);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMentry([In, Out] TwainIdentity origin, IntPtr zeroptr, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainIdentity idds);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMstatus([In, Out] TwainIdentity origin, IntPtr zeroptr, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainStatus dsmstat);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSuserif([In, Out] TwainIdentity origin, [In, Out] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, TwainUserInterface guif);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSevent([In, Out] TwainIdentity origin, [In, Out] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, ref TwainEvent evt);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSstatus([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainStatus dsmstat);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DScap([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainCapability capa);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSiinf([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainImageInfo imginf);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSixfer([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, ref IntPtr hbitmap);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMemixfer([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainImageMemXfer memxfr);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSpxfer([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainPendingXfers pxfr);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSilayout([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainImageLayout layout);
[DllImport("twain_32.dll", EntryPoint = "#1")]
internal static extern TwainReturnCode DSMEntry([In, Out] TwainIdentity origin, [In] TwainIdentity dest, TwainDataGroups dg, TwainDataArgumentType dat, TwainMessage msg, [In, Out] TwainSetupFileXfer fileXf);
}
}
最后,需要工作的其他东西(结构和诸如此类的东西):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace TwainLayoutWindowsFormsApplication
{
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)]
internal class TwainIdentity
{
public IntPtr Id;
public TwainVersion Version;
public short ProtocolMajor;
public short ProtocolMinor;
public int SupportedGroups;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]
public string Manufacturer;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]
public string ProductFamily;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]
public string ProductName;
}
internal enum TwainReturnCode : short
{
Success = 0x0000,
Failure = 0x0001,
CheckStatus = 0x0002,
Cancel = 0x0003,
DSEvent = 0x0004,
NotDSEvent = 0x0005,
XferDone = 0x0006,
EndOfList = 0x0007,
InfoNotSupported = 0x0008,
DataNotAvailable = 0x0009
}
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Ansi)]
internal struct TwainVersion
{
public short MajorNum;
public short MinorNum;
public short Language;
public short Country;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 34)]
public string Info;
}
[Flags]
internal enum TwainDataGroups : short
{
Control = 0x0001,
Image = 0x0002,
Audio = 0x0004
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct TwainEvent
{
public IntPtr EventPtr;
public short Message;
}
internal enum TwainDataArgumentType : short
{
Null = 0x0000,
Capability = 0x0001,
Event = 0x0002,
Identity = 0x0003,
Parent = 0x0004,
PendingXfers = 0x0005,
SetupMemXfer = 0x0006,
SetupFileXfer = 0x0007,
Status = 0x0008,
UserInterface = 0x0009,
XferGroup = 0x000a,
TwunkIdentity = 0x000b,
CustomDSData = 0x000c,
DeviceEvent = 0x000d,
FileSystem = 0x000e,
PassThru = 0x000f,
ImageInfo = 0x0101,
ImageLayout = 0x0102,
ImageMemXfer = 0x0103,
ImageNativeXfer = 0x0104,
ImageFileXfer = 0x0105,
CieColor = 0x0106,
GrayResponse = 0x0107,
RGBResponse = 0x0108,
JpegCompression = 0x0109,
Palette8 = 0x010a,
ExtImageInfo = 0x010b,
SetupFileXfer2 = 0x0301
}
internal enum TwainMessage : short
{
Null = 0x0000,
Get = 0x0001,
GetCurrent = 0x0002,
GetDefault = 0x0003,
GetFirst = 0x0004,
GetNext = 0x0005,
Set = 0x0006,
Reset = 0x0007,
QuerySupport = 0x0008,
XFerReady = 0x0101,
CloseDSReq = 0x0102,
CloseDSOK = 0x0103,
DeviceEvent = 0x0104,
CheckStatus = 0x0201,
OpenDSM = 0x0301,
CloseDSM = 0x0302,
OpenDS = 0x0401,
CloseDS = 0x0402,
UserSelect = 0x0403,
DisableDS = 0x0501,
EnableDS = 0x0502,
EnableDSUIOnly = 0x0503,
ProcessEvent = 0x0601,
EndXfer = 0x0701,
StopFeeder = 0x0702,
ChangeDirectory = 0x0801,
CreateDirectory = 0x0802,
Delete = 0x0803,
FormatMedia = 0x0804,
GetClose = 0x0805,
GetFirstFile = 0x0806,
GetInfo = 0x0807,
GetNextFile = 0x0808,
Rename = 0x0809,
Copy = 0x080A,
AutoCaptureDir = 0x080B,
PassThru = 0x0901
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct TwainWindowMessage
{
public IntPtr hwnd;
public int message;
public IntPtr wParam;
public IntPtr lParam;
public int time;
public int x;
public int y;
}
internal enum TwainOn : short
{
Array = 0x0003,
Enum = 0x0004,
One = 0x0005,
Range = 0x0006,
DontCare = -1
}
internal enum TwainCapabilityType : short
{
XferCount = 0x0001,
ICompression = 0x0100,
IPixelType = 0x0101,
IUnits = 0x0102,
IXferMech = 0x0103,
Author = 0x1000,
Caption = 0x1001,
FeederEnabled = 0x1002,
FeederLoaded = 0x1003,
Timedate = 0x1004,
SupportedCapabilities = 0x1005,
Extendedcaps = 0x1006,
AutoFeed = 0x1007,
ClearPage = 0x1008,
FeedPage = 0x1009,
RewindPage = 0x100a,
Indicators = 0x100b,
SupportedCapsExt = 0x100c,
PaperDetectable = 0x100d,
UIControllable = 0x100e,
DeviceOnline = 0x100f,
AutoScan = 0x1010,
ThumbnailsEnabled = 0x1011,
Duplex = 0x1012,
DuplexEnabled = 0x1013,
Enabledsuionly = 0x1014,
CustomdsData = 0x1015,
Endorser = 0x1016,
JobControl = 0x1017,
Alarms = 0x1018,
AlarmVolume = 0x1019,
AutomaticCapture = 0x101a,
TimeBeforeFirstCapture = 0x101b,
TimeBetweenCaptures = 0x101c,
ClearBuffers = 0x101d,
MaxBatchBuffers = 0x101e,
DeviceTimeDate = 0x101f,
PowerSupply = 0x1020,
CameraPreviewUI = 0x1021,
DeviceEvent = 0x1022,
SerialNumber = 0x1024,
Printer = 0x1026,
PrinterEnabled = 0x1027,
PrinterIndex = 0x1028,
PrinterMode = 0x1029,
PrinterString = 0x102a,
PrinterSuffix = 0x102b,
Language = 0x102c,
FeederAlignment = 0x102d,
FeederOrder = 0x102e,
ReAcquireAllowed = 0x1030,
BatteryMinutes = 0x1032,
BatteryPercentage = 0x1033,
CameraSide = 0x1034,
Segmented = 0x1035,
CameraEnabled = 0x1036,
CameraOrder = 0x1037,
MicrEnabled = 0x1038,
FeederPrep = 0x1039,
Feederpocket = 0x103a,
Autobright = 0x1100,
Brightness = 0x1101,
Contrast = 0x1103,
CustHalftone = 0x1104,
ExposureTime = 0x1105,
Filter = 0x1106,
Flashused = 0x1107,
Gamma = 0x1108,
Halftones = 0x1109,
Highlight = 0x110a,
ImageFileFormat = 0x110c,
LampState = 0x110d,
LightSource = 0x110e,
Orientation = 0x1110,
PhysicalWidth = 0x1111,
PhysicalHeight = 0x1112,
Shadow = 0x1113,
Frames = 0x1114,
XNativeResolution = 0x1116,
YNativeResolution = 0x1117,
XResolution = 0x1118,
YResolution = 0x1119,
MaxFrames = 0x111a,
Tiles = 0x111b,
Bitorder = 0x111c,
Ccittkfactor = 0x111d,
Lightpath = 0x111e,
Pixelflavor = 0x111f,
Planarchunky = 0x1120,
Rotation = 0x1121,
Supportedsizes = 0x1122,
Threshold = 0x1123,
Xscaling = 0x1124,
Yscaling = 0x1125,
Bitordercodes = 0x1126,
Pixelflavorcodes = 0x1127,
Jpegpixeltype = 0x1128,
Timefill = 0x112a,
BitDepth = 0x112b,
Bitdepthreduction = 0x112c,
Undefinedimagesize = 0x112d,
Imagedataset = 0x112e,
Extimageinfo = 0x112f,
Minimumheight = 0x1130,
Minimumwidth = 0x1131,
Fliprotation = 0x1136,
Barcodedetectionenabled = 0x1137,
Supportedbarcodetypes = 0x1138,
Barcodemaxsearchpriorities = 0x1139,
Barcodesearchpriorities = 0x113a,
Barcodesearchmode = 0x113b,
Barcodemaxretries = 0x113c,
Barcodetimeout = 0x113d,
Zoomfactor = 0x113e,
Patchcodedetectionenabled = 0x113f,
Supportedpatchcodetypes = 0x1140,
Patchcodemaxsearchpriorities = 0x1141,
Patchcodesearchpriorities = 0x1142,
Patchcodesearchmode = 0x1143,
Patchcodemaxretries = 0x1144,
Patchcodetimeout = 0x1145,
Flashused2 = 0x1146,
Imagefilter = 0x1147,
Noisefilter = 0x1148,
Overscan = 0x1149,
Automaticborderdetection = 0x1150,
Automaticdeskew = 0x1151,
Automaticrotate = 0x1152,
Jpegquality = 0x1153,
Feedertype = 0x1154,
Iccprofile = 0x1155,
Autosize = 0x1156,
AutomaticCropUsesFrame = 0x1157,
AutomaticLengthDetection = 0x1158,
AutomaticColorEnabled = 0x1159,
AutomaticColorNonColorPixelType = 0x115a,
ColorManagementEnabled = 0x115b,
ImageMerge = 0x115c,
ImageMergeHeightThreshold = 0x115d,
SupoortedExtImageInfo = 0x115e,
Audiofileformat = 0x1201,
Xfermech = 0x1202
}
internal enum TwainType : short
{
Int8 = 0x0000,
Int16 = 0x0001,
Int32 = 0x0002,
UInt8 = 0x0003,
UInt16 = 0x0004,
UInt32 = 0x0005,
Bool = 0x0006,
Fix32 = 0x0007,
Frame = 0x0008,
Str32 = 0x0009,
Str64 = 0x000a,
Str128 = 0x000b,
Str255 = 0x000c,
Str1024 = 0x000d,
Str512 = 0x000e
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainStatus
{
public short ConditionCode;
public short Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainUserInterface
{
public short ShowUI;
public short ModalUI;
public IntPtr ParentHand;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainImageInfo
{
public int XResolution;
public int YResolution;
public int ImageWidth;
public int ImageLength;
public short SamplesPerPixel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public short[] BitsPerSample;
public short BitsPerPixel;
public short Planar;
public short PixelType;
public short Compression;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwMemory
{
public uint Flags;
public uint Length;
IntPtr TheMem;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainImageMemXfer
{
public ushort Compression;
public uint BytesPerRow;
public uint Columns;
public uint Rows;
public uint XOffset;
public uint YOffset;
public uint BytesWritten;
[MarshalAs(UnmanagedType.Struct)]
TwMemory Memory;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct TwainFix32
{
public short Whole;
public ushort Frac;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainFrame
{
public TwainFix32 Left;
public TwainFix32 Top;
public TwainFix32 Right;
public TwainFix32 Bottom;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainImageLayout
{
public TwainFrame Frame;
public int DocumentNumber;
public int PageNumber;
public int FrameNumber;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainPendingXfers
{
public short Count;
public int EOJ;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainSetupFileXfer
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string FileName;
public ushort Format;
public short VRefNum;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal class TwainCapability : IDisposable
{
internal TwainCapability(TwainCapabilityType cap)
{
Cap = (short)cap;
ConType = -1;
}
internal TwainCapability(TwainCapabilityType cap, short sval)
{
Cap = (short)cap;
ConType = (short)TwainOn.One;
Handle = NativeMethods.GlobalAlloc(0x42, 6);
IntPtr pv = NativeMethods.GlobalLock(Handle);
Marshal.WriteInt16(pv, 0, (short)TwainType.Int16);
Marshal.WriteInt32(pv, 2, (int)sval);
NativeMethods.GlobalUnlock(Handle);
}
~TwainCapability()
{
Dispose(false);
}
public short Cap;
public short ConType;
public IntPtr Handle;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (Handle != IntPtr.Zero)
NativeMethods.GlobalFree(Handle);
}
}
}
答案 0 :(得分:1)
所以,如果有人有兴趣,我最终完全放弃TWAIN - 我认为根本不可能。
我做的是安装:
gcc-core
,make
和libusb-win32
个包裹)经过一整堆配置,制作和安装后,我终于能够从Cygwin提示符发出此命令:
scanimage -t 30 -y 30 --mode Color --depth 8 --resolution 1200 --sharpness 2 --format=tiff --source TPU8x10 > out.tiff
并且你是否相信它out.tiff
宽广而尖锐,比TWAIN更好。
所以,这是一个我知道的可怕的kludge,但我没有一大堆选项(它必须是一个Windows,胖客户端应用程序,它运行在连接扫描仪的机器上),所以我只是推出这个:
c:\cygwin\bin\bash.exe --login -c "scanimage -t 30 -y 30 --mode Color --depth 8 --resolution 1200 --sharpness 2 --format=tiff --source TPU8x10 > ~/out.tiff"
通过.NET应用程序中的Process,当它返回时,我将文件加载到Bitmap并继续进行,好像刚刚发生了什么怪异(意味着应用程序现在有一整堆额外的先决条件和繁琐的配置步骤,但是,好吧,meh,起诉我。)