Sdílet prostřednictvím


Implementace IWICMetadataBlockReader

IWICMetadataBlockReader

V obrázku často existuje několik bloků metadat, z nichž každý v různých formátech vystavuje různé typy informací. V modelu WIC (Windows Imaging Component) jsou zpracovatelé metadat samostatné komponenty, které lze zjistit za běhu programu stejně jako dekodéry. Každý formát metadat má samostatnou obslužnou rutinu a každý z těchto obslužných rutin metadat lze použít s libovolným formátem obrázku, který podporuje formát metadat, který zpracovává. Proto pokud formát obrázku podporuje EXIF, XMP, IPTC nebo jiný formát, můžete využít standardní obslužné rutiny metadat pro tyto formáty, které jsou dodávány s WIC, a nemusíte psát vlastní. Pokud samozřejmě vytvoříte nový formát metadat, musíte pro něj napsat obslužnou rutinu metadat, která bude zjištěna a vyvolána za běhu stejně jako standardní.

Poznámka

Pokud je formát obrázku založený na kontejneru TIFF (Tagged Image File Format) nebo JPEG, nebudete muset psát žádné obslužné rutiny metadat (pokud nevyvíjíte nový nebo proprietární formát metadat). V kontejnerech TIFF a JPEG se bloky metadat nacházejí v ifd a každý kontejner má jinou strukturu IFD. WIC poskytuje obslužné rutiny IFD pro oba tyto formáty kontejnerů, které procházejí strukturou IFD a delegují na standardní obslužné rutiny metadat, aby získaly přístup k metadatům uvnitř nich. Pokud je tedy formát image založený na některém z těchto kontejnerů, můžete automaticky využít obslužné rutiny WIC IFD. Pokud však máte proprietární formát kontejneru, který má vlastní jedinečnou strukturu metadat nejvyšší úrovně, musíte napsat obslužnou rutinu, která může procházet tuto strukturu nejvyšší úrovně a delegovat na příslušné obslužné rutiny metadat, stejně jako obslužné rutiny IFD.)

 

Stejně jako WIC poskytuje vrstvu abstrakce pro aplikace, která jim umožňuje pracovat se všemi formáty obrázků stejným způsobem prostřednictvím konzistentní sady rozhraní, WIC poskytuje vrstvu abstrakce pro autory kodeků s ohledem na formáty metadat. Jak jsme si poznamenali dříve, autoři kodeků obecně nemusí pracovat přímo s různými formáty metadat, které mohou být přítomné na obrázku. Každý autor kodeku ale zodpovídá za poskytování výčtu bloků metadat, aby bylo možné zjistit a vytvořit instanci příslušné obslužné rutiny metadat pro každý blok.

Toto rozhraní musíte implementovat ve třídě dekódování na úrovni rámce. Pokud váš formát obrázků odhaluje globální metadata mimo jednotlivé snímky, může být také nutné tuto funkci implementovat ve vaší dekódovací třídě na úrovni kontejneru.

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 je stejná jako metoda GetContainerFormat na ImplementaciIWICBitmapDecoder.

GetCount

GetCount vrátí počet bloků metadat nejvyšší úrovně přidružených k rámci.

GetEnumerator

GetEnumerator vrátí enumerátor, pomocí kterého může volající vytvořit výčet bloků metadat v rámci a číst jejich metadata. Pokud chcete tuto metodu implementovat, musíte vytvořit čtenář metadat pro každý blok metadat a implementovat objekt výčtu, který vytvoří výčet nad kolekcí čtenářů metadat. Objekt výčtu musí implementovat IEnumUnknown, abyste jej mohli přetypovat na IEnumUnknown, když jej vracíte v parametru ppIEnumMetadata.

Při implementaci objektu výčtu můžete vytvořit všechny čtenáře metadat buď při prvním vytvoření objektu IWICMetadataBlockReader, nebo při prvním vytvoření objektu výčtu, nebo je můžete líně vytvářet uvnitř implementace metody IEnumUnknown::Next. V mnoha případech je efektivnější je vytvořit laziálně, ale v následujícím příkladu jsou čtečky bloků vytvořeny v konstruktoru, aby ušetřily místo.

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
    ...
}

