// This function enumerates items recursively starting from the root item and calls DownloadItem() on those items
// after checking their item types.
// DownloadItem() will only be called on file items. Folder items are recursively enumerated.
HRESULT EnumerateAndDownloadItems( IWiaItem2 *pWiaItem2 )
{
    // Validate arguments
    if (NULL == pWiaItem2)
    {
        HRESULT hr = E_INVALIDARG;
        ReportError(TEXT("Invalid argument passed to EnumerateAndDownloadItems()"),hr);
        return hr;
    }

    // Get the item type for this item
    LONG lItemType = 0;
    HRESULT hr = pWiaItem2->GetItemType( &lItemType );

    // Print the item name.
    PrintItemName( pWiaItem2 );

    //Find the item category
    GUID itemCategory = GUID_NULL;
    ReadPropertyGuid(pWiaItem2,WIA_IPA_ITEM_CATEGORY,&itemCategory );
     
    // If this is an transferrable file(except finished files) , download it.
    // We have deliberately left finished files for simplicity
    if ( (lItemType & WiaItemTypeFile) && (lItemType & WiaItemTypeTransfer) && (itemCategory != WIA_CATEGORY_FINISHED_FILE) )
    {
        hr = DownloadItem( pWiaItem2 );
    }

    // If it is a folder, enumerate its children
    if (lItemType & WiaItemTypeFolder)
    {
        // Get the child item enumerator for this item
        IEnumWiaItem2 *pEnumWiaItem2 = NULL;
        hr = pWiaItem2->EnumChildItems(0, &pEnumWiaItem2 );
        if (SUCCEEDED(hr))
        {
            // We will loop until we get an error or pEnumWiaItem->Next returns
            // S_FALSE to signal the end of the list.
            while (S_OK == hr )
            {
                // Get the next child item
                IWiaItem2 *pChildWiaItem2 = NULL;
                hr = pEnumWiaItem2->Next( 1, &pChildWiaItem2, NULL );

                // pEnumWiaItem->Next will return S_FALSE when the list is
                // exhausted, so check for S_OK before using the returned
                // value.
                if (S_OK == hr)
                {
                    // Recurse into this item
                    EnumerateAndDownloadItems( pChildWiaItem2 );

                    // Release this item
                    pChildWiaItem2->Release();
                    pChildWiaItem2 = NULL;
                }
                else if (FAILED(hr))
                {
                    // Report that an error occurred during enumeration
                    ReportError( TEXT("Error calling pEnumWiaItem2->Next"), hr );
                }
            }

            // If the result of the enumeration is S_FALSE, since this
            // is normal, we will change it to S_OK
            if (S_FALSE == hr)
            {
                hr = S_OK;
            }

            // Release the enumerator
            pEnumWiaItem2->Release();
            pEnumWiaItem2 = NULL;
        }
        else
        {
            ReportError(TEXT("pWiaItem2->EnumChildItems() failed"),hr);
        }
    }
    return  hr;
}
示例#2
0
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;
}
// This function downloads item after setting the format for the item and initializing callback (depending on category,itemtype)
// with the directory to download images to as well as the filename for the downloaded image.
HRESULT DownloadItem(IWiaItem2* pWiaItem2)
{
    if( (!pWiaItem2) )
    {
        HRESULT hr = E_INVALIDARG;
        ReportError(TEXT("Invalid argument passed to DownloadItem()"),hr);
        return hr;
    }
     // Get the IWiaTransfer interface
    IWiaTransfer *pWiaTransfer = NULL;
    HRESULT hr = pWiaItem2->QueryInterface( IID_IWiaTransfer, (void**)&pWiaTransfer );
    if (SUCCEEDED(hr))
    {
        // Create our callback class
        CWiaTransferCallback *pWiaClassCallback = new CWiaTransferCallback;
        if (pWiaClassCallback)
        {
            // Get the IWiaTransferCallback interface from our callback class.
            IWiaTransferCallback *pWiaTransferCallback = NULL;
            hr = pWiaClassCallback->QueryInterface( IID_IWiaTransferCallback, (void**)&pWiaTransferCallback );
            if (SUCCEEDED(hr))
            {
                //Set the format for the item to BMP
                IWiaPropertyStorage* pWiaPropertyStorage = NULL;
                HRESULT hr = pWiaItem2->QueryInterface( IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage );
                if(SUCCEEDED(hr))
                {
                    hr = WritePropertyGuid(pWiaPropertyStorage,WIA_IPA_FORMAT,WiaImgFmt_BMP);
                    if(FAILED(hr))
                    {
                        ReportError(TEXT("WritePropertyGuid() failed in DownloadItem().Format couldn't be set to BMP"),hr);
                    }
           
                    //Get the file extension and initialize callback with this extension and directory in which to transfer image 
                    //along with feeder flag.
                    //This will result in m_szFileName member callback class being set on which GetNextStream() will create and return a stream 
                    BSTR bstrFileExtension = NULL;
                    ReadPropertyBSTR(pWiaPropertyStorage,WIA_IPA_FILENAME_EXTENSION, &bstrFileExtension);
            
                    //Get the temporary folder path which is the directory where we will download the images
                    TCHAR bufferTempPath[MAX_TEMP_PATH];
                    GetTempPath(MAX_TEMP_PATH , bufferTempPath);
            
                    // Find out item type
                    GUID itemCategory = GUID_NULL;
                    ReadPropertyGuid(pWiaItem2,WIA_IPA_ITEM_CATEGORY,&itemCategory );
                    
                    BOOL bFeederTransfer = FALSE;
                    
                    if(IsEqualGUID(itemCategory,WIA_CATEGORY_FEEDER))
                    {
                        //Set WIA_IPS_PAGES to ALL_PAGES will enable transfer of all pages in the document feeder (multi-page transfer).
                        //If somebody wants to scan a specific number of pages say N, he should set WIA_IPS_PAGES to N. 
                        WritePropertyLong(pWiaPropertyStorage,WIA_IPS_PAGES,ALL_PAGES);
                         
                        bFeederTransfer = TRUE;
            
                    }

                    //Initialize the callback class with the directory, file extension and feeder flag
                    pWiaClassCallback->InitializeCallback(bufferTempPath,bstrFileExtension,bFeederTransfer);
                    
                    //Now download file item
                    hr = pWiaTransfer->Download(0,pWiaTransferCallback);
                    if(S_OK == hr)
                    {
                        _tprintf(TEXT("\npWiaTransfer->Download() on file item SUCCEEDED"));
                    }
                    else if(S_FALSE == hr)
                    {
                        ReportError(TEXT("pWiaTransfer->Download() on file item returned S_FALSE. File may be empty"),hr);
                    }
                    else if(FAILED(hr))
                    {
                        ReportError(TEXT("pWiaTransfer->Download() on file item failed"),hr);
                    }
            
                    //Release pWiaPropertyStorage interface
                    pWiaPropertyStorage->Release();
                    pWiaPropertyStorage = NULL;
                }
                else
                {
                    ReportError(TEXT("QueryInterface failed on IID_IWiaPropertyStorage"),hr);
                }

                // Release the callback interface
                pWiaTransferCallback->Release();
                pWiaTransferCallback = NULL;
            }
            else
            {
                ReportError( TEXT("pWiaClassCallback->QueryInterface failed on IID_IWiaTransferCallback"), hr );
            }
            // Release our callback.  It should now delete itself.
            pWiaClassCallback->Release();
            pWiaClassCallback = NULL;
        }
        else
        {
            ReportError( TEXT("Unable to create CWiaTransferCallback class instance") );
        }
            
        // Release the IWiaTransfer
        pWiaTransfer->Release();
        pWiaTransfer = NULL;
    }
    else
    {
        ReportError( TEXT("pIWiaItem2->QueryInterface failed on IID_IWiaTransfer"), hr );
    }
    return hr;
}
HRESULT WIACamera::DigitalCameraCapture(IWiaItem* pIWiaRoot, IplImage** ppIplImage)
{
	HRESULT hr = S_OK;

	IWiaItem* pIWiaItem = NULL;
	hr = pIWiaRoot->DeviceCommand( 0, &WIA_CMD_TAKE_PICTURE, &pIWiaItem );

	if (pIWiaItem==NULL) {
		cvReleaseImage(ppIplImage);
		(*ppIplImage) = NULL;
		return hr;
	}
	IStream **ppStream = NULL;
	LONG	lCount = 0;
	// Create the data callback interface
	CDataCallback *pDataCallback = new CDataCallback( &lCount,&ppStream );
	if (pDataCallback == NULL) {
		return E_OUTOFMEMORY;
	}

	{
		// Get the interface pointers
		IWiaPropertyStorage *pWiaPropertyStorage;
		hr = pIWiaItem->QueryInterface(IID_IWiaPropertyStorage,(void**)&pWiaPropertyStorage);
		if (hr != S_OK) {
			return E_NOINTERFACE;
		}

		IWiaDataTransfer *pIWiaDataTransfer;
		hr = pIWiaItem->QueryInterface(IID_IWiaDataTransfer, (void**)&pIWiaDataTransfer);
		if (hr != S_OK) {
			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;
		GUID *pguidFormat = &guidFormat;
		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;
		PROPVARIANT varFormat;
		specFormat.ulKind = PRSPEC_PROPID;
		specFormat.propid = WIA_IPA_FORMAT;
		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 (pWiaPropertyStorage) {
			pWiaPropertyStorage->Release();
			pWiaPropertyStorage = NULL;
		}
		if (pIWiaDataTransfer) {
			pIWiaDataTransfer->Release();
			pIWiaDataTransfer = NULL;
		}
	}
	if (pIWiaItem) {
		// Delete file from DigitalCamera storage
		pIWiaItem->DeleteItem(0);
		pIWiaItem->Release();
		pIWiaItem = NULL;
	}

	if (lCount!=1) throw "Error.\n"; 

	if ( SUCCEEDED(hr) ) { 
		Gdiplus::Bitmap myBmp(ppStream[0]);
		int Width = myBmp.GetWidth();
		int Height = myBmp.GetHeight();
		Gdiplus::Rect rect(0, 0, Width, Height);
		Gdiplus::BitmapData myBitmapData;
		Gdiplus::Status res = 
			myBmp.LockBits(
			&rect, Gdiplus::ImageLockModeRead,
			PixelFormat24bppRGB, &myBitmapData
		);
		if ( (*ppIplImage)==NULL ) {
			(*ppIplImage) = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_8U,3);
		} else {
			CvSize oldSize = cvGetSize((*ppIplImage));
			if ( oldSize.width!=Width || oldSize.height!=Height ) {
				throw "Warning.\n";
				cvReleaseImage(&(*ppIplImage));
				(*ppIplImage) = cvCreateImage(cvSize(Width,Height),IPL_DEPTH_8U,3);
			}
		}

		unsigned char *pIplData = (unsigned char*)(*ppIplImage)->imageData;
		for ( int h=0; h < Height; h++) {
			unsigned char *pIplLine = &pIplData[(*ppIplImage)->widthStep*h];
			unsigned char *pBitmapLine = &((unsigned char*)myBitmapData.Scan0)[myBitmapData.Stride*h];
			memcpy( pIplLine, pBitmapLine, sizeof(unsigned char)*Width*3 );
			/*
			for ( int w=0; w < Width; w++) {
				pIplLine[w*3+0] = pBitmapLine[w*3+2];
				pIplLine[w*3+1] = pBitmapLine[w*3+1];
				pIplLine[w*3+2] = pBitmapLine[w*3+0];
			}
			*/
		}

	} else {
		delete (*ppIplImage);
		(*ppIplImage) = NULL;
	}
	ppStream[0]->Release();

	return hr;
}