使用 WIA 或 TWAIN 扫描页面

Posted

技术标签:

【中文标题】使用 WIA 或 TWAIN 扫描页面【英文标题】:scanning pages using WIA or TWAIN 【发布时间】:2012-02-07 09:35:52 【问题描述】:

编辑:是否有关于如何在 c++ 中使用 WIA 或 TWAIN 的教程,解释如何扫描页面、调整设置(DPI、使用自动进纸器等)并将它们保存为 PNG 文件?

我想使用 WIA 扫描页面并将它们存储为 png 文件。如果扫描仪支持自动进纸,我也想使用该功能。目前我正在按照this 教程的步骤进行操作,并被困在Transferring Image Data in WIA 2.0 部分。

到目前为止,我的扫描仪已经找到并且我能够创建设备,并且已经创建了 IWiaItem2*。如何使用它以 300dpi 进行扫描并将结果存储为 png 文件?

教程不清楚如何启动扫描过程或如何设置扫描的dpi,所以希望有人能帮我写代码。

这实质上是获取所有本地设备的代码:

bool init(IWiaDevMgr2* devMgr)

    //creating the device manager
    *devMgr = 0; 
    CoCreateInstance( CLSID_WiaDevMgr2, 0, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr2, (void**)&devMgr); 

    //enumerating wia devices
    IEnumWIA_DEV_INFO* enumDevInfo = 0; 
    HRESULT hr = devMgr->EnumDeviceInfo( WIA_DEVINFO_ENUM_LOCAL, &enumDevInfo); 

    if(SUCCEEDED(hr))
    
        //loop until an error occurs or end of list
        while(hr == S_OK)
        
            IWiaPropertyStorage* storage = 0; 
            hr = enumDevInfo->Next( 1, &storage, 0); 

            if(hr == S_OK)
            
                readProperties(storage); 
                storage->Release(); 
                storage = 0; 
            
        

        //set hr to ok, so no error code is returned
        if(hr == S_FALSE) hr = S_OK; 

        enumDevInfo->Release();
        enumDevInfo = 0; 
    
    return SUCCEEDED(hr); 


void readProperties(IWiaPropertyStorage* storage)

    PROPSPEC propSpec[2] = 0;
    PROPVARIANT propVar[2] = 0;

    const ULONG propCount = sizeof(propSpec) / sizeof(propSpec[0]); 

    propSpec[0].ulKind = PRSPEC_PROPID;
    propSpec[0].propid = WIA_DIP_DEV_ID; 

    propSpec[1].ulKind = PRSPEC_PROPID; 
    propSpec[1].propid = WIA_DIP_DEV_NAME; 

    HRESULT hr = storage->ReadMultiple(propCount, propSpec, propVar); 

    if(SUCCEEDED(hr))
    
        Device* dev = new Device(propVar[0].bstrVal, propVar[1].bstrVal); 
        devices.push_back( dev ); 
        FreePropVariantArray( propCount, propVar ); 
    

然后设备被初始化如下:

bool createDevice(BSTR id, IWiaItem2** item)

*item = 0; 
HRESULT hr = devMgr->CreateDevice( 0, deviceId, item); 
return SUCCEEDED(hr); 

然后枚举项:

bool enumerateItems(IWiaItem2* item)

    LONG itemType = 0; 
    HRESULT hr = item->GetItemType(&itemType); 

    if(SUCCEEDED(hr))
    
        if(itemType & WiaItemTypeFolder || itemType & WiaItemTypeHasAttachments)
        
            IEnumWiaItem2* enumItem = 0; 
            hr = item->EnumChildItems(0, &enumItem );

            while(hr == S_OK)
            
                IWiaItem2* child = 0; 
                hr = enumItem->Next( 1, &child, 0 ); 

                if(hr == S_OK)
                
                    hr = enumerateItems( child ); 

                    child->Release();
                    child = 0; 
                
            

            if(hr == S_FALSE) hr = S_OK; 

            enumItem->Release(); 
            enumItem = 0; 
        
    

    return SUCCEEDED(hr); 

现在一切都已初始化,我想实现一个扫描功能。但是,教程中提供的代码用于传输文件和文件夹,而不是用于扫描图像。

void scanAndSaveAsPNG(IWiaItem2* item, unsigned int dpi, std::string targetPath)



编辑: 我安装了最新版本的扫描仪驱动程序(WIA 和 TWAIN),并在使用此代码检查支持的命令后

void printCommands(IWiaItem2* i)

    IEnumWIA_DEV_CAPS* caps = 0; 
    HRESULT h = item->EnumDeviceCapabilities(WIA_DEVICE_COMMANDS, &caps);  

    if(SUCCEEDED(h))
    
        ULONG count = 0;
        caps->GetCount(&count); 

        if(count > 0)
        
            WIA_DEV_CAP* cap = new WIA_DEV_CAP[ count ]; 
            ULONG fetched; 
            caps->Next(count, cap, &fetched); 

            for(int i = 0; i < fetched; i++)
            
                std::cout << bstr_t( cap[i].bstrName ) << "\n"; 
            
        

        caps->Release();
    

我注意到它只列出了WIA Synchronize command。我不确定我是否没有正确初始化设备,或者即使安装了驱动程序,设备是否不支持所有 WIA 命令。

所以除非这个问题得到解决,否则我也会寻找基于 TWAIN 的相同代码。

【问题讨论】:

不确定您是否考虑过使用商业 SDK。使用一些 TWAIN 控件,您可以在 1 小时内完成您在几行代码中列出的任务。我的公司有 Dynamic Web TWAIN。我建议你试试看。 在此处查看 VBS 示例 ru.***.com/a/1024162/17974 【参考方案1】:

您想使用IWiaItem2::DeviceCommand 向图像捕获设备发送命令。您可以发送的命令列表列在here。

【讨论】:

当我执行 IWiaItem2* p = 0; item-&gt;DeviceCommand(0, &amp;WIA_CMD_TAKE_PICTURE, &amp;p); 时,我收到代码 0x80004001 的错误消息“未实现”。我该如何解决?我发送命令的设备肯定能够扫描文档。

以上是关于使用 WIA 或 TWAIN 扫描页面的主要内容,如果未能解决你的问题,请参考以下文章

文档扫描:TWAIN、WIA、ISIS 还是 SANE?

需要信息 TWAIN 和 WIA 驱动程序来扫描 C# 中的图像?

C# 应用程序的 WIA/TWAIN 包装器类? [关闭]

在 WIA 2.0 中扫描时设置页面大小

设置 TWAIN 扫描的分辨率

使用 WIA 2.0 和 C# 扫描多页时跳过的页面