Implementieren von IWICMetadataBlockReader

Iwicmetadatablockreader

In einem Bild sind häufig mehrere Metadatenblöcke vorhanden, die jeweils unterschiedliche Informationstypen in unterschiedlichen Formaten verfügbar macht. Im WIC-Modell (Windows Imaging Component) sind Metadatenhandler unterschiedliche Komponenten, die wie Decoder zur Laufzeit auffindbar sind. Jedes Metadatenformat verfügt über einen separaten Handler, und jeder dieser Metadatenhandler kann mit jedem Bildformat verwendet werden, das das verarbeitete Metadatenformat unterstützt. Wenn Ihr Bildformat EXIF, XMP, IPTC oder ein anderes Format unterstützt, können Sie daher die Standardmetadatenhandler für diese Formate nutzen, die mit WIC geliefert werden, und Sie müssen keine eigenen schreiben. Wenn Sie ein neues Metadatenformat erstellen, müssen Sie natürlich einen Metadatenhandler dafür schreiben, der zur Laufzeit ermittelt und aufgerufen wird, genau wie die Standardformate.

Hinweis

Wenn Ihr Bildformat auf einem TIFF- oder JPEG-Container (Tagged Image File Format) basiert, müssen Sie keine Metadatenhandler schreiben (es sei denn, Sie entwickeln ein neues oder proprietäres Metadatenformat). In TIFF- und JPEG-Containern befinden sich Metadatenblöcke innerhalb von IFDs, und jeder Container verfügt über eine andere IFD-Struktur. WIC stellt IFD-Handler für beide Containerformate bereit, die in der IFD-Struktur navigieren und zu den Standardmetadatenhandlern delegieren, um auf die darin enthaltenen Metadaten zuzugreifen. Wenn Ihr Imageformat also auf einem dieser Container basiert, können Sie automatisch die WIC-IFD-Handler nutzen. Wenn Sie jedoch über ein proprietäres Containerformat verfügen, das über eine eigene eindeutige Metadatenstruktur der obersten Ebene verfügt, müssen Sie einen Handler schreiben, der diese Struktur der obersten Ebene navigieren und wie die IFD-Handler an die entsprechenden Metadatenhandler delegieren kann.)

 

Ebenso wie WIC eine Abstraktionsebene für Anwendungen bereitstellt, die es ihnen ermöglicht, mit allen Bildformaten auf die gleiche Weise über einen konsistenten Satz von Schnittstellen zu arbeiten, stellt WIC eine Abstraktionsebene für Codecautoren in Bezug auf Metadatenformate bereit. Wie bereits erwähnt, müssen Codecautoren in der Regel nicht direkt mit den verschiedenen Metadatenformaten arbeiten, die in einem Bild vorhanden sein können. Jeder Codecautor ist jedoch dafür verantwortlich, eine Möglichkeit zum Aufzählen der Metadatenblöcke bereitzustellen, damit für jeden Block ein geeigneter Metadatenhandler ermittelt und instanziiert werden kann.

Sie müssen diese Schnittstelle in Ihrer Decodierungsklasse auf Frameebene implementieren. Möglicherweise müssen Sie es auch in Ihrer Decoderklasse auf Containerebene implementieren, wenn Ihr Bildformat globale Metadaten außerhalb einzelner Bildframes verfügbar macht.

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 ist identisch mit der GetContainerFormat-Methode unter Implementieren von IWICBitmapDecoder.

GetCount

GetCount gibt die Anzahl der Metadatenblöcke der obersten Ebene zurück, die dem Frame zugeordnet sind.

GetEnumerator

GetEnumerator gibt einen Enumerator zurück, mit dem der Aufrufer die Metadatenblöcke im Frame auflisten und deren Metadaten lesen kann. Um diese Methode zu implementieren, müssen Sie einen Metadatenleser für jeden Metadatenblock erstellen und ein Enumerationsobjekt implementieren, das die Auflistung von Metadatenlesern aufzählt. Das Enumerationsobjekt muss IEnumUnknown implementieren, damit Sie es in IEnumUnknown umwandeln können, wenn Sie es im ppIEnumMetadata-Parameter zurückgeben.

Beim Implementieren des Enumerationsobjekts können Sie alle Metadatenleser beim ersten Erstellen des IWICMetadataBlockReader-Objekts oder beim erstmaligen Erstellen des Enumerationsobjekts erstellen, oder Sie können sie in der Implementierung der IEnumUnknown::Next-Methode verzögert erstellen. In vielen Fällen ist es effizienter, sie verzögert zu erstellen, aber im folgenden Beispiel werden die Blocklesevorgänge alle im Konstruktor erstellt, um Platz zu sparen.

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

