HRESULT WIACamera::VideoCameraCapture(IWiaItem* pIWiaRoot, IplImage** ppIplImage) { static int COUNTER = 0; COUNTER++; HRESULT hr = S_OK; if (pIWiaRoot==NULL) { cvReleaseImage(ppIplImage); (*ppIplImage) = NULL; return hr; } IWiaPropertyStorage *pIWiaPropStg = NULL; // Get the next WIA device hr = pIWiaRoot->QueryInterface(IID_IWiaPropertyStorage,(void**)&pIWiaPropStg); if (SUCCEEDED(hr)) { // Get the device type of the device PROPSPEC PropSpec[3]; PROPVARIANT PropVar[3]; memset(PropVar,0,sizeof(PropVar)); PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_DIP_DEV_ID; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_DIP_DEV_TYPE; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_DPV_IMAGES_DIRECTORY; // Get the type and the ID of each device hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC), PropSpec, PropVar); WORD myDev = GET_STIDEVICE_TYPE(PropVar[1].lVal); if (SUCCEEDED(hr)) { hr = m_pWiaVideo->put_ImagesDirectory(PropVar[2].bstrVal); } if (SUCCEEDED(hr)) { hr = m_pWiaVideo->put_PreviewVisible(FALSE); hr = m_pWiaVideo->CreateVideoByWiaDevID(PropVar[0].bstrVal, NULL, FALSE, TRUE); } } // // Take a picture. When this function returns, WIA Video will have already // captured a still image from the video stream, and it saved the image in // the 'FileName' file. // BSTR bstrFileName = NULL; if (SUCCEEDED(hr)) { Sleep(2000); hr = m_pWiaVideo->TakePicture(&bstrFileName); } if (SUCCEEDED(hr)) { cvReleaseImage(ppIplImage); // Convert to a char* const int BUFFER_SIZE = 4096; char filepath[BUFFER_SIZE]; _bstr_t bstrIntermediate(bstrFileName); // convert to // _bstr_t // you have to go through _bstr_t to have it work in ANSI // and Unicode sprintf_s(filepath, BUFFER_SIZE, "%s", (LPCTSTR)bstrIntermediate); (*ppIplImage) = cvLoadImage((char*)filepath); } return hr; }
HRESULT WiaGetImage( HWND hWndParent, LONG lDeviceType, LONG lFlags, LONG lIntent, IWiaDevMgr *pSuppliedWiaDevMgr, IWiaItem *pSuppliedItemRoot, PFNPROGRESSCALLBACK pfnProgressCallback, PVOID pProgressCallbackParam, GUID *pguidFormat, LONG *plCount, IStream ***pppStream ) { HRESULT hr; // Validate and initialize output parameters if (plCount == NULL) { return E_POINTER; } if (pppStream == NULL) { return E_POINTER; } *plCount = 0; *pppStream = NULL; // Initialize the local root item variable with the supplied value. // If no value is supplied, display the device selection common dialog. CComPtr<IWiaItem> pItemRoot = pSuppliedItemRoot; if (pItemRoot == NULL) { // Initialize the device manager pointer with the supplied value // If no value is supplied, connect to the local device manager CComPtr<IWiaDevMgr> pWiaDevMgr = pSuppliedWiaDevMgr; if (pWiaDevMgr == NULL) { hr = pWiaDevMgr.CoCreateInstance(CLSID_WiaDevMgr); if (FAILED(hr)) { return hr; } } // Display the device selection common dialog hr = pWiaDevMgr->SelectDeviceDlg( hWndParent, lDeviceType, lFlags, 0, &pItemRoot ); if (FAILED(hr) || hr == S_FALSE) { return hr; } } // Display the image selection common dialog CComPtrArray<IWiaItem> ppIWiaItem; hr = pItemRoot->DeviceDlg( hWndParent, lFlags, lIntent, &ppIWiaItem.Count(), &ppIWiaItem ); if (FAILED(hr) || hr == S_FALSE) { return hr; } // For ADF scanners, the common dialog explicitly sets the page count to one. // So in order to transfer multiple images, set the page count to ALL_PAGES // if the WIA_DEVICE_DIALOG_SINGLE_IMAGE flag is not specified, if (!(lFlags & WIA_DEVICE_DIALOG_SINGLE_IMAGE)) { // Get the property storage interface pointer for the root item CComQIPtr<IWiaPropertyStorage> pWiaRootPropertyStorage(pItemRoot); if (pWiaRootPropertyStorage == NULL) { return E_NOINTERFACE; } // Determine if the selected device is a scanner or not PROPSPEC specDevType; specDevType.ulKind = PRSPEC_PROPID; specDevType.propid = WIA_DIP_DEV_TYPE; LONG nDevType; hr = ReadPropertyLong( pWiaRootPropertyStorage, &specDevType, &nDevType ); if (SUCCEEDED(hr) && (GET_STIDEVICE_TYPE(nDevType) == StiDeviceTypeScanner)) { // Determine if the document feeder is selected or not PROPSPEC specDocumentHandlingSelect; specDocumentHandlingSelect.ulKind = PRSPEC_PROPID; specDocumentHandlingSelect.propid = WIA_DPS_DOCUMENT_HANDLING_SELECT; LONG nDocumentHandlingSelect; hr = ReadPropertyLong( pWiaRootPropertyStorage, &specDocumentHandlingSelect, &nDocumentHandlingSelect ); if (SUCCEEDED(hr) && (nDocumentHandlingSelect & FEEDER)) { PROPSPEC specPages; specPages.ulKind = PRSPEC_PROPID; specPages.propid = WIA_DPS_PAGES; PROPVARIANT varPages; varPages.vt = VT_I4; varPages.lVal = ALL_PAGES; pWiaRootPropertyStorage->WriteMultiple( 1, &specPages, &varPages, WIA_DPS_FIRST ); PropVariantClear(&varPages); } } } // If a status callback function is not supplied, use the default. // The default displays a simple dialog with a progress bar and cancel button. CComPtr<CProgressDlg> pProgressDlg; if (pfnProgressCallback == NULL) { pfnProgressCallback = DefaultProgressCallback; pProgressDlg = new CProgressDlg(hWndParent); pProgressCallbackParam = (CProgressDlg *) pProgressDlg; } // Create the data callback interface CComPtr<CDataCallback> pDataCallback = new CDataCallback( pfnProgressCallback, pProgressCallbackParam, plCount, pppStream ); if (pDataCallback == NULL) { return E_OUTOFMEMORY; } // Start the transfer of the selected items for (int i = 0; i < ppIWiaItem.Count(); ++i) { // Get the interface pointers CComQIPtr<IWiaPropertyStorage> pWiaPropertyStorage(ppIWiaItem[i]); if (pWiaPropertyStorage == NULL) { return E_NOINTERFACE; } CComQIPtr<IWiaDataTransfer> pIWiaDataTransfer(ppIWiaItem[i]); if (pIWiaDataTransfer == NULL) { return E_NOINTERFACE; } // Set the transfer type PROPSPEC specTymed; specTymed.ulKind = PRSPEC_PROPID; specTymed.propid = WIA_IPA_TYMED; PROPVARIANT varTymed; varTymed.vt = VT_I4; varTymed.lVal = TYMED_CALLBACK; hr = pWiaPropertyStorage->WriteMultiple( 1, &specTymed, &varTymed, WIA_IPA_FIRST ); PropVariantClear(&varTymed); if (FAILED(hr)) { return hr; } // If there is no transfer format specified, use the device default GUID guidFormat = GUID_NULL; if (pguidFormat == NULL) { pguidFormat = &guidFormat; } if (*pguidFormat == GUID_NULL) { PROPSPEC specPreferredFormat; specPreferredFormat.ulKind = PRSPEC_PROPID; specPreferredFormat.propid = WIA_IPA_PREFERRED_FORMAT; hr = ReadPropertyGuid( pWiaPropertyStorage, &specPreferredFormat, pguidFormat ); if (FAILED(hr)) { return hr; } } // Set the transfer format PROPSPEC specFormat; specFormat.ulKind = PRSPEC_PROPID; specFormat.propid = WIA_IPA_FORMAT; PROPVARIANT varFormat; varFormat.vt = VT_CLSID; varFormat.puuid = (CLSID *) CoTaskMemAlloc(sizeof(CLSID)); if (varFormat.puuid == NULL) { return E_OUTOFMEMORY; } *varFormat.puuid = *pguidFormat; hr = pWiaPropertyStorage->WriteMultiple( 1, &specFormat, &varFormat, WIA_IPA_FIRST ); PropVariantClear(&varFormat); if (FAILED(hr)) { return hr; } // Read the transfer buffer size from the device, default to 64K PROPSPEC specBufferSize; specBufferSize.ulKind = PRSPEC_PROPID; specBufferSize.propid = WIA_IPA_BUFFER_SIZE; LONG nBufferSize; hr = ReadPropertyLong( pWiaPropertyStorage, &specBufferSize, &nBufferSize ); if (FAILED(hr)) { nBufferSize = 64 * 1024; } // Choose double buffered transfer for better performance WIA_DATA_TRANSFER_INFO WiaDataTransferInfo = { 0 }; WiaDataTransferInfo.ulSize = sizeof(WIA_DATA_TRANSFER_INFO); WiaDataTransferInfo.ulBufferSize = 2 * nBufferSize; WiaDataTransferInfo.bDoubleBuffer = TRUE; // Start the transfer hr = pIWiaDataTransfer->idtGetBandedData( &WiaDataTransferInfo, pDataCallback ); if (FAILED(hr) || hr == S_FALSE) { return hr; } } return S_OK; }
HRESULT WIACamera::Initialize() { // CoInitialize(NULL); CoInitializeEx(NULL, COINIT_MULTITHREADED); IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL; // // Create an instance of the device manager // HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&m_pWiaDevMgr ); hr = CoCreateInstance(CLSID_WiaVideo, NULL, CLSCTX_INPROC_SERVER, IID_IWiaVideo, (void**) &m_pWiaVideo); if (SUCCEEDED(hr)) { // // Enumerate WIA devices on the system // hr = m_pWiaDevMgr->EnumDeviceInfo(WIA_DEVINFO_ENUM_LOCAL, &pWiaEnumDevInfo); } // // Reset the enumeration to start at the beginning of the list. // if (SUCCEEDED(hr)) { // // Call Reset on Enumerator // hr = pWiaEnumDevInfo->Reset(); } BOOL bFound = FALSE; while ( SUCCEEDED(hr) ) { IWiaPropertyStorage *pIWiaPropStg = NULL; ULONG ulFetched = NULL; // // Get the next WIA device // hr = pWiaEnumDevInfo->Next(1, &pIWiaPropStg, &ulFetched); if (hr == S_OK) { // // Get the device type of the device // PROPSPEC PropSpec[3]; PROPVARIANT PropVar[3]; memset(PropVar,0,sizeof(PropVar)); PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = WIA_DIP_DEV_ID; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = WIA_DIP_DEV_TYPE; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = WIA_DIP_DEV_NAME; // // Get the type and the ID of each device // hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC), PropSpec, PropVar); // // If the device is a streaming video device/digital camera, // get its ID // if (GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeStreamingVideo || GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeDigitalCamera) { std::wcerr << "WIA_DIP_DEV_ID :\t" << PropVar[0].bstrVal << std::endl << "WIA_DIP_DEV_NAME :\t" << PropVar[2].bstrVal << std::endl; bFound = TRUE; const size_t BUFFER_SIZE = 1024; char buf[BUFFER_SIZE]; _bstr_t bstrIntermediate; bstrIntermediate.Assign(PropVar[0].bstrVal); sprintf_s((char*)buf, BUFFER_SIZE, "%s", (LPCTSTR)bstrIntermediate); char* strID = new char [strlen(buf)+1]; strcpy_s( strID, strlen(buf)+1, buf ); m_vCameraID.push_back(strID); bstrIntermediate.Assign(PropVar[2].bstrVal); sprintf_s((char*)buf, BUFFER_SIZE, "%s", (LPCTSTR)bstrIntermediate); char* strName = new char [strlen(buf)+1]; strcpy_s( strID, strlen(buf)+1, buf ); m_vCameraName.push_back(strName); delete [] strID; delete [] strName; // // Create a WIA device and get the recommended // images directory // IWiaItem *pRootItem = NULL; hr = m_pWiaDevMgr->CreateDevice(PropVar[0].bstrVal, &pRootItem); if (GET_STIDEVICE_TYPE(PropVar[1].lVal) == StiDeviceTypeStreamingVideo) { // ビデオカメラ特有の処理 m_pCaptureFunc.push_back( &WIACamera::VideoCameraCapture ); } else { // デジタルカメラ特有の処理 m_pCaptureFunc.push_back( &WIACamera::DigitalCameraCapture ); } if (SUCCEEDED(hr)) { m_vRootItem.push_back(pRootItem); } else { m_vRootItem.push_back(NULL); throw "Error:\n"; return hr; } } } else { break; } if (pIWiaPropStg) { pIWiaPropStg->Release(); pIWiaPropStg = NULL; } } if (pWiaEnumDevInfo) { pWiaEnumDevInfo->Release(); pWiaEnumDevInfo = NULL; } if (!bFound) { // // We did not find any WIA video streaming devices. There is nothing left // to do. Set result to E_FAIL // hr = E_FAIL; return hr; } m_iCount = (unsigned int)m_vRootItem.size(); // // Return the result of creating the device manager // return hr; }