Visão geral dos metadados de imagem de leitura e gravação

Este tópico fornece uma visão geral de como você pode usar as APIs do WIC (Componente de Imagem do Windows) para ler e gravar metadados inseridos em arquivos de imagem.

Este tópico inclui as seções a seguir.

Pré-requisitos

Para entender este tópico, você deve estar familiarizado com o sistema de metadados wic, conforme descrito na Visão geral dos metadados do WIC. Você também deve estar familiarizado com a linguagem de consulta usada para ler e gravar metadados, conforme descrito em Visão geral da linguagem de consulta de metadados.

Introdução

O WIC fornece aos desenvolvedores de aplicativos componentes COM (Component Object Model) para ler e gravar metadados inseridos em arquivos de imagem. Há duas maneiras de ler e gravar metadados:

  • Usando um leitor/gravador de consulta e uma expressão de consulta para consultar blocos de metadados para blocos aninhados ou metadados específicos dentro de um bloco.
  • Usando um manipulador de metadados (um leitor de metadados ou um gravador de metadados) para acessar os blocos de metadados aninhados ou metadados específicos dentro dos blocos de metadados.

A mais fácil delas é usar um leitor/gravador de consulta e uma expressão de consulta para acessar os metadados. Um leitor de consulta (IWICMetadataQueryReader) é usado para ler metadados enquanto um gravador de consulta (IWICMetadataQueryWriter) é usado para gravar metadados. Ambos usam uma expressão de consulta para ler ou gravar os metadados desejados. Nos bastidores, um leitor de consulta (e gravador) usa um manipulador de metadados para acessar os metadados descritos pela expressão de consulta.

O método mais avançado é acessar diretamente os manipuladores de metadados. Um manipulador de metadados é obtido dos quadros individuais usando um leitor de bloco (IWICMetadataBlockReader) ou um gravador de blocos (IWICMetadataBlockWriter). Os dois tipos de manipuladores de metadados disponíveis são o leitor de metadados (IWICMetadataReader) e o gravador de metadados (IWICMetadataWriter).

O diagrama a seguir do conteúdo de um arquivo de imagem JPEG é usado em todos os exemplos neste tópico. A imagem representada por esse diagrama foi criada usando Microsoft Paint; os metadados de classificação foram adicionados usando o recurso Galeria de Fotos do Windows Vista.

ilustração da imagem jpeg com metadados de classificação

Lendo Metadadata usando um leitor de consulta

A maneira mais fácil de ler metadados é usar a interface do leitor de consulta, IWICMetadataQueryReader. O leitor de consulta permite que você leia blocos de metadados e itens em blocos de metadados usando uma expressão de consulta.

Há três maneiras de obter um leitor de consulta: por meio de um decodificador de bitmap (IWICBitmapDecoder), por meio de seus quadros individuais (IWICBitmapFrameDecode) ou por meio de um gravador de consulta (IWICMetadataQueryWriter).

Obtendo um leitor de consulta

O código de exemplo a seguir mostra como obter um decodificador bitmap da fábrica de imagens e recuperar um quadro de bitmap individual. Esse código também executa o trabalho de instalação necessário para obter um leitor de consulta de um quadro decodificado.

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

O decodificador de bitmap para o arquivo test.jpg é obtido usando o método CreateDecoderFromFilename da fábrica de imagens. Nesse método, o quarto parâmetro é definido como o valor WICDecodeMetadataCacheOnDemand da enumeração WICDecodeOptions . Isso informa ao decodificador para armazenar em cache os metadados quando os metadados forem necessários; obtendo um leitor de consulta ou o leitor de metadados subjacente. Usar essa opção permite manter o fluxo para os metadados necessários para codificação rápida de metadados e habilita a decodificação sem perda da imagem JPEG. Como alternativa, você pode usar o outro valor WICDecodeOptions , WICDecodeMetadataCacheOnLoad, que armazena em cache os metadados da imagem inserida assim que a imagem é carregada.

Para obter o leitor de consulta do quadro, faça uma chamada simples para o método GetMetadataQueryReader do quadro. O código a seguir demonstra essa chamada.

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

