Metadane obrazu

W tym artykule pokazano, jak odczytywać i zapisywać właściwości metadanych obrazu oraz jak używać plików geotagu przy użyciu klasy narzędzi GeotagHelper.

Właściwości obrazu

Właściwość StorageFile.Properties zwraca właściwość StorageItemContentProperties, który zapewnia dostęp do informacji związanych z zawartością pliku. Pobierz właściwości specyficzne dla obrazu, wywołując polecenie GetImagePropertiesAsync. Zwrócony obiekt ImageProperties uwidacznia elementy członkowskie zawierające podstawowe pola metadanych obrazu, takie jak tytuł obrazu i data przechwytywania.

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

Aby uzyskać dostęp do większego zestawu metadanych pliku, użyj systemu właściwości Windows, zestawu właściwości metadanych pliku, które można pobrać za pomocą unikatowego identyfikatora ciągu. Utwórz listę ciągów i dodaj identyfikator dla każdej właściwości, którą chcesz pobrać. Metoda ImageProperties.RetrievePropertiesAsync przyjmuje tę listę ciągów i zwraca słownik par klucz/wartość, gdzie klucz jest identyfikatorem właściwości, a wartość jest wartością właściwości.

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"];
    }
}
  • Aby uzyskać pełną listę właściwości Windows, w tym identyfikatory i typ każdej właściwości, zobacz Windows Właściwości.

  • Niektóre właściwości są obsługiwane tylko w przypadku niektórych kontenerów plików i koderów obrazów. Aby uzyskać listę metadanych obrazu obsługiwanych dla każdego typu obrazu, zobacz Zasady metadanych zdjęć.

  • Ponieważ właściwości, które nie są obsługiwane, mogą zwracać wartość null po pobraniu, zawsze sprawdzaj wartość null przed użyciem zwróconej wartości metadanych.

Pomocnik geotagu

GeotagHelper to klasa narzędzi, która ułatwia tagowanie obrazów przy użyciu danych geograficznych przy użyciu Windows. Devices.Geolocation interfejsy API bezpośrednio bez konieczności ręcznego analizowania lub konstruowania formatu metadanych.

Jeśli masz już obiekt Geopoint reprezentujący lokalizację, którą chcesz oznaczyć na obrazie, czy to z wcześniejszego użycia interfejsów API geolokalizacji, czy z innego źródła, możesz ustawić dane geotagu, wywołując GeotagHelper.SetGeotagAsync i przekazując obiekty StorageFile oraz Geopoint.

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

    await GeotagHelper.SetGeotagAsync(imageFile, point);
}

Aby ustawić dane geotagu przy użyciu bieżącej lokalizacji urządzenia, utwórz nowy obiekt Geolocator i wywołaj obiekt GeotagHelper.SetGeotagFromGeolocatorAsync przekazując Geolocator i plik do otagowania.

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);
    }
}
  • Aby używać interfejsu API SetGeotagFromGeolocatorAsync, musisz uwzględnić w manifeście aplikacji funkcję urządzenia location.

  • Przed wywołaniem metody SetGeotagFromGeolocatorAsync należy wywołać metodę RequestAccessAsync, aby upewnić się, że użytkownik udzielił aplikacji uprawnień do korzystania z ich lokalizacji.

  • Aby uzyskać więcej informacji na temat geolokalizacji i interfejsów API map, zobacz sekcję Formant mapy.

Aby uzyskać geopoint reprezentujący lokalizację geotagowaną pliku obrazu, wywołaj metodę GetGeotagAsync.

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

Dekoduj i koduj metadane obrazu

Najbardziej zaawansowanym sposobem pracy z danymi obrazu jest odczytywanie i zapisywanie właściwości na poziomie strumienia przy użyciu BitmapDecoder lub BitmapEncoder. W przypadku tych operacji można użyć właściwości Windows, aby określić dane odczytywane lub pisane, ale można również użyć języka zapytań metadanych dostarczonego przez składnik Windows Imaging Component (WIC), aby określić ścieżkę do żądanej właściwości.

Odczytywanie metadanych obrazu przy użyciu tej techniki wymaga posiadania obiektu BitmapDecoder, który został utworzony na podstawie strumienia źródłowego pliku obrazu. Aby uzyskać informacje na temat tego, jak to zrobić, zobacz Tworzenie, edytowanie i zapisywanie obrazów map bitowych.

Po utworzeniu dekodera utwórz listę ciągów i dodaj nowy wpis dla każdej właściwości metadanych, którą chcesz pobrać, przy użyciu ciągu identyfikatora właściwości Windows lub zapytania metadanych WIC. Wywołaj metodę BitmapPropertiesView.GetPropertiesAsync na składniku BitmapProperties dekodera, aby zażądać określonych właściwości. Właściwości są zwracane w postaci słownika par klucz-wartość zawierających nazwę lub ścieżkę właściwości oraz jej wartość.

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;
        }
    }
}
  • Aby uzyskać informacje na temat języka zapytań metadanych WIC i obsługiwanych właściwości, zobacz Zapytania dotyczące natywnych metadanych w formacie obrazu WIC.

  • Wiele właściwości metadanych jest obsługiwanych tylko przez podzestaw typów obrazów. Polecenie GetPropertiesAsync zakończy się niepowodzeniem z kodem błędu 0x88982F41, jeśli jedna z żądanych właściwości nie jest obsługiwana przez obraz skojarzony z dekoderem i 0x88982F81, jeśli obraz w ogóle nie obsługuje metadanych. Stałe powiązane z tymi kodami błędów to WINCODEC_ERR_PROPERTYNOTSUPPORTED i WINCODEC_ERR_UNSUPPORTEDOPERATION i są one zdefiniowane w pliku nagłówkowym winerror.h.

  • Ponieważ obraz może lub nie może zawierać wartości określonej właściwości, przed podjęciem próby uzyskania do niej dostępu użyj elementu IDictionary.ContainsKey , aby sprawdzić, czy właściwość znajduje się w wynikach.

Zapisywanie metadanych obrazu w strumieniu wymaga elementu BitmapEncoder skojarzonego z plikiem wyjściowym obrazu.

Utwórz obiekt BitmapPropertySet zawierający wartości właściwości, które chcesz ustawić. Utwórz obiekt BitmapTypedValue reprezentujący wartość właściwości. Ten obiekt używa obiektu object jako wartości oraz elementu członkowskiego wyliczenia PropertyType, które definiuje typ wartości. Dodaj element BitmapTypedValue do elementu BitmapPropertySet, a następnie wywołaj metodę BitmapProperties.SetPropertiesAsync, aby koder zapisał właściwości do strumienia.

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