加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 在TWAIN中是否可以强制扫描仪将区域设置为整个宽度?

发布时间:2020-12-15 21:42:47 所属栏目:百科 来源:网络整理
导读:我正在编写一个需要在.net中扫描的应用程序(c#version 4.0,Visual Studio 2010).我正在使用TWAIN API进行扫描,我的布局功能有问题.以下代码在Microtek i800,CanoScan 9000F和Microtek Artix Scan F2上运行得非常好,但是当我对 Epson Perfection V700运行它时
我正在编写一个需要在.net中扫描的应用程序(c#version 4.0,Visual Studio 2010).我正在使用TWAIN API进行扫描,我的布局功能有问题.以下代码在Microtek i800,CanoScan 9000F和Microtek Artix Scan F2上运行得非常好,但是当我对 Epson Perfection V700运行它时,真的很奇怪.

即使我将布局的左边距设置为0,图像的左边缘也会被切断.我尝试将其设置为负值,但这没有任何区别.似乎有一些奇怪的东西,它迫使它成为一个电影大小(也许是因为我正在开灯).如果我使用扫描仪附带的工具,它允许我选择包含两个边缘的区域(并打开灯),因此必须可以.此外,顶部和底部坐标完美地工作.

所以我的问题是……

Does anyone know of any way I can make it scan the entire width? Is there some other setting in TWAIN that I can set first to get it to forget its paper sizes perhaps? (I tried setting PaperDetectable to false too but it made no difference).

另外一件事:如果我没有设置布局,它仍然会切断边缘的图片(只是不是顶部和底部),但如果我也没有设置灯光(或者我没有设置灯光,但我做设置尺寸)它做我所期望的:专门从最左边扫描整个画面(但问题是,我真的需要光线和扫描的整个宽度 – 当然,这不是太多问题. ..).

这是代码(它是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:userspublicscan.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,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,TwainMessage.Set,layout);
            if (rc != TwainReturnCode.Success)
                throw new InvalidOperationException("Failed to set layout");

            var s = new TwainStatus();

            rc = NativeMethods.DSstatus(appid,TwainDataGroups.Control,TwainDataArgumentType.Status,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,TwainDataArgumentType.ImageInfo,iinf);
                if (rc != TwainReturnCode.Success)
                    throw new InvalidOperationException("Could not INF");

                rc = NativeMethods.DSixfer(appid,TwainDataArgumentType.ImageNativeXfer,ref hbitmap);
                if (rc != TwainReturnCode.XferDone)
                    throw new InvalidOperationException("Could DSI XFER");

                rc = NativeMethods.DSpxfer(appid,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,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,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,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,TwainDataArgumentType.Capability,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,TwainDataArgumentType.Identity,TwainMessage.CloseDS,scanner);
        }

        private static void Open(TwainIdentity appid,TwainIdentity scanner)
        {
            var rc = NativeMethods.DSMident(appid,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,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,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,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,rectangle.Width,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,[In,Out] TwainIdentity idds);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSMentry([In,EntryPoint = "#1")]
        internal static extern TwainReturnCode DSMstatus([In,Out] TwainStatus dsmstat);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSuserif([In,Out] TwainIdentity dest,TwainUserInterface guif);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSevent([In,ref TwainEvent evt);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSstatus([In,[In] TwainIdentity dest,EntryPoint = "#1")]
        internal static extern TwainReturnCode DScap([In,Out] TwainCapability capa);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSiinf([In,Out] TwainImageInfo imginf);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSixfer([In,ref IntPtr hbitmap);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSMemixfer([In,Out] TwainImageMemXfer memxfr);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSpxfer([In,Out] TwainPendingXfers pxfr);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSilayout([In,Out] TwainImageLayout layout);

        [DllImport("twain_32.dll",EntryPoint = "#1")]
        internal static extern TwainReturnCode DSMEntry([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,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,(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);
        }
    }
}

解决方法

所以,如果有人感兴趣我最终完全放弃了 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

并且你会相信它吗..tiff宽阔而锋利,比TWAIN更好.

所以,这是一个我知道的可怕的kludge,但我没有一大堆选项(它必须是一个Windows,胖客户端应用程序在连接扫描仪的机器上运行),所以我只是启动它:

c:cygwinbinbash.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,起诉我).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读