2012-01-10 108 views
4

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

我想使用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的相同代码。

+0

不确定您是否考虑使用商用SDK。使用一些TWAIN控件,您可以在几小时内完成您在几行代码中列出的任务。我的公司有Dynamic Web TWAIN。我建议你尝试一下。 – flysakura 2012-02-13 06:28:44

回答

0

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

+0

当我执行'IWiaItem2 * p = 0; item-> DeviceCommand(0,&WIA_CMD_TAKE_PICTURE,&p);'我得到一个代码为0x80004001的错误消息'not implemented'。我该如何解决这个问题?我发送命令的设备肯定能够扫描文档。 – Pedro 2012-01-13 02:39:48