Vue d’ensemble de la lecture et de l’écriture de métadonnées d’image

Cette rubrique fournit une vue d’ensemble de la façon dont vous pouvez utiliser les API WIC (Windows Imaging Component) pour lire et écrire des métadonnées incorporées dans des fichiers image.

Cette rubrique contient les sections suivantes.

Prérequis

Pour comprendre cette rubrique, vous devez vous familiariser avec le système de métadonnées WIC, comme décrit dans vue d’ensemble des métadonnées WIC. Vous devez également vous familiariser avec le langage de requête utilisé pour lire et écrire des métadonnées, comme décrit dans Vue d’ensemble du langage de requête de métadonnées.

Introduction

WIC fournit aux développeurs d’applications des composants COM (Component Object Model) pour lire et écrire des métadonnées incorporées dans des fichiers image. Il existe deux façons de lire et d’écrire des métadonnées :

  • Utilisation d’un lecteur/enregistreur de requête et d’une expression de requête pour interroger des blocs de métadonnées imbriqués ou des métadonnées spécifiques dans un bloc.
  • Utilisation d’un gestionnaire de métadonnées (lecteur de métadonnées ou enregistreur de métadonnées) pour accéder aux blocs de métadonnées imbriqués ou aux métadonnées spécifiques dans les blocs de métadonnées.

Le plus simple est d’utiliser un lecteur/enregistreur de requête et une expression de requête pour accéder aux métadonnées. Un lecteur de requête (IWICMetadataQueryReader) est utilisé pour lire les métadonnées, tandis qu’un enregistreur de requête (IWICMetadataQueryWriter) est utilisé pour écrire des métadonnées. Les deux utilisent une expression de requête pour lire ou écrire les métadonnées souhaitées. En arrière-plan, un lecteur de requête (et un enregistreur) utilise un gestionnaire de métadonnées pour accéder aux métadonnées décrites par l’expression de requête.

La méthode la plus avancée consiste à accéder directement aux gestionnaires de métadonnées. Un gestionnaire de métadonnées est obtenu à partir des images individuelles à l’aide d’un lecteur de blocs (IWICMetadataBlockReader) ou d’un enregistreur de blocs (IWICMetadataBlockWriter). Les deux types de gestionnaires de métadonnées disponibles sont le lecteur de métadonnées (IWICMetadataReader) et l’enregistreur de métadonnées (IWICMetadataWriter).

Le diagramme suivant du contenu d’un fichier image JPEG est utilisé dans les exemples de cette rubrique. L’image représentée par ce diagramme a été créée à l’aide de Microsoft Paint ; les métadonnées d’évaluation ont été ajoutées à l’aide de la fonctionnalité Galerie de photos de Windows Vista.

illustration d’une image jpeg avec des métadonnées d’évaluation

Lecture de Metadadata à l’aide d’un lecteur de requête

Le moyen le plus simple de lire les métadonnées consiste à utiliser l’interface de lecteur de requête , IWICMetadataQueryReader. Le lecteur de requête vous permet de lire des blocs de métadonnées et des éléments dans des blocs de métadonnées à l’aide d’une expression de requête.

Il existe trois façons d’obtenir un lecteur de requête : par le biais d’un décodeur bitmap (IWICBitmapDecoder), de ses images individuelles (IWICBitmapFrameDecode) ou d’un enregistreur de requêtes (IWICMetadataQueryWriter).

Obtention d’un lecteur de requête

L’exemple de code suivant montre comment obtenir un décodeur bitmap à partir de la fabrique d’images et récupérer un cadre bitmap individuel. Ce code effectue également le travail d’installation nécessaire pour obtenir un lecteur de requête à partir d’une trame décodée.

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

