Metadata obrázků

Tento článek ukazuje, jak číst a zapisovat vlastnosti metadat obrázků a jak přidávat souborům zeměpisné značky pomocí pomocné třídy GeotagHelper.

Vlastnosti obrázku

Vlastnost StorageFile.Properties vrátí StorageItemContentProperties objekt, který poskytuje přístup k informacím o souboru souvisejícím s obsahem. Získejte vlastnosti specifické pro image voláním GetImagePropertiesAsync. Vrácený objekt ImageProperties zveřejňuje členy, které obsahují základní pole metadat obrázků, jako je název obrázku a datum zachycení.

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

Pokud chcete získat přístup k větší sadě metadat souborů, použijte systém vlastností Windows, sadu vlastností metadat souboru, které lze načíst s jedinečným identifikátorem řetězce. Vytvořte seznam řetězců a přidejte identifikátor pro každou vlastnost, kterou chcete načíst. Metoda ImageProperties.RetrievePropertiesAsync vezme tento seznam řetězců a vrátí slovník párů klíč/hodnota, kde klíč je identifikátor vlastnosti a hodnota je hodnota vlastnosti.

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"];
    }
}
  • Úplný seznam vlastností Windows, včetně identifikátorů a typů pro každou vlastnost, najdete v tématu Windows Vlastnosti.

  • Některé vlastnosti jsou podporovány pouze pro určité kontejnery souborů a kodeky obrázků. Seznam metadat obrázků podporovaných pro každý typ obrázku najdete v tématu Zásady metadat fotografií.

  • Vzhledem k tomu, že vlastnosti, které nejsou podporovány, mohou při načtení vrátit hodnotu null, vždy zkontrolujte hodnotu null před použitím vrácené hodnoty metadat.

Pomocník pro geografické značky

GeotagHelper je třída nástrojů, která usnadňuje označování obrázků s geografickými daty pomocí Windows. Devices.Geolocation API přímo, aniž byste museli ručně analyzovat nebo vytvářet formát metadat.

Pokud už máte objekt Geopoint, který představuje umístění, jež chcete v obrázku označit zeměpisnou značkou, ať už z předchozího použití rozhraní API geolokace nebo z nějakého jiného zdroje, můžete data zeměpisné značky nastavit voláním GeotagHelper.SetGeotagAsync a předáním objektu StorageFile a objektu Geopoint.

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

    await GeotagHelper.SetGeotagAsync(imageFile, point);
}

Chcete-li nastavit data geoznačky pomocí aktuální polohy zařízení, vytvořte nový objekt Geolocator a zavolejte metodu GeotagHelper.SetGeotagFromGeolocatorAsync, které předejte objekt Geolocator a soubor, který chcete označit geoznačkou.

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

Pokud chcete získat geopoint představující geograficky oznamované umístění souboru obrázku, zavolejte GetGeotagAsync.

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

Dekódování a kódování metadat obrázků

Nejpokročilejší způsob práce s daty obrázků je čtení a zápis vlastností na úrovni datového proudu pomocí BitmapDecoder nebo BitmapEncoder. U těchto operací můžete použít Windows Vlastnosti k určení dat, která čtete nebo píšete, ale můžete také použít dotazovací jazyk metadat poskytnutý komponentou Windows Imaging Component (WIC) k určení cesty k požadované vlastnosti.

Čtení metadat obrázku pomocí této techniky vyžaduje, abyste měli objekt BitmapDecoder, který byl vytvořen z datového proudu zdrojového souboru obrázku. Informace o tom, jak to udělat, naleznete v tématu Vytváření, úpravy a ukládání rastrových obrázků.

Jakmile budete mít dekodér, vytvořte seznam řetězců a přidejte novou položku pro každou vlastnost metadat, kterou chcete načíst, pomocí řetězce identifikátoru vlastnosti Windows nebo dotazu metadat WIC. Zavolejte metodu BitmapPropertiesView.GetPropertiesAsync u členu BitmapProperties dekodéru a vyžádejte si zadané vlastnosti. Vlastnosti se vrátí ve slovníku párů klíč/hodnota obsahující název vlastnosti nebo cestu a hodnotu vlastnosti.

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;
        }
    }
}
  • Informace o dotazovacím jazyce metadat WIC a podporovaných vlastnostech najdete v dotazech nativních metadat ve formátu bitové kopie WIC.

  • Mnoho vlastností metadat je podporováno pouze podmnožinou typů obrázků. GetPropertiesAsync selže s kódem chyby 0x88982F41 pokud některý z požadovaných vlastností není podporován obrázkem přidruženým k dekodéru a 0x88982F81, pokud image vůbec nepodporuje metadata. Konstanty přidružené k těmto kódům chyb jsou WINCODEC_ERR_PROPERTYNOTSUPPORTED a WINCODEC_ERR_UNSUPPORTEDOPERATION a jsou definovány v souboru hlavičky winerror.h.

  • Vzhledem k tomu, že obrázek může nebo nemusí obsahovat hodnotu pro určitou vlastnost, použijte IDictionary.ContainsKey k ověření, zda je vlastnost přítomna ve výsledcích před pokusem o přístup k této vlastnosti.

Zápis metadat obrázků do datového proudu vyžaduje BitmapEncoder přidružený k výstupnímu souboru obrázku.

Vytvořte objekt BitmapPropertySet obsahující hodnoty vlastností, které chcete nastavit. Vytvořte objekt BitmapTypedValue představující hodnotu vlastnosti. Tento objekt používá object jako hodnotu a člena PropertyType výčet definující typ hodnoty. Přidejte BitmapTypedValue do BitmapPropertySet a potom zavolejte BitmapProperties.SetPropertiesAsync, aby kodér zapsal vlastnosti do datového proudu.

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