このトピックでは、Windows イメージング コンポーネント (WIC) API を使用して、イメージ ファイルに埋め込まれているメタデータの読み取りと書き込みを行う方法の概要について説明します。
このトピックは、次のセクションで構成されています。
[前提条件]
このトピックを理解するには、「 WIC メタデータの概要」の説明に従って WIC メタデータ システムについて理解している必要があります。 メタデータの読み取りと書き込みに使用されるクエリ言語についても理解しておく必要があります。詳細については、「メタデータ クエリ言語の概要」参照してください。
イントロダクション
WIC は、アプリケーション開発者にコンポーネント オブジェクト モデル (COM) コンポーネントを提供し、イメージ ファイルに埋め込まれたメタデータの読み取りと書き込みを行います。 メタデータの読み取りと書き込みには、次の 2 つの方法があります。
- クエリ リーダー/ライターとクエリ式を使用して、入れ子になったブロックまたはブロック内の特定のメタデータのメタデータ ブロックに対してクエリを実行します。
- メタデータ ハンドラー (メタデータ リーダーまたはメタデータ ライター) を使用して、入れ子になったメタデータ ブロックまたはメタデータ ブロック内の特定のメタデータにアクセスします。
最も簡単なのは、クエリ リーダー/ライターとクエリ式を使用してメタデータにアクセスすることです。 クエリ ライター (IWICMetadataQueryWriter) を使用してメタデータを書き込むときに、クエリ リーダー (IWICMetadataQueryReader) を使用してメタデータを読み取ります。 どちらもクエリ式を使用して、目的のメタデータの読み取りまたは書き込みを行います。 バックグラウンドでは、クエリ リーダー (およびライター) はメタデータ ハンドラーを使用して、クエリ式で記述されたメタデータにアクセスします。
より高度な方法は、メタデータ ハンドラーに直接アクセスすることです。 メタデータ ハンドラーは、ブロック リーダー (IWICMetadataBlockReader) またはブロック ライター (IWICMetadataBlockWriter) を使用して、個々のフレームから取得されます。 使用できるメタデータ ハンドラーの 2 種類は、メタデータ リーダー (IWICMetadataReader) とメタデータ ライター (IWICMetadataWriter) です。
このトピックの例全体で、JPEG イメージ ファイルの内容を次の図に示します。 この図で表されるイメージは、Microsoft Paint を使用して作成されました。評価メタデータは、Windows Vista のフォト ギャラリー機能を使用して追加されました。
クエリ リーダーを使用したメタダデータの読み取り
メタデータを読み取る最も簡単な方法は、クエリ リーダー インターフェイス IWICMetadataQueryReader を使用することです。 クエリ リーダーを使用すると、クエリ式を使用してメタデータ ブロックとメタデータ ブロック内の項目を読み取ることができます。
クエリ リーダーを取得するには、ビットマップ デコーダー (IWICBitmapDecoder)、個々のフレーム (IWICBitmapFrameDecode)、またはクエリ ライター (IWICMetadataQueryWriter) の 3 つの方法があります。
クエリ リーダーの取得
次のコード例は、イメージング ファクトリからビットマップ デコーダーを取得し、個々のビットマップ フレームを取得する方法を示しています。 このコードでは、デコードされたフレームからクエリ リーダーを取得するために必要なセットアップ作業も実行します。
IWICImagingFactory *pFactory = NULL;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pFrameDecode = NULL;
IWICMetadataQueryReader *pQueryReader = NULL;
IWICMetadataQueryReader *pEmbedReader = NULL;
PROPVARIANT value;
// Initialize COM
CoInitialize(NULL);
// Initialize PROPVARIANT
PropVariantInit(&value);
//Create the COM imaging factory
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&pFactory);
// Create the decoder
if (SUCCEEDED(hr))
{
hr = pFactory->CreateDecoderFromFilename(
L"test.jpg",
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
&pDecoder);
}
// Get a single frame from the image
if (SUCCEEDED(hr))
{
hr = pDecoder->GetFrame(
0, //JPEG has only one frame.
&pFrameDecode);
}
test.jpg ファイルのビットマップ デコーダーは、イメージング ファクトリの CreateDecoderFromFilename メソッドを使用して取得されます。 このメソッドでは、4 番目のパラメーターは、 WICDecodeOptions 列挙体の値 WICDecodeMetadataCacheOnDemand に設定されます。 これにより、メタデータが必要になったときにメタデータをキャッシュするようにデコーダーに指示します。クエリ リーダーまたは基になるメタデータ リーダーを取得します。 このオプションを使用すると、高速メタデータ エンコードに必要なメタデータへのストリームを保持でき、JPEG イメージの無損失デコードが可能になります。 または、他の WICDecodeOptions 値 WICDecodeMetadataCacheOnLoad を使用することもできます。この値は、イメージが読み込まれるとすぐに埋め込まれたイメージ メタデータをキャッシュします。
フレームのクエリ リーダーを取得するには、フレームの GetMetadataQueryReader メソッドを簡単に呼び出します。 次のコードは、この呼び出しを示しています。
// Get the query reader
if (SUCCEEDED(hr))
{
hr = pFrameDecode->GetMetadataQueryReader(&pQueryReader);
}
同様に、クエリ リーダーもデコーダー レベルで取得できます。 デコーダーの GetMetadataQueryReader メソッドを簡単に呼び出すと、デコーダーのクエリ リーダーが取得されます。 デコーダーのクエリ リーダーは、フレームのクエリ リーダーとは異なり、個々のフレームの外部にあるイメージのメタデータを読み取ります。 ただし、このシナリオは一般的ではなく、ネイティブ イメージ形式ではこの機能をサポートしていません。 WIC によって提供されるネイティブ イメージ コーデックは、JPEG などの単一フレーム形式の場合でも、フレーム レベルでメタデータを読み書きします。
メタデータの読み取り
実際にメタデータを読み取る前に、埋め込まれたメタデータ ブロックと取得する実際のデータを含む JPEG ファイルの次の図を参照してください。 この図では、画像内の特定のメタデータ ブロックと項目への吹き出しを提供し、各ブロックまたは項目にメタデータ クエリ式を提供します。
埋め込みメタデータ ブロックまたは特定の項目を名前で照会するには、 GetMetadataByName メソッドを呼び出します。 このメソッドは、クエリ式と、メタデータ項目が返される PROPVARIANT を受け取ります。 次のコードは、入れ子になったメタデータ ブロックを照会し、PROPVARIANT 値によって提供される IUnknown コンポーネントが見つかった場合にクエリ リーダーに変換します。
if (SUCCEEDED(hr))
{
// Get the nested IFD reader
hr = pQueryReader->GetMetadataByName(L"/app1/ifd", &value);
if (value.vt == VT_UNKNOWN)
{
hr = value.punkVal->QueryInterface(IID_IWICMetadataQueryReader, (void **)&pEmbedReader);
}
PropVariantClear(&value); // Clear value for new query
}
クエリ式 "/app1/ifd" は、App1 ブロックに入れ子になった IFD ブロックに対してクエリを実行しています。 JPEG イメージ ファイルには IFD 入れ子になったメタデータ ブロックが含まれているため、 PROPVARIANT は VT_UNKNOWN
の変数型 (vt) と IUnknown インターフェイス (punkVal) へのポインターを使用して返されます。 その後、クエリ リーダーの IUnknown インターフェイスに対してクエリを実行します。
次のコードは、入れ子になった IFD ブロックに対する新しいクエリ リーダーに基づく新しいクエリを示しています。
if (SUCCEEDED(hr))
{
hr = pEmbedReader->GetMetadataByName(L"/{ushort=18249}", &value);
PropVariantClear(&value); // Clear value for new query
}
クエリ式 "/{ushort=18249}" は、タグ 18249 の下に埋め込まれた MicrosoftPhoto レーティングの IFD ブロックに対してクエリを実行します。
PROPVARIANT 値には、VT_UI2
の値型と 50 のデータ値が含まれるようになりました。
ただし、特定のデータ値を照会する前に、入れ子になったブロックを取得する必要はありません。 たとえば、入れ子になった IFD に対してクエリを実行する代わりに、MicrosoftPhoto レーティングに対してクエリを実行する代わりに、ルート メタデータ ブロックと次のコードに示すクエリを使用して、同じ情報を取得できます。
if (SUCCEEDED(hr))
{
hr = pQueryReader->GetMetadataByName(L"/app1/ifd/{ushort=18249}", &value);
PropVariantClear(&value);
}
メタデータ ブロック内の特定のメタデータ項目に対するクエリに加えて、メタデータ ブロック内のすべてのメタデータ 項目を列挙することもできます (入れ子になったメタデータ ブロックにメタデータ項目を含めません)。 現在のブロック内のメタデータ項目を列挙するために、クエリ リーダーの GetEnumeration メソッドが使用されます。 このメソッドは、現在のブロック内のメタデータ項目が設定された IEnumString インターフェイスを取得します。 たとえば、次のコードは、前に取得した入れ子になった IFD ブロックの XMP 評価と MicrosoftPhoto 評価を列挙します。
IEnumString *metadataItems = NULL;
if (SUCCEEDED(hr))
{
hr = pEmbedReader->GetEnumerator(&metadataItems);
}
さまざまな画像形式とメタデータ形式に適したタグを識別する方法の詳細については、「 ネイティブ イメージ形式のメタデータ クエリ」を参照してください。
その他のクエリ リーダー メソッド
メタデータの読み取りに加えて、クエリ リーダーに関する追加情報を取得し、他の方法でメタデータを取得することもできます。 クエリ リーダーには、クエリ リーダー GetContainerFormat と GetLocation に関する情報を提供する 2 つのメソッド が用意されています。
埋め込みクエリ リーダーを使用すると、 GetContainerFormat を 使用してメタデータ ブロックの種類を確認できます。 また、GetLocation を呼び出して、ルート メタデータ ブロックに対する相対パスを取得できます。 次のコードは、埋め込みクエリ リーダーの場所を照会します。
// Determine the metadata block format
if (SUCCEEDED(hr))
{
hr = pEmbedReader->GetContainerFormat(&containerGUID);
}
// Determine the query reader's location
if (SUCCEEDED(hr))
{
UINT length;
WCHAR readerNamespace[100];
hr = pEmbedReader->GetLocation(100, readerNamespace, &length);
}
埋め込みクエリ リーダーの GetContainerFormat の呼び出しは、IFD メタデータ形式 GUID を返します。 GetLocation の呼び出しは、名前空間 "/app1/ifd" を返します。新しいクエリ リーダーへの後続のクエリの実行元となる相対パスを指定します。 もちろん、上記のコードはあまり役に立ちませんが、入れ子になったメタデータ ブロックを検索するために GetLocation メソッドを使用する方法を示しています。
クエリ ライターを使用したメタデータの書き込み
注
このセクションで説明するコード例の一部は、メタデータの書き込みに必要な実際の手順のコンテキストでは示されていません。 実際のサンプルのコンテキストでコード例を表示するには、「方法: メタデータを使用してイメージを再エンコードする」チュートリアルを参照してください。
メタデータを書き込むための主要なコンポーネントは、クエリ ライター (IWICMetadataQueryWriter) です。 クエリ ライターを使用すると、メタデータ ブロックとメタデータ ブロック内の項目を設定および削除できます。
クエリ リーダーと同様に、クエリ ライターを取得するには、ビットマップ エンコーダー (IWICBitmapEncoder)、個々のフレーム (IWICBitmapFrameEncode)、高速メタデータ エンコーダー (IWICFastMetadataEncoder) の 3 つの方法があります。
クエリ ライターの取得
最も一般的なクエリ ライターは、ビットマップの個々のフレーム用です。 このクエリ ライターは、イメージ フレームのメタデータ ブロックと項目を設定および削除します。 イメージ フレームのクエリ ライターを取得するには、フレームの GetMetadataQueryWriter メソッドを呼び出します。 次のコードは、フレームのクエリ ライターを取得するための単純なメソッド呼び出しを示しています。
IWICMetadataQueryWriter &pFrameQWriter = NULL;
//Obtain a query writer from the frame.
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
同様に、エンコーダー レベルのクエリ ライターも取得できます。 エンコーダーの GetMetadataQueryWriter メソッドを簡単に呼び出すと、エンコーダーのクエリ ライターが取得されます。 エンコーダーのクエリ ライターは、フレームのクエリ ライターとは異なり、個々のフレームの外部にあるイメージのメタデータを書き込みます。 ただし、このシナリオは一般的ではなく、ネイティブ イメージ形式ではこの機能をサポートしていません。 WIC によって提供されるネイティブ イメージ コーデックは、JPEG などの単一フレーム形式の場合でも、フレーム レベルでメタデータを読み書きします。
また、イメージング ファクトリ (IWICImagingFactory) から直接クエリ ライターを取得することもできます。 クエリ ライターを返すイメージング ファクトリ メソッドには、CreateQueryWriter と CreateQueryWriterFromReader の 2 つがあります。
CreateQueryWriter は、指定されたメタデータ形式とベンダーのクエリ ライターを作成します。 このクエリ ライターを使用すると、特定のメタデータ形式のメタデータを書き込んでイメージに追加できます。 次のコードは、XMP クエリ ライターを作成するための CreateQueryWriter 呼び出しを示しています。
IWICMetadataQueryWriter *pXMPWriter = NULL;
// Create XMP block
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriter(
GUID_MetadataFormatXMP,
&vendor,
&pXMPWriter);
この例では、 GUID_MetadataFormatXMP
フレンドリ名が guidMetadataFormat パラメーターとして使用されます。 これは XMP メタデータ形式 GUID を表し、ベンダーは Microsoft が作成したハンドラーを表します。 または、他の XMP ハンドラーが存在しない場合は、同じ結果を持つ pguidVendor パラメーターとして NULL を渡すことができます。 ネイティブ XMP ハンドラーと共にカスタム XMP ハンドラーがインストールされている場合、ベンダーに NULL を渡すと、最も低い GUID のクエリライターが返されます。
CreateQueryWriterFromReader は CreateQueryWriter メソッドに似ていますが、新しいクエリ ライターにクエリ リーダーによって提供されるデータが事前に入力される点が異なります。 これは、既存のメタデータを維持しながらイメージを再エンコードする場合や、不要なメタデータを削除する場合に便利です。 次のコードは、 CreateQueryWriterFromReader 呼び出しを示しています。
hr = pFrameDecode->GetMetadataQueryReader(&pFrameQReader);
// Copy metadata using query readers
if(SUCCEEDED(hr) && pFrameQReader)
{
IWICMetadataQueryWriter *pNewWriter = NULL;
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriterFromReader(
pFrameQReader,
&vendor,
&pNewWriter);
メタデータの追加
クエリ ライターを取得したら、それを使用してメタデータ ブロックと項目を追加できます。 メタデータを書き込むには、クエリ ライターの SetMetadataByName メソッドを使用します。 SetMetadataByName は、クエリ式 (wzName) と PROPVARIANT (pvarValue) へのポインターの 2 つのパラメーターを受け取ります。 クエリ式は、設定するブロックまたは項目を定義しますが、PROPVARIANT は設定する実際のデータ値を提供します。
次の例では、 CreateQueryWriter メソッドを使用して以前に取得した XMP クエリ ライターを使用してタイトルを追加する方法を示します。
// Write metadata to the XMP writer
if (SUCCEEDED(hr))
{
PROPVARIANT value;
PropVariantInit(&value);
value.vt = VT_LPWSTR;
value.pwszVal = L"Metadata Test Image.";
hr = pXMPWriter->SetMetadataByName(L"/dc:title", &value);
PropVariantClear(&value);
}
この例では、値の型 (vt) が VT_LPWSTR
に設定され、文字列がデータ値として使用されることを示します。
値の型は文字列であるため、pwszVal は使用するタイトルを設定するために使用されます。
SetMetadataByName は、クエリ式 "/dc:title" と新しく設定された PROPVARIANT を使用して呼び出されます。 使用されるクエリ式は、デジタル カメラ (dc) スキーマの title プロパティを設定する必要があることを示します。 式が "/xmp/dc:title" ではないことに注意してください。これは、クエリライターが既に XMP に固有で、埋め込み XMP ブロックを含まないためです。"/xmp/dc:title" は埋め込み XMP ブロックを示唆するためです。
ここまでは、実際に画像フレームにメタデータを追加していません。 クエリライターに単純にデータを入力しました。 クエリ ライターによって表されるメタデータ ブロックをフレームに追加するには、再び PROPVARIANT の値としてクエリ ライターを使用して SetMetadataByName を呼び出します。 これにより、クエリ ライターのメタデータがイメージ フレームに効果的にコピーされます。 次のコードは、以前に取得した XMP クエリ ライターのメタデータをフレームのルート メタデータ ブロックに追加する方法を示しています。
// Get the frame's query writer and write the XMP query writer to it
if (SUCCEEDED(hr))
{
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
// Copy the metadata in the XMP query writer to the frame
if (SUCCEEDED(hr))
{
PROPVARIANT value;
PropVariantInit(&value);
value.vt = VT_UNKNOWN;
value.punkVal = pXMPWriter;
value.punkVal->AddRef();
hr = pFrameQWriter->SetMetadataByName(L"/", &value);
PropVariantClear(&value);
}
}
この例では、 VT_UNKOWN
の値型 (vt) が使用されます。COM インターフェイス値の型を示します。 その後、XMP クエリ ライター (piXMPWriter) が PROPVARIANT の値として使用され、AddRef メソッドを使用して参照が追加されます。 最後に、XMP クエリ ライターを設定するには、フレームの SetMetadataByName メソッドを呼び出し、クエリ式 "/" を渡し、ルート ブロックと新しく設定された PROPVARIANT を示します。
注
追加しようとしているメタデータ ブロックがフレームに既に含まれている場合は、追加するメタデータが追加され、既存のメタデータが上書きされます。
メタデータの削除
クエリ ライターを使用すると、 RemoveMetadataByName メソッドを呼び出してメタデータを削除することもできます。 RemoveMetadataByName はクエリ式を受け取り、メタデータ ブロックまたはアイテムが存在する場合は削除します。 次のコードは、以前に追加されたタイトルを削除する方法を示しています。
if (SUCCEEDED(hr))
{
hr = pFrameQWriter->RemoveMetadataByName(L"/xmp/dc:title");
}
次のコードは、XMP メタデータ ブロック全体を削除する方法を示しています。
if (SUCCEEDED(hr))
{
hr = pFrameQWriter->RemoveMetadataByName(L"/xmp");
}
再エンコードのためのメタデータのコピー
注
このセクションのコードは、コピー元とコピー先のイメージの形式が同じ場合にのみ有効です。 別のイメージ形式にエンコードする場合、イメージのすべてのメタデータを 1 回の操作でコピーすることはできません。
イメージを同じイメージ形式に再エンコードするときにメタデータを保持するために、すべてのメタデータを 1 回の操作でコピーできるメソッドがあります。 これらの各操作は、同様のパターンに従います。デコードされたフレームのメタデータは、エンコードされる新しいフレームに直接設定されます。
メタデータをコピーする方法として、デコードされたフレームのブロック リーダーを使用して、新しいフレームのブロック ライターを初期化することをお勧めします。 次のコードは、このメソッドを示しています。
if (SUCCEEDED(hr) && formatsEqual)
{
// Copy metadata using metadata block reader/writer
if (SUCCEEDED(hr))
{
pFrameDecode->QueryInterface(
IID_IWICMetadataBlockReader,
(void**)&pBlockReader);
}
if (SUCCEEDED(hr))
{
pFrameEncode->QueryInterface(
IID_IWICMetadataBlockWriter,
(void**)&pBlockWriter);
}
if (SUCCEEDED(hr))
{
pBlockWriter->InitializeFromBlockReader(pBlockReader);
}
}
この例では、ブロック リーダーとブロック ライターは、それぞれソース フレームと宛先フレームから取得されます。 ブロック ライターは、ブロック リーダーから初期化されます。 これにより、ブロック リーダーの事前設定されたメタデータを使用してブロック リーダーが初期化されます。
メタデータをコピーするもう 1 つの方法は、エンコーダーのクエリ ライターを使用してクエリ リーダーによって参照されるメタデータ ブロックを書き込む方法です。 次のコードは、このメソッドを示しています。
if (SUCCEEDED(hr) && formatsEqual)
{
hr = pFrameDecode->GetMetadataQueryReader(&pFrameQReader);
// Copy metadata using query readers
if(SUCCEEDED(hr))
{
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
if (SUCCEEDED(hr))
{
PropVariantClear(&value);
value.vt=VT_UNKNOWN;
value.punkVal=pFrameQReader;
value.punkVal->AddRef();
hr = pFrameQWriter->SetMetadataByName(L"/", &value);
PropVariantClear(&value);
}
}
}
ここで、クエリ リーダーはデコードされたフレームから取得され、値型が VT_UNKNOWN に設定された PROPVARIANT のプロパティ値として使用されます。 エンコーダーのクエリ ライターが取得され、クエリ式 "/" を使用して、ルート ナビゲーション パスにメタデータが設定されます。 このメソッドは、入れ子になったメタデータ ブロックを設定するときに、クエリ式を目的の場所に調整して使用することもできます。
同様に、イメージング ファクトリの CreateQueryWriterFromReader メソッドを使用して、デコードされたフレームのクエリ リーダーに基づいてクエリ ライターを作成できます。 この操作で作成されたクエリ ライターには、クエリ リーダーからのメタデータが事前に設定され、フレームで設定できます。 次のコードは、 CreateQueryWriterFromReader コピー操作を示しています。
IWICMetadataQueryWriter *pNewWriter = NULL;
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriterFromReader(
pFrameQReader,
&vendor,
&pNewWriter);
if (SUCCEEDED(hr))
{
// Get the frame's query writer
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);
}
// Set the query writer to the frame.
if (SUCCEEDED(hr))
{
PROPVARIANT value;
PropVariantInit(&value);
value.vt = VT_UNKNOWN;
value.punkVal = pNewWriter;
value.punkVal->AddRef();
hr = pFrameQWriter->SetMetadataByName(L"/",&value);
}
このメソッドは、クエリ リーダーのデータに基づいて作成される個別のクエリ ライターを使用します。 その後、この新しいクエリ ライターがフレームに設定されます。
ここでも、メタデータをコピーするこれらの操作は、ソース イメージとコピー先イメージの形式が同じ場合にのみ機能します。 これは、メタデータ ブロックが異なる場所に格納されるイメージ形式が異なるためです。 たとえば、JPEG と TIFF の両方で XMP メタデータ ブロックがサポートされます。 JPEG 画像では、「 WIC メタデータの概要」に示すように、XMP ブロックはルート メタデータ ブロックにあります。 ただし、TIFF イメージでは、XMP ブロックはルート IFD ブロックにネストされています。 次の図は、JPEG 画像と同じ評価メタデータを持つ TIFF イメージの違いを示しています。
高速メタデータ エンコード
新しいメタデータを書き込むには、必ずしもイメージを再エンコードする必要はありません。 高速メタデータ エンコーダーを使用してメタデータを書き込むこともできます。 高速メタデータ エンコーダーでは、イメージを再エンコードすることなく、限られた量のメタデータをイメージに書き込むことができます。 これは、一部のメタデータ形式で提供される空のパディング内に新しいメタデータを書き込むことで実現されます。 メタデータの埋め込みをサポートするネイティブ メタデータ形式は、Exif、IFD、GPS、XMP です。
メタデータ ブロックへのパディングの追加
高速メタデータ エンコードを実行する前に、メタデータ ブロック内にさらにメタデータを書き込むスペースが必要です。 既存のパディング内に新しいメタデータを書き込むための十分なスペースがない場合、高速メタデータ エンコードは失敗します。 画像にメタデータパディングを追加するには、イメージを再エンコードする必要があります。 埋め込み中のメタデータ ブロックでサポートされている場合は、クエリ式を使用して、他のメタデータ項目を追加するのと同じ方法でパディングを追加できます。 次の例では、App1 ブロックに埋め込まれた IFD ブロックにパディングを追加する方法を示します。
if (SUCCEEDED(hr))
{
// Add metadata padding
PROPVARIANT padding;
PropVariantInit(&padding);
padding.vt = VT_UI4;
padding.uiVal = 4096; // 4KB
hr = pFrameQWriter->SetMetadataByName(L"/app1/ifd/PaddingSchema:padding", &padding);
PropVariantClear(&padding);
}
パディングを追加するには、VT_UI4型の PROPVARIANT と、追加するパディングのバイト数に対応する値を作成します。 一般的な値は 4096 バイトです。 JPEG、TIFF、および JPEG-XR のメタデータ クエリを次の表に示します。
メタデータ形式 | JPEG メタデータ クエリ | TIFF、JPEG-XR メタデータ クエリ |
---|---|---|
IFD(インカム・フロウ・ディストリビューション) | /app1/ifd/PaddingSchema:Padding | /ifd/PaddingSchema:Padding |
EXIF | /app1/ifd/exif/PaddingSchema:Padding | /ifd/exif/PaddingSchema:Padding |
XMP | /xmp/PaddingSchema:Padding | /ifd/xmp/PaddingSchema:Padding |
GPS | /app1/ifd/gps/PaddingSchema:Padding | /ifd/gps/PaddingSchema:Padding |
高速メタデータ エンコーダーの取得
メタデータ パディングを含むイメージがある場合は、イメージング ファクトリ メソッド CreateFastMetadataEncoderFromDecoder と CreateFastMetadataEncoderFromFrameDecode を使用して高速メタデータ エンコーダーを取得できます。
名前が示すように、 CreateFastMetadataEncoderFromDecoder はデコーダー レベルのメタデータ用の高速メタデータ エンコーダーを作成します。 WIC によって提供されるネイティブ イメージ形式はデコーダー レベルのメタデータをサポートしていませんが、このようなイメージ形式が将来開発される場合に備えて、このメソッドが提供されます。
より一般的なシナリオは、 CreateFastMetadataEncoderFromFrameDecode を使用して、イメージ フレームから高速メタデータ エンコーダーを取得することです。 次のコードは、デコードされたフレームの高速メタデータ エンコーダーを取得し、App1 ブロックの評価値を変更します。
if (SUCCEEDED(hr))
{
IWICFastMetadataEncoder *pFME = NULL;
IWICMetadataQueryWriter *pFMEQW = NULL;
hr = pFactory->CreateFastMetadataEncoderFromFrameDecode(
pFrameDecode,
&pFME);
}
高速メタデータ エンコーダーの使用
高速メタデータ エンコーダーから、クエリ ライターを取得できます。 これにより、前に示したようにクエリ式を使用してメタデータを記述できます。 クエリ ライターでメタデータが設定されたら、高速メタデータ エンコーダーをコミットしてメタデータの更新を完了します。 次のコードは、メタデータの変更の設定とコミットを示しています
if (SUCCEEDED(hr))
{
hr = pFME->GetMetadataQueryWriter(&pFMEQW);
}
if (SUCCEEDED(hr))
{
// Add additional metadata
PROPVARIANT value;
PropVariantInit(&value);
value.vt = VT_UI4;
value.uiVal = 99;
hr = pFMEQW->SetMetadataByName(L"/app1/ifd/{ushort=18249}", &value);
PropVariantClear(&value);
}
if (SUCCEEDED(hr))
{
hr = pFME->Commit();
}
}
何らかの理由で コミット が失敗した場合は、イメージを再エンコードして、新しいメタデータがイメージに追加されるようにする必要があります。
関連トピック
-
概念
-
方法: メタデータ を使用して JPEG イメージを再エンコードする