Le décodeur bitmap du fichier test.jpg est obtenu à l’aide de la méthode CreateDecoderFromFilename de la fabrique d’images. Dans cette méthode, le quatrième paramètre est défini sur la valeur WICDecodeMetadataCacheOnDemand de l’énumération WICDecodeOptions . Cela indique au décodeur de mettre en cache les métadonnées lorsque les métadonnées sont nécessaires ; soit en obtenant un lecteur de requête ou le lecteur de métadonnées sous-jacent. L’utilisation de cette option vous permet de conserver le flux vers les métadonnées requises pour un encodage rapide des métadonnées et permet le décodage sans perte de l’image JPEG. Vous pouvez également utiliser l’autre valeur WICDecodeOptions , WICDecodeMetadataCacheOnLoad, qui met en cache les métadonnées d’image incorporées dès que l’image est chargée.

Pour obtenir le lecteur de requête du frame, effectuez un appel simple à la méthode GetMetadataQueryReader du frame. Le code suivant illustre cet appel.

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

De même, un lecteur de requête peut également être obtenu au niveau du décodeur. Un simple appel à la méthode GetMetadataQueryReader du décodeur obtient le lecteur de requête du décodeur. Le lecteur de requête d’un décodeur, contrairement au lecteur de requête d’une trame, lit les métadonnées d’une image qui se trouve en dehors des trames individuelles. Toutefois, ce scénario n’est pas courant et les formats d’image natifs ne prennent pas en charge cette fonctionnalité. Les codecs d’image natifs fournis par WIC lisent et écrivent des métadonnées au niveau de l’image, même pour les formats mono frame tels que JPEG.

Lecture des métadonnées

Avant de passer à la lecture des métadonnées, consultez le diagramme suivant d’un fichier JPEG qui inclut des blocs de métadonnées incorporés et des données réelles à récupérer. Ce diagramme fournit des légendes pour des blocs de métadonnées et des éléments spécifiques dans l’image fournissant l’expression de requête de métadonnées pour chaque bloc ou élément.

illustration d’une image jpeg avec des légendes de métadonnées

Pour rechercher des blocs de métadonnées incorporés ou des éléments spécifiques par nom, appelez la méthode GetMetadataByName . Cette méthode prend une expression de requête et un PROPVARIANT dans lequel l’élément de métadonnées est retourné. Le code suivant interroge un bloc de métadonnées imbriqué et convertit le composant IUnknown fourni par la valeur PROPVARIANT en lecteur de requête s’il est trouvé.

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’expression de requête « /app1/ifd » interroge le bloc IFD imbriqué dans le bloc App1. Le fichier image JPEG contient le bloc de métadonnées imbriquées IFD, de sorte que le PROPVARIANT est retourné avec un type variable (vt) de VT_UNKNOWN et un pointeur vers une interface IUnknown (punkVal). Vous interrogez ensuite l’interface IUnknown pour un lecteur de requête.

Le code suivant illustre une nouvelle requête basée sur le nouveau lecteur de requête par rapport au bloc IFD imbriqué.

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

L’expression de requête « /{ushort=18249} » interroge le bloc IFD pour l’évaluation MicrosoftPhoto incorporée sous la balise 18249. La valeur PROPVARIANT contient désormais un type valeur de VT_UI2 et une valeur de données de 50.

Toutefois, il n’est pas nécessaire d’obtenir un bloc imbriqué avant d’interroger des valeurs de données spécifiques. Par instance, au lieu d’interroger l’IFD imbriqué et l’évaluation MicrosoftPhoto, vous pouvez utiliser le bloc de métadonnées racine et la requête indiquée dans le code suivant pour obtenir les mêmes informations.

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

En plus d’interroger des éléments de métadonnées spécifiques dans un bloc de métadonnées, vous pouvez également énumérer tous les éléments de métadonnées d’un bloc de métadonnées (sans inclure les éléments de métadonnées dans les blocs de métadonnées imbriqués). Pour énumérer les éléments de métadonnées dans le bloc actuel, la méthode GetEnumeration du lecteur de requête est utilisée. Cette méthode obtient une interface IEnumString remplie avec les éléments de métadonnées dans le bloc actif. Par exemple, le code suivant énumère l’évaluation XMP et l’évaluation MicrosoftPhoto pour le bloc IFD imbriqué obtenu précédemment.

