Métadonnées d’image

Cet article explique comment lire et écrire des propriétés de métadonnées d’image et comment géotagiser des fichiers à l’aide de la classe utilitaire GeotagHelper .

Propriétés de l’image

La propriété StorageFile.Properties renvoie un objet StorageItemContentProperties qui fournit l’accès aux informations relatives au contenu sur le fichier. Obtenez les propriétés spécifiques de l’image en appelant GetImagePropertiesAsync. L’objet ImageProperties renvoyé indique les membres qui contiennent des champs de métadonnées d’image de base, tels que le titre de l’image et la date de capture.

private async void GetImageProperties(StorageFile imageFile)
{
    ImageProperties props = await imageFile.Properties.GetImagePropertiesAsync();

    string title = props.Title;
    if (title == null)
    {
        // Format does not support, or image does not contain Title property
    }

    DateTimeOffset date = props.DateTaken;
    if (date == null)
    {
        // Format does not support, or image does not contain DateTaken property
    }
}

Pour accéder à un plus vaste ensemble de métadonnées de fichier, utilisez le système de propriétés Windows, qui est un ensemble de propriétés de métadonnées de fichier pouvant être récupéré à l’aide d’un identificateur de chaîne unique. Créez une liste de chaînes et ajoutez l’identificateur pour chaque propriété que vous souhaitez récupérer. La méthode ImageProperties.RetrievePropertiesAsync prend cette liste de chaînes et renvoie un dictionnaire de paires clé/valeur où la clé correspond à l’identificateur de propriété et la valeur à la valeur de propriété.

ImageProperties props = await imageFile.Properties.GetImagePropertiesAsync();

var requests = new System.Collections.Generic.List<string>();
requests.Add("System.Photo.Orientation");
requests.Add("System.Photo.Aperture");

IDictionary<string, object> retrievedProps = await props.RetrievePropertiesAsync(requests);

ushort orientation;
if (retrievedProps.ContainsKey("System.Photo.Orientation"))
{
    orientation = (ushort)retrievedProps["System.Photo.Orientation"];
}

double aperture;
if (retrievedProps.ContainsKey("System.Photo.Aperture"))
{
    aperture = (double)retrievedProps["System.Photo.Aperture"];
}
  • Pour obtenir la liste complète des propriétés Windows, y compris les identificateurs et le type de chaque propriété, voir Propriétés Windows.

  • Certaines propriétés sont uniquement prises en charge pour certains conteneurs de fichiers et codecs d’image. Pour obtenir la liste des métadonnées d’image prises en charge pour chaque type d’image, voir Stratégies de métadonnées de photos.

  • Étant donné que les propriétés qui ne sont pas prises en charge peuvent renvoyer une valeur null une fois récupérées, vérifiez toujours la présence d’une telle valeur avant d’utiliser une valeur de métadonnées renvoyée.

Assistance d’indication de position géographique

GeotagHelper est une classe utilitaire qui permet d’étiqueter facilement des images avec des données géographiques à l’aide des API Windows.Devices.Geolocation directement, sans avoir à analyser ou à construire manuellement le format de métadonnées.

Si vous possédez déjà un objet Geopoint représentant l’emplacement que vous souhaitez baliser dans l’image, à partir d’une précédente utilisation d’API de géolocalisation ou d’une autre source, vous pouvez définir les données d’indication de la position géographique en appelant GeotagHelper.SetGeotagAsync et en transmettant StorageFile et Geopoint.

var point = new Geopoint(
new BasicGeoposition
{
    Latitude = 48.8567,
    Longitude = 2.3508,
});

await GeotagHelper.SetGeotagAsync(imageFile, point);

Pour définir les données d’indication de la position géographique à l’aide de la localisation actuelle de l’appareil, créez un objet Geolocator et appelez GeotagHelper.SetGeotagFromGeolocatorAsync en transmettant Geolocator et le fichier à baliser.

var locator = new Geolocator();

// Shows the user consent UI if needed
var accessStatus = await Geolocator.RequestAccessAsync();
if (accessStatus == GeolocationAccessStatus.Allowed)
{
    await GeotagHelper.SetGeotagFromGeolocatorAsync(imageFile, locator);
}

Pour obtenir un GeoPoint indiquant la position géographique d’un fichier image, appelez GetGeotagAsync.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

Décoder et encoder des métadonnées d’image

La manière la plus avancée de travailler avec des données d’image consiste à lire et à écrire les propriétés au niveau de flux à l’aide d’une classe BitmapDecoder ou d’un BitmapEncoder. Pour ces opérations, vous pouvez utiliser les propriétés de Windows pour spécifier les données en cours de lecture ou d’écriture, et également le langage de requête de métadonnées fourni par le composant Imagerie Windows (WIC) pour spécifier le chemin d’accès à une propriété demandée.

