Реализация IWICMetadataBlockReader

IWICMetadataBlockReader

В изображении часто существует несколько блоков метаданных, каждый из которых представляет различные типы информации в разных форматах. В модели windows Imaging Component (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 совпадает с методом GetContainerFormat в разделе Implementing IWICBitmapDecoder.

GetCount

GetCount возвращает количество блоков метаданных верхнего уровня, связанных с кадром.

GetEnumerator

GetEnumerator возвращает перечислитель, который вызывающий объект может использовать для перечисления блоков метаданных во фрейме и чтения их метаданных. Для реализации этого метода необходимо создать средство чтения метаданных для каждого блока метаданных и реализовать объект перечисления, который выполняет перечисление по коллекции средств чтения метаданных. Объект перечисления должен реализовывать IEnumUnknown , чтобы его можно было привести к IEnumUnknown при возврате в параметре ppIEnumMetadata .

При реализации объекта перечисления можно создать все средства чтения метаданных при первом создании объекта 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 . Если у вас есть предпочтение поставщика для средства чтения метаданных, вы можете передать GUID предпочтительного поставщика в параметре pGuidVendor . Например, если ваша компания записывает обработчики метаданных и вы хотите использовать собственные, если они имеются, вы можете передать GUID поставщика. В большинстве случаев необходимо просто передать значение NULL и позволить системе выбрать соответствующее средство чтения метаданных. Если вы запрашиваете определенного поставщика и у этого поставщика на компьютере установлено средство чтения метаданных, WIC вернет средство чтения этого поставщика. Однако если у запрошенного поставщика на компьютере не установлено средство чтения метаданных, а также если доступно соответствующее средство чтения метаданных, это средство чтения будет возвращено, даже если оно не от предпочтительного поставщика. Если на компьютере нет средства чтения метаданных для типа метаданных в блоке, фабрика компонентов вернет неизвестный обработчик метаданных, который будет обрабатывать блок метаданных как большой двоичный объект (BLOB) и десериализовать блок метаданных из файла без каких-либо попыток его анализа.

Для параметра dwOptions выполните операцию OR между соответствующим wicPersistOptions с соответствующим wicMetadataCreationOptions. WiCPersistOptions описывает, как расположен контейнер. По умолчанию используется маленький байт.

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

WiCMetadataCreationOptionOptions указывает, нужно ли вернуть UnknownMetadataHandler, если на компьютере, который может считывать формат метаданных определенного блока, не найден модуль чтения метаданных. WICMetadataCreationAllowUnknown используется по умолчанию, и вы всегда должны разрешать создание UnknownMetadtataHandler. UnknownMetadataHandler обрабатывает нераспознанные метаданные как большой двоичный объект. Он не может проанализировать его, но записывает его в поток как большой двоичный объект и сохраняет его без изменений при записи обратно в поток во время кодирования. Это позволяет безопасно создавать обработчики метаданных для собственных метаданных или форматов метаданных, которые не поставляются вместе с системой. Поскольку метаданные сохраняются без изменений, даже если на компьютере, распознаваемом их, отсутствует обработчик, при последующей установке соответствующего обработчика метаданных метаданные будут оставаться там и могут быть прочитаны. Если вы не разрешаете создание UnknownMetadataHandler, альтернативным вариантом является удаление или перезапись нераспознанных метаданных. Это форма потери данных.

Примечание

Если вы создаете собственный обработчик метаданных для собственных метаданных, никогда не следует включать ссылки на что-либо за пределами самого блока метаданных. Несмотря на то, что UnknownMetadataHandler сохраняет метаданные без изменений, метаданные перемещаются при редактировании файлов, а все ссылки на что-либо за пределами собственного блока больше не будут действительными в этом случае.

 

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

Параметр pIStream — это фактический поток, который вы декодируете. Перед передачей потока необходимо найти начало блока метаданных, для которого запрашивается средство чтения. Соответствующее средство чтения метаданных для блока метаданных в текущей позиции в IStream будет возвращено в параметре ppiReader .

GetReaderByIndex

GetReaderByIndex возвращает средство чтения метаданных по запрошенным индексам в коллекции.

Reference

IWICMetadataBlockReader

Основные понятия

Реализация IWICBitmapFrameDecode

Реализация IWICBitmapSourceTransform

Написание кодека WIC-Enabled

Общие сведения о компоненте обработки образов Windows