是否有可能在TWAIN强制扫描仪的区域设置的整个宽度? [英] Is it possible in TWAIN to force a scanner to set the region to the entire width?

查看:691
本文介绍了是否有可能在TWAIN强制扫描仪的区域设置的整个宽度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个需要扫描的.NET应用程序(C#版本 4.0 时,Visual Studio 2010 <$ C C $>)。我使用了 TWAIN API,以做扫描和我的布局功能的问题。下面code工作完全正常的一个中晶i800型,一个佳能CanoScan 9000F 晶Artix产品扫描F2 但是当我运行它针对的 一些很奇怪的发生爱普生Perfection V700。

尽管我设置布局的左旁 0 图像的左边缘被切断。我试着将它设置为负值,但并没有区别。好像有一些陌生感,这迫使它是一个胶片尺寸(也许是因为我开灯)。如果我用自带的扫描工具它可以让我选择,其中包括两个边缘区域(以及对光线),因此它必须是可能的。此外,顶部和底部的坐标完全正常工作。

所以我的问题是...

  

有谁知道什么办法可以让它扫描整个宽度是多少?是否有TWAIN,我可以先设置让它忘记了它的纸张尺寸,可能还有一些其他的设置? (我试过设置PaperDetectable为false太多,但它并没有区别)。

另一件事:如果我没有设置布局,它仍然切断与边缘(只是没有顶部和底部)的图片,但如果我也没有设置光(或我没有设置做 - 当然那不是'专门扫描从最左侧边缘的整个画面(但问题是,我真正需要的光扫描的整个宽度:对,但我设置的大小),它做什么,我希望光牛逼过分的要求...)。


下面是code(它的背后与上一个按钮1表格Windows窗体应用程序的code):

 使用系统;
使用System.Collections.Generic;
使用System.Drawing中;
使用System.Drawing.Imaging;
使用System.Linq的;
使用System.Windows.Forms的;

命名空间TwainLayoutWindowsFormsApplication
{
    公共部分类Form1中:形态
    {
        公共Form1中()
        {
            的InitializeComponent();
        }

        私人无效的button1_Click(对象发件人,EventArgs的)
        {
            TwainIdentity的appid = NULL;
            TwainIdentity扫描仪= NULL;
            布尔启用=假;

            尝试
            {
                APPID = InitializeTwain(手柄);

                扫描仪=的getSource(APPID,爱普生Perfection V700 / V750);

                打开(APPID,扫描仪);

                SetLightOn(APPID,扫描仪);

                的setLayout(APPID,扫描仪);

                启用(APPID,扫描仪,手柄);
                启用=真;

                VAR骨形态发生蛋白=扫描(APPID,扫描仪);

                禁用(APPID,扫描仪);
                启用=假;

                。bmps.First()保存(@C:\用户\公用\ scan.bmp,ImageFormat.Bmp);

            }
            赶上(例外前)
            {
                的MessageBox.show(ex.Message);
            }
            最后
            {
                如果(APPID = NULL和放大器;!&安培;!扫描仪= NULL)
                {
                    如果(启用)
                    {
                        尝试
                        {
                            禁用(APPID,扫描仪);
                        }
                        赶上(InvalidOperationException异常)
                        {
                        }
                    }

                    关闭(APPID,扫描仪);
                }
            }
        }

        私有静态无效的setLayout(TwainIdentity APPID,
                                      TwainIdentity扫描仪)
        {
            TwainImageLayout布局=新TwainImageLayout();

            VAR RC = NativeMethods.DSilayout(APPID,
                                             扫描器,
                                             TwainDataGroups.Image,
                                             TwainDataArgumentType.ImageLayout,
                                             TwainMessage.Get,
                                             布局);

            从左边顶部和0 // 1英寸
            layout.Frame.Top =新TwainFix32();
            layout.Frame.Top.Whole = 1;

            layout.Frame.Left =新TwainFix32();
            layout.Frame.Left.Whole = 0;

            layout.Frame.Right =新TwainFix32();
            layout.Frame.Right.Whole = 6;

            layout.Frame.Bottom =新TwainFix32();
            layout.Frame.Bottom.Whole = 3;

            layout.FrameNumber = 1;
            layout.PageNumber = 1;
            layout.DocumentNumber = 1;

            RC = NativeMethods.DSilayout(APPID,
                                         扫描器,
                                         TwainDataGroups.Image,
                                         TwainDataArgumentType.ImageLayout,
                                         TwainMessage.Set,
                                         布局);
            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法设置布局);

            变种S =新TwainStatus();

            RC = NativeMethods.DSstatus(APPID,
                                        扫描器,
                                        TwainDataGroups.Control,
                                        TwainDataArgumentType.Status,
                                        TwainMessage.Get,多个);

            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法得到的布局);
        }

        私人的IEnumerable&LT;位图&GT;扫描(TwainIdentity APPID,
                                         TwainIdentity扫描仪)
        {
            VAR照片=新的名单,其中,位图&GT;();

            TwainReturn code RC;
            IntPtr的HBITMAP;
            VAR pxfr =新TwainPendingXfers();

            做
            {
                pxfr.Count = 10;
                HBITMAP = IntPtr.Zero;

                VAR iinf =新TwainImageInfo();
                RC = NativeMethods.DSiinf(APPID,
                                          扫描器,
                                          TwainDataGroups.Image,
                                          TwainDataArgumentType.ImageInfo,
                                          TwainMessage.Get,
                                          iinf);
                如果(RC!= TwainReturn code.Success)
                    抛出新的InvalidOperationException异常(无法INF);

                RC = NativeMethods.DSixfer(APPID,
                                           扫描器,
                                           TwainDataGroups.Image,
                                           TwainDataArgumentType.ImageNativeXfer,
                                           TwainMessage.Get,
                                           裁判HBITMAP);
                如果(RC!= TwainReturn code.XferDone)
                    抛出新的InvalidOperationException异常(莫非DSI XFER);

                RC = NativeMethods.DSpxfer(APPID,
                                           扫描器,
                                           TwainDataGroups.Control,
                                           TwainDataArgumentType.PendingXfers,
                                           TwainMessage.EndXfer,
                                           pxfr);
                如果(RC!= TwainReturn code.Success)
                    抛出新的InvalidOperationException异常(莫非DSP XFER);

                VAR BMP = TwainBitmapConvertor.ToBitmap(HBITMAP);
                pictures.Add(BMP);
            }
            而(pxfr.Count!= 0);

            NativeMethods.DSpxfer(APPID,
                                  扫描器,
                                  TwainDataGroups.Control,
                                  TwainDataArgumentType.PendingXfers,
                                  TwainMessage.StopFeeder,
                                  pxfr);

            返回图片;
        }

        私有静态无效启用(TwainIdentity APPID,
                                   TwainIdentity扫描仪,
                                   IntPtr的HWND)
        {
            VAR guif =新TwainUserInterface();
            guif.ShowUI = 0;
            guif.ModalUI = 1;
            guif.ParentHand = HWND;

            VAR RC = NativeMethods.DSuserif(APPID,
                                            扫描器,
                                            TwainDataGroups.Control,
                                            TwainDataArgumentType.UserInterface,
                                            TwainMessage.EnableDS,
                                            guif);
            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法启用);
        }

        私有静态无效禁用(TwainIdentity的appid,TwainIdentity扫描仪)
        {
            VAR guif =新TwainUserInterface();

            VAR RC = NativeMethods.DSuserif(APPID,
                                            扫描器,
                                            TwainDataGroups.Control,
                                            TwainDataArgumentType.UserInterface,
                                            TwainMessage.DisableDS,
                                            guif);

            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法禁止);
        }

        私有静态无效SetLightOn(TwainIdentity的appid,TwainIdentity扫描仪)
        {
            使用(VAR能力=新TwainCapability(TwainCapabilityType.Lightpath,1))
            {
                VAR RC = NativeMethods.DScap(APPID,
                                             扫描器,
                                             TwainDataGroups.Control,
                                             TwainDataArgumentType.Capability,
                                             TwainMessage.Set,
                                             能力);

                如果(RC!= TwainReturn code.Success)
                    抛出新的InvalidOperationException异常(无法设置光);
            }
        }

        私有静态无效关闭(TwainIdentity APPID,TwainIdentity扫描仪)
        {
            NativeMethods.DSMident(APPID,
                                   IntPtr.Zero,
                                   TwainDataGroups.Control,
                                   TwainDataArgumentType.Identity,
                                   TwainMessage.CloseDS,
                                   扫描器);
        }

        私有静态无效公开赛(TwainIdentity APPID,TwainIdentity扫描仪)
        {
            VAR RC = NativeMethods.DSMident(APPID,
                                            IntPtr.Zero,
                                            TwainDataGroups.Control,
                                            TwainDataArgumentType.Identity,
                                            TwainMessage.OpenDS,
                                            扫描器);

            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法打开);
        }

        私有静态TwainIdentity InitializeTwain(IntPtr的hwndp)
        {
            VAR的appid =新TwainIdentity();

            appid.Version.MajorNum = 1;
            appid.Version.MinorNum = 0;
            appid.Version.Language = 13;
            appid.Version.Country = 1;
            appid.Version.Info =测试;

            appid.Id = IntPtr.Zero;
            appid.ProtocolMajor = 1;
            appid.ProtocolMinor = 9;
            appid.SupportedGroups =(INT)(TwainDataGroups.Image | TwainDataGroups.Control);
            appid.Manufacturer =测试制造商;
            appid.ProductFamily =测试系列;
            appid.ProductName =试验品;

            VAR RC = NativeMethods.DSMparent(APPID,
                                             IntPtr.Zero,
                                             TwainDataGroups.Control,
                                             TwainDataArgumentType.Parent,
                                             TwainMessage.OpenDSM,
                                             裁判hwndp);

            如果(RC!= TwainReturn code.Success)
                抛出新的InvalidOperationException异常(无法DSMParent);

            返回的appid;
        }

        私有静态TwainIdentity的getSource(TwainIdentity的appid,字符串名称)
        {
            无功装置=新TwainIdentity {n = IntPtr.Zero};

            VAR RC = NativeMethods.DSMentry(APPID,
                                            IntPtr.Zero,
                                            TwainDataGroups.Control,
                                            TwainDataArgumentType.Identity,
                                            TwainMessage.GetFirst,
                                            设备);

            如果(RC = TwainReturn code.EndOfList和放大器;!&安培;
                device.ProductName.Equals(姓名,
                                          StringComparison.OrdinalIgnoreCase))
            {
                返回装置;
            }

            而(RC!= TwainReturn code.EndOfList)
            {
                设备=新TwainIdentity {n = IntPtr.Zero};
                RC = NativeMethods.DSMentry(APPID,
                                            IntPtr.Zero,
                                            TwainDataGroups.Control,
                                            TwainDataArgumentType.Identity,
                                            TwainMessage.GetNext,
                                            设备);

                如果(RC = TwainReturn code.EndOfList和放大器;!&安培;
                   device.ProductName.Equals(姓名,
                                          StringComparison.OrdinalIgnoreCase))
                {
                    返回装置;
                }
            }

            抛出新的InvalidOperationException异常(找不到设备);
        }
    }
}
 

