Condividi tramite


Metadati di immagine

Questo articolo illustra come leggere e scrivere le proprietà dei metadati dell'immagine e come geotaggare i file usando la classe di utility GeotagHelper.

Proprietà immagine

La proprietà StorageFile.Properties restituisce un oggetto StorageItemContentProperties che consente di accedere alle informazioni relative al contenuto sul file. Ottenere le proprietà specifiche dell'immagine chiamando GetImagePropertiesAsync. L'oggetto ImageProperties restituito espone i membri che contengono campi di metadati immagine di base, ad esempio il titolo dell'immagine e la data di acquisizione.

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

Per accedere a un set di metadati di file di dimensioni maggiori, usare Il sistema delle proprietà di Windows, un set di proprietà dei metadati di file che possono essere recuperate con un identificatore di stringa univoco. Creare un elenco di stringhe e aggiungere l'identificatore per ogni proprietà da recuperare. Il metodo ImageProperties.RetrievePropertiesAsync accetta questo elenco di stringhe e restituisce un dizionario di coppie chiave/valore in cui la chiave è l'identificatore della proprietà e il valore è il valore della proprietà.

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"];
}
  • Per un elenco completo delle proprietà di Windows, inclusi gli identificatori e il tipo per ogni proprietà, vedere Proprietà di Windows.

  • Alcune proprietà sono supportate solo per determinati contenitori di file e codec immagine. Per un elenco dei metadati dell'immagine supportati per ogni tipo di immagine, vedere Criteri dei metadati delle foto.

  • Poiché le proprietà non supportate possono restituire un valore Null durante il recupero, verificare sempre la presenza di valori Null prima di usare un valore di metadati restituito.

Helper geotag

GeotagHelper è una classe di utility che semplifica l'assegnazione di tag alle immagini con dati geografici usando direttamente le API Windows.Devices.Geolocation, senza dover analizzare o costruire manualmente il formato dei metadati.

Se si dispone già di un oggetto Geopoint che rappresenta la posizione da contrassegnare nell'immagine, da un uso precedente delle API di georilevazione o di un'altra origine, è possibile impostare i dati del geotag chiamando GeotagHelper.SetGeotagAsync e passando in uno StorageFile e in Geopoint.

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

await GeotagHelper.SetGeotagAsync(imageFile, point);

Per impostare i dati del geotag usando la posizione corrente del dispositivo, creare un nuovo oggetto Geolocator e chiamare GeotagHelper.SetGeotagFromGeolocatorAsync passando in Geolocator e il file da taggare.

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

Per ottenere un geopoint che rappresenta la posizione geografica di un file di immagine, chiamare GetGeotagAsync.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

Decodificare e codificare i metadati immagine

Il modo più avanzato per usare i dati dell'immagine consiste nel leggere e scrivere le proprietà a livello di flusso usando un BitmapDecoder o un BitmapEncoder. Per queste operazioni è possibile utilizzare Le proprietà di Windows per specificare i dati letti o scritti, ma è anche possibile utilizzare il linguaggio di query dei metadati fornito da Windows Imaging Component (WIC) per specificare il percorso di una proprietà richiesta.

Per leggere i metadati dell'immagine usando questa tecnica è necessario disporre di un BitmapDecoder creato con il flusso del file di immagine di origine. Per altre informazioni su come eseguire questa operazione, vedere Imaging.

Dopo aver creato il decodificatore, creare un elenco di stringhe e aggiungere una nuova voce per ogni proprietà di metadati da recuperare, usando la stringa dell'identificatore di proprietà di Windows o una query di metadati WIC. Chiamare il metodo BitmapPropertiesView.GetPropertiesAsync nel membro BitmapProperties del decodificatore per richiedere le proprietà specificate. Le proprietà vengono restituite in un dizionario di coppie chiave/valore contenenti il nome o il percorso della proprietà e il valore della proprietà.

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;
        }
    }
}
  • Per informazioni sul linguaggio di query dei metadati WIC e sulle proprietà supportate, vedere Query sui metadati nativi in formato immagine WIC.

  • Molte proprietà dei metadati sono supportate solo da un subset di tipi di immagine. GetPropertiesAsync avrà esito negativo con il codice di errore 0x88982F41 se una delle proprietà richieste non è supportata dall'immagine associata al decodificatore e 0x88982F81 se l'immagine non supporta affatto i metadati. Le costanti associate a questi codici di errore sono WINCODEC_ERR_PROPERTYNOTSUPPORTED e WINCODEC_ERR_UNSUPPORTEDOPERATION e sono definite nel file di intestazione winerror.h.

  • Poiché un'immagine può contenere o meno un valore per una determinata proprietà, utilizzare IDictionary.ContainsKey per verificare che nei risultati sia presente una proprietà prima di tentare di accedervi.

La scrittura dei metadati dell'immagine nel flusso richiede un BitmapEncoder associato al file di output dell'immagine.

Creare un oggetto BitmapPropertySet per contenere i valori delle proprietà da impostare. Creare un oggetto BitmapTypedValue per rappresentare il valore della proprietà. Questo oggetto utilizza un oggetto come valore e membro dell'enumerazione PropertyType che definisce il tipo del valore. Aggiungere BitmapTypedValue a BitmapPropertySet e quindi chiamare BitmapProperties.SetPropertiesAsync per fare in modo che il codificatore scriva le proprietà nel flusso.

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