在C#中使用WIA.docx

上传人:b****4 文档编号:6867441 上传时间:2023-05-10 格式:DOCX 页数:17 大小:810.06KB
下载 相关 举报
在C#中使用WIA.docx_第1页
第1页 / 共17页
在C#中使用WIA.docx_第2页
第2页 / 共17页
在C#中使用WIA.docx_第3页
第3页 / 共17页
在C#中使用WIA.docx_第4页
第4页 / 共17页
在C#中使用WIA.docx_第5页
第5页 / 共17页
在C#中使用WIA.docx_第6页
第6页 / 共17页
在C#中使用WIA.docx_第7页
第7页 / 共17页
在C#中使用WIA.docx_第8页
第8页 / 共17页
在C#中使用WIA.docx_第9页
第9页 / 共17页
在C#中使用WIA.docx_第10页
第10页 / 共17页
在C#中使用WIA.docx_第11页
第11页 / 共17页
在C#中使用WIA.docx_第12页
第12页 / 共17页
在C#中使用WIA.docx_第13页
第13页 / 共17页
在C#中使用WIA.docx_第14页
第14页 / 共17页
在C#中使用WIA.docx_第15页
第15页 / 共17页
在C#中使用WIA.docx_第16页
第16页 / 共17页
在C#中使用WIA.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

在C#中使用WIA.docx

《在C#中使用WIA.docx》由会员分享,可在线阅读,更多相关《在C#中使用WIA.docx(17页珍藏版)》请在冰点文库上搜索。

在C#中使用WIA.docx

在C#中使用WIA

在C#中使用WIA获取扫描仪数据

(一)

WIA(WindowsImageAcquire,最新版本2.0)是Windows中一组从设备中捕获图像的标准API集合,它可以从设备(例如扫描仪、数码相机)中获取静态图像,以及管理这些设备。

它既是API,又是DDI(DeviceDriverInterface)。

因此,只要是满足这个规范的设备,都能够利用WIA直接和应用程序交互,而不是通过驱动。

WIA甚至提供了统一的对话框来获取图片。

WIA是基于Com的,有两种使用方式:

c++:

使用WIA自定义接口

其他:

使用WIAAL(WIAAutomationLayer)。

注:

在WindowsXPsp1以前的版本,WIAAL还不存在,因此第二种方式用的是WIAScriptingModel。

在.Net中使用WIA,我们用的是第二种方法。

接下来做一个简单的图像扫描程序:

界面

新建一个WinForm应用程序,在上面添加一个按钮和一个图片框,点击按钮时启动扫描进程,然后在图片框中显示图像,应用程序界面如下:

使用WIA

VisualStudio2008有一个好处,可以自动装配Com组件,在工程中添加一个WIA的COM引用:

点击确定后,会在工程引用中添加一个WIA.Interop.dll的文件,可以在对象浏览器中查看它:

打开扫描对话框

接下来可以利用WIA来进行扫描了,步骤很简单,首先引用命名空间:

usingWIA;接下来,在button的Click事件中,添加如下代码:

ImageFileimageFile=null;

CommonDialogClasscdc=newWIA.CommonDialogClass();

try

{

imageFile=cdc.ShowAcquireImage(WIA.WiaDeviceType.ScannerDeviceType,

WIA.WiaImageIntent.TextIntent,

WIA.WiaImageBias.MaximizeQuality,

"{00000000-0000-0000-0000-000000000000}",

true,

true,

false);

}

catch(System.Runtime.InteropServices.COMException)

{

imageFile=null;

}WIA会自动弹出标准扫描对话框,进行扫描操作:

获取图像

调用ShowAcquireImage后,扫描后的数据就保存在ImageFile对象里了。

用以下方法读取ImageFile中的数据(该方法很傻很傻……很傻)

if(imageFile!

=null)

