Métadonnées d’image

Cet article explique comment lire et écrire des propriétés de métadonnées d’image et comment geotag files using the GeotagHelper utility class.

Propriétés de l’image

La propriété StorageFile.Properties retourne un objet StorageItemContentProperties qui fournit l’accès aux informations relatives au contenu sur le fichier. Obtenez les propriétés spécifiques à l’image en appelant GetImagePropertiesAsync. L’objet ImageProperties retourné expose les membres qui contiennent des champs de métadonnées d’image de base, comme 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 grand ensemble de métadonnées de fichier, utilisez le système de propriétés Windows, un ensemble de propriétés de métadonnées de fichier qui peuvent être récupérées avec 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 retourne un dictionnaire de paires clé/valeur où la clé est l’identificateur de propriété et la valeur est la valeur de la 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é, consultez 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, consultez Stratégies de métadonnées de photo.

  • Étant donné que les propriétés qui ne sont pas prises en charge peuvent retourner une valeur Null lors de la récupération, vérifiez toujours la valeur Null avant d’utiliser une valeur de métadonnées retournée.

Helper geotag

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

Si vous disposez déjà d’un objet Geopoint représentant l’emplacement que vous souhaitez baliser dans l’image, soit à partir d’une utilisation précédente des API de géolocalisation, soit d’une autre source, vous pouvez définir les données de géolocalisation en appelant GeotagHelper.SetGeotagAsync et en passant un StorageFile et le Geopoint.

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

await GeotagHelper.SetGeotagAsync(imageFile, point);

Pour définir les données de géolocalisation à l’aide de l’emplacement actuel de l’appareil, créez un objet Geolocator et appelez GeotagHelper.SetGeotagFromGeolocatorAsync en passant le Geolocator et le fichier à marquer.

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 représentant l’emplacement géographique d’un fichier image, appelez GetGeotagAsync.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

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

La méthode la plus avancée d’utilisation des données d’image consiste à lire et à écrire les propriétés au niveau du flux à l’aide d’un BitmapDecoder ou d’un BitmapEncoder. Pour ces opérations, vous pouvez utiliser les propriétés Windows pour spécifier les données que vous lisez ou écrivez, mais vous pouvez également utiliser le langage de requête de métadonnées fourni par le composant WIC (Windows Imaging Component) 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 vous oblige à disposer d’un BitmapDecoder créé avec le flux de fichiers image source. Pour plus d’informations sur la procédure à suivre, consultez Acquisition d’images.

Une fois que vous disposez du décodeur, créez une liste de chaînes et ajoutez une nouvelle 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 BitmapProperties du décodeur pour demander les propriétés spécifiées. Les propriétés sont retournées dans un dictionnaire de paires clé/valeur contenant le nom de la propriété ou le chemin d’accès et la valeur de la propriété.

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, consultez les requêtes de métadonnées natives au format d’image WIC.

  • De nombreuses propriétés de métadonnées ne sont prises en charge que 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.

  • Étant donné qu’une image peut contenir ou non une valeur pour une propriété particulière, utilisez IDictionary.ContainsKey pour vérifier qu’une propriété est présente dans les résultats avant de tenter de l’accéder.

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

Créez un objet BitmapPropertySet pour contenir les valeurs de propriété que vous souhaitez définir. Créez un objet BitmapTypedValue pour représenter la valeur de propriété. Cet objet utilise un objet comme valeur et membre de l’énumération PropertyType qui définit le type de la valeur. Ajoutez 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;
        }
    }
}