2012-01-10 105 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