La lecture des métadonnées d’image à l’aide de cette technique nécessite de disposer d’un BitmapDecoder qui a été créé avec le flux du fichier image source. Pour plus d’informations sur la façon de procéder, voir Acquisition d’images.

Une fois que vous disposez du décodeur, créez une liste de chaînes et ajoutez une entrée pour chaque propriété de métadonnées que vous souhaitez récupérer, à l’aide de la chaîne d’identificateur de propriété Windows ou d’une requête de métadonnées WIC. Appelez la méthode BitmapPropertiesView.GetPropertiesAsync sur le membre du décodeur BitmapProperties pour demander les propriétés spécifiées. Les propriétés sont renvoyées dans un dictionnaire de paires clé/valeur contenant le nom de la propriété ou son chemin d’accès et sa valeur.

private async void ReadImageMetadata(BitmapDecoder bitmapDecoder)
{

    var requests = new System.Collections.Generic.List<string>();
    requests.Add("System.Photo.Orientation"); // Windows property key for EXIF orientation
    requests.Add("/xmp/dc:creator"); // WIC metadata query for Dublin Core creator

    try
    {
        var retrievedProps = await bitmapDecoder.BitmapProperties.GetPropertiesAsync(requests);

        ushort orientation;
        if (retrievedProps.ContainsKey("System.Photo.Orientation"))
        {
            orientation = (ushort)retrievedProps["System.Photo.Orientation"].Value;
        }

        string creator;
        if (retrievedProps.ContainsKey("/xmp/dc:creator"))
        {
            creator = (string)retrievedProps["/xmp/dc:creator"].Value;
        }
    }
    catch (Exception err)
    {
        switch (err.HResult)
        {
            case unchecked((int)0x88982F41): // WINCODEC_ERR_PROPERTYNOTSUPPORTED
                                             // The file format does not support the requested metadata.
                break;
            case unchecked((int)0x88982F81): // WINCODEC_ERR_UNSUPPORTEDOPERATION
                                             // The file format does not support any metadata.
            default:
                throw err;
        }
    }
}
  • Pour plus d’informations sur le langage de requête de métadonnées WIC et les propriétés prises en charge, voir Requêtes de métadonnées natives au format d’image WIC.

  • De nombreuses propriétés de métadonnées sont uniquement prises en charge par un sous-ensemble de types d’images. GetPropertiesAsync échoue avec le code d’erreur 0x88982F41 si l’une des propriétés demandées n’est pas prise en charge par l’image associée au décodeur et 0x88982F81 si l’image ne prend pas en charge les métadonnées du tout. Les constantes associées à ces codes d’erreur sont WINCODEC_ERR_PROPERTYNOTSUPPORTED et WINCODEC_ERR_UNSUPPORTEDOPERATION et sont définies dans le fichier d’en-tête winerror.h.

  • Dans la mesure où une image peut contenir ou non une valeur pour une propriété particulière, utilisez IDictionary.ContainsKey pour vérifier la présence d’une propriété dans les résultats avant d’essayer d’y accéder.

L’écriture de métadonnées d’image dans le flux nécessite un élément BitmapEncoder associé au fichier de sortie image.

Créez un objet BitmapPropertySet destiné à contenir les valeurs de propriété que vous voulez définir. Créez un objet BitmapTypedValue pour représenter la valeur de la propriété. Cet objet utilise un object comme valeur et membre de l’énumération PropertyType qui définit le type de valeur. Ajoutez l’élément BitmapTypedValue à BitmapPropertySet, puis appelez BitmapProperties.SetPropertiesAsync pour que l’encodeur écrive les propriétés dans le flux.

private async void WriteImageMetadata(BitmapEncoder bitmapEncoder)
{
    var propertySet = new Windows.Graphics.Imaging.BitmapPropertySet();
    var orientationValue = new Windows.Graphics.Imaging.BitmapTypedValue(
        1, // Defined as EXIF orientation = "normal"
        Windows.Foundation.PropertyType.UInt16
        );

    propertySet.Add("System.Photo.Orientation", orientationValue);

    try
    {
        await bitmapEncoder.BitmapProperties.SetPropertiesAsync(propertySet);
    }
    catch (Exception err)
    {
        switch (err.HResult)
        {
            case unchecked((int)0x88982F41): // WINCODEC_ERR_PROPERTYNOTSUPPORTED
                                             // The file format does not support this property.
                break;
            default:
                throw err;
        }
    }
}