Da mesma forma, um leitor de consulta também pode ser obtido no nível do decodificador. Uma chamada simples para o método GetMetadataQueryReader do decodificador obtém o leitor de consulta do decodificador. O leitor de consulta de um decodificador, ao contrário do leitor de consulta de um quadro, lê metadados de uma imagem que está fora dos quadros individuais. No entanto, esse cenário não é comum e os formatos de imagem nativos não dão suporte a essa funcionalidade. Os CODECS de imagem nativa fornecidos pelo WIC leem e gravam metadados no nível do quadro, mesmo para formatos de quadro único, como JPEG.

Lendo metadados

Antes de passar para realmente ler metadados, examine o diagrama a seguir de um arquivo JPEG que inclui blocos de metadados inseridos e dados reais a serem recuperados. Este diagrama fornece textos explicativos para blocos e itens de metadados específicos dentro da imagem, fornecendo a expressão de consulta de metadados para cada bloco ou item.

ilustração da imagem jpeg com textos explicativos de metadados

Para consultar blocos de metadados inseridos ou itens específicos por nome, chame o método GetMetadataByName . Esse método usa uma expressão de consulta e um PROPVARIANT no qual o item de metadados é retornado. O código a seguir consulta um bloco de metadados aninhado e converte o componente IUnknown fornecido pelo valor PROPVARIANT em um leitor de consulta, se encontrado.

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
}

A expressão de consulta "/app1/ifd" está consultando o bloco IFD aninhado no bloco App1. O arquivo de imagem JPEG contém o bloco de metadados aninhados IFD, portanto, o PROPVARIANT é retornado com um tipo de variável (vt) de VT_UNKNOWN e um ponteiro para uma interface IUnknown (punkVal). Em seguida, você consulta a interface IUnknown para um leitor de consulta.

O código a seguir demonstra uma nova consulta com base no novo leitor de consulta em relação ao bloco IFD aninhado.

if (SUCCEEDED(hr))
{
    hr = pEmbedReader->GetMetadataByName(L"/{ushort=18249}", &value);
    PropVariantClear(&value); // Clear value for new query
}

A expressão de consulta "/{ushort=18249}" consulta o bloco IFD para a classificação MicrosoftPhoto inserida na marca 18249. O valor PROPVARIANT agora conterá um tipo de valor de VT_UI2 e um valor de dados de 50.

No entanto, não é necessário obter um bloco aninhado antes de consultar valores de dados específicos. Por exemplo, em vez de consultar o IFD aninhado e, em seguida, para a classificação MicrosoftPhoto, você pode usar o bloco de metadados raiz e a consulta mostrada no código a seguir para obter as mesmas informações.

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

Além de consultar itens de metadados específicos em um bloco de metadados, você também pode enumerar todos os itens de metadados em um bloco de metadados (sem incluir itens de metadados em blocos de metadados aninhados). Para enumerar os itens de metadados no bloco atual, o método GetEnumeration do leitor de consulta é usado. Esse método obtém uma interface IEnumString preenchida com os itens de metadados no bloco atual. Por exemplo, o código a seguir enumera a classificação XMP e a classificação MicrosoftPhoto para o bloco IFD aninhado que foi obtido anteriormente.

IEnumString *metadataItems = NULL;

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

Para obter mais informações sobre como identificar marcas apropriadas para vários formatos de imagem e formatos de metadados, consulte Consultas de metadados de formato de imagem nativa.

Métodos de leitor de consulta adicionais

Além de ler metadados, você também pode obter informações adicionais sobre o leitor de consulta e obter metadados por meio de outros meios. O leitor de consulta fornece dois métodos que fornecem informações sobre o leitor de consulta, GetContainerFormat e GetLocation.

Com o leitor de consulta inserido, você pode usar GetContainerFormat para determinar o tipo de bloco de metadados e pode chamar GetLocation para obter o caminho relativo ao bloco de metadados raiz. O código a seguir consulta o leitor de consulta inserido para sua localização.

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

A chamada para GetContainerFormat para o leitor de consulta inserido retorna o GUID de formato de metadados IFD. A chamada para GetLocation retorna um namespace de "/app1/ifd"; fornecendo o caminho relativo do qual as consultas subsequentes para o novo leitor de consulta serão executadas. É claro que o código anterior não é muito útil, mas demonstra como usar o método GetLocation para localizar blocos de metadados aninhados.

