Condividi tramite


Panoramica della lettura e scrittura dei metadati dell'immagine

Questo argomento offre una panoramica di come è possibile usare le API Windows Imaging Component (WIC) per leggere e scrivere metadati incorporati nei file di immagine.

Questo argomento contiene le sezioni seguenti.

Prerequisiti

Per comprendere questo argomento, è necessario avere familiarità con il sistema di metadati WIC, come descritto nella Panoramica dei metadati WIC . È anche necessario avere familiarità con il linguaggio di query usato per leggere e scrivere metadati, come descritto in Panoramica del linguaggio di query dei metadati .

Introduzione

WIC fornisce agli sviluppatori di applicazioni componenti COM (Component Object Model) per leggere e scrivere metadati incorporati nei file di immagine. Esistono due modi per leggere e scrivere metadati:

  • Uso di un lettore/scrittore di query e di un'espressione di query per interrogare i blocchi di metadati, inclusi blocchi annidati o metadati specifici all'interno di un blocco.
  • Uso di un gestore di metadati (lettore di metadati o writer di metadati) per accedere ai blocchi di metadati annidati o a metadati specifici all'interno dei blocchi di metadati.

La cosa più semplice è usare un lettore/scrittore di query e un'espressione di query per accedere ai metadati. Un lettore di query (IWICMetadataQueryReader) viene usato per leggere i metadati mentre un writer di query (IWICMetadataQueryWriter) viene usato per scrivere metadati. Entrambi usano un'espressione di query per leggere o scrivere i metadati desiderati. Dietro le quinte, un lettore di query (e scrittore) utilizza un gestore di metadati per accedere ai metadati descritti dall'espressione di query.

Il metodo più avanzato consiste nell'accedere direttamente ai gestori di metadati. Un gestore di metadati viene ottenuto dai singoli fotogrammi usando un lettore di blocchi (IWICMetadataBlockReader) o uno scrittore di blocchi (IWICMetadataBlockWriter). I due tipi di gestori di metadati disponibili sono il lettore di metadati (IWICMetadataReader) e il writer di metadati (IWICMetadataWriter).

Il diagramma seguente del contenuto di un file di immagine JPEG viene usato in tutti gli esempi di questo argomento. L'immagine rappresentata da questo diagramma è stata creata usando Microsoft Paint; i metadati di classificazione sono stati aggiunti usando la funzionalità Raccolta foto di Windows Vista.

illustrazione dell'immagine jpeg con metadati di classificazione

Lettura di metadadata tramite un lettore di query

Il modo più semplice per leggere i metadati consiste nell'usare l'interfaccia del lettore di query, IWICMetadataQueryReader. Il lettore di query consente di leggere blocchi di metadati ed elementi all'interno di blocchi di metadati usando un'espressione di query.

Esistono tre modi per ottenere un lettore di query: tramite un decodificatore bitmap (IWICBitmapDecoder), tramite i singoli fotogrammi (IWICBitmapFrameDecode) o tramite un writer di query (IWICMetadataQueryWriter).

Ottenimento di un lettore di query

Il codice di esempio seguente illustra come ottenere un decodificatore bitmap dalla factory di imaging e recuperare un singolo frame bitmap. Questo codice esegue anche il lavoro di installazione necessario per ottenere un lettore di query da un frame decodificato.

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

Il decodificatore bitmap per il file test.jpg viene ottenuto tramite il metodo CreateDecoderFromFilename della fabbrica di imaging. In questo metodo, il quarto parametro viene impostato sul valore WICDecodeMetadataCacheOnDemand dall'enumerazione WICDecodeOptions. Questo indica al decodificatore di memorizzare nella cache i metadati quando sono necessari i metadati; ottenendo un lettore di query o il lettore di metadati sottostante. L'uso di questa opzione consente di conservare il flusso ai metadati necessari per la codifica rapida dei metadati e di abilitare la decodifica senza perdita di dati dell'immagine JPEG. In alternativa, puoi usare l'altro valore WICDecodeOptions, WICDecodeMetadataCacheOnLoad, che memorizza nella cache i metadati dell'immagine incorporata appena l'immagine viene caricata.

Per ottenere il lettore di query del frame, effettuare una semplice chiamata al metodo GetMetadataQueryReader del frame. Il codice seguente illustra questa chiamata.

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

