用C#和WIA扫描

用C#和WIA扫描,c#,.net,scanning,wia,C#,.net,Scanning,Wia,我正在尝试使用平板扫描仪和Windows10从C#应用程序扫描A4页面。为了加快速度,我使用了ScanWIA库,可以在这里找到: 但是,我在正确配置页面设置时遇到了巨大的问题 将页面大小(WIA ID 3097)设置为AUTO,会出现“不支持属性”异常 设置“水平延伸”和“垂直延伸”(WIA ID 61516152)会导致结果过小(裁剪)或出现“值超出范围”异常 设置A4页面和可变DPI设置的正确方法是什么? 如何正确设置捕获区域的大小? 如何控制输出图像的大小? 哪个设置使用哪个单位?最大

我正在尝试使用平板扫描仪和Windows10从C#应用程序扫描A4页面。为了加快速度,我使用了ScanWIA库,可以在这里找到:

但是,我在正确配置页面设置时遇到了巨大的问题

  • 将页面大小(WIA ID 3097)设置为AUTO,会出现“不支持属性”异常
  • 设置“水平延伸”和“垂直延伸”(WIA ID 61516152)会导致结果过小(裁剪)或出现“值超出范围”异常
设置A4页面和可变DPI设置的正确方法是什么? 如何正确设置捕获区域的大小? 如何控制输出图像的大小? 哪个设置使用哪个单位?最大值范围是多少


MSDN在这些主题上没有太大帮助…

我已经创建了一个用户控件,用于从附加的扫描仪扫描文档。
我可以在这里解释细节

在附加的表单图像中,有两个图片框、一个预览按钮、一个保存按钮、两个用于显示保存路径的标签和一个用于显示可用扫描仪设备的下拉列表。请参见上图,以获得有关表单设计的清晰图片

有一个名为WIAScanner.cs的类文件,请参见下面的代码

using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using WIA;
namespace TESTSCAN
{
    class WIAScanner
    {
        const string wiaFormatBMP = "{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}";
        const string WIA_DEVICE_PROPERTY_PAGES_ID = "3096";
        const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
        const string WIA_SCAN_CONTRAST_PERCENTS = "6155";
        const string WIA_SCAN_COLOR_MODE = "6146";
        class WIA_DPS_DOCUMENT_HANDLING_SELECT
        {
            public const uint FEEDER = 0x00000001;
            public const uint FLATBED = 0x00000002;
        }
        class WIA_DPS_DOCUMENT_HANDLING_STATUS
        {
            public const uint FEED_READY = 0x00000001;
        }
        class WIA_PROPERTIES
        {
            public const uint WIA_RESERVED_FOR_NEW_PROPS = 1024;
            public const uint WIA_DIP_FIRST = 2;
            public const uint WIA_DPA_FIRST = WIA_DIP_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
            public const uint WIA_DPC_FIRST = WIA_DPA_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
            //
            // Scanner only device properties (DPS)
            //
            public const uint WIA_DPS_FIRST = WIA_DPC_FIRST + WIA_RESERVED_FOR_NEW_PROPS;
            public const uint WIA_DPS_DOCUMENT_HANDLING_STATUS = WIA_DPS_FIRST + 13;
            public const uint WIA_DPS_DOCUMENT_HANDLING_SELECT = WIA_DPS_FIRST + 14;

        }
        //public void SetProperty(Property property, int value)
        //{
        //    IProperty x = (IProperty)property;
        //    Object val = value;
        //    x.set_Value(ref val);
        //}

        /// <summary>
        /// Use scanner to scan an image (with user selecting the scanner from a dialog).
        /// </summary>
        /// <returns>Scanned images.</returns>
        public static List<Image> Scan()
        {
            WIA.ICommonDialog dialog = new WIA.CommonDialog();
            WIA.Device device = dialog.ShowSelectDevice(WIA.WiaDeviceType.UnspecifiedDeviceType, true, false);
            if (device != null)
            {

                return Scan(device.DeviceID,1);
            }
            else
            {
                throw new Exception("You must select a device for scanning.");
            }
        }