Gravando metadados usando um gravador de consulta

Observação

Alguns dos exemplos de código fornecidos nesta seção não são mostrados no contexto das etapas reais necessárias para gravar metadados. Para exibir os exemplos de código no contexto de um exemplo de trabalho, consulte o tutorial Como codificar novamente uma imagem com metadados.

 

O componente main para gravar metadados é o gravador de consulta (IWICMetadataQueryWriter). O gravador de consulta permite que você defina e remova blocos de metadados e itens em um bloco de metadados.

Assim como o leitor de consulta, há três maneiras de obter um gravador de consulta: por meio de um codificador bitmap (IWICBitmapEncoder), por meio de seus quadros individuais (IWICBitmapFrameEncode) ou por meio de um codificador de metadados rápido (IWICFastMetadataEncoder).

Obtendo um gravador de consulta

O gravador de consulta mais comum é para um quadro individual de um bitmap. Esse gravador de consulta define e remove os blocos e itens de metadados de um quadro de imagem. Para obter o gravador de consulta de um quadro de imagem, chame o método GetMetadataQueryWriter do quadro. O código a seguir demonstra a chamada de método simples para obter o gravador de consulta de um quadro.

IWICMetadataQueryWriter &pFrameQWriter = NULL;

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

Da mesma forma, um gravador de consulta também pode ser obtido para o nível do codificador. Uma chamada simples para o método GetMetadataQueryWriter do codificador obtém o gravador de consulta do codificador. O gravador de consulta de um codificador, ao contrário do gravador de consulta de um quadro, grava metadados para uma imagem fora do quadro individual. No entanto, esse cenário não é comum e os formatos de imagem nativos não dão suporte a essa funcionalidade. Os codecs de imagem nativos fornecidos pelo WIC leem e gravam metadados no nível do quadro, mesmo para formatos de quadro único, como JPEG.

Você também pode obter um gravador de consulta diretamente da fábrica de imagens (IWICImagingFactory). Há dois métodos de fábrica de imagens que retornam um gravador de consulta: CreateQueryWriter e CreateQueryWriterFromReader.

CreateQueryWriter cria um gravador de consulta para o formato de metadados e o fornecedor especificados. Esse gravador de consulta permite que você escreva metadados para um formato de metadados específico e adicione-os à imagem. O código a seguir demonstra uma chamada CreateQueryWriter para criar um gravador de consulta XMP.

IWICMetadataQueryWriter *pXMPWriter = NULL;

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

Neste exemplo, o nome GUID_MetadataFormatXMP amigável é usado como o parâmetro guidMetadataFormat . Ele representa o GUID de formato de metadados XMP e o fornecedor representa o manipulador criado pela Microsoft. Como alternativa, NULL poderá ser passado como o parâmetro pguidVendor com os mesmos resultados se nenhum outro manipulador XMP existir. Se um manipulador XMP personalizado estiver instalado junto com o manipulador XMP nativo, passar NULL para o fornecedor resultará no gravador de consulta com o GUID mais baixo sendo retornado.

CreateQueryWriterFromReader é semelhante ao método CreateQueryWriter , exceto que ele preenche previamente o novo gravador de consulta com os dados fornecidos pelo leitor de consulta. Isso é útil para recodificar uma imagem enquanto mantém os metadados existentes ou para remover metadados indesejados. O código a seguir demonstra uma chamada 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);

Adicionando metadados

Depois de obter um gravador de consulta, você pode usá-lo para adicionar blocos de metadados e itens. Para gravar metadados, use o método SetMetadataByName do gravador de consulta. SetMetadataByName usa dois parâmetros: uma expressão de consulta (wzName) e um ponteiro para um PROPVARIANT (pvarValue). A expressão de consulta define o bloco ou item a ser definido enquanto o PROPVARIANT fornece o valor de dados real a ser definido.

O exemplo a seguir demonstra como adicionar um título usando o gravador de consulta XMP obtido anteriormente usando o método 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);
}

