在 TWAIN 中是不是可以强制扫描仪将区域设置为整个宽度?
Posted
技术标签:
【中文标题】在 TWAIN 中是不是可以强制扫描仪将区域设置为整个宽度?【英文标题】:Is it possible in TWAIN to force a scanner to set the region to the entire width?在 TWAIN 中是否可以强制扫描仪将区域设置为整个宽度? 【发布时间】:2012-11-01 16:17:03 【问题描述】:我正在编写一个需要在 .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 窗体 windows 窗体应用程序的代码):
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);
【问题讨论】:
对于这么多代码,我建议开始赏金.. 【参考方案1】:所以,如果有人感兴趣,我最终完全放弃了TWAIN - 我认为这根本不可能。
我所做的是安装:
Cygwin(基本安装加上gcc-core
、make
和 libusb-win32
包)
libusb-win32
SANE。
经过一大堆配置、制作和安装后,我终于能够从Cygwin 提示符发出这个命令:
scanimage -t 30 -y 30 --mode Color --depth 8 --resolution 1200 --sharpness 2 --format=tiff --source TPU8x10 > out.tiff
您是否相信out.tiff
宽而锐利,比我使用TWAIN 所能达到的效果要好得多。
所以,我知道这是一个可怕的组合,但我没有一大堆选择(它必须是一个 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 并继续进行,好像没有发生任何奇怪的事情(意味着应用程序现在有一大堆额外的先决条件和繁琐配置步骤,但是,嗯,告我)。
【讨论】:
以上是关于在 TWAIN 中是不是可以强制扫描仪将区域设置为整个宽度?的主要内容,如果未能解决你的问题,请参考以下文章