Condividi tramite


Panoramica della lettura e della scrittura dei metadati dell'immagine

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

In questo argomento sono contenute 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 consigliabile acquisire 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 Component Object Model (COM) per leggere e scrivere metadati incorporati nei file di immagine. Esistono due modi per leggere e scrivere metadati:

  • Uso di un lettore di query/writer e un'espressione di query per eseguire query sui blocchi di metadati per 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 ai metadati specifici all'interno dei blocchi di metadati.

La soluzione più semplice consiste nell'usare un lettore di query/writer e un'espressione di query per accedere ai metadati. Un lettore di query (IWICMetadataQueryReader) viene usato per leggere i metadati mentre viene usato un writer di query (IWICMetadataQueryWriter) per scrivere metadati. Entrambi usano un'espressione di query per leggere o scrivere i metadati desiderati. Dietro le quinte, un lettore di query (e writer) usa 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 dei metadati viene ottenuto dai singoli frame usando un lettore a blocchi (IWICMetadataBlockReader) o un writer a 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 di lettura query IWICMetadataQueryReader. Il lettore di query consente di leggere blocchi di metadati e 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 frame (IWICBitmapFrameDecode) o tramite un writer di query (IWICMetadataQueryWriter).

Recupero 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 configurazione necessario per ottenere un lettore di query da una cornice decodificata.

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 usando il metodo CreateDecoderFromFilename della factory di imaging. In questo metodo il quarto parametro è impostato sul valore WICDecodeMetadataCacheOnDemand dall'enumerazione WICDecodeOptions . Questo indica al decodificatore di memorizzare nella cache i metadati quando sono necessari i metadati; ottiene 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 dell'immagine JPEG. In alternativa, è possibile usare l'altro valore WICDecodeOptions, WICDecodeMetadataCacheOnLoad , che memorizza nella cache i metadati dell'immagine incorporati non appena viene caricata l'immagine.

Per ottenere il lettore di query del frame, eseguire 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 ottiene il lettore di query del decodificatore. 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à. I CODEC di immagine nativi forniti da WIC leggono e scrivono metadati a livello di frame anche per i formati a frame singolo, ad esempio JPEG.

Lettura dei metadati

Prima di passare alla lettura dei metadati in realtà, 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 fornisce l'espressione di query dei metadati a ogni blocco o elemento.

illustrazione dell'immagine jpeg con callout dei metadati

Per eseguire una query per 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 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" esegue una query per il blocco IFD annidato nel blocco App1. Il file di immagine JPEG contiene il blocco di metadati annidato IFD, quindi il PROPVARIANT viene restituito con un tipo di variabile (vt) di VT_UNKNOWN e un puntatore a un'interfaccia IUnknown (punkVal). Si esegue quindi una query sull'interfaccia IUnknown per un lettore di query.

Il codice seguente illustra una nuova query basata sul nuovo lettore di query rispetto 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}" esegue una query sul blocco IFD per la classificazione MicrosoftPhoto incorporata nel tag 18249. Il valore PROPVARIANT conterrà ora un tipo di valore e VT_UI2 un valore di dati pari a 50.

Tuttavia, non è necessario ottenere un blocco annidato prima di eseguire query per valori di dati specifici. Ad esempio, anziché eseguire query per l'IFD annidata e quindi per la classificazione MicrosoftPhoto, è possibile usare il blocco dei 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 a eseguire 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 dei metadati nei blocchi di metadati annidati). Per enumerare gli elementi dei metadati nel blocco corrente, viene usato il metodo GetEnumeration del lettore di query. Questo metodo ottiene un'interfaccia IEnumString popolata con gli elementi dei metadati nel blocco corrente. Ad esempio, il codice seguente enumera la classificazione XMP e La classificazione MicrosoftPhoto per il blocco IFD annid annid ottenuto in precedenza.

IEnumString *metadataItems = NULL;

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

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

Metodi aggiuntivi di lettura query

Oltre alla lettura dei 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 e è 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 dei metadati IFD. La chiamata a GetLocation restituisce uno spazio dei nomi "/app1/ifd"; fornendo il percorso relativo da cui verranno eseguite query successive al nuovo lettore di query. Naturalmente, il codice precedente non è molto utile, ma illustra come usare il metodo GetLocation per trovare blocchi di metadati annidati.

Scrittura di metadati tramite un writer di query

Nota

Alcuni degli esempi di codice forniti in questa sezione non vengono visualizzati nel contesto dei passaggi effettivi necessari per scrivere metadati. Per visualizzare gli esempi di codice nel contesto di un esempio funzionante, vedere l'esercitazione Procedura: Codificare nuovamente un'immagine con metadati.

 

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

Come il lettore di query, esistono tre modi per ottenere un writer di query: tramite un codificatore bitmap (IWICBitmapEncoder), tramite i singoli frame (IWICBitmapFrameEncode) o tramite un codificatore di metadati veloce (IWICFastMetadataEncoder).