Neste exemplo, o tipo de valor (vt) é definido VT_LPWSTRcomo , indicando que uma cadeia de caracteres será usada como o valor de dados. Como o tipo de valor é uma cadeia de caracteres, pwszVal é usado para definir o título a ser usado. SetMetadataByName é chamado usando a expressão de consulta "/dc:title" e o PROPVARIANT recém-definido. A expressão de consulta usada indica que a propriedade title no esquema da câmera digital (dc) deve ser definida. Observe que a expressão não é "/xmp/dc:title"; isso ocorre porque o gravador de consulta já é específico do XMP e não contém um bloco XMP inserido, o que "/xmp/dc:title" sugeriria.

Até agora, você não adicionou nenhum metadado a um quadro de imagem. Você simplesmente preencheu um gravador de consultas com dados. Para adicionar a um quadro um bloco de metadados representado pelo gravador de consulta, chame SetMetadataByName novamente usando o gravador de consulta como o valor do PROPVARIANT. Isso copia efetivamente os metadados no gravador de consulta para o quadro de imagem. O código a seguir demonstra como adicionar os metadados no gravador de consultas XMP obtidos anteriormente no bloco de metadados raiz de um quadro.

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

Neste exemplo, um tipo de valor (vt) de VT_UNKOWN é usado, indicando um tipo de valor de interface COM. O gravador de consulta XMP (piXMPWriter) é usado como o valor do PROPVARIANT, adicionando uma referência a ele usando o método AddRef. Por fim, o gravador de consulta XMP é definido chamando o método SetMetadataByName do quadro e passando a expressão de consulta "/", indicando o bloco raiz e o PROPVARIANT recém-definido.

Observação

Se o quadro já contiver o bloco de metadados que você está tentando adicionar, os metadados que você está adicionando serão adicionados e os metadados existentes serão substituídos.

 

Removendo metadados

Um gravador de consulta também permite remover metadados chamando o método RemoveMetadataByName . RemoveMetadataByName usa uma expressão de consulta e remove o bloco ou item de metadados, se existir. O código a seguir demonstra como remover o título que foi adicionado anteriormente.

if (SUCCEEDED(hr))
{
    hr = pFrameQWriter->RemoveMetadataByName(L"/xmp/dc:title");
}

O código a seguir demonstra como remover todo o bloco de metadados XMP.

if (SUCCEEDED(hr))
{
    hr = pFrameQWriter->RemoveMetadataByName(L"/xmp");
}

Copiando metadados para recodificação

Observação

O código nesta seção é válido somente quando os formatos de imagem de origem e destino são os mesmos. Não é possível copiar todos os metadados de uma imagem em uma única operação ao codificar para um formato de imagem diferente.

 

Para preservar metadados ao recodificar uma imagem para o mesmo formato de imagem, há métodos disponíveis para copiar todos os metadados em uma única operação. Cada uma dessas operações segue um padrão semelhante; cada um define os metadados do quadro decodificado diretamente no novo quadro que está sendo codificado.

O método preferencial para copiar metadados é inicializar o gravador de blocos do novo quadro com o leitor de blocos do quadro decodificado. O código a seguir demonstra esse método.

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

Neste exemplo, o leitor de bloco e o gravador de bloco são obtidos do quadro de origem e do quadro de destino, respectivamente. Em seguida, o gravador de bloco é inicializado do leitor de bloco. Isso inicializa o leitor de blocos com os metadados pré-preenchidos do leitor de bloco.

Outro método para copiar metadados é gravar o bloco de metadados referenciado pelo leitor de consulta usando o gravador de consulta do codificador. O código a seguir demonstra esse método.

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

Aqui, um leitor de consulta é obtido do quadro decodificado e, em seguida, usado como o valor da propriedade do PROPVARIANT com um tipo de valor definido como VT_UNKNOWN. O gravador de consulta para o codificador é obtido e a expressão de consulta "/" é usada para definir os metadados no caminho de navegação raiz. Você também pode usar esse método ao definir blocos de metadados aninhados ajustando a expressão de consulta para o local desejado.

Da mesma forma, você pode criar um gravador de consulta com base no leitor de consulta do quadro decodificado usando o método CreateQueryWriterFromReader da fábrica de imagens. O gravador de consulta criado nesta operação será preenchido previamente com os metadados do leitor de consulta e, em seguida, poderá ser definido no quadro. O código a seguir demonstra a operação de cópia 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);
}

Esse método usa um gravador de consulta separado criado com base nos dados do leitor de consulta. Esse novo gravador de consulta, em seguida, definido no quadro.

