Bildmetadaten

In diesem Artikel werden das Lesen und Schreiben von Eigenschaften von Bildmetadaten und das Hinzufügen von Geomarkierungen zu Dateien mithilfe der GeotagHelper-Hilfsklasse erläutert.

Image-Eigenschaften

Die StorageFile.Properties-Eigenschaft gibt ein StorageItemContentProperties-Objekt zurück, das Zugriff auf inhaltsbezogene Informationen zur Datei bietet. Rufen Sie die bildspezifischen Eigenschaften durch Aufruf von GetImagePropertiesAsync ab. Das zurückgegebene ImageProperties-Objekt macht Member verfügbar, die Felder mit grundlegenden Bildmetadaten enthalten, z. B. den Titel des Bilds und das Aufnahmedatum.

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

Verwenden Sie für den Zugriff auf eine größere Menge von Dateimetadaten das Windows-Eigenschaftensystem, eine Reihe von Eigenschaften von Dateimetadaten, die mit einem eindeutigen Zeichenfolgenbezeichner abgerufen werden können. Erstellen Sie eine Liste mit Zeichenfolgen, und fügen Sie den Bezeichner für jede Eigenschaft hinzu, die Sie abrufen möchten. Die ImageProperties.RetrievePropertiesAsync-Methode verwendet diese Liste mit Zeichenfolgen und gibt ein Wörterbuch von Schlüssel-Wert-Paaren zurück, bei denen der Schlüssel der Eigenschaftsbezeichner und der Wert der Eigenschaftswert ist.

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"];
}
  • Eine vollständige Liste der Windows-Eigenschaften, einschließlich der Bezeichner und des Typs für jede Eigenschaft, finden Sie unter Windows-Eigenschaften.

  • Einige Eigenschaften werden nur für bestimmte Dateicontainer und Bildcodecs unterstützt. Eine Liste der für jeden Bildtyp unterstützten Bildmetadaten finden Sie unter Richtlinien für Fotometadaten.

  • Da nicht unterstützte Eigenschaften beim Abrufen möglicherweise einen NULL-Wert zurückgeben, prüfen Sie immer auf NULL, bevor Sie einen zurückgegebenen Metadatenwert verwenden.

GeotagHelper

„GeotagHelper“ ist eine Hilfsklasse, die das problemlose und direkte Markieren von Bildern mit geografischen Daten unter Verwendung der Windows.Devices.Geolocation-APIs ermöglicht, ohne dass das Metadatenformat manuell analysiert oder konstruiert werden muss.

Wenn Sie bereits über ein Geopoint-Objekt verfügen, das die Position darstellt, die Sie im Bild markieren möchten (entweder aus einer früheren Verwendung der Geolocation-APIs oder aus einer anderen Quelle), können Sie die Geomarkierungsdaten festlegen, indem Sie GeotagHelper.SetGeotagAsync aufrufen und eine StorageFile und einen Geopoint übergeben.

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

await GeotagHelper.SetGeotagAsync(imageFile, point);

Um die Geomarkierungsdaten mithilfe der aktuellen Position des Geräts festzulegen, erstellen Sie ein neues Geolocator-Objekt, und rufen Sie GeotagHelper.SetGeotagFromGeolocatorAsync auf. Übergeben Sie dabei die Geolocator-Klasse und die zu markierende Datei.

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

Um einen GeoPoint abzurufen, der die geomarkierte Position einer Bilddatei darstellt, rufen Sie GetGeotagAsync auf.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

Decodieren und Codieren von Bildmetadaten

Die fortschrittlichste Methode zum Arbeiten mit Bilddaten ist das Lesen und Schreiben der Eigenschaften auf Datenstromebene mithilfe von BitmapDecoder oder BitmapEncoder. Für diese Vorgänge können Sie Windows-Eigenschaften verwenden, um die gelesenen oder geschriebenen Daten anzugeben. Sie können aber auch die von der Windows-Bilderstellungskomponente (WIC) bereitgestellte Metadatenabfragesprache verwenden, um den Pfad zu einer angeforderten Eigenschaft anzugeben.

Um Bildmetadaten mit diesem Verfahren lesen zu können, benötigen Sie einen BitmapDecoder, der mit dem Dateidatenstrom des Quellbilds erstellt wurde. Informationen zur Vorgehensweise finden Sie unter Bildverarbeitung.

Nachdem Sie über den Decoder verfügen, erstellen Sie eine Liste mit Zeichenfolgen, und fügen Sie für jede abzurufende Metadateneigenschaft einen neuen Eintrag hinzu; verwenden Sie dabei entweder die ID-Zeichenfolge der Windows-Eigenschaft oder eine WIC-Metadatenabfrage. Rufen Sie die BitmapPropertiesView.GetPropertiesAsync-Methode für den BitmapProperties-Member des Decoders auf, um die angegebenen Eigenschaften anzufordern. Die Eigenschaften werden in einem Wörterbuch mit Schlüssel-Wert-Paaren zurückgegeben, die den Eigenschaftsnamen oder den Pfad und den Eigenschaftswert enthalten.

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;
        }
    }
}
  • Informationen zur WIC-Metadatenabfragesprache und den unterstützten Eigenschaften finden Sie unter Native Metadatenabfragen im WIC-Imageformat.

  • Viele Metadateneigenschaften werden nur von einer Teilmenge aller Bildtypen unterstützt. Bei Ausführung von GetPropertiesAsync tritt ein Fehler mit Fehlercode 0x88982F41 auf, wenn eine der angeforderten Eigenschaften von dem dem Decoder zugeordneten Bild nicht unterstützt wird, und mit Fehlercode 0x88982F81, wenn das Bild überhaupt keine Metadaten unterstützt. Die diesen Fehlercodes zugeordneten Konstanten sind WINCODEC_ERR_PROPERTYNOTSUPPORTED und WINCODEC_ERR_UNSUPPORTEDOPERATION und werden in der Winerror.h-Headerdatei definiert.

  • Da ein Bild nicht unbedingt einen Wert für eine bestimmte Eigenschaft enthält, überprüfen Sie mithilfe von IDictionary.ContainsKey, ob eine Eigenschaft in den Ergebnissen vorhanden ist, bevor Sie versuchen, darauf zuzugreifen.

Um Bildmetadaten in den Datenstrom zu schreiben, muss der Bildausgabedatei ein BitmapEncoder zugeordnet sein.

Erstellen Sie ein BitmapPropertySet-Objekt als Container für die festzulegenden Eigenschaftswerte. Erstellen Sie ein BitmapTypedValue-Objekt für den Eigenschaftswert. Dieses Objekt verwendet object als Wert und Member der PropertyType-Enumeration, die den Typ des Werts definiert. Fügen Sie den BitmapTypedValue dem BitmapPropertySet hinzu, und rufen Sie dann BitmapProperties.SetPropertiesAsync auf, damit der Encoder die Eigenschaften in den Datenstrom schreibt.

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