Edit: are there any guides on using WIA or TWAIN in C ++ that explain how to scan pages, adjust settings (DPI using automatic feeder, etc.) and save them as PNG files?
I would like to use WIA to scan pages and save them as png files. If the scanner supports automatic feed, I would also like to use this feature. I am currently following the steps of this tutorial and am stuck in the Transferring Image Data in WIA 2.0 section.
So far, my scanner has been found, and I can create a device, and IWiaItem2* was created. How to use it to scan at 300 dpi and save the result as a png file?
The manual does not indicate how to start the scanning process or how to configure dpi for scanning, so I hope someone can help me with the code.
This is essentially the code to get all local devices:
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 ); } }
Then the device is initialized as follows:
bool createDevice(BSTR id, IWiaItem2** item) { *item = 0; HRESULT hr = devMgr->CreateDevice( 0, deviceId, item); return SUCCEEDED(hr); }
Then the items are listed:
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); }
Now that everything has been initialized, I would like to implement a scan function. However, the code provided in the tutorial is for transferring files and folders, not for scanning images.
void scanAndSaveAsPNG(IWiaItem2* item, unsigned int dpi, std::string targetPath) { }
EDIT: I installed the latest scanner driver (WIA and TWAIN) and checked the supported commands with this code
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(); } }
I noticed that it only lists the WIA Synchronize command . I'm not sure if I initialized the device correctly, or if the device does not support all WIA commands, although the driver is installed.
Therefore, if this problem is not resolved, I am also looking for the same TWAIN-based code.