Recupero di un writer di query

Il writer di query più comune è per un singolo frame di una bitmap. Questo writer di query imposta e rimuove i blocchi e gli elementi dei metadati di un frame di immagine. Per ottenere il writer di query di un frame di immagini, 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, è anche possibile ottenere un writer 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 metadati per un'immagine all'esterno del singolo frame. Tuttavia, questo scenario non è comune e i formati di immagine nativa non supportano questa funzionalità. I codec immagine nativi forniti da WIC leggono e scrivono metadati a livello di frame anche per formati a fotogrammi singoli, ad esempio JPEG.

È anche possibile ottenere un writer di query direttamente dalla factory di imaging (IWICImagingFactory). Esistono due metodi di imaging factory che restituiscono un writer di query: CreateQueryWriter e CreateQueryWriterFromReader.

CreateQueryWriter crea un writer di query per il formato di metadati e il fornitore specificati. Questo writer di query consente di scrivere metadati per un formato di metadati specifico e aggiungerli all'immagine. Il codice seguente illustra 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 GUID_MetadataFormatXMP descrittivo viene usato come parametro guidMetadataFormat . Rappresenta il GUID del formato di metadati XMP e il fornitore rappresenta il gestore creato da Microsoft. In alternativa, è possibile passare NULL 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, il passaggio di NULL per il fornitore comporterà la restituzione del writer di query con il GUID più basso.

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 la ridecrittura di 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 un writer di query, è possibile usarlo per aggiungere blocchi di metadati ed elementi. Per scrivere metadati, usare il metodo SetMetadataByName del writer di 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é il tipo di valore è 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 utilizzata 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é il writer di query è già specifico per XMP e non contiene un blocco XMP incorporato, che "/xmp/dc:title" suggerisce.

Fino a questo punto non sono stati effettivamente aggiunti metadati a un frame di immagine. È stato semplicemente popolato un writer di query con dati. Per aggiungere a un frame un blocco di metadati rappresentato dal writer di query, chiamare di nuovo SetMetadataByName usando il writer di query come valore di PROPVARIANT. In questo modo i metadati nel writer 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 utilizzato 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 di 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 set PROPVARIANT.

Nota

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

 

Rimozione dei metadati

Un writer di query consente anche 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 riscrittura

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 mantenere i metadati durante la riprocrittura 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; ognuno imposta i metadati del frame decodificato direttamente nel nuovo frame codificato.

Il metodo preferito per copiare i metadati consiste nell'inizializzare il writer 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. Il writer di blocchi viene quindi inizializzato dal lettore di blocchi. Inizializza il lettore di blocchi con i metadati prepopolato del lettore di blocchi.

Un altro metodo per copiare i metadati consiste nel scrivere il blocco di metadati a cui fa riferimento il lettore di query usando il writer 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à di PROPVARIANT con un tipo valore impostato su VT_UNKNOWN. Il writer di query per il codificatore viene ottenuto e l'espressione di query "/" viene usata per impostare i metadati nel percorso di spostamento 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 factory di imaging. Il writer di query creato in questa operazione verrà prepopolato con i metadati del lettore di query e potrà quindi essere impostato nel frame. 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 usa un writer di query separato che si basa sui dati del lettore di query. Questo nuovo writer di query viene quindi impostato nel frame.

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 diversi formati di immagine archiviano i blocchi di metadati in posizioni diverse. Ad esempio, jpeg e 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. In un'immagine TIFF, tuttavia, il blocco XMP viene 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 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 rapido. 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 la codifica rapida dei metadati, è necessario disporre di spazio all'interno del blocco di metadati per scrivere altri metadati. Se non è presente spazio sufficiente all'interno della spaziatura interna esistente 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 si sta spaziando lo supporta. Nell'esempio seguente viene illustrato come aggiungere la 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 la spaziatura interna, 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.

Formato metadati Query sui metadati JPEG Query sui metadati 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

 

Recupero di un codificatore di metadati veloce

Quando si dispone di un'immagine con spaziatura interna dei metadati, è possibile ottenere un codificatore di metadati rapido usando i metodi 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 rapido da un frame di immagine usando CreateFastMetadataEncoderFromFrameDecode. Il codice seguente ottiene un codificatore di metadati rapido 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 rapidi

Dal codificatore di metadati rapido è possibile ottenere un writer di query. 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 dei 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 non riesce per qualsiasi motivo, sarà necessario codificare nuovamente l'immagine per assicurarsi che i nuovi metadati vengano aggiunti all'immagine.

Informazioni concettuali

Panoramica del componente Windows Imaging

Panoramica dei metadati WIC

Panoramica del linguaggio di query sui metadati

Panoramica dell'estendibilità dei metadati

Procedura: Codificare nuovamente un'immagine JPEG con metadati