在 WIA 2.0 中传输图像数据
注意
本教程演示如何在 Windows Vista 或更高版本上运行的应用程序中传输图像数据。 有关在 Windows XP 或更早版本上运行的应用程序中传输图像数据的信息,请参阅在 WIA 1.0 中传输图像数据。
由于映像数据传输在 Windows 映像采集 (WIA) 2.0 中基于流,因此无需指定目标类型 (例如内存或文件) 。 应用程序只是为 WIA 2.0 提供要使用的流,驱动程序将读取或写入流。 该流可以是文件流、内存流或任何其他类型的流,并且对驱动程序是透明的。 使用流还可以轻松与图像处理筛选器集成。
使用 IWiaTransfer 接口的方法将数据从 WIA 2.0 设备传输到应用程序。 此接口通过 IWiaItem2 接口提供。 IWiaTransfer 接口具有用于请求在设备中上传或下载数据的方法。 这些方法采用应用程序提供的回调,并使用应用程序提供的 IStream 作为数据传输的实际目标。
应用程序必须查询图像项以获取指向其 IWiaTransfer 接口的 指针,如以下代码示例所示:
// Get the IWiaTransfer interface
//
IWiaTransfer *pWiaTransfer = NULL;
hr = pIWiaItem2->QueryInterface(IID_IWiaTransfer,(void**)&pWiaTransfer);
在前面的代码中,我们假定 pWiaItem2 是指向 IWiaItem2 接口的有效指针。 对 IUnknown::QueryInterface 的调用使用指向 pWiaItem2 引用的项的 IWiaTransfer 接口的指针填充 pWiaTransfer。
然后,应用程序实例化回调对象,如下所示。
// Instantiate the object which receives the callbacks
//
CWiaTransferCallback *pWiaClassCallback = new CWiaTransferCallback;
接下来,应用程序使用 IWiaItem2 项的 IWiaPropertyStorage 接口设置属性,并执行传输。
下载:
// Download
hr = pWiaTransfer->Download(0,pWiaClassCallback);
上传:
//Create child item which eventually will be the uploaded image
IWiaItem2* pWiaItemChild = NULL;
HRESULT hr = pIWiaItem2->CreateChildItem(WiaItemTypeImage|WiaItemTypeFile,0,bzUploadFileName,&pWiaItemChild);
if(SUCCEEDED(hr))
{
//Set the format for the child item as BMP
IWiaPropertyStorage* pWiaChildPropertyStorage = NULL;
hr = pWiaItemChild->QueryInterface( IID_IWiaPropertyStorage, (void**)&pWiaChildPropertyStorage );
if(SUCCEEDED(hr))
{
WritePropertyGuid(pWiaChildPropertyStorage,WIA_IPA_FORMAT,WiaImgFmt_BMP );
//release pWiaChildPropertyStorage
pWiaChildPropertyStorage->Release();
pWiaChildPropertyStorage = NULL;
}
//Get the IWiaTransfer interface of the child
IWiaTransfer* pWiaTransferChild = NULL;
hr = pWiaItemChild->QueryInterface( IID_IWiaTransfer, (void**)&pWiaTransferChild );
if(SUCCEEDED(hr)){
IStream* pUploadStream = NULL;
//Create stream on test.BMP file
hr = SHCreateStreamOnFile(L"test.BMP",STGM_READ, &pUploadStream);
if(SUCCEEDED(hr)){
pWiaTransferChild->Upload(0,pUploadStream,pWiaClassCallback);
}
}
}
下面是完整的数据传输示例:
HRESULT TransferWiaItem( IWiaItem2 *pIWiaItem2)
{
// Validate arguments
if (NULL == pIWiaItem2)
{
_tprintf(TEXT("\nInvalid parameters passed"));
return E_INVALIDARG;
}
// Get the IWiaTransfer interface
IWiaTransfer *pWiaTransfer = NULL;
HRESULT hr = pIWiaItem2->QueryInterface( IID_IWiaTransfer, (void**)&pWiaTransfer );
if (SUCCEEDED(hr))
{
// Create our callback class
CWiaTransferCallback *pWiaClassCallback = new CWiaTransferCallback;
if (pWiaClassCallback)
{
LONG lItemType = 0;
hr = pIWiaItem2->GetItemType( &lItemType );
//download all items which have WiaItemTypeTransfer flag set
if(lItemType & WiaItemTypeTransfer)
{
// If it is a folder, do folder download . Hence with one API call, all the leaf nodes of this folder
// will be transferred
if ((lItemType & WiaItemTypeFolder))
{
_tprintf ( L"\nI am a folder item");
hr = pWiaTransfer->Download(WIA_TRANSFER_ACQUIRE_CHILDREN, pWiaClassCallback);
if(S_OK == hr)
{
_tprintf(TEXT("\npWiaTransfer->Download() on folder item SUCCEEDED"));
}
else if(S_FALSE == hr)
{
ReportError(TEXT("\npWiaTransfer->Download() on folder item returned S_FALSE. Folder may not be having child items"),hr);
}
else if(FAILED(hr))
{
ReportError(TEXT("\npWiaTransfer->Download() on folder item failed"),hr);
}
}
// If this is an file type, do file download
else if (lItemType & WiaItemTypeFile )
{
hr = pWiaTransfer->Download(0,pWiaClassCallback);
if(S_OK == hr)
{
_tprintf(TEXT("\npWiaTransfer->Download() on file item SUCCEEDED"));
}
else if(S_FALSE == hr)
{
ReportError(TEXT("\npWiaTransfer->Download() on file item returned S_FALSE. File may be empty"),hr);
}
else if(FAILED(hr))
{
ReportError(TEXT("\npWiaTransfer->Download() on file item failed"),hr);
}
}
}
// Release our callback. It should now delete itself.
pWiaClassCallback->Release();
pWiaClassCallback = NULL;
}
else
{
ReportError( TEXT("\nUnable to create CWiaTransferCallback class instance") );
}
// Release the IWiaTransfer
pWiaTransfer->Release();
pWiaTransfer = NULL;
}
else
{
ReportError( TEXT("\npIWiaItem2->QueryInterface failed on IID_IWiaTransfer"), hr );
}
return hr;
}
// Callback Class should be something like this:
class CWiaTransferCallback : public IWiaTransferCallback
{
public: // Constructors, destructor
CWiaTransferCallback () : m_cRef(1) {};
~ CWiaTransferCallback () {};
public: // IWiaTransferCallback
HRESULT __stdcall TransferCallback(
LONG lFlags,
WiaTransferParams *pWiaTransferParams)
{
HRESULT hr = S_OK;
switch (pWiaTransferParams->lMessage)
{
case WIA_TRANSFER_MSG_STATUS:
...
break;
case WIA_TRANSFER_MSG_END_OF_STREAM:
...
break;
case WIA_TRANSFER_MSG_END_OF_TRANSFER:
...
break;
default:
break;
}
return hr;
}
HRESULT __stdcall GetNextStream(
LONG lFlags,
BSTR bstrItemName,
BSTR bstrFullItemName,
IStream **ppDestination)
{
HRESULT hr = S_OK;
// Return a new stream for this item's data.
//
hr = CreateDestinationStream(bstrItemName, ppDestination);
return hr;
}
public: // IUnknown
.
.
. // Etc.
private:
/// For ref counting implementation
LONG m_cRef;
};