Общие сведения о чтении и записи метаданных изображения

В этом разделе представлен обзор использования API-интерфейсов windows Imaging Component (WIC) для чтения и записи метаданных, внедренных в файлы изображений.

В этом разделе содержатся следующие подразделы.

Предварительные требования

Чтобы понять эту статью, необходимо ознакомиться с системой метаданных WIC, как описано в обзоре метаданных WIC. Вы также должны быть знакомы с языком запросов, используемым для чтения и записи метаданных, как описано в статье Общие сведения о языке запросов метаданных.

Введение

WIC предоставляет разработчикам приложений компоненты com для чтения и записи метаданных, внедренных в файлы изображений. Существует два способа чтения и записи метаданных:

  • Использование средства чтения или записи запросов и выражения запроса для запроса блоков метаданных для вложенных блоков или конкретных метаданных в блоке.
  • Использование обработчика метаданных (средства чтения метаданных или записи метаданных) для доступа к вложенным блокам метаданных или определенным метаданным в блоках метаданных.

Проще всего использовать средство чтения или записи запроса и выражение запроса для доступа к метаданным. Средство чтения запросов (IWICMetadataQueryReader) используется для чтения метаданных, а модуль записи запросов (IWICMetadataQueryWriter) — для записи метаданных. Оба они используют выражение запроса для чтения или записи нужных метаданных. В фоновом режиме средство чтения запросов (и модуля записи) использует обработчик метаданных для доступа к метаданным, описанным в выражении запроса.

Более сложный метод — прямой доступ к обработчикам метаданных. Обработчик метаданных получается из отдельных кадров с помощью средства чтения блоков (IWICMetadataBlockReader) или модуля записи блоков (IWICMetadataBlockWriter). Доступны два типа обработчиков метаданных: читатель метаданных (IWICMetadataReader) и модуль записи метаданных (IWICMetadataWriter).

Следующая схема содержимого файла изображений JPEG используется в примерах в этом разделе. Изображение, представленное этой схемой, было создано с помощью Microsoft Paint. Метаданные оценки были добавлены с помощью функции "Фотоальбом" в Windows Vista.

Изображение jpeg с метаданными оценки

Чтение Метададанных с помощью средства чтения запросов

Самый простой способ чтения метаданных — использовать интерфейс чтения запросов IWICMetadataQueryReader. Средство чтения запросов позволяет считывать блоки метаданных и элементы в блоках метаданных с помощью выражения запроса.

Существует три способа получения средства чтения запросов: через декодер растровых изображений (IWICBitmapDecoder), через отдельные кадры (IWICBitmapFrameDecode) или с помощью модуля записи запросов (IWICMetadataQueryWriter).

Получение средства чтения запросов

В следующем примере кода показано, как получить декодер растровых изображений из фабрики образов и получить отдельный кадр растрового изображения. Этот код также выполняет работу по настройке, необходимую для получения средства чтения запросов из декодированного кадра.

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 фабрики образов. В этом методе четвертому параметру присваивается значение WICDecodeMetadataCacheOnDemand из перечисления WICDecodeOptions . Это указывает декодеру кэшировать метаданные, когда метаданные необходимы. либо путем получения средства чтения запросов, либо базового средства чтения метаданных. Использование этого параметра позволяет сохранить поток метаданных, необходимых для быстрого кодирования метаданных, и обеспечивает декодирование изображения JPEG без потерь. Кроме того, можно использовать другое значение WICDecodeOptions , WICDecodeMetadataCacheOnLoad, которое кэширует метаданные внедренного образа сразу после загрузки образа.

Чтобы получить средство чтения запроса кадра, выполните простой вызов метода GetMetadataQueryReader кадра. Этот вызов показан в следующем коде.

// Get the query reader
if (SUCCEEDED(hr))
{
    hr = pFrameDecode->GetMetadataQueryReader(&pQueryReader);
}

Аналогичным образом, средство чтения запросов также можно получить на уровне декодера. При простом вызове метода GetMetadataQueryReader декодера получается средство чтения запросов декодера. Средство чтения запросов декодера, в отличие от средства чтения запросов кадра, считывает метаданные изображения, которое находится за пределами отдельных кадров. Однако этот сценарий не является распространенным, и собственные форматы изображений не поддерживают эту возможность. Собственные кодеки изображения, предоставляемые WIC, считывают и записывают метаданные на уровне кадра даже для однокадровых форматов, таких как JPEG.

Чтение метаданных

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

Иллюстрация изображения jpeg с выносками метаданных

Чтобы запросить внедренные блоки метаданных или определенные элементы по имени, вызовите метод GetMetadataByName . Этот метод принимает выражение запроса и PROPVARIANT , в котором возвращается элемент метаданных. Следующий код запрашивает вложенный блок метаданных и преобразует компонент IUnknown , предоставленный значением PROPVARIANT, в средство чтения запроса, если он найден.

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" запрашивает блок IFD, вложенный в блок App1. 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}" запрашивает блок IFD для оценки MicrosoftPhoto, внедренной в тег 18249. Значение PROPVARIANT теперь будет содержать тип VT_UI2 значения и значение данных 50.

