Bildmetadata

Den här artikeln visar hur du läser och skriver egenskaper för bildmetadata och hur du geotaggerar filer med hjälp av GeotagHelper verktygsklass.

Bildegenskaper

Egenskapen StorageFile.Properties returnerar egenskapen StorageItemContentProperties som ger åtkomst till innehållsrelaterad information om filen. Hämta de bildspecifika egenskaperna genom att anropa GetImagePropertiesAsync. Det returnerade objektet ImageProperties exponerar medlemmar som innehåller grundläggande bildmetadatafält, till exempel bildens rubrik och avbildningsdatum.

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 dateTaken = props.DateTaken;
}

Om du vill komma åt en större uppsättning filmetadata använder du Windows Egenskapssystem, en uppsättning egenskaper för filmetadata som kan hämtas med en unik strängidentifierare. Skapa en lista med strängar och lägg till identifieraren för varje egenskap som du vill hämta. Metoden ImageProperties.RetrievePropertiesAsync tar den här listan med strängar och returnerar en ordlista med nyckel/värde-par där nyckeln är egenskapsidentifieraren och värdet är egenskapsvärdet.

private async void GetWindowsProperties(StorageFile imageFile)
{
    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"];
    }
}
  • En fullständig lista över Windows Egenskaper, inklusive identifierare och typ för varje egenskap, finns i Windows Egenskaper.

  • Vissa egenskaper stöds bara för vissa filcontainrar och avbildnings codecs. En lista över de bildmetadata som stöds för varje bildtyp finns i Principer för fotometadata.

  • Eftersom egenskaper som inte stöds kan returnera ett null-värde när de hämtas kontrollerar du alltid null innan du använder ett returnerat metadatavärde.

Geotag-hjälp

GeotagHelper är en verktygsklass som gör det enkelt att tagga bilder med geografiska data med hjälp av Windows. Devices.Geolocation API:er direkt, utan att behöva parsa eller konstruera metadataformatet manuellt.

Om du redan har ett Geopoint-objekt som representerar den plats som du vill tagga i bilden, antingen från en tidigare användning av API:er för geolokalisering eller någon annan källa, kan du ange geotaggdata genom att anropa GeotagHelper.SetGeotagAsync och skicka med en StorageFile och Geopoint.

private async void SetGeoDataFromPoint(StorageFile imageFile)
{
    var point = new Geopoint(
        new BasicGeoposition
        {
            Latitude = 48.8567,
            Longitude = 2.3508,
        });

    await GeotagHelper.SetGeotagAsync(imageFile, point);
}

Om du vill ange geotaggdata med enhetens aktuella plats skapar du ett nytt objekt Geolocator och anropar GeotagHelper.SetGeotagFromGeolocatorAsync som skickar Geolocator och filen som ska taggas.

private async void SetGeoDataFromGeolocator(StorageFile imageFile)
{
    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);
    }
}

Om du vill hämta en GeoPoint som representerar den geotaggade platsen för en bildfil anropar du GetGeotagAsync.

private async void GetGeoData(StorageFile imageFile)
{
    Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);
}

Avkoda och koda bildmetadata

Det mest avancerade sättet att arbeta med bilddata är att läsa och skriva egenskaperna på strömnivå med hjälp av en BitmapDecoder eller en BitmapEncoder. För dessa åtgärder kan du använda Windows Egenskaper för att ange de data som du läser eller skriver, men du kan också använda metadatafrågespråket som tillhandahålls av WIC (Windows Imaging Component) för att ange sökvägen till en begärd egenskap.

Om du läser bildmetadata med den här tekniken måste du ha en BitmapDecoder som skapades med källavbildningsfilströmmen. Information om hur du gör detta finns i Skapa, redigera och spara bitmappsbilder.

När du har avkodaren skapar du en lista med strängar och lägger till en ny post för varje metadataegenskap som du vill hämta, antingen med hjälp av strängen Windows egenskapsidentifierare eller en WIC-metadatafråga. Anropa metoden BitmapPropertiesView.GetPropertiesAsync på avkodarens BitmapProperties för att begära de angivna egenskaperna. Egenskaperna returneras i en ordlista med nyckel/värde-par där varje par innehåller egenskapsnamnet eller sökvägen samt egenskapsvärdet.

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;
        }
    }
}
  • Information om frågespråket för WIC-metadata och vilka egenskaper som stöds finns i WIC-bildformatets interna metadatafrågor.

  • Många metadataegenskaper stöds bara av en delmängd av bildtyper. GetPropertiesAsync misslyckas med felkoden 0x88982F41 om en av de begärda egenskaperna inte stöds av den avbildning som är associerad med avkodaren och 0x88982F81 om bilden inte stöder metadata alls. Konstanterna som är associerade med dessa felkoder är WINCODEC_ERR_PROPERTYNOTSUPPORTED och WINCODEC_ERR_UNSUPPORTEDOPERATION och definieras i huvudfilen winerror.h.

  • Eftersom en bild kanske inte innehåller ett värde för en viss egenskap använder du IDictionary.ContainsKey för att kontrollera att en egenskap finns i resultatet innan du försöker komma åt den.

För att kunna skriva bildmetadata till strömmen krävs en BitmapEncoder som är associerad med bildutdatafilen.

Skapa ett BitmapPropertySet objekt som ska innehålla de egenskapsvärden som du vill ange. Skapa ett BitmapTypedValue objekt som representerar egenskapsvärdet. Det här objektet använder ett object som värde och medlem i PropertyType uppräkning som definierar värdets typ. Lägg till BitmapTypedValue i BitmapPropertySet och anropa sedan BitmapProperties.SetPropertiesAsync för att få kodaren att skriva egenskaperna till strömmen.

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