Analogamente, un lettore di query può essere ottenuto anche a livello di decodificatore. Una semplice chiamata al metodo GetMetadataQueryReader del decodificatore permette di ottenere facilmente il lettore di query. Il lettore di query di un decodificatore, a differenza del lettore di query di un frame, legge i metadati per un'immagine esterna ai singoli fotogrammi. Tuttavia, questo scenario non è comune e i formati di immagine nativi non supportano questa funzionalità. Codec dell'immagine nativa fornita da WIC leggono e scrivono metadati a livello di fotogramma anche per formati a frame singolo, ad esempio JPEG.

Lettura dei metadati

Prima di passare alla lettura effettiva dei metadati, esaminare il diagramma seguente di un file JPEG che include blocchi di metadati incorporati e dati effettivi da recuperare. Questo diagramma fornisce callout a blocchi di metadati e elementi specifici all'interno dell'immagine che forniscono l'espressione di query dei metadati a ogni blocco o elemento.

illustrazione dell'immagine jpeg con annotazioni sui metadati

Per eseguire una query per i blocchi di metadati incorporati o elementi specifici in base al nome, chiamare il metodo GetMetadataByName. Questo metodo accetta un'espressione di query e un PROPVARIANT in cui viene restituito l'elemento di metadati. Il codice seguente esegue una query per un blocco di metadati annidato e converte il componente IUnknown fornito dal valore PROPVARIANT in un lettore di query, se trovato.

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
}

L'espressione di query "/app1/ifd" cerca il blocco IFD annidato all'interno del blocco App1. Il file di immagine JPEG contiene il blocco di metadati annidati IFD, quindi il PROPVARIANT viene restituito con un tipo di variabile (vt) di VT_UNKNOWN e un puntatore a un' interfaccia IUnknown (punkVal). Quindi, eseguire una query sull'interfaccia IUnknown per ottenere un lettore di query.

Il codice seguente dimostra una nuova query basata sul nuovo motore di lettura delle query in relazione al blocco IFD annidato.

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

L'espressione di query "/{ushort=18249}" interroga il blocco IFD per la valutazione di MicrosoftPhoto incorporata nel tag 18249. Il valore PROPVARIANT conterrà ora un tipo di valore di VT_UI2 e un valore di dati pari a 50.

Non è tuttavia necessario ottenere un blocco annidato prima di eseguire query su valori di dati specifici. Ad esempio, invece di eseguire query per l'IFD annidato e quindi per la classificazione MicrosoftPhoto, è invece possibile usare il blocco di metadati radice e la query illustrata nel codice seguente per ottenere le stesse informazioni.

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

Oltre all'esecuzione di query per elementi di metadati specifici in un blocco di metadati, è anche possibile enumerare tutti gli elementi di metadati in un blocco di metadati (non inclusi gli elementi di metadati nei blocchi di metadati annidati). Per enumerare gli elementi di metadati nel blocco corrente, viene utilizzato il metodo GetEnumeration del lettore di query. Questo metodo ottiene un'interfaccia IEnumString popolata con gli elementi di metadati nel blocco corrente. Il codice seguente, ad esempio, enumera la classificazione XMP e MicrosoftPhoto per il blocco IFD annidato ottenuto in precedenza.

IEnumString *metadataItems = NULL;

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

Per altre informazioni sull'identificazione dei tag appropriati per vari formati di immagine e metadati, vedere Query sui metadati in formato immagine nativo.

Metodi aggiuntivi per il lettore di query

Oltre a leggere i metadati, è anche possibile ottenere informazioni aggiuntive sul lettore di query e ottenere metadati tramite altri mezzi. Il lettore di query fornisce due metodi che forniscono informazioni sul lettore di query, GetContainerFormat e GetLocation.

Con il lettore di query incorporato, è possibile usare GetContainerFormat per determinare il tipo di blocco di metadati ed è possibile chiamare GetLocation per ottenere il percorso relativo al blocco di metadati radice. Il codice seguente esegue una query sul lettore di query incorporato per la relativa posizione.

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

La chiamata a GetContainerFormat per il lettore di query incorporato restituisce il GUID del formato di metadati IFD. La chiamata a GetLocation restituisce uno spazio dei nomi "/app1/ifd"; specificando il percorso relativo da cui verranno eseguite le query successive al nuovo lettore di query. Naturalmente, il codice precedente non è molto utile, ma dimostra come usare il metodo GetLocation per trovare blocchi di metadati annidati.