Однако нет необходимости получать вложенный блок перед запросом конкретных значений данных. Например, вместо того, чтобы запрашивать вложенные значения IFD, а затем для оценки MicrosoftPhoto, можно использовать корневой блок метаданных и запрос, показанный в следующем коде, для получения тех же сведений.

if (SUCCEEDED(hr))
{
    hr = pQueryReader->GetMetadataByName(L"/app1/ifd/{ushort=18249}", &value);
    PropVariantClear(&value);
}

Помимо запросов к определенным элементам метаданных в блоке метаданных, можно также перечислить все элементы метаданных в блоке метаданных (не включая элементы метаданных во вложенных блоках метаданных). Для перечисления элементов метаданных в текущем блоке используется метод GetEnumeration читателя запроса. Этот метод получает интерфейс IEnumString , заполненный элементами метаданных в текущем блоке. Например, следующий код перечисляет оценку XMP и оценку MicrosoftPhoto для вложенного блока IFD, полученного ранее.

IEnumString *metadataItems = NULL;

if (SUCCEEDED(hr))
{
    hr = pEmbedReader->GetEnumerator(&metadataItems);
}

Дополнительные сведения об определении подходящих тегов для различных форматов изображений и метаданных см. в разделе Запросы метаданных в собственном формате изображений.

Дополнительные методы чтения запросов

Помимо чтения метаданных, можно также получить дополнительные сведения о средстве чтения запросов и получить метаданные с помощью других средств. Средство чтения запросов предоставляет два метода, которые предоставляют сведения о средстве чтения запросов: GetContainerFormat и GetLocation.

С помощью встроенного средства чтения запросов можно использовать 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 для внедренного средства чтения запросов возвращает GUID формата метаданных IFD. Вызов GetLocation возвращает пространство имен "/app1/ifd"; предоставляет относительный путь, из которого будут выполняться последующие запросы к новому средству чтения запросов. Конечно, приведенный выше код не очень полезен, но он демонстрирует, как использовать метод GetLocation для поиска вложенных блоков метаданных.

Запись метаданных с помощью модуля записи запросов

Примечание

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

 

Компонентом main для записи метаданных является модуль записи запросов (IWICMetadataQueryWriter). Модуль записи запросов позволяет задавать и удалять блоки метаданных и элементы внутри блока метаданных.

Как и средство чтения запросов, существует три способа получения записи запросов: с помощью кодировщика точечных изображений (IWICBitmapEncoder), через отдельные кадры (IWICBitmapFrameEncode) или через быстрый кодировщик метаданных (IWICFastMetadataEncoder).

Получение модуля записи запросов

Наиболее распространенным модулем записи запросов является отдельный кадр растрового изображения. Этот модуль записи запросов задает и удаляет блоки и элементы метаданных кадра изображения. Чтобы получить модуль записи запросов кадра изображения, вызовите метод GetMetadataQueryWriter кадра. В следующем коде показан простой вызов метода для получения модуля записи запросов кадра.

IWICMetadataQueryWriter &pFrameQWriter = NULL;

//Obtain a query writer from the frame.
hr = pFrameEncode->GetMetadataQueryWriter(&pFrameQWriter);

Аналогичным образом можно получить модуль записи запросов для уровня кодировщика. Простой вызов метода GetMetadataQueryWriter кодировщика получает модуль записи запросов кодировщика. Модуль записи запросов кодировщика, в отличие от модуля записи запросов кадра, записывает метаданные для изображения за пределами отдельного кадра. Однако этот сценарий не является распространенным, и собственные форматы изображений не поддерживают эту возможность. Собственные кодеки изображений, предоставляемые WIC, считывают и записывают метаданные на уровне кадра даже для однокадровых форматов, таких как JPEG.

Модуль записи запросов также можно получить непосредственно из фабрики образов (IWICImagingFactory). Существует два метода фабрики образов, которые возвращают модуль записи запросов: CreateQueryWriter и CreateQueryWriterFromReader.

CreateQueryWriter создает модуль записи запросов для указанного формата метаданных и поставщика. Этот модуль записи запросов позволяет записывать метаданные для определенного формата метаданных и добавлять их в изображение. В следующем коде показан вызов CreateQueryWriter для создания модуля записи запросов XMP.

IWICMetadataQueryWriter *pXMPWriter = NULL;

// Create XMP block
GUID vendor = GUID_VendorMicrosoft;
hr = pFactory->CreateQueryWriter(
        GUID_MetadataFormatXMP,
        &vendor,
        &pXMPWriter);