IEnumString *metadataItems = NULL;

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

Pour plus d’informations sur l’identification des balises appropriées pour différents formats d’image et formats de métadonnées, consultez Requêtes de métadonnées de format d’image native.

Méthodes de lecteur de requête supplémentaires

En plus de lire les métadonnées, vous pouvez également obtenir des informations supplémentaires sur le lecteur de requête et obtenir des métadonnées par d’autres moyens. Le lecteur de requête fournit deux méthodes qui fournissent des informations sur le lecteur de requête : GetContainerFormat et GetLocation.

Avec le lecteur de requête incorporé, vous pouvez utiliser GetContainerFormat pour déterminer le type de bloc de métadonnées, et vous pouvez appeler GetLocation pour obtenir le chemin d’accès relatif au bloc de métadonnées racine. Le code suivant interroge le lecteur de requête incorporé pour son emplacement.

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

L’appel à GetContainerFormat pour le lecteur de requête incorporé retourne le GUID de format de métadonnées IFD. L’appel à GetLocation renvoie un espace de noms « /app1/ifd » ; vous fournissant le chemin d’accès relatif à partir duquel les requêtes suivantes vers le nouveau lecteur de requête seront exécutées. Bien sûr, le code précédent n’est pas très utile, mais il montre comment utiliser la méthode GetLocation pour rechercher les blocs de métadonnées imbriqués.

Écriture de métadonnées à l’aide d’un enregistreur de requêtes

Notes

Certains des exemples de code fournis dans cette section ne s’affichent pas dans le contexte des étapes réelles requises pour écrire des métadonnées. Pour afficher les exemples de code dans le contexte d’un exemple de travail, consultez le tutoriel Procédure : réencoder une image avec des métadonnées.

 

Le composant main pour l’écriture de métadonnées est l’enregistreur de requêtes (IWICMetadataQueryWriter). L’enregistreur de requêtes vous permet de définir et de supprimer des blocs de métadonnées et des éléments dans un bloc de métadonnées.

À l’instar du lecteur de requête, il existe trois façons d’obtenir un enregistreur de requête : via un encodeur bitmap (IWICBitmapEncoder), via ses trames individuelles (IWICBitmapFrameEncode) ou via un encodeur de métadonnées rapide (IWICFastMetadataEncoder).

Obtention d’un enregistreur de requêtes

L’enregistreur de requêtes le plus courant est pour une image individuelle d’une bitmap. Cet enregistreur de requêtes définit et supprime les blocs de métadonnées et les éléments d’un cadre d’image. Pour obtenir l’enregistreur de requêtes d’une image, appelez la méthode GetMetadataQueryWriter de l’image. Le code suivant illustre l’appel de méthode simple pour obtenir l’enregistreur de requête d’un frame.

IWICMetadataQueryWriter &pFrameQWriter = NULL;

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

De même, un enregistreur de requêtes peut également être obtenu pour le niveau de l’encodeur. Un simple appel à la méthode GetMetadataQueryWriter de l’encodeur obtient l’enregistreur de requêtes de l’encodeur. L’enregistreur de requêtes d’un encodeur, contrairement à l’enregistreur de requêtes d’une image, écrit des métadonnées pour une image en dehors du cadre individuel. Toutefois, ce scénario n’est pas courant et les formats d’image natifs ne prennent pas en charge cette fonctionnalité. Les codecs d’image natifs fournis par WIC lisent et écrivent des métadonnées au niveau de l’image, même pour les formats mono frame tels que JPEG.

Vous pouvez également obtenir un enregistreur de requêtes directement à partir de la fabrique d’images (IWICImagingFactory). Il existe deux méthodes de fabrique d’images qui retournent un enregistreur de requêtes : CreateQueryWriter et CreateQueryWriterFromReader.