scrittura di metadati tramite uno scrittore di query

Nota

Alcuni degli esempi di codice forniti in questa sezione non vengono visualizzati nel contesto dei passaggi effettivi necessari per scrivere i metadati. Per visualizzare gli esempi di codice nel contesto di un esempio funzionante, vedere il tutorial su come Ricodificare un'immagine con metadati.

 

Il componente principale per la scrittura di metadati è lo scrittore di query (IWICMetadataQueryWriter). Il writer di query consente di impostare e rimuovere blocchi di metadati e elementi all'interno di un blocco di metadati.

Analogamente al lettore di query, esistono tre modi per ottenere uno scrittore di query: tramite un codificatore bitmap (IWICBitmapEncoder), tramite i singoli fotogrammi (IWICBitmapFrameEncode) o tramite un codificatore di metadati veloce (IWICFastMetadataEncoder).

Ottenimento di un generatore di query

Il creatore di query più comune è per un singolo fotogramma di una bitmap. Questo writer di query imposta e rimuove i blocchi di metadati e gli elementi di un frame di immagine. Per ottenere il writer di query per un frame di immagine, chiamare il metodo GetMetadataQueryWriter del frame. Il codice seguente illustra la semplice chiamata al metodo per ottenere il writer di query di un frame.

IWICMetadataQueryWriter &pFrameQWriter = NULL;

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

Analogamente, è possibile ottenere anche uno scrittore di query per il livello del codificatore. Una semplice chiamata al metodo GetMetadataQueryWriter del codificatore ottiene il writer di query del codificatore. Il writer di query di un codificatore, a differenza del writer di query di un frame, scrive i metadati per un'immagine all'esterno del singolo frame. Tuttavia, questo scenario non è comune e i formati di immagine nativi non supportano questa funzionalità. I codec immagine nativi forniti da WIC leggono e scrivono metadati a livello di fotogramma anche per formati a frame singolo, ad esempio JPEG.

È anche possibile ottenere un gestore di query direttamente dalla fabbrica di imaging (IWICImagingFactory). Esistono due metodi di fabbrica per la creazione di immagini che restituiscono uno scrittore di query: CreateQueryWriter e CreateQueryWriterFromReader.

CreateQueryWriter crea un writer di query per il formato di metadati e il fornitore specificati. Questo modulo di scrittura di query consente di redigere metadati per un formato di metadati specifico e aggiungerli all'immagine. Il codice seguente dimostra una chiamata CreateQueryWriter per creare un writer di query XMP.

IWICMetadataQueryWriter *pXMPWriter = NULL;

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

In questo esempio, il nome descrittivo GUID_MetadataFormatXMP viene usato come parametro guidMetadataFormat. Rappresenta il GUID del formato di metadati XMP e il fornitore rappresenta il gestore creato da Microsoft. In alternativa, NULL può essere passato come parametro pguidVendor con gli stessi risultati se non esiste alcun altro gestore XMP. Se un gestore XMP personalizzato viene installato insieme al gestore XMP nativo, passando NULL per il fornitore genererà il writer di query con il GUID più basso restituito.

CreateQueryWriterFromReader è simile al metodo CreateQueryWriter, ad eccezione del fatto che prepopola il nuovo writer di query con i dati forniti dal lettore di query. Ciò è utile per ri-codificare un'immagine mantenendo i metadati esistenti o rimuovendo i metadati indesiderati. Il codice seguente illustra una chiamata 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);

Aggiunta di metadati

Dopo aver ottenuto uno scrittore di query, è possibile utilizzarlo per aggiungere blocchi di metadati e elementi. Per scrivere metadati, si utilizza il metodo SetMetadataByName del writer della query. SetMetadataByName accetta due parametri: un'espressione di query (wzName) e un puntatore a un PROPVARIANT (pvarValue). L'espressione di query definisce il blocco o l'elemento da impostare mentre PROPVARIANT fornisce il valore di dati effettivo da impostare.

Nell'esempio seguente viene illustrato come aggiungere un titolo usando il writer di query XMP ottenuto in precedenza usando il metodo 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);
}

