使用WIA或TWAIN扫描页面

scanning pages using WIA or TWAIN

本文关键字:扫描 TWAIN WIA 使用      更新时间:2023-10-16

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

我想使用WIA扫描页面并将其存储为png文件。如果扫描仪支持自动进纸,我也想使用这个功能。目前,我正在遵循本教程的步骤,并停留在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的相同代码。

您想要使用IWiaItem2::DeviceCommand,它向图像捕获设备发送命令。此处列出了您可以发送的命令列表。