        /// <summary>
        /// Use scanner to scan an image (scanner is selected by its unique id).
        /// </summary>
        /// <param name="scannerName"></param>
        /// <returns>Scanned images.</returns>
        public static List<Image> Scan(string scannerId, int pages)
        {
            List<Image> images = new List<Image>();
            bool hasMorePages = true;
            int numbrPages = pages;
            while (hasMorePages)
            {
                // select the correct scanner using the provided scannerId parameter
                WIA.DeviceManager manager = new WIA.DeviceManager();
                WIA.Device device = null;
                foreach (WIA.DeviceInfo info in manager.DeviceInfos)
                {
                    if (info.DeviceID == scannerId)
                    {
                        // connect to scanner
                        device = info.Connect();
                        break;
                    }
                }
                // device was not found
                if (device == null)
                {
                    // enumerate available devices
                    string availableDevices = "";
                    foreach (WIA.DeviceInfo info in manager.DeviceInfos)
                    {
                        availableDevices += info.DeviceID + "\n";
                    }

                    // show error with available devices
                    throw new Exception("The device with provided ID could not be found. Available Devices:\n" + availableDevices);
                }
                SetWIAProperty(device.Properties, WIA_DEVICE_PROPERTY_PAGES_ID, 1);
                WIA.Item item = device.Items[1] as WIA.Item;
                AdjustScannerSettings(item, 150, 0, 0, 1250, 1700, 0, 0, 1);
                try
                {
                    // scan image
                    WIA.ICommonDialog wiaCommonDialog = new WIA.CommonDialog();
                    WIA.ImageFile image = (WIA.ImageFile)wiaCommonDialog.ShowTransfer(item, wiaFormatBMP, false);

                    // save to temp file
                    string fileName = Path.GetTempFileName();
                    File.Delete(fileName);
                    image.SaveFile(fileName);
                    image = null;
                    // add file to output list
                    images.Add(Image.FromFile(fileName));
                }
                catch (Exception exc)
                {
                    throw exc;
                }
                finally
                {
                    item = null;
                    //determine if there are any more pages waiting
                    WIA.Property documentHandlingSelect = null;
                    WIA.Property documentHandlingStatus = null;
                    foreach (WIA.Property prop in device.Properties)
                    {
                        if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_SELECT)
                            documentHandlingSelect = prop;
                        if (prop.PropertyID == WIA_PROPERTIES.WIA_DPS_DOCUMENT_HANDLING_STATUS)
                            documentHandlingStatus = prop;
                    }
                    // assume there are no more pages
                    hasMorePages = false;
                    // may not exist on flatbed scanner but required for feeder
                    if (documentHandlingSelect != null)
                    {
                        // check for document feeder
                        if ((Convert.ToUInt32(documentHandlingSelect.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_SELECT.FEEDER) != 0)
                        {
                            hasMorePages = ((Convert.ToUInt32(documentHandlingStatus.get_Value()) & WIA_DPS_DOCUMENT_HANDLING_STATUS.FEED_READY) != 0);
                        }
                    }
                }
                numbrPages -= 1;
                if (numbrPages > 0)
                    hasMorePages = true;
                else
                    hasMorePages = false;

            }
            return images;
        }
        /// <summary>
        /// Gets the list of available WIA devices.
        /// </summary>
        /// <returns></returns>
        public static List<string> GetDevices()
        {
            List<string> devices = new List<string>();
            WIA.DeviceManager manager = new WIA.DeviceManager();
            foreach (WIA.DeviceInfo info in manager.DeviceInfos)
            {
                devices.Add(info.DeviceID);
            }
            return devices;
        }
        private static void SetWIAProperty(WIA.IProperties properties,
               object propName, object propValue)
        {
            WIA.Property prop = properties.get_Item(ref propName);
            prop.set_Value(ref propValue);
        }
        private static void AdjustScannerSettings(IItem scannnerItem, int scanResolutionDPI, int scanStartLeftPixel, int scanStartTopPixel,
         int scanWidthPixels, int scanHeightPixels, int brightnessPercents, int contrastPercents, int colorMode)
        {
            const string WIA_SCAN_COLOR_MODE = "6146";
            const string WIA_HORIZONTAL_SCAN_RESOLUTION_DPI = "6147";
            const string WIA_VERTICAL_SCAN_RESOLUTION_DPI = "6148";
            const string WIA_HORIZONTAL_SCAN_START_PIXEL = "6149";
            const string WIA_VERTICAL_SCAN_START_PIXEL = "6150";
            const string WIA_HORIZONTAL_SCAN_SIZE_PIXELS = "6151";
            const string WIA_VERTICAL_SCAN_SIZE_PIXELS = "6152";
            const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
            const string WIA_SCAN_CONTRAST_PERCENTS = "6155";

            SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
            SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
            SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel);
            SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel);
            SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_SIZE_PIXELS, scanWidthPixels);
            SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_SIZE_PIXELS, scanHeightPixels);
            SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents);
            SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents);
            SetWIAProperty(scannnerItem.Properties, WIA_SCAN_COLOR_MODE, colorMode);
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用系统图;
使用WIA;
名称空间测试扫描
{
WIAScanner类
{
常量字符串wiaFormatBMP=“{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}”;
常量字符串WIA\U设备\u属性\u页面\u ID=“3096”;
常量字符串WIA_扫描_亮度_百分比=“6154”;
常量字符串WIA_扫描_对比度_PERCENTS=“6155”;
常量字符串WIA_扫描_颜色_模式=“6146”;
类别WIA\u DPS\u文档\u处理\u选择
{
公安馈线=0x00000001;
公共警察平板车=0x00000002;
}
类别WIA\u DPS\u文件处理\u状态
{
公共警察供给准备就绪=0x00000001;
}
类WIA_属性
{
为新道具保留的公共建筑=1024;
公共警察局:第一个=2;
公共建筑WIA\u DPA\u FIRST=WIA\u DIP\u FIRST+WIA\u保留给新道具;
公共建筑WIA_DPC_FIRST=WIA_DPA_FIRST+WIA_保留用于新道具;
//
//仅扫描仪设备属性(DPS)
//
公共建筑WIA_DPS_FIRST=WIA_DPC_FIRST+WIA_保留用于新道具;
公共警察WIA\U DPS\U文件处理状态=WIA\U DPS\U优先+13;
公共警察WIA\u DPS\u文件处理\u选择=WIA\u DPS\u优先+14;
}
//公共void SetProperty(属性属性,int值)
//{
//IProperty x=(IProperty)属性;
//对象值=值;
//x.设定值(参考值);
//}
/// 
///使用扫描仪扫描图像(用户从对话框中选择扫描仪)。
/// 
///扫描图像。
公共静态列表扫描()
{
WIA.ICommonDialog=新建WIA.CommonDialog();
WIA.Device Device=dialog.ShowSelectDevice(WIA.WiaDeviceType.UnspecifiedDeviceType,true,false);
如果(设备!=null)
{
返回扫描(设备.DeviceID,1);
}
其他的
{
抛出新异常(“您必须选择要扫描的设备”);
}
}
/// 
///使用扫描仪扫描图像(扫描仪由其唯一id选择)。
/// 
/// 
///扫描图像。
公共静态列表扫描(字符串scannerId,int页)
{
列表图像=新列表();
bool hasMorePages=true;
int numberpage=页数;
while(hasMorePages)
{
//使用提供的scannerId参数选择正确的扫描仪
WIA.DeviceManager manager=新的WIA.DeviceManager();
WIA.Device=null;
foreach(manager.DeviceInfo中的WIA.DeviceInfo信息)
{
if(info.DeviceID==scannerId)
{
//连接到扫描仪
device=info.Connect();
打破
}
}
//找不到设备
如果(设备==null)
{
//列举可用设备
字符串availableDevices=“”;
foreach(manager.DeviceInfo中的WIA.DeviceInfo信息)
{
availableDevices+=info.DeviceID+“\n”;
}
//显示可用设备的错误
抛出新异常(“找不到提供ID的设备。可用设备:\n”+可用设备);
}
SetWIAProperty(device.Properties,WIA_device_PROPERTY_PAGES_ID,1);
WIA.Item=device.Items[1]作为WIA.Item;
调整扫描仪设置(项目150、0、0、1250、1700、0、0、1);
尝试
{
//扫描图像
WIA.ICommonDialog wiaCommonDialog=新建WIA.CommonDialog();
WIA.ImageFile image=(WIA.ImageFile)wiaCommonDialog.ShowTransfer(item,wiaFormatBMP,false);
//保存到临时文件
字符串文件名=Path.GetTempFileName();
删除(文件名);
image.SaveFile(文件名);
image=null;
//将文件添加到输出列表
Image.Add(Image.FromFile(文件名));
}
捕获(异常exc)
{
抛出exc;
}
最后
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;


namespace TESTSCAN
{
    public partial class Form1 : Form
    {
        int cropX, cropY, cropWidth, cropHeight;
        //here rectangle border pen color=red and size=2;
        Pen borderpen = new Pen(Color.Red, 2);
        Image _orgImage;
        Bitmap crop;
        List<string> devices;
        //fill the rectangle color =white
        SolidBrush rectbrush = new SolidBrush(Color.FromArgb(100, Color.White));
        int pages;
        int currentPage = 0;
        public Form1()
        {
            InitializeComponent();
            IsSaved = false;
        }
        List<Image> images;
        private string f_path;
        private string doc_no;
        private bool savedOrNot = false;
        private List<string> fNames;
        public List<string> fileNames
        {
            get { return fNames; }
            set { fNames = value; }
        }
        public String SavePath
        {
            get { return f_path; }
            set { f_path = value; }
        }
        public String DocNo
        {
            get { return doc_no; }
            set { doc_no = value; }
        }
        public bool IsSaved
        {
            get { return savedOrNot; }
            set { savedOrNot = value; }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            lblPath.Text = SavePath;
            lblDocNo.Text = DocNo;

            //get list of devices available
            devices = WIAScanner.GetDevices();

            foreach (string device in devices)
            {
                lbDevices.Items.Add(device);
            }
            //check if device is not available
            if (lbDevices.Items.Count != 0)
            {
                lbDevices.SelectedIndex = 0;

            }
        }

        private void btnPreview_Click(object sender, EventArgs e)
        {
            try
            {
                //get list of devices available

                if (lbDevices.Items.Count == 0)
                {
                    MessageBox.Show("You do not have any WIA devices.");

                }
                else
                {
                    //get images from scanner
                    pages =3;
                    images = WIAScanner.Scan((string)lbDevices.SelectedItem, pages);
                    pages = images.Count;
                    if (images != null)
                    {
                        foreach (Image image in images)
                        {
                            pic_scan.Image = images[0];
                            pic_scan.Show();
                            pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
                            _orgImage = images[0];
                            crop = new Bitmap(images[0]);
                            btnOriginal.Enabled = true;
                            btnSave.Enabled = true;
                            currentPage = 0;
                            //pic_scan.Image = image;
                            //pic_scan.Show();
                            //pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
                            //_orgImage = image;
                            //crop = new Bitmap(image);
                            //btnOriginal.Enabled = true;
                            //btnSave.Enabled = true;
                        }
                    }
                }


            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }

        }


        List<string> sss = new List<string>();
        private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                if (crop != null)
                {
                    SavePath = @"D:\NAJEEB\scanned images\";
                    DocNo = "4444";
                    string currentFName = DocNo + Convert.ToString(currentPage + 1) + ".jpeg";
                    crop.Save(SavePath + currentFName, ImageFormat.Jpeg);
                    sss.Add(currentFName);
                    MessageBox.Show("Document Saved Successfully");
                    IsSaved = true;
                    currentPage += 1;
                    if (currentPage < (pages))
                    {
                        pic_scan.Image = images[currentPage];
                        pic_scan.Show();
                        pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
                        _orgImage = images[currentPage];
                        crop = new Bitmap(images[currentPage]);
                        btnOriginal.Enabled = true;
                        btnSave.Enabled = true;

                    }
                    else
                    { btnSave.Enabled =false;
                    fileNames = sss;
                    }
                }

            }
            catch (Exception exc)
            {
                IsSaved = false;
                MessageBox.Show(exc.Message);
            }
        }

        private void btnOriginal_Click(object sender, EventArgs e)
        {
            if (_orgImage != null)
            {
                crop = new Bitmap(_orgImage);
                pic_scan.Image = _orgImage;
                pic_scan.SizeMode = PictureBoxSizeMode.StretchImage;
                pic_scan.Refresh();
            }
        }

        private void pic_scan_MouseDown(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == MouseButtons.Left)//here i have use mouse click left button only
                {
                    pic_scan.Refresh();
                    cropX = e.X;
                    cropY = e.Y;
                    Cursor = Cursors.Cross;
                }
                pic_scan.Refresh();
            }
            catch { }
        }

        private void pic_scan_MouseMove(object sender, MouseEventArgs e)
        {
            try
            {
                if (pic_scan.Image == null)
                    return;

                if (e.Button == MouseButtons.Left)//here i have use mouse click left button only
                {
                    pic_scan.Refresh();
                    cropWidth = e.X - cropX;
                    cropHeight = e.Y - cropY;
                }
                pic_scan.Refresh();
            }
            catch { }
        }

        private void pic_scan_MouseUp(object sender, MouseEventArgs e)
        {
            try
            {
                Cursor = Cursors.Default;
                if (cropWidth < 1)
                {
                    return;
                }
                Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
                Bitmap bit = new Bitmap(pic_scan.Image, pic_scan.Width, pic_scan.Height);
                crop = new Bitmap(cropWidth, cropHeight);
                Graphics gfx = Graphics.FromImage(crop);
                gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;//here add  System.Drawing.Drawing2D namespace;
                gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;//here add  System.Drawing.Drawing2D namespace;
                gfx.CompositingQuality = CompositingQuality.HighQuality;//here add  System.Drawing.Drawing2D namespace;
                gfx.DrawImage(bit, 0, 0, rect, GraphicsUnit.Pixel);

            }
            catch { }
        }

        private void pic_scan_Paint(object sender, PaintEventArgs e)
        {
            Rectangle rect = new Rectangle(cropX, cropY, cropWidth, cropHeight);
            Graphics gfx = e.Graphics;
            gfx.DrawRectangle(borderpen, rect);
            gfx.FillRectangle(rectbrush, rect);
        }
    }
}