【问题标题】:Scanning with C# and WIA使用 C# 和 WIA 进行扫描
【发布时间】:2024-05-22 23:40:01
【问题描述】:

我正在尝试使用平板扫描仪和 Windows 10 从 C# 应用程序扫描 A4 页面。为了加快速度,我使用了此处的 ScanWIA 库:https://scanwia.codeplex.com/

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

  • 将页面大小 (WIA ID 3097) 设置为 AUTO,会出现“不支持的属性”异常。
  • 设置水平和垂直扩展(WIA ID 6151、6152)会导致结果太小(裁剪)或“值超出范围”异常。

为 A4 页面和可变 DPI 设置进行此设置的正确方法是什么? 如何正确设置捕获区域的大小? 如何控制输出图像的大小? 哪个设置使用哪个单位?最大值范围是多少?

MSDN 在这些主题上不是很有帮助...

【问题讨论】:

    标签: c# .net scanning wia


    【解决方案1】:

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

    在附加的表单图像中有 2 个图片框、一个预览按钮、一个保存按钮、两个用于显示保存路径的标签和一个用于显示可用扫描仪设备的下拉菜单。请参阅上图以清楚了解表单设计。

    有一个名为 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);
            }
    
        }
    }
    

    然后看下面名为Form1的表单的.cs文件

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

    工作流程的简短描述:

    1. 在表单加载事件中,可用的扫描仪设备添加到下拉列表中。 用户可以从此下拉列表中选择任何设备。
    2. 点击预览按钮,文档被扫描到应用程序并显示在图片框中。
    3. 表单中有另一个图片框用于保存裁剪后的图像。如果您从图片框中的图片中选择任何区域,您就会感受到裁剪效果。裁剪后的图像保留在第一个图片框后面的第二个图片框中。
    4. 在保存按钮上单击图像保存到磁盘中的指定位置。 这个位置我们可以从应用程序中配置。查看代码。

    【讨论】:

    最近更新 更多