WIA 2.0 での画像データの転送
Note
このチュートリアルでは、Windows Vista 以降で実行されるアプリケーションでイメージ データを転送する方法について説明します。 Windows XP 以前で実行されるアプリケーションでのイメージ データの転送については、「 WIA 1.0 でのイメージ データの転送」を参照してください。
イメージ データ転送は Windows Image Acquisition (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;
};