有关完整性这里是code我用的HBITMAP转换为的 System.Drawing.Bitmap

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Threading.Tasks;
使用System.Diagnostics程序;
使用System.Drawing中;
使用了System.Runtime.InteropServices;
使用System.Globalization;

命名空间TwainLayoutWindowsFormsApplication
{
    内部静态类TwainBitmapConvertor
    {
        [StructLayout(LayoutKind.Sequential,包= 2)]
        私有类BITMAPINFOHEADER
        {
            公众诠释大小;
            公众诠释宽度;
            公众诠释高度;
            公共短飞机;
            公共短位计数;
            公众诠释的COM pression;
            公众诠释SizeImage;
            公众诠释XPelsPerMeter;
            公众诠释YPelsPerMeter;
            公众诠释ClrUsed;
            公众诠释ClrImportant;
        }

        内部静态位图ToBitmap(IntPtr的dibHandle)
        {
            VAR bitmapPointer = NativeMethods.GlobalLock(dibHandle);

            VAR BITMAPINFO =新BITMAPINFOHEADER();
            Marshal.PtrToStructure(bitmapPointer,BITMAPINFO);

            VAR矩形=新的Rectangle();
            rectangle.X = rectangle.Y = 0;
            rectangle.Width = bitmapInfo.Width;
            rectangle.Height = bitmapInfo.Height;

            如果(bitmapInfo.SizeImage == 0)
            {
                bitmapInfo.SizeImage =
                    ((((bitmapInfo.Width * bitmapInfo.BitCount)+ 31)及〜31)GT;→3)
                    * bitmapInfo.Height;
            }

            //下面code只能在x86
            如果(Marshal.SizeOf(typeof运算(IntPtr的))!= 4)
                抛出新NotSupportedException异常(只支持86);

            INT pixelInfoPointer = bitmapInfo.ClrUsed;
            如果((pixelInfoPointer == 0)及及(bitmapInfo.BitCount&其中; = 8))
            {
                pixelInfoPointer = 1&其中;&其中; bitmapInfo.BitCount;
            }

            pixelInfoPointer =(pixelInfoPointer * 4)+ bitmapInfo.Size
                + bitmapPointer.ToInt32();

            IntPtr的pixelInfoIntPointer =新的IntPtr(pixelInfoPointer);

            VAR位图=新位图(rectangle.Width,rectangle.Height);

            使用(图形显卡= Graphics.FromImage(位图))
            {
                IntPtr的HDC = graphics.GetHdc();

                尝试
                {
                    NativeMethods.SetDIBitsToDevice(HDC,
                        0,0,rectangle.Width,rectangle.Height,0,0,0,
                        rectangle.Height,pixelInfoIntPointer,bitmapPointer,0);
                }
                最后
                {
                    graphics.ReleaseHdc(HDC);
                }
            }

            bitmap.SetResolution(PpmToDpi(bitmapInfo.XPelsPerMeter)
                PpmToDpi(bitmapInfo.YPelsPerMeter));

            NativeMethods.GlobalUnlock(dibHandle);
            NativeMethods.GlobalFree(dibHandle);

            返回的位图;
        }

        私有静态浮动PpmToDpi(双pixelsPerMeter)
        {
            双pixelsPerMillimeter =(双)pixelsPerMeter / 1000.0;
            双dotsPerInch = pixelsPerMillimeter * 25.4;
            返回(浮动)Math.Round(dotsPerInch,2);
        }
    }
}
 