CreateQueryWriter crée un enregistreur de requêtes pour le format de métadonnées et le fournisseur spécifiés. Cet enregistreur de requêtes vous permet d’écrire des métadonnées pour un format de métadonnées spécifique et de les ajouter à l’image. Le code suivant illustre un appel CreateQueryWriter pour créer un enregistreur de requêtes XMP.

IWICMetadataQueryWriter *pXMPWriter = NULL;

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

Dans cet exemple, le nom GUID_MetadataFormatXMP convivial est utilisé comme paramètre guidMetadataFormat . Il représente le GUID de format de métadonnées XMP et le fournisseur représente le gestionnaire créé par Microsoft. Vous pouvez également passer null en tant que paramètre pguidVendor avec les mêmes résultats si aucun autre gestionnaire XMP n’existe. Si un gestionnaire XMP personnalisé est installé en même temps que le gestionnaire XMP natif, la transmission de la valeur NULL pour le fournisseur entraîne le renvoi de l’enregistreur de requêtes avec le GUID le plus bas.

CreateQueryWriterFromReader est similaire à la méthode CreateQueryWriter , sauf qu’elle préremplie le nouvel enregistreur de requêtes avec les données fournies par le lecteur de requête. Cela est utile pour réécoder une image tout en conservant les métadonnées existantes ou pour supprimer les métadonnées indésirables. Le code suivant illustre un appel 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);

Ajout de métadonnées

Une fois que vous avez obtenu un enregistreur de requête, vous pouvez l’utiliser pour ajouter des blocs de métadonnées et des éléments. Pour écrire des métadonnées, vous utilisez la méthode SetMetadataByName de l’enregistreur de requêtes. SetMetadataByName prend deux paramètres : une expression de requête (wzName) et un pointeur vers un PROPVARIANT (pvarValue). L’expression de requête définit le bloc ou l’élément à définir tandis que PROPVARIANT fournit la valeur de données réelle à définir.

L’exemple suivant montre comment ajouter un titre à l’aide de l’enregistreur de requêtes XMP obtenu précédemment à l’aide de la méthode 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);
}

Dans cet exemple, le type de valeur (vt) est défini sur VT_LPWSTR, ce qui indique qu’une chaîne sera utilisée comme valeur de données. Étant donné que le type de value est une chaîne, pwszVal est utilisé pour définir le titre à utiliser. SetMetadataByName est ensuite appelé à l’aide de l’expression de requête « /dc:title » et du nouveau paramètre PROPVARIANT. L’expression de requête utilisée indique que la propriété title dans le schéma de l’appareil photo numérique (dc) doit être définie. Notez que l’expression n’est pas « /xmp/dc:title » ; cela est dû au fait que l’enregistreur de requêtes est déjà spécifique à XMP et ne contient pas de bloc XMP incorporé, ce que « /xmp/dc:title » suggérerait.

Jusqu’à ce stade, vous n’avez pas ajouté de métadonnées à un cadre d’image. Vous avez simplement rempli un enregistreur de requêtes avec des données. Pour ajouter à une trame un bloc de métadonnées représenté par l’enregistreur de requête, vous appelez à nouveau SetMetadataByName en utilisant l’enregistreur de requête comme valeur du PROPVARIANT. Cela copie efficacement les métadonnées de l’enregistreur de requête dans le cadre de l’image. Le code suivant montre comment ajouter les métadonnées dans l’enregistreur de requête XMP précédemment obtenu au bloc de métadonnées racine d’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);
    }
}