In questo esempio il tipo di valore (vt) è impostato su VT_LPWSTR, a indicare che una stringa verrà usata come valore di dati. Poiché valoretipo è una stringa, pwszVal viene usato per impostare il titolo da usare. SetMetadataByName viene quindi chiamato usando l'espressione di query "/dc:title" e il nuovo set PROPVARIANT. L'espressione di query usata indica che la proprietà title nello schema della fotocamera digitale (dc) deve essere impostata. Si noti che l'espressione non è "/xmp/dc:title". Questo perché l'autore delle query è già specifico per XMP e non contiene un blocco XMP incorporato, come suggerirebbe "/xmp/dc:title".

Fino a questo punto non sono stati effettivamente aggiunti metadati a un frame di immagine. Hai semplicemente popolato un writer di query con i dati. Per aggiungere un blocco di metadati, rappresentato dal query writer, a un frame, chiamare nuovamente SetMetadataByName utilizzando il query writer come valore del PROPVARIANT. In questo modo i metadati nello scrittore di query vengono copiati nel frame dell'immagine. Il codice seguente illustra come aggiungere i metadati nel writer di query XMP ottenuto in precedenza al blocco di metadati radice di un frame.

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

In questo esempio viene usato un tipo valore (vt) di VT_UNKOWN; che indica un tipo di valore dell'interfaccia COM. Il writer di query XMP (piXMPWriter) viene quindi usato come valore del PROPVARIANT, aggiungendo un riferimento a esso usando il metodo AddRef. Infine, il writer di query XMP viene impostato chiamando il metodo SetMetadataByName del frame e passando l'espressione di query "/", che indica il blocco radice, e il nuovo PROPVARIANT impostato.

Nota

Se il frame contiene già il blocco di metadati che si sta tentando di aggiungere, verranno aggiunti i metadati aggiunti e i metadati esistenti sovrascritti.

 

Rimozione dei metadati

Un writer di query consente inoltre di rimuovere i metadati chiamando il metodo RemoveMetadataByName. RemoveMetadataByName accetta un'espressione di query e rimuove il blocco di metadati o l'elemento, se esistente. Il codice seguente illustra come rimuovere il titolo aggiunto in precedenza.

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

Il codice seguente illustra come rimuovere l'intero blocco di metadati XMP.

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

Copia dei metadati per la ricodifica

Nota

Il codice in questa sezione è valido solo quando i formati di immagine di origine e di destinazione sono uguali. Non è possibile copiare tutti i metadati di un'immagine in una singola operazione quando si esegue la codifica in un formato di immagine diverso.

 

Per conservare i metadati durante la riscrittura di un'immagine nello stesso formato di immagine, sono disponibili metodi per copiare tutti i metadati in una singola operazione. Ognuna di queste operazioni segue un modello simile; ogni imposta i metadati del frame decodificato direttamente nel nuovo frame da codificare.

Il metodo preferito per copiare i metadati consiste nell'inizializzare lo scrittore di blocchi del nuovo frame con il lettore di blocchi del frame decodificato. Il codice seguente illustra questo metodo.

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

In questo esempio, il lettore di blocchi e il writer di blocchi vengono ottenuti rispettivamente dal frame di origine e dal frame di destinazione. Lo scrittore di blocchi viene quindi inizializzato dal lettore di blocchi. Inizializza il lettore di blocchi con i metadati precompilati.

Un altro metodo per copiare i metadati consiste nello scrivere il blocco di metadati a cui fa riferimento il lettore di query usando lo scrittore di query del codificatore. Il codice seguente illustra questo metodo.

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

In questo caso, un lettore di query viene ottenuto dal frame decodificato e quindi usato come valore della proprietà del PROPVARIANT con un tipo di valore impostato su VT_UNKNOWN. Il generatore di query per il codificatore viene ottenuto e l'espressione di query "/" viene utilizzata per impostare i metadati nel percorso di navigazione radice. È anche possibile usare questo metodo quando si impostano blocchi di metadati annidati modificando l'espressione di query in base alla posizione desiderata.

Analogamente, è possibile creare un writer di query basato sul lettore di query del frame decodificato usando il metodo CreateQueryWriterFromReader della fabbrica di imaging. Il generatore di query creato in questa operazione verrà precompilato con i metadati del lettore di query e quindi può essere impostato nel quadro. Il codice seguente illustra l'operazione di copia 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);
}

Questo metodo crea un writer di query separato che si basa sui dati del lettore di query. Questo nuovo creatore di query viene quindi inserito nel contesto.