K vytvoření čtenářů metadat použijte metodu CreateMetadataReaderFromContainer. Při vyvolání této metody předáte identifikátor GUID formátu kontejneru v parametru guidContainerFormat. Pokud máte upřednostnění dodavatele pro čtečku metadat, můžete předat identifikátor GUID preferovaného dodavatele v parametru pGuidVendor. Pokud například vaše společnost zapisuje obslužné rutiny metadat a v případě přítomnosti chcete použít vlastní, můžete předat identifikátor GUID dodavatele. Ve většině případů stačí předat NULLa nechat systém vybrat odpovídající čtečku metadat. Pokud požádáte o konkrétního dodavatele a tento dodavatel má na počítači nainstalovanou čtečku metadat, WIC vrátí čtečku tohoto dodavatele. Pokud však požadovaný dodavatel nemá v počítači nainstalovanou čtečku metadat a pokud je k dispozici příslušná čtečka metadat, bude tato čtečka vrácena, i když není od preferovaného dodavatele. Pokud v počítači není k dispozici žádná čtečka metadat pro typ metadat v bloku, továrna na komponenty vrátí obslužnou rutinu Unknown Metadata, která bude zacházet s blokem metadat jako s binárním velkým objektem (BLOB) a deserializuje blok metadat ze souboru bez pokusu o jeho analýzu.

U parametru dwOptions proveďte operaci OR mezi příslušnými WICPersistOptions a příslušnými WICMetadataCreationOptions. WICPersistOptions popisují, jak je kontejner rozložený. Little-endian je výchozí nastavení.

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

WICMetadataCreationOptions určují, zda chcete obdržet UnknownMetadataHandler, pokud se na počítači nenajde žádná čtečka metadat, která by mohla číst formát metadat konkrétního bloku. WICMetadataCreationAllowUnknown je výchozí a měli byste vždy povolit vytváření UnknownMetadtataHandler. UnknownMetadataHandler zpracovává nerozpoznaná metadata jako BLOB. Nemůže ho analyzovat, ale zapíše ho do datového proudu jako objekt blob a při zápisu zpět do datového proudu během kódování ho zachová beze změny. Díky tomu je bezpečné vytvářet obslužné rutiny metadat pro proprietární metadata nebo formáty metadat, které nejsou dodávány se systémem. Protože metadata zůstávají zachována beze změny, i když v počítači není přítomen žádný program, který by je rozpoznal, po instalaci vhodného programu pro zpracování metadata budou metadata stále dostupná a lze je přečíst. Pokud nepovolíte vytvoření UnknownMetadataHandler, alternativou je zahození nebo přepsání nerozpoznaných metadat. Jedná se o formu ztráty dat.

Poznámka

Pokud zapíšete vlastní obslužnou rutinu metadat pro proprietární metadata, nikdy byste neměli obsahovat odkazy na nic mimo samotný blok metadat. I když UnknownMetadataHandler zachovává metadata beze změny, metadata se přesunou při úpravách souborů a všechny odkazy na cokoli mimo vlastní blok už nebudou platné, když k tomu dojde.

 

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

Parametr pIStream je skutečný datový proud, který dekódujete. Před předáním datového proudu byste měli vyhledat začátek bloku metadat, pro který žádáte čtenáře. Odpovídající čtečka metadat pro blok metadat na aktuální pozici v IStream bude vrácena v parametru ppiReader.

GetReaderByIndex

GetReaderByIndex vrátí čtečku metadat v požadovaném indexu v kolekci.

Referenční

IWICMetadataBlockReader

Koncepční

implementace IWICBitmapFrameDecode

implementace IWICBitmapSourceTransform

Jak napsat WIC-Enabled kodek

Přehled komponent Windows Imaging