Dans cet exemple, un type de valeur (vt) de VT_UNKOWN est utilisé, indiquant un type de valeur d’interface COM. L’enregistreur de requête XMP (piXMPWriter) est ensuite utilisé comme valeur de PROPVARIANT, en y ajoutant une référence à l’aide de la méthode AddRef. Enfin, l’enregistreur de requêtes XMP est défini en appelant la méthode SetMetadataByName de l’image et en passant l’expression de requête « / », indiquant le bloc racine et le nouveau paramètre PROPVARIANT.

Notes

Si le cadre contient déjà le bloc de métadonnées que vous essayez d’ajouter, les métadonnées que vous ajoutez seront ajoutées et les métadonnées existantes remplacées.

 

Suppression des métadonnées

Un enregistreur de requêtes vous permet également de supprimer des métadonnées en appelant la méthode RemoveMetadataByName . RemoveMetadataByName prend une expression de requête et supprime le bloc de métadonnées ou l’élément s’il existe. Le code suivant montre comment supprimer le titre précédemment ajouté.

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

Le code suivant montre comment supprimer l’intégralité du bloc de métadonnées XMP.

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

Copie de métadonnées pour le ré-encodage

Notes

Le code de cette section est valide uniquement lorsque les formats d’image source et d’image de destination sont identiques. Vous ne pouvez pas copier toutes les métadonnées d’une image en une seule opération lors de l’encodage dans un autre format d’image.

 

Pour conserver les métadonnées lors de l’encodage d’une image au même format d’image, il existe des méthodes permettant de copier toutes les métadonnées en une seule opération. Chacune de ces opérations suit un modèle similaire ; chaque définit les métadonnées de l’image décodée directement dans la nouvelle image en cours d’encodage.

La méthode recommandée pour copier les métadonnées consiste à initialiser l’enregistreur de blocs du nouveau frame avec le lecteur de blocs de l’image décodée. Le code suivant illustre cette méthode.

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

Dans cet exemple, le lecteur de blocs et l’enregistreur de blocs sont obtenus respectivement à partir de l’image source et de l’image de destination. L’enregistreur de blocs est ensuite initialisé à partir du lecteur de blocs. Cela initialise le lecteur de blocs avec les métadonnées préremplies du lecteur de blocs.

Une autre méthode de copie des métadonnées consiste à écrire le bloc de métadonnées référencé par le lecteur de requête à l’aide de l’enregistreur de requêtes de l’encodeur. Le code suivant illustre cette méthode.

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

Ici, un lecteur de requête est obtenu à partir du cadre décodé, puis utilisé comme valeur de propriété du PROPVARIANT avec un type de valeur défini sur VT_UNKNOWN. L’enregistreur de requêtes pour l’encodeur est obtenu et l’expression de requête « / » est utilisée pour définir les métadonnées au niveau du chemin de navigation racine. Vous pouvez également utiliser cette méthode lors de la définition de blocs de métadonnées imbriqués, en ajustant l’expression de requête à l’emplacement souhaité.

De même, vous pouvez créer un enregistreur de requêtes basé sur le lecteur de requête du frame décodé à l’aide de la méthode CreateQueryWriterFromReader de la fabrique d’images. L’enregistreur de requête créé dans cette opération est prérempli avec les métadonnées du lecteur de requête et peut ensuite être défini dans le cadre. Le code suivant illustre l’opération de copie 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);
}

Cette méthode utilise un enregistreur de requête distinct qui est créé en fonction des données du lecteur de requête. Ce nouvel enregistreur de requête est ensuite défini dans le cadre.

Là encore, ces opérations de copie des métadonnées ne fonctionnent que lorsque les images source et de destination ont le même format. Cela est dû au fait que les différents formats d’image stockent les blocs de métadonnées à différents emplacements. Par instance, JPEG et TIFF prennent en charge les blocs de métadonnées XMP. Dans les images JPEG, le bloc XMP se trouve au niveau du bloc de métadonnées racine, comme illustré dans vue d’ensemble des métadonnées WIC. Toutefois, dans une image TIFF, le bloc XMP est imbriqué dans un bloc IFD racine. Le diagramme suivant illustre les différences entre une image JPEG et une image TIFF avec les mêmes métadonnées d’évaluation.