{

imageFile.SaveFile(@"c:

\1.bmp");

using(FileStreamstream=newFileStream(@"c:

\1.bmp",FileMode.Open,

FileAccess.Read,FileShare.Read))

{

pictureBox1.Image=Image.FromStream(stream);

}File.Delete(@"c:

\1.bmp");

}结果如下:

在C#中使用WIA获取扫描仪数据(二、WIAAutomationLayer)

前文说过,在WIA2.0里,有一个叫AutomationLayer的东西,来负责WIA和应用程序交互。

既然被命名为Automation了,那么意味着比直接试用WIA接口,WIAAL更容易、更方便。

实际上的确如此。

关于WIAAutomationLayer

文档上说,WIAAutomationLayer是一个高级的,全能的图像操作组件,能为应用程序(例如ASP,C#)提供首尾相连的处理能力。

利用WIAAL,在程序中可以很容易地从诸如数码相机、扫描仪等图像设备中捕获图像,以及进行简单处理(缩放、旋转)。

对象分级结构

WIAAL的对象不多,总的来说分成来两块,第一块是可以被创建的类(例如在c#里我们用关键字new来创建),另一部分是不能被创建的类(在c#里,这些类虽然也有构造函数,不过即使创建了,也没有任何东西),它们必须由第一种类创建。

如下图:

可见,上面有我们熟悉的CommonDialog(在Interop后,这些类后面都加上了Class表示实现,例如CommonDialogClass就是CommonDialog的实现)。

改进的例子

在前面的文章中,我用了一个很“囧”的方法来保存图片,实际上大可不必如此,从上面的关系图可以看到,ImageFile对象有一个Vector的对象,该对象保存了图片的像素值。

修改代码如下:

if(imageFile!

=null)

{

varbuffer=imageFile.FileData.get_BinaryData()asbyte[];

using(MemoryStreamms=newMemoryStream())

{

ms.Write(buffer,0,buffer.Length);

pictureBox1.Image=Image.FromStream(ms);

}

}

在C#中使用WIA获取扫描仪数据(三、利用Filter处理图片)

WIAAutomationLayer不仅能从设备中捕获照片,还能进行简单的处理。

当WIAAutomationLayer从设备中捕获照片,保存为一个ImageFile对象,我们可以通过访问该ImageFile对象来访问照片的属性。

然而,为了保护原来的照片,不能直接通过修改该ImageFile对象的方法修改图片。

代替的方法是,使用ImageProcess和一个或多个Filter对象创建一个副本,修改图片。

代码

以下代码把扫描得到的图片顺时针旋转90度:

if(imageFile!

=null)

{

ImageProcessip=newImageProcessClass();

objectfilterName="RotateFlip";

ObjectpropertyName="RotationAngle";

ObjectpropertyValue=90;

ip.Filters.Add(ip.FilterInfos.get_Item(reffilterName).FilterID,0);

ip.Filters[1].Properties.get_Item(refpropertyName).set_Value(refpropertyValue);

varbuffer=ip.Apply(imageFile).FileData.get_BinaryData()asbyte[];

using(MemoryStreamms=newMemoryStream())

{

ms.Write(buffer,0,buffer.Length);

pictureBox1.Image=Image.FromStream(ms);

}

}

FilterID

以下是可用的FilterID

RotateFlip

以90度增量旋转,以及水平或垂直翻转。

RotationAngle-如果希望旋转,可将RotationAngle属性设置为90、180或270,

否则设置为0[默认值]

FlipHorizontal-如果希望水平翻转图像,可将FlipHorizontal属性设置为True,

否则设置为False[默认值]

FlipVertical-如果希望垂直翻转图像,可将FlipVertical属性设置为True,

否则设置为False[默认值]

FrameIndex-如果希望修改除ActiveFrame之外的帧,

可将FrameIndex属性设置为帧的索引,

否则设置为0[默认值]Crop

以指定的左、右、上、下边距裁剪图像。

Left-如果希望沿左侧裁剪,可将Left属性设置为左边距(单位为像素),

否则设置为0[默认值]

Top-如果希望沿顶部裁剪,可将Top属性设置为上边距(单位为像素),

否则设置为0[默认值]

Right-如果希望沿右侧裁剪,可将Right属性设置为右边距(单位为像素),

否则设置为0[默认值]

Bottom-如果希望沿底部裁剪,可将Bottom属性设置为下边距(单位为像素),

否则设置为0[默认值]

FrameIndex-如果希望修改除ActiveFrame之外的帧,

可将FrameIndex属性设置为帧的索引,否则设置为0[默认值]Scale

将图像缩放到指定的最大宽度和最大高度,如有必要,保留纵横比。

MaximumWidth-将MaximumWidth属性设置为希望将图像缩放到的宽度(单位为像素)。

MaximumHeight-将MaximumHeight属性设置为希望将图像缩放到的高度(单位为像素)。

PreserveAspectRatio-如果希望保持图像当前的纵横比,可将PreserveAspectRatio属性设置为True[默认值],

否则设置为False,图像将被拉伸到MaximumWidth和MaximumHeight

FrameIndex-如果希望修改除ActiveFrame之外的帧,可将FrameIndex属性设置为帧的索引,

否则设置为0[默认值]Stamp

在指定的Left和Top坐标处标记指定的ImageFile。

ImageFile-将ImageFile属性设置为希望标记的ImageFile对象

Left-将Left属性设置为希望将ImageFile标记到的从左侧开始的偏移(单位为像素)[默认值为0]

Top-将Top属性设置为希望将ImageFile标记到的从顶部开始的偏移(单位为像素)[默认值为0]

FrameIndex-如果希望修改除ActiveFrame之外的帧,可将FrameIndex属性设置为帧的索引,否则设置为0[默认值]Exif

添加/删除指定的Exif属性。

Remove-如果希望删除指定的Exif属性,可将Remove属性设置为True,否则设置为False[默认值]以添加

指定的exif属性

ID-将ID属性设置为希望添加或删除的PropertyID

Type-设置Type属性以指示希望添加的Exif属性的WiaImagePropertyType(对于删除则忽略)

Value-将Value属性设置为希望添加的Exif属性的值(对于删除则忽略)

FrameIndex-如果希望修改除ActiveFrame之外的帧,可将FrameIndex属性设置为帧的索引,否则设置为0[默认值]Frame

Remove-如果希望删除指定的FrameIndex,可将Remove属性设置为True,

否则设置为False[默认值]以在指定的FrameIndex之前插入ImageFile

ImageFile-将ImageFile属性设置为希望添加其ActiveFrame的ImageFile对象(对于删除则忽略)

FrameIndex-对于删除,将FrameIndex属性设置为希望删除的帧的索引,

对于添加,将FrameIndex设置为要在其之前插入ImageFile的帧的索引,否则设置为0[默认值]

以从指定的ImageFile追加帧ARGB

ARGBData-将ARGBData属性设置为表示指定FrameIndex的ARGB数据的Longs的矢量(宽度和高度必须匹配)

FrameIndex-将FrameIndex属性设置为希望修改其ARGB数据的帧的索引,否则设置为0[默认值]以修改ActiveFrameConvert

将得到的ImageFile转换为指定的类型。

FormatID-将FormatID属性设置为所需支持的光栅图像格式,当前可选择的格式有wiaFormatBMP、

wiaFormatPNG、wiaFormatGIF、wiaFormatJPEG或wiaFormatTIFF

Quality-对于JPEG文件,可将Quality属性设置为从1到100[默认值]之间的任何值,以指定JPEG压缩的质量

Compression-对于TIFF文件,可将Compression属性设置为CCITT3、CCITT4、RLE或Uncompressed以指定压缩方案,

否则可设置为LZW[默认值]小节

总的来说,在c#中利用AutomationLayer中的Filter非常麻烦(要写一堆Object),这些简单的图像处理操作还不如用GDI+来实现。

在C#中使用WIA获取扫描仪数据(四、通过编程方式扫描图像)

在前面几节,我通过调用CommonDialog对象的ShowAcquireImage方法来扫描图像,这是一个弹出选择设备对话框,让用户自己扫描的过程。

有时候,我们不想把过程弄得那么复杂,只想用户点击按钮后,自动开始扫描。

本节我将尝试这个需求。

WIAAL模型

在开始代码前,再回顾以下WIAAL模型,这里选取其中的一小部分:

从上图不难想象,一台扫描仪,实际上就是一个Device对象,因此,我们可以通过DeviceManager来“获取”这台设备的“引用”,然后通过得到的Device对象,执行相应的扫描工作。

从而跳过了使用ShowAcquireImage方法带来的一系列“多余的鼠标操作问题”。

获取Device对象

按照上面思路,首先需要建立一个DeviceManager对象:

DeviceManagermanager=newDeviceManagerClass();然后获取Device对象,在这里,我假设我的电脑上只有一台扫描仪,因此不做诸如“判断使用哪台扫描仪进行扫描”之类的操作。

Devicedevice=null;

foreach(DeviceInfoinfoinmanager.DeviceInfos)

{

if(info.Type!

=WiaDeviceType.ScannerDeviceType)continue;

device=info.Connect();

break;

}扫描图像

WIA把Device设备的图像数据看做一个个Item对象,可以通过方法GetItem(ItemID)来实现。

不过,对于扫描仪做种东西,和数码相机不同,一般只有一个Item对象,因此可以简单的使用数组的方法(注意:

index是从1开始的,而不是从0):

Itemitem=device.Items[1];最后,调用CommonDialog的ShowTransfer方法,用一个进度条,来显示扫描过程:

CommonDialogClasscdc=newWIA.CommonDialogClass();

ImageFileimageFile=cdc.ShowTransfer(item,

"{B96B3CAB-0728-11D3-9D7B-0000F81EF32E}",

true)asImageFile;

if(imageFile!

=null)

{

varbuffer=imageFile.FileData.get_BinaryData()asbyte[];

using(MemoryStreamms=newMemoryStream())

{

ms.Write(buffer,0,buffer.Length);

pictureBox1.Image=Image.FromStream(ms);

}

}关于ShowTransfer方法

CommonDialog的ShowTransfer方法,实际上就是ShowAcquireImage方法的最后一个步骤,显示一个获取图片的进度条:

声明如下:

publicvirtualobjectShowTransfer(ItemItem,stringFormatID,boolCancelError);对于第二个参数,FormatID,可以使用以下值:

wiaFormatBMP({B96B3CAB-0728-11D3-9D7B-0000F81EF32E})

wiaFormatPNG({B96B3CAF-0728-11D3-9D7B-0000F81EF32E})

wiaFormatGIF({B96B3CB0-0728-11D3-9D7B-0000F81EF32E})

wiaFormatJPEG({B96B3CAE-0728-11D3-9D7B-0000F81EF32E})

wiaFormatTIFF({B96B3CB1-0728-11D3-9D7B-0000F81EF32E})

在C#中使用WIA获取扫描仪数据(五、注册事件)

好了,现在我们能在c#里通过编程扫描图像了。

还不满足?

对,在前面的例子里,需要扫描的时候总是要按下一个扫描按钮,既傻又费事。

现在的扫描仪,上面往往会多几个额外的按钮用来和用户交互,例如我是用的HPG2410上就有两个按钮:

扫描及复制。

那么,能不能用这两个按钮来代替程序里的那个难看的按钮呢?

注意左上角那个难看的按钮了吗?

在WIAAL里,我们可以同过注册设备事件,监听事件等方式和设备上的按钮交互。

注册事件

还记得我们在上节提到的DeviceManager对象吗?

MSDN官方文档描述:

TheMicrosoftWindowsImageAcquisition(WIA)DeviceManagerisanextensionoftheStillImage(STI)EventMonitor.TheWIADeviceManagerprovidesobjects,methods,andinterfacesforthefollowing:

Installingdevices

Enumeratingdevices

Queryingpropertiesofinstalleddevices

Creatingdeviceobjects

Monitoringdeviceevents

Acquiringimages

Registeringdestinationapplications.

和传统.Net编程不同,WIA的事件,需要先通过DeviceManager的RegisterEvent的方法注册,才能使用。

RegisterEvent定义如下:

voidRegisterEvent(stringEventID,stringDeviceID);其中,EventID是事件的GUID,DeviceID是扫描仪的GUID。

在类EventID里,WIA定义了几种基本的事件类型,从定义上不难理解这些ID的所代表的具体事件:

publicconststringwiaEventDeviceConnected="{A28BBADE-64B6-11D2-A231-00C04FA31809}";

publicconststringwiaEventDeviceDisconnected="{143E4E83-6497-11D2-A231-00C04FA31809}";

publicconststringwiaEventItemCreated="{4C8F4EF5-E14F-11D2-B326-00C04F68CE61}";

publicconststringwiaEventItemDeleted="{1D22A559-E14F-11D2-B326-00C04F68CE61}";

publicconststringwiaEventScanEmailImage="{C686DCEE-54F2-419E-9A27-2FC7F2E98F9E}";

publicconststringwiaEventScanFaxImage="{C00EB793-8C6E-11D2-977A-0000F87A926F}";

publicconststringwiaEventScanFilmImage="{9B2B662C-6185-438C-B68B-E39EE25E71CB}";

publicconststringwiaEventScanImage="{A6C5A715-8C6E-11D2-977A-0000F87A926F}";

publicconststringwiaEventScanImage2="{FC4767C1-C8B3-48A2-9CFA-2E90CB3D3590}";

publicconststringwiaEventScanImage3="{154E27BE-B617-4653-ACC5-0FD7BD4C65CE}";

publicconststringwiaEventScanImage4="{A65B704A-7F3C-4447-A75D-8A26DFCA1FDF}";

publicconststringwiaEventScanOCRImage="{9D095B89-37D6-4877-AFED-62A297DC6DBE}";

publicconststringwiaEventScanPrintImage="{B441F425-8C6E-11D2-977A-0000F87A926F}";例如,我们可以使用以下来吗来注册一个事件,并监听它:

manager.RegisterEvent(EventID.wiaEventScanImage,device.DeviceID);

manager.OnEvent+=(eventID,deviceID,itemID)=>

{

//…………

}枚举设备事件

如果你向我这般,兴冲冲地在OnEvent里加入扫描处理逻辑,然后按下HPG2410上的扫描按钮,你一定会像我一样,在漫长的等待中渐渐失望:

扫描仪根本没有按我所想的那样扫描图片。

也就是说,wiaEventScanImage这个事件根本不起作用。

幸好能够通过Device类来枚举设备支持的事件,我写了以下一段代码:

Console.WriteLine("Events:

");

foreach(DeviceEventeveindevice.Events)

{

Console.WriteLine("{0}:

{1}:

{2}",eve.EventID,eve.Name,eve.Description);

}运行后,发现该扫描仪仅仅支持wiaEventDeviceConnec

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2