В этом примере понятное имя GUID_MetadataFormatXMP используется в качестве параметра guidMetadataFormat . Он представляет GUID формата метаданных XMP, а поставщик — обработчик, созданный корпорацией Майкрософт. Кроме того, значение NULL можно передать в качестве параметра pguidVendor с теми же результатами, если другой обработчик XMP не существует. Если пользовательский обработчик 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). Выражение запроса определяет блок или элемент для задания, в то время как PROPVARIANT предоставляет фактическое значение данных для задания.

В следующем примере показано, как добавить заголовок с помощью модуля записи запросов XMP, ранее полученного с помощью метода CreateQueryWriter .

// 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".

До этого момента вы не добавили метаданные в кадр изображения. Вы просто заполнили модуль записи запросов данными. Чтобы добавить в кадр блок метаданных, представленный модулем записи запросов, снова вызовите Метод SetMetadataByName , используя модуль записи запросов в качестве значения PROPVARIANT. При этом метаданные из модуля записи запросов копируются в кадр изображения. В следующем коде показано, как добавить метаданные в модуль записи запросов 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) для , указывающий VT_UNKOWN тип значения 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");
}

Копирование метаданных для повторного кодирования

Примечание

Код в этом разделе действителен, только если исходный и целевой форматы изображений совпадают. Невозможно скопировать все метаданные изображения за одну операцию при кодировании в другой формат изображения.

 

Чтобы сохранить метаданные при повторном кодировании изображения в том же формате, существуют методы копирования всех метаданных в одной операции. Каждая из этих операций соответствует аналогичной схеме; каждый из них задает метаданные декодированного кадра непосредственно в новый закодированный кадр.

Предпочтительным способом копирования метаданных является инициализация модуля записи блоков нового кадра с помощью средства чтения блоков декодированного кадра. Этот метод демонстрируется в следующем коде.

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);
    }
}

В этом примере модуль чтения блоков и модуль записи блоков получаются из исходного и целевого кадров соответственно. Затем модуль записи блоков инициализируется из средства чтения блоков. При этом модуль чтения блоков инициализируется предварительно заполненными метаданными модуля чтения блоков.

Другим способом копирования метаданных является запись блока метаданных, на который ссылается средство чтения запросов, с помощью модуля записи запросов кодировщика. Этот метод демонстрируется в следующем коде.

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);
        }
    }
}

Здесь средство чтения запросов получается из декодированного кадра, а затем используется в качестве значения свойства PROPVARIANT с типом значения, равным VT_UNKNOWN. Получается модуль записи запросов для кодировщика, а выражение запроса "/" используется для задания метаданных в корневом пути навигации. Этот метод также можно использовать при настройке вложенных блоков метаданных путем настройки выражения запроса в нужном расположении.

Аналогичным образом можно создать модуль записи запросов на основе средства чтения запросов декодированного кадра с помощью метода 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 блок XMP находится в корневом блоке метаданных, как показано в обзоре метаданных WIC. Однако в TIFF-образе блок XMP вложен в корневой блок IFD. На следующей схеме показаны различия между изображениями JPEG и TIFF с одинаковыми метаданными оценки.

Сравнение jpeg и tiff.

Быстрое кодирование метаданных

Не всегда требуется повторно кодировать изображение для записи в него новых метаданных. Метаданные также можно записать с помощью быстрого кодировщика метаданных. Быстрый кодировщик метаданных может записывать ограниченный объем метаданных в изображение без повторного кодирования изображения. Это достигается путем записи новых метаданных в пустое заполнение, предоставляемое в некоторых форматах метаданных. Собственные форматы метаданных, поддерживающие заполнение метаданных: Exif, IFD, GPS и XMP.

Добавление заполнения в блоки метаданных

Прежде чем выполнять быстрое кодирование метаданных, в блоке метаданных должно быть место для записи дополнительных метаданных. Если в существующем заполнении недостаточно места для записи новых метаданных, быстрая кодировка метаданных завершится ошибкой. Чтобы добавить заполнение метаданных к изображению, изображение должно быть закодировано повторно. Вы можете добавить заполнение так же, как и любой другой элемент метаданных, используя выражение запроса, если блок метаданных, который вы заполняете, поддерживает его. В следующем примере показано, как добавить заполнение в блок IFD, внедренный в блок App1.

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);
}

Чтобы добавить заполнение, создайте PROPVARIANT типа VT_UI4 и значение, соответствующее количеству добавляемых байтов. Обычное значение — 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();
    }
}

Если фиксация по какой-либо причине завершается сбоем, вам потребуется повторно закодировать изображение, чтобы обеспечить добавление новых метаданных в образ.

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

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

Общие сведения о метаданных WIC

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

Общие сведения о расширяемости метаданных

Практическое руководство. Повторное кодирование изображения JPEG с помощью метаданных