IWICMetadataBlockReader の実装

IWICMetadataBlockReader

多くの場合、メタデータの複数のブロックがイメージ内に存在し、それぞれが異なる形式で異なる種類の情報を公開します。 Windows イメージング コンポーネント (WIC) モデルでは、メタデータ ハンドラーは、デコーダーと同様に実行時に検出可能な個別のコンポーネントです。 各メタデータ形式には個別のハンドラーがあり、これらの各メタデータ ハンドラーは、処理するメタデータ形式をサポートする任意のイメージ形式で使用できます。 したがって、イメージ形式が EXIF、XMP、IPTC、または別の形式をサポートしている場合は、WIC に付属するこれらの形式の標準メタデータ ハンドラーを利用できます。独自の形式を記述する必要はありません。 もちろん、新しいメタデータ形式を作成する場合は、標準と同様に実行時に検出および呼び出されるメタデータ ハンドラーを記述する必要があります。

注意

画像形式がタグ付き画像ファイル形式 (TIFF) または JPEG コンテナーに基づいている場合は、メタデータ ハンドラーを記述する必要はありません (新しいメタデータ形式または独自のメタデータ形式を開発する場合を除く)。 TIFF および JPEG コンテナーでは、メタデータのブロックは IFD 内に配置され、各コンテナーは異なる IFD 構造を持ちます。 WIC は、IFD 構造体を移動し、その中のメタデータにアクセスするための標準メタデータ ハンドラーに委任する、これらの両方のコンテナー形式に対して IFD ハンドラーを提供します。 そのため、イメージ形式がこれらのコンテナーのいずれかに基づいている場合は、WIC IFD ハンドラーを自動的に利用できます。 ただし、独自の最上位レベルのメタデータ構造を持つ独自のコンテナー形式がある場合は、IFD ハンドラーと同様に、その最上位の構造を移動し、適切なメタデータ ハンドラーに委任できるハンドラーを記述する必要があります。

 

WIC が提供するアプリケーションの抽象化レイヤーが提供されるのと同じ方法で、一貫したインターフェイス セットを介してすべてのイメージ形式を操作できるように、WIC はメタデータ形式に関してコーデック作成者に抽象化レイヤーを提供します。 前述のように、コーデック作成者は通常、画像に存在する可能性があるさまざまなメタデータ形式を直接操作する必要はありません。 ただし、すべてのコーデック作成者は、メタデータのブロックを列挙して、ブロックごとに適切なメタデータ ハンドラーを検出してインスタンス化できるようにする方法を提供する役割を担います。

このインターフェイスは、フレーム レベルのデコード クラスに実装する必要があります。 また、イメージ形式が個々のイメージ フレームの外部でグローバル メタデータを公開する場合は、コンテナー レベルのデコーダー クラスに実装する必要がある場合もあります。

interface IWICMetadataBlockReader : IUnknown
{
   // All methods required
   HRESULT GetContainerFormat ( GUID *pguidContainerFormat );
   HRESULT GetCount ( UINT *pcCount );
   HRESULT GetEnumerator ( IEnumUnknown **ppIEnumMetadata );
   HRESULT GetReaderByIndex ( UINT nIndex, IWICMetadataReader **ppIMetadataReader );
}

GetContainerFormat

GetContainerFormat は、IWICBitmapDecoder の実装に関する GetContainerFormat メソッドと同じです。

GetCount

GetCount は 、フレームに関連付けられている最上位レベルのメタデータ ブロックの数を返します。

GetEnumerator

GetEnumerator は、フレーム内のメタデータ ブロックを列挙し、そのメタデータを読み取るために呼び出し元が使用できる列挙子を返します。 このメソッドを実装するには、メタデータのブロックごとにメタデータ リーダーを作成し、メタデータ リーダーのコレクションを列挙する列挙オブジェクトを実装する必要があります。 列挙オブジェクトは 、ppIEnumMetadata パラメーターで返すときに IEnumUnknown にキャストできるように 、IEnumUnknown を実装する必要があります。

列挙オブジェクトを実装する場合は、 最初に IWICMetadataBlockReader オブジェクトを作成するとき、または列挙オブジェクトを初めて作成するときに、すべてのメタデータ リーダーを作成するか、 IEnumUnknown::Next メソッドの実装内で遅延して作成できます。 多くの場合、遅延して作成する方が効率的ですが、次の例では、スペースを節約するためにブロック リーダーがすべてコンストラクターに作成されます。

public class MetadataReaderEnumerator : public IEnumUnknown
{
   UINT m_current;
   UINT m_blockCount;
   IWICMetadataReader** m_ppMetadataReader;
   IStream* m_pStream;