Anche in questo caso, queste operazioni per copiare i metadati funzionano solo quando le immagini di origine e di destinazione hanno lo stesso formato. Ciò è dovuto al fatto che i diversi formati di immagine archiviano i blocchi di metadati in posizioni diverse. Ad esempio, sia JPEG che TIFF supportano blocchi di metadati XMP. Nelle immagini JPEG, il blocco XMP si trova nel blocco di metadati radice, come illustrato nella Panoramica dei Metadati WIC . Tuttavia, in un'immagine TIFF, il blocco XMP è annidato in un blocco IFD radice. Il diagramma seguente illustra le differenze tra un'immagine JPEG e un'immagine TIFF con gli stessi metadati di classificazione.

confronto tra jpeg e tiff.

Codifica rapida dei metadati

Non è sempre necessario codificare nuovamente un'immagine per scrivere nuovi metadati. I metadati possono essere scritti anche usando un codificatore di metadati veloce. Un codificatore di metadati veloce può scrivere una quantità limitata di metadati in un'immagine senza codificare nuovamente l'immagine. A tale scopo, scrivere i nuovi metadati all'interno della spaziatura interna vuota fornita da alcuni formati di metadati. I formati di metadati nativi che supportano la spaziatura interna dei metadati sono Exif, IFD, GPS e XMP.

Aggiunta di spaziatura interna ai blocchi di metadati

Prima di poter eseguire una codifica rapida dei metadati, è necessario disporre di spazio all'interno del blocco di metadati per scrivere altri metadati. Se la spaziatura interna esistente non è sufficiente per scrivere i nuovi metadati, la codifica rapida dei metadati avrà esito negativo. Per aggiungere la spaziatura interna dei metadati a un'immagine, l'immagine deve essere codificata nuovamente. È possibile aggiungere la spaziatura interna allo stesso modo in cui si aggiunge qualsiasi altro elemento di metadati, usando un'espressione di query, se il blocco di metadati che stai imbottendo lo supporta. L'esempio seguente illustra come aggiungere spaziatura interna a un blocco IFD incorporato in un blocco 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);
}

Per aggiungere riempimento, creare un PROPVARIANT di tipo VT_UI4 e un valore corrispondente al numero di byte di riempimento da aggiungere. Un valore tipico è 4096 byte. Le query sui metadati per JPEG, TIFF e JPEG-XR si trovano in questa tabella.

Il formato dei metadati Interrogazione sui metadati JPEG TIFF, interrogazione dei metadati 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

 

Ottenere un encoder rapido di metadati

Quando si dispone di un'immagine con riempimento dei metadati, è possibile ottenere un codificatore di metadati rapido usando i metodi della fabbrica di imaging CreateFastMetadataEncoderFromDecoder e CreateFastMetadataEncoderFromFrameDecode.

Come suggerisce il nome, CreateFastMetadataEncoderFromDecoder crea un codificatore di metadati rapido per i metadati a livello di decodificatore. I formati di immagine nativi forniti da WIC non supportano i metadati a livello di decodificatore, ma questo metodo viene fornito nel caso in cui tale formato di immagine venga sviluppato in futuro.

Lo scenario più comune consiste nel ottenere un codificatore di metadati veloce da un frame di immagine usando CreateFastMetadataEncoderFromFrameDecode. Il codice seguente ottiene un codificatore di metadati veloce di un frame decodificato e modifica il valore di classificazione nel blocco App1.

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

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

Uso del codificatore di metadati veloci

Puoi ottenere uno scrittore di query dal codificatore di metadati rapido. In questo modo è possibile scrivere metadati usando un'espressione di query come illustrato in precedenza. Dopo aver impostato i metadati nel writer di query, eseguire il commit del codificatore di metadati rapido per finalizzare l'aggiornamento dei metadati. Il codice seguente illustra l'impostazione e il commit delle modifiche ai metadati

    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 ha esito negativo per qualsiasi motivo, sarà necessario codificare nuovamente l'immagine per assicurarsi che i nuovi metadati vengano aggiunti all'immagine.

concettuale

Panoramica del componente Windows Imaging

panoramica dei metadati WIC

panoramica del linguaggio di query dei metadati

panoramica dell'estendibilità dei metadati

Procedura: Codificare nuovamente un'immagine JPEG con metadati