Zum Erstellen der Metadatenleser verwenden Sie die CreateMetadataReaderFromContainer-Methode . Wenn Sie diese Methode aufrufen, übergeben Sie die GUID des Containerformats im guidContainerFormat-Parameter . Wenn Sie den Anbieter für einen Metadatenleser bevorzugen, können Sie die GUID Ihres bevorzugten Anbieters im pGuidVendor-Parameter übergeben. Wenn Ihr Unternehmen beispielsweise Metadatenhandler schreibt und Sie ihre eigenen verwenden möchten, falls vorhanden, können Sie Ihre Anbieter-GUID übergeben. In den meisten Fällen übergeben Sie einfach NULL und lassen das System den entsprechenden Metadatenleser auswählen. Wenn Sie einen bestimmten Anbieter anfordern und dieser Anbieter einen Metadatenleser auf dem Computer installiert hat, gibt WIC den Reader dieses Anbieters zurück. Wenn der angeforderte Anbieter jedoch keinen Metadatenleser auf dem Computer installiert hat und ein entsprechender Metadatenleser verfügbar ist, wird dieser Reader zurückgegeben, obwohl er nicht vom bevorzugten Anbieter stammt. Wenn auf dem Computer kein Metadatenleser für den Typ der Metadaten im Block vorhanden ist, gibt die Komponentenfactory den Unbekannten Metadatenhandler zurück, der den Metadatenblock als binäres großes Objekt (Blob) behandelt und den Metadatenblock aus der Datei deserialisiert, ohne ihn zu analysieren.

Führen Sie für den dwOptions-Parameter einen OR-Vorgang zwischen den entsprechenden WICPersistOptions mit den entsprechenden WICMetadataCreationOptions aus. Die WICPersistOptions beschreiben, wie Ihr Container angeordnet ist. Little-Endian ist die Standardeinstellung.

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

Die WICMetadataCreationOptions geben an, ob Sie den UnknownMetadataHandler wiederherstellen möchten, wenn auf dem Computer, der das Metadatenformat eines bestimmten Blocks lesen kann, kein Metadatenleser gefunden wird. WICMetadataCreationAllowUnknown ist die Standardeinstellung, und Sie sollten die Erstellung des UnknownMetadtataHandlers immer zulassen. Der UnknownMetadataHandler behandelt nicht erkannte Metadaten als BLOB. Sie kann sie nicht analysieren, schreibt sie jedoch als BLOB in den Stream und behält sie intakt bei, wenn sie während der Codierung zurück in den Stream geschrieben wird. Dadurch ist es sicher, Metadatenhandler für proprietäre Metadaten oder Metadatenformate zu erstellen, die nicht im System enthalten sind. Da Metadaten intakt beibehalten werden, auch wenn kein Handler auf dem Computer vorhanden ist, der sie erkennt, sind die Metadaten bei späterer Installation eines entsprechenden Metadatenhandlers weiterhin vorhanden und können gelesen werden. Wenn Sie die Erstellung des UnknownMetadataHandler nicht zulassen, besteht die Alternative darin, nicht erkannte Metadaten zu verwerfen oder zu überschreiben. Dies ist eine Form von Datenverlust.

Hinweis

Wenn Sie einen eigenen Metadatenhandler für proprietäre Metadaten schreiben, sollten Sie niemals Verweise auf etwas außerhalb des Metadatenblocks selbst einschließen. Obwohl der UnknownMetadataHandler Metadaten intakt behält, werden Metadaten verschoben, wenn Dateien bearbeitet werden, und alle Verweise auf elemente außerhalb des eigenen Blocks sind in diesem Fall nicht mehr gültig.

 

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

Der pIStream-Parameter ist der tatsächliche Datenstrom, den Sie decodieren. Bevor Sie den Stream übergeben, sollten Sie den Anfang des Metadatenblocks suchen, für den Sie einen Leser anfordern. Der entsprechende Metadatenleser für den Metadatenblock an der aktuellen Position im IStream wird im ppiReader-Parameter zurückgegeben.

GetReaderByIndex

GetReaderByIndex gibt den Metadatenleser am angeforderten Index in der Auflistung zurück.

Referenz

Iwicmetadatablockreader

Konzept

Implementieren von IWICBitmapFrameDecode

Implementieren von IWICBitmapSourceTransform

Schreiben eines WIC-Enabled CODEC

Übersicht über die Windows-Imageerstellungskomponente