   MetadataReaderEnumerator() 
   {
       // Set m_blockCount to the number of metadata blocks in the frame. 
      ...
      m_ppMetadataReader = IWICMetadataReader*[m_blockCount];
       m_current = 0;

      for (UINT x=0; x < m_blockCount; x++) 
      {
         // Find the position in the file where the xth
         // block of metadata lives and seek m_piStream 
         // to that position.
         ...

         m_pComponentFactory->CreateMetadataReaderFromContainer(
            GUID_ContainerFormatTiff,
                        NULL,
                        WICPersistOptions.WICPersistOptionsDefault | 
            WICMetadataCreationOptions.WICMetadataCreationDefault, 
                        m_pStream, &m_ppMetadataReader[x]);
        }
    }

    // Implementation of IEnumUnknown and IUnknown interfaces
    ...
}

メタデータ リーダーを作成するには、 CreateMetadataReaderFromContainer メソッドを使用します。 このメソッドを呼び出すときは、コンテナー形式の GUID を guidContainerFormat パラメーターで渡します。 メタデータ リーダーのベンダーを優先する場合は、 pGuidVendor パラメーターで優先ベンダーの GUID を渡すことができます。 たとえば、会社がメタデータ ハンドラーを記述していて、存在する場合は独自のものを使用する場合は、ベンダー GUID を渡すことができます。 ほとんどの場合、 NULL を渡すだけで、システムで適切なメタデータ リーダーを選択できます。 特定のベンダーを要求し、そのベンダーにコンピューターにメタデータ リーダーがインストールされている場合、WIC はそのベンダーの閲覧者を返します。 ただし、要求されたベンダーにコンピューターにメタデータ リーダーがインストールされておらず、使用可能な適切なメタデータ リーダーがある場合は、優先ベンダーからではない場合でも、そのリーダーが返されます。 ブロック内のメタデータの種類のメタデータ リーダーがコンピューターに存在しない場合、コンポーネント ファクトリは不明なメタデータ ハンドラーを返します。これにより、メタデータのブロックがバイナリ ラージ オブジェクト (BLOB) として扱われ、解析を試みることなくファイルからメタデータのブロックが逆シリアル化されます。

dwOptions パラメーターの場合は、適切な WICPersistOptions と適切な WICMetadataCreationOptions の間で OR 操作を実行します。 WICPersistOptions では、コンテナーのレイアウト方法について説明します。リトル エンディアンが既定値です。

enum WICPersistOptions
{   
   WICPersistOptionDefault,
   WICPersistOptionLittleEndian,
   WICPersistOptionBigEndian,
   WICPersistOptionStrictFormat,
   WICPersistOptionNoCacheStream,
   WICPersistOptionPreferUTF8
};

WICMetadataCreationOptions は、特定のブロックのメタデータ形式を読み取ることができるメタデータ リーダーがマシンに見つからない場合に UnknownMetadataHandler を取得するかどうかを指定します。 WICMetadataCreationAllowUnknown が既定値であり、常に UnknownMetadtataHandler の作成を許可する必要があります。 UnknownMetadataHandler は、認識されないメタデータを BLOB として扱います。 解析することはできませんが、BLOB としてストリームに書き込み、エンコード中にストリームに書き戻されたときにそのまま保持されます。 これにより、システムに付属していない独自のメタデータまたはメタデータ形式のメタデータ ハンドラーを安全に作成できます。 メタデータはそのまま保持されるため、認識するコンピューターにハンドラーが存在しない場合でも、適切なメタデータ ハンドラーが後でインストールされると、メタデータは引き続き存在し、読み取ることができます。 UnknownMetadataHandler の作成を許可しない場合は、認識されないメタデータを破棄または上書きします。 これはデータ損失の一種です。

注意

独自のメタデータ用に独自のメタデータ ハンドラーを記述する場合は、メタデータ ブロック自体の外部への参照を含めてはいけません。 UnknownMetadataHandler はメタデータをそのまま保持しますが、ファイルの編集時にメタデータは移動され、そのブロックの外部にあるものへの参照は無効になります。

 

enum WICMetadataCreationOptions
{
   WICMetadataCreationDefault = 0x00000000,
   WICMetadataCreationAllowUnknown = WICMetadataCreationDefault,
   WICMetadataCreationFailUnknown = 0x00010000,
   WICMetadataCreationMask = 0xFFFF0000
};

pIStream パラメーターは、デコードする実際のストリームです。 ストリームを渡す前に、リーダーを要求しているメタデータ ブロックの先頭をシークする必要があります。 IStream 内の現在位置にあるメタデータ ブロックの適切なメタデータ リーダーは、ppiReader パラメーターで返されます。

GetReaderByIndex

GetReaderByIndex は、コレクション内の要求されたインデックスにあるメタデータ リーダーを返します。

リファレンス

IWICMetadataBlockReader

概念

IWICBitmapFrameDecode の実装

IWICBitmapSourceTransform の実装

WIC-Enabled コーデックを記述する方法

Windows Imaging コンポーネントの概要