Novamente, essas operações para copiar metadados só funcionam quando as imagens de origem e destino têm o mesmo formato. Isso ocorre porque diferentes formatos de imagem armazenam os blocos de metadados em locais diferentes. Por exemplo, JPEG e TIFF dão suporte a blocos de metadados XMP. Em imagens JPEG, o bloco XMP está no bloco de metadados raiz, conforme ilustrado na Visão geral de metadados do WIC. No entanto, em uma imagem TIFF, o bloco XMP está aninhado em um bloco IFD raiz. O diagrama a seguir ilustra as diferenças entre uma imagem JPEG e uma imagem TIFF com os mesmos metadados de classificação.

comparação jpeg e tiff.

Codificação rápida de metadados

Nem sempre é necessário codificar novamente uma imagem para gravar novos metadados nela. Os metadados também podem ser gravados usando um codificador de metadados rápido. Um codificador de metadados rápido pode gravar uma quantidade limitada de metadados em uma imagem sem recodificar a imagem. Isso é feito escrevendo os novos metadados no preenchimento vazio fornecido por alguns formatos de metadados. Os formatos de metadados nativos que dão suporte ao preenchimento de metadados são Exif, IFD, GPS e XMP.

Adicionando preenchimento a blocos de metadados

Antes de executar a codificação rápida de metadados, deve haver espaço dentro do bloco de metadados para gravar mais metadados. Se não houver espaço suficiente no preenchimento existente para gravar os novos metadados, a codificação de metadados rápida falhará. Para adicionar o preenchimento de metadados a uma imagem, a imagem deve ser codificada novamente. Você pode adicionar o preenchimento da mesma maneira que adicionaria qualquer outro item de metadados, usando uma expressão de consulta, se o bloco de metadados que você está preenchendo der suporte a ele. O exemplo a seguir demonstra como adicionar preenchimento a um bloco IFD inserido em um bloco 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);
}

Para adicionar preenchimento, crie um PROPVARIANT do tipo VT_UI4 e um valor correspondente ao número de bytes de preenchimento a serem adicionados. Um valor típico é 4096 bytes. As consultas de metadados para JPEG, TIFF e JPEG-XR estão nesta tabela.

Formato de metadados Consulta de metadados JPEG Consulta de metadados 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

 

Obtendo um codificador de metadados rápido

Quando você tem uma imagem com preenchimento de metadados, um codificador de metadados rápido pode ser obtido usando os métodos de fábrica de imagens CreateFastMetadataEncoderFromDecoder e CreateFastMetadataEncoderFromFrameDecode.

Como o nome implica, CreateFastMetadataEncoderFromDecoder cria um codificador de metadados rápido para metadados no nível do decodificador. Os formatos de imagem nativos fornecidos pelo WIC não dão suporte a metadados no nível do decodificador, mas esse método é fornecido caso esse formato de imagem seja desenvolvido no futuro.

O cenário mais comum é obter um codificador de metadados rápido de um quadro de imagem usando CreateFastMetadataEncoderFromFrameDecode. O código a seguir obtém o codificador de metadados rápidos de um quadro decodificado e altera o valor de classificação no bloco App1.

if (SUCCEEDED(hr))
{
    IWICFastMetadataEncoder *pFME = NULL;
    IWICMetadataQueryWriter *pFMEQW = NULL;

    hr = pFactory->CreateFastMetadataEncoderFromFrameDecode(
        pFrameDecode, 
        &pFME);
}

Usando o Codificador de Metadados Rápidos

No codificador de metadados rápido, você pode obter um gravador de consulta. Isso permite que você escreva metadados usando uma expressão de consulta, conforme demonstrado anteriormente. Depois que os metadados forem definidos no gravador de consulta, confirme o codificador de metadados rápido para finalizar a atualização de metadados. O código a seguir demonstra a configuração e a confirmação das alterações de metadados

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

Se Commit falhar por algum motivo, você precisará recodificar a imagem para garantir que os novos metadados sejam adicionados à imagem.

Conceitual

Visão geral do componente de imagem do Windows

Visão geral dos metadados do WIC

Visão geral da linguagem de consulta de metadados

Visão geral da extensibilidade de metadados

Instruções: recodificar uma imagem JPEG com metadados