和这里的P /调用:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用了System.Runtime.InteropServices;
使用System.Text;
使用System.Threading.Tasks;

命名空间TwainLayoutWindowsFormsApplication
{
    内部静态类NativeMethods
    {

        [的DllImport(KERNEL32.DLL,ExactSpelling =真)
        内部静态外部的IntPtr的GlobalAlloc(INT标志,INT尺寸);

        [的DllImport(KERNEL32.DLL,ExactSpelling =真)
        内部静态外部的IntPtr GlobalLock(IntPtr的手柄);

        [的DllImport(KERNEL32.DLL,ExactSpelling =真)
        内部静态外部布尔GlobalUnlock(IntPtr的手柄);

        [的DllImport(KERNEL32.DLL,ExactSpelling =真)
        内部静态外部的IntPtr GlobalFree(IntPtr的手柄);

        [的DllImport(GDI32.DLL,ExactSpelling =真)
        公共静态外部INT的SetDIBitsToDevice(IntPtr的HDC,诠释xdst,诠释ydst,诠释的宽度,高度INT,
            INT xsrc,诠释ysrc,诠释开始,诠释线,IntPtr的bitsptr,IntPtr的bmiptr,INT的颜色);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSMparent([输入,输出] TwainIdentity出身,IntPtr的zeroptr,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,楼盘的IntPtr refptr);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSMident([输入,输出] TwainIdentity出身,IntPtr的zeroptr,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainIdentity IDDS);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSMentry([输入,输出] TwainIdentity出身,IntPtr的zeroptr,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainIdentity IDDS);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSMstatus([输入,输出] TwainIdentity出身,IntPtr的zeroptr,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainStatus dsmstat);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSuserif([输入,输出] TwainIdentity起源,[输入,输出] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,TwainUserInterface guif);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSevent([输入,输出] TwainIdentity起源,[输入,输出] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,裁判TwainEvent EVT);

        [的DllImport(twain_32.dll,入口点=#1)]
        ÇDSSTATUS内部静态外部TwainReturn $ C $([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainStatus dsmstat);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DScap([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainCapability CAPA);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSiinf([输入,输出] TwainIdentity出身,TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType [在] DAT,TwainMessage味精,[输入,输出] TwainImageInfo imginf);

        [的DllImport(twain_32.dll,入口点=#1)]
        ÇDSixfer内部静态外部TwainReturn $ C $([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,楼盘的IntPtr HBITMAP);

        [的DllImport(twain_32.dll,入口点=#1)]
        ÇDSMemixfer内部静态外部TwainReturn $ C $([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainImageMemXfer memxfr);

        [的DllImport(twain_32.dll,入口点=#1)]
        ÇDSpxfer内部静态外部TwainReturn $ C $([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainPendingXfers pxfr);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSilayout([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainImageLayout布局);

        [的DllImport(twain_32.dll,入口点=#1)]
        内部静态外部TwainReturn code DSMEntry([输入,输出] TwainIdentity起源,[在] TwainIdentity DEST,TwainDataGroups DG,TwainDataArgumentType DAT,TwainMessage味精,[输入,输出] TwainSetupFileXfer fileXf);
    }
}
 

最后,对剩下的东西(结构和诸如此类的东西),这需要工作的:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用了System.Runtime.InteropServices;
使用System.Text;
使用System.Threading.Tasks;

命名空间TwainLayoutWindowsFormsApplication
{
    [StructLayout(LayoutKind.Sequential,包= 2,字符集= CharSet.Ansi)
    内部类TwainIdentity
    {
        公共IntPtr的标识;
        公共TwainVersion版本;
        公共短ProtocolMajor;
        公共短ProtocolMinor;
        公众诠释SupportedGroups;
        [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 34)]
        公共字符串制造商;
        [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 34)]
        公共字符串ProductFamily;
        [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 34)]
        公共字符串产品名称;
    }

    内部枚举TwainReturn code:短
    {
        成功= 0×0000,
        失败= 0×0001,
        的checkStatus = 0×0002,
        取消=为0x0003,
        DSEvent =×0004,
        NotDSEvent = 0×0005,
        XferDone = 0x0006,
        EndOfList = 0x0007,
        InfoNotSupported =×0008,
        DataNotAvailable = 0x0009
    }

    [StructLayout(LayoutKind.Sequential,包= 2,字符集= CharSet.Ansi)
    内部结构TwainVersion
    {
        公共短MajorNum;
        公共短MinorNum;
        公共短语;
        公共短国家;
        [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 34)]
        公共字符串信息;
    }

    [国旗]
    内部枚举TwainDataGroups:短
    {
        控制= 0×0001,
        图片= 0×0002,
        音频=×0004
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部结构TwainEvent
    {
        公众的IntPtr EventPtr;
        公共短消息;
    }

    内部枚举TwainDataArgumentType:短
    {
        空= 0×0000,
        能力= 0×0001,
        事件= 0×0002,
        标识=为0x0003,
        父=×0004,
        PendingXfers = 0×0005,
        SetupMemXfer = 0x0006,
        SetupFileXfer = 0x0007,
        状态=×0008,
        的UserInterface = 0x0009,
        XferGroup = 0x000a,
        TwunkIdentity = 0x000b,
        CustomDSData = 0x000c,
        DeviceEvent = 0x000d,
        文件系统= 0x000e,
        的PASSThru = 0x000f,

        的imageinfo = 0x0101,
        ImageLayout = 0x0102,
        ImageMemXfer = 0x0103,
        ImageNativeXfer = 0x0104,
        ImageFileXfer = 0x0105,
        CieColor = 0x0106,
        GrayResponse = 0x0107,
        RGBResponse = 0x0108,
        JpegCom pression = 0x0109,
        Palette8 = 0x010A时,
        ExtImageInfo = 0x010b,

        SetupFileXfer2 = 0x0301
    }

    内部枚举TwainMessage:短
    {
        空= 0×0000,
        获取= 0×0001,
        GetCurrent = 0×0002,
        GetDefault =为0x0003,
        GetFirst =×0004,
        的GetNext = 0×0005,
        套装= 0x0006,
        复位= 0x0007,
        QuerySupport =×0008,

        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,
        删除= 0x0803,
        FormatMedia = 0x0804,
        GetClose = 0x0805,
        GetFirstFile = 0x0806,
        的GetInfo = 0x0807,
        GetNextFile = 0x0808,
        重命名= 0x0809,
        复制= 0x080A,
        AutoCaptureDir = 0x080B,

        的PASSThru = 0x0901
    }

    [StructLayout(LayoutKind.Sequential,包= 4)]
    内部结构TwainWindowMessage
    {
        公众的IntPtr HWND;
        公众诠释消息;
        公众的IntPtr的wParam;
        公共IntPtr的lParam的;
        公众诠释的时间;
        公众诠释X;
        公众诠释Ÿ;
    }

    内部枚举TwainOn:短
    {
        阵列=为0x0003,
        枚举=×0004,
        一= 0×0005,
        范围= 0x0006,
        是dontCare = -1
    }

    内部枚举TwainCapabilityType:短
    {
        XferCount = 0×0001,

        ICOM pression = 0100,
        IPixelType = 0x0101,
        IUnits = 0x0102,
        IXferMech = 0x0103,

        作者= 0x1000中,
        标题= 0x1001的,
        FeederEnabled = 0x1002,
        FeederLoaded = 0x1003,
        TIMEDATE = 0x1004,
        SupportedCapabilities = 0x1005,
        Extendedcaps = 0x1006,
        AUTOFEED = 0x1007,
        ClearPage = 0x1008,
        FeedPage = 0x1009,
        RewindPage = 0x100A中,

        指标= 0x100b,
        SupportedCapsExt = 0x100c,
        PaperDetectable = 0x100d,
        UIControllable = 0x100e,
        DeviceOnline = 0x100f,
        自动扫描= 0x1010,
        ThumbnailsEnabled = 0x1011,
        复式= 0x1012,
        DuplexEnabled = 0x1013,
        Enabledsuionly = 0x1014,
        CustomdsData = 0x1015,
        背书= 0x1016,
        JobControl作业控制= 0x1017,
        报警= 0x1018,
        AlarmVolume = 0x1019,
        AutomaticCapture = 0x101a,
        TimeBeforeFirstCapture = 0x101b,
        TimeBetweenCaptures = 0x101c,
        ClearBuffers = 0x101d,
        MaxBatchBuffers = 0x101e,
        DeviceTimeDate = 0x101f,
        POWERSUPPLY = 0x1020,
        相机previewUI = 0x1021,
        DeviceEvent = 0x1022,
        的SerialNumber = 0x1024,
        打印机= 0x1026,
        PrinterEnabled = 0x1027,
        PrinterIndex = 0x1028,
        PrinterMode = 0x1029,
        PrinterString = 0x102a,
        PrinterSuffix = 0x102b,
        语言= 0x102c,
        FeederAlignment = 0x102d,
        FeederOrder = 0x102e,
        ReAcquireAllowed = 0x1030,
        BatteryMinutes = 0x1032,
        BatteryPercentage = 0x1033,
        CameraSide = 0x1034,
        分段= 0x1035,
        CameraEnabled = 0x1036,
        CameraOrder = 0x1037,
        MicrEnabled = 0x1038,
        进纸器$ P $页= 0x1039,
        Feederpocket = 0x103a,

        自动亮度调节=到0x1100,
        亮度= 0x1101,
        相比之下= 0x1103,
        CustHalftone = 0x1104,
        ExposureTime = 0x1105,
        过滤器= 0x1106,
        Flashused = 0x1107,
        伽玛= 0x1108,
        半色调= 0x1109,
        亮点= 0x110a,
        ImageFileFormat = 0x110c,
        LampState = 0x110d,
        LightSource = 0x110e,
        方向= 0x1110,
        PhysicalWidth = 0x1111,
        PhysicalHeight = 0x1112,
        阴影= 0x1113,
        帧= 0x1114,
        XNativeResolution = 0x1116,
        YNativeResolution = 0x1117,
        XResolution = 0x1118,
        YResolution = 0x1119,
        MaxFrames = 0x111a,

        瓷砖= 0x111b,
        Bitorder = 0x111c,
        Ccittkfactor = 0x111d,
        光路= 0x111e,
        Pixelflavor = 0x111f,
        Planarchunky = 0x1120,
        旋转= 0x1121,
        Supportedsizes = 0x1122,
        阈值= 0x1123,
        Xscaling = 0x1124,
        Yscaling = 0x1125,
        Bitorder codeS = 0x1126,
        Pixelflavor codeS = 0x1127,
        Jpegpixeltype = 0x1128,
        Timefill = 0x112a,
        位深度= 0x112b,
        Bitdepthreduction = 0x112c,
        Undefinedimagesize = 0x112d,
        Imagedataset = 0x112e,
        Extimageinfo = 0x112f,
        Minimumheight = 0x1130,
        Minimumwidth = 0x1131,
        Fliprotation = 0x1136,
        酒吧codedetectionenabled = 0x1137,
        Supportedbar $ C $的ctypes = 0x1138,
        酒吧codemaxsearchpriorities = 0x1139,
        酒吧codesearchpriorities = 0x113a,
        酒吧codesearchmode = 0x113b,
        酒吧codemaxretries = 0x113c,
        酒吧codetimeout = 0x113d,
        Zoomfactor = 0x113e,
        补丁codedetectionenabled = 0x113f,
        Supportedpatch $ C $的ctypes = 0x1140,
        补丁codemaxsearchpriorities = 0x1141,
        补丁codesearchpriorities = 0x1142,
        补丁codesearchmode = 0x1143,
        补丁codemaxretries = 0x1144,
        补丁codetimeout = 0x1145,
        Flashused2 = 0x1146,
        的ImageFilter = 0x1147,
        Noisefilter = 0x1148,
        过扫描= 0x1149,
        Automaticborderdetection = 0x1150,
        Automaticdeskew = 0x1151,
        Automaticrotate = 0x1152,
        Jpegquality = 0x1153,
        Feedertype = 0x1154,
        Iccprofile = 0x1155,
        自动调整大小= 0x1156,
        AutomaticCropUsesFrame = 0x1157,
        AutomaticLengthDetection = 0x1158,
        AutomaticColorEnabled = 0x1159,
        AutomaticColorNonColorPixelType = 0x115a,
        ColorManagementEnabled = 0x115b,
        ImageMerge = 0x115c,
        ImageMergeHeightThreshold = 0x115d,
        SupoortedExtImageInfo = 0x115e,
        Audiofileformat = 0x1201,
        Xfermech = 0x1202
    }

    内部枚举TwainType:短
    {
        INT8 = 0×0000,
        INT16 = 0×0001,
        INT32 = 0×0002,
        UINT8 =为0x0003,
        UINT16 =×0004,
        UInt32的= 0×0005,
        布尔= 0x0006,
        FIX32 = 0x0007,
        帧=×0008,
        Str32 = 0x0009,
        Str64 = 0x000a,
        Str128 = 0x000b,
        Str255 = 0x000c,
        Str1024 = 0x000d,
        Str512 = 0x000e
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainStatus
    {
        公共短条件code;
        公共短保留;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainUserInterface
    {
        公共短ShowUI;
        公共短ModalUI;
        公众的IntPtr ParentHand;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainImageInfo
    {
        公众诠释XResolution;
        公众诠释YResolution;
        公众诠释ImageWidth等;
        公众诠释ImageLength;
        公共短SamplesPerPixel;
        [的MarshalAs(UnmanagedType.ByValArray,SizeConst = 8)]
        公共短[] bitspersample的;
        公共短BitsPerPixel;
        公共短平面;
        公共短PixelType;
        公共短的COM pression;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwMemory
    {
        公共UINT标志;
        公共UINT长度;
        IntPtr的TheMem;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainImageMemXfer
    {
        公共USHORT的COM pression;
        公共UINT BytesPerRow;
        公共UINT列;
        公共UINT行;
        公共UINT XOffset;
        公共UINT YOffset;
        公共UINT BytesWritten;
        [的MarshalAs(UnmanagedType.Struct)
        TwMemory内存;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部结构TwainFix32
    {
        公共短整;
        公共USHORT压裂;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainFrame
    {
        公共TwainFix32左;
        公共TwainFix32顶部;
        公共TwainFix32权利;
        公共TwainFix32底部;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainImageLayout
    {
        公共TwainFrame框架;
        公众诠释DocumentNumber;
        公众诠释的PageNumber;
        公众诠释帧编号;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainPendingXfers
    {
        公共短计数;
        公众诠释EOJ;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainSetupFileXfer
    {
        [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 255)
        公共字符串文件名;
        公共USHORT格式;
        公共短的vRefNum;
    }

    [StructLayout(LayoutKind.Sequential,包= 2)]
    内部类TwainCapability:IDisposable的
    {

        内部TwainCapability(TwainCapabilityType帽)
        {
            帽=(短期),帽;
            ConType首= -1;
        }

        内部TwainCapability(TwainCapabilityType帽,短SVAL)
        {
            帽=(短期),帽;
            ConType报=(短期)TwainOn.One;
            手柄= NativeMethods.GlobalAlloc(0x42后,6);
            IntPtr的PV = NativeMethods.GlobalLock(手柄);
            Marshal.WriteInt16(PV,0,(短)TwainType.Int16);
            Marshal.WriteInt32(PV,2,(int)的SVAL);
            NativeMethods.GlobalUnlock(手柄);
        }

        〜TwainCapability()
        {

            处置(假);
        }

        公共短帽;

        公共短ConType首;

        公众的IntPtr句柄;

        公共无效的Dispose()
        {
            处置(真);
            GC.Sup pressFinalize(本);
        }

        受保护的虚拟无效的Dispose(BOOL处置)
        {
            如果(处理!= IntPtr.Zero)
                NativeMethods.GlobalFree(手柄);
        }
    }
}
 

解决方案

所以,如果有人有兴趣,我结束了在放弃TWAIN 的完全 - 我认为这根本是不可能的。

我是不是安装什么:

配置,制造和安装我终于能发出从 Cygwin的提示:

  scanimage -t 30 -y 30 --mode颜色--depth 8 --resolution 1200 --sharpness 2 --format = TIFF --source TPU8x10&GT; out.tiff
 

,你会相信吗 out.tiff 很宽,锋利和很多比我更可以实现与的 TWAIN

所以,这是一个可怕的杂牌我知道,但我没有一个选项整个堆(它必须是一台机器连接了扫描仪上运行的窗口,胖客户端应用程序),所以我才推出这个

  C:\ cygwin的\斌\ bash.exe --login -cscanimage -t 30 -y 30 --mode颜色--depth 8 --resolution 1200 --sharpness 2 --format = TIFF --source TPU8x10&GT;〜/ out.tiff
 

通过过程在.NET应用程序当它返回我加载文件到位图并进行好像什么都没有奇特刚刚发生(指现在的应用程序有额外的prerequisites和繁琐的配置步骤的一大堆,但是,好了,咩,告我)。

I am writing an application that requires scanning in .net (c# version 4.0, Visual Studio 2010). I'm using the TWAIN API in order to do the scanning and I have a problem with the layout feature. The following code works perfectly fine on a Microtek i800, a CanoScan 9000F and a Microtek Artix Scan F2 but when I run it against an Epson Perfection V700 something really strange occurs.

Even though I am setting the left margin of the layout to 0 the left edge of the image is cut off. I tried setting it to negative values but that made no difference. It seems like there is some strangeness and it is forcing it to be a film size (perhaps because I am turning the light on). If I use the tool that comes with the scanner it allows me to select a region that includes both edges (and have the light on) so it must be possible. Also, the top and bottom coordinates work perfectly fine.

So my question is...

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).

One other thing: If I do not set the layout, it still cuts off the picture on the edges (just not top and bottom) but if I also do not set the light on (or I do not set the light on but I do set the size) it does what I would expect: specifically scans the entire picture from the left most edge (but the problem is, I really need the light and the entire width of the scan - surely that isn't too much to ask...).


Here is the code (it is the code behind for a 1 form windows form application with a single button on it):

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

For completeness here is the code I use to convert the HBITMAP to a 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);
        }
    }
}

and here are the 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);
    }
}

and finally, the rest of the stuff (structures and whatnot) that that needs to work:

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

解决方案

So, in case anyone is interested I ended up giving up on TWAIN entirely - I think it is simply not possible.

What I did instead was install:

After a whole heap of configuring, making and installing I finally was able to issue this command from the Cygwin prompt:

scanimage -t 30 -y 30 --mode Color --depth 8 --resolution 1200 --sharpness 2 --format=tiff --source TPU8x10 > out.tiff

and would you believe it out.tiff was wide and sharp and a whole lot better than I could achieve with TWAIN.

So, it is a horrible kludge I know, but I don't have a whole heap of options (it must be a windows, thick client application that runs on a machine with a scanner connected), so I just launch this:

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"

via a Process in the .NET application and when it returns I load up the file into a Bitmap and carry on as if nothing freaky just happened (means the application has now a whole heap of extra prerequisites and fiddly configuration steps, but, well, meh, sue me).

这篇关于是否有可能在TWAIN强制扫描仪的区域设置的整个宽度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