jpeg et tiff comparaison.

Encodage rapide des métadonnées

Il n’est pas toujours nécessaire de réencoder une image pour y écrire de nouvelles métadonnées. Les métadonnées peuvent également être écrites à l’aide d’un encodeur de métadonnées rapide. Un encodeur de métadonnées rapide peut écrire une quantité limitée de métadonnées dans une image sans ré-encodage de l’image. Pour ce faire, écrivez les nouvelles métadonnées dans le remplissage vide fourni par certains formats de métadonnées. Les formats de métadonnées natifs qui prennent en charge le remplissage des métadonnées sont Exif, IFD, GPS et XMP.

Ajout d’un remplissage à des blocs de métadonnées

Avant de pouvoir effectuer un encodage de métadonnées rapide, il doit y avoir de la place dans le bloc de métadonnées pour écrire davantage de métadonnées. S’il n’y a pas suffisamment de place dans le remplissage existant pour écrire les nouvelles métadonnées, l’encodage rapide des métadonnées échoue. Pour ajouter un remplissage de métadonnées à une image, l’image doit être réencodée. Vous pouvez ajouter un remplissage de la même façon que vous ajouteriez n’importe quel autre élément de métadonnées, en utilisant une expression de requête, si le bloc de métadonnées que vous remplissez prend en charge. L’exemple suivant montre comment ajouter un remplissage à un bloc IFD incorporé dans un bloc 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);
}

Pour ajouter un remplissage, créez un PROPVARIANT de type VT_UI4 et une valeur correspondant au nombre d’octets de remplissage à ajouter. Une valeur typique est 4 096 octets. Les requêtes de métadonnées pour JPEG, TIFF et JPEG-XR se trouvent dans ce tableau.

Format de métadonnées Requête de métadonnées JPEG TIFF, requête de métadonnées 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

 

Obtention d’un encodeur de métadonnées rapide

Lorsque vous avez une image avec remplissage des métadonnées, un encodeur de métadonnées rapide peut être obtenu à l’aide des méthodes de fabrique d’images CreateFastMetadataEncoderFromDecoder et CreateFastMetadataEncoderFromFrameDecode.

Comme son nom l’indique, CreateFastMetadataEncoderFromDecoder crée un encodeur de métadonnées rapide pour les métadonnées au niveau du décodeur. Les formats d’image natifs fournis par WIC ne prennent pas en charge les métadonnées au niveau du décodeur, mais cette méthode est fournie dans le cas où un tel format d’image est développé à l’avenir.

Le scénario le plus courant consiste à obtenir un encodeur de métadonnées rapide à partir d’une trame d’image à l’aide de CreateFastMetadataEncoderFromFrameDecode. Le code suivant obtient l’encodeur de métadonnées rapide d’un frame décodé et modifie la valeur d’évaluation dans le bloc App1.

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

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

Utilisation de l’encodeur de métadonnées rapide

À partir de l’encodeur de métadonnées rapide, vous pouvez obtenir un enregistreur de requêtes. Cela vous permet d’écrire des métadonnées à l’aide d’une expression de requête, comme illustré précédemment. Une fois les métadonnées définies dans l’enregistreur de requête, validez l’encodeur de métadonnées rapide pour finaliser la mise à jour des métadonnées. Le code suivant illustre la définition et la validation des modifications de métadonnées

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

Si la validation échoue pour une raison quelconque, vous devez réencoder l’image pour vous assurer que les nouvelles métadonnées sont ajoutées à l’image.

Conceptuel

Vue d’ensemble du composant d’acquisition d’images Windows

Vue d’ensemble des métadonnées WIC

Vue d’ensemble du langage de requête de métadonnées

Vue d’ensemble de l’extensibilité des métadonnées

Procédure : réencoder une image JPEG avec des métadonnées