Partilhar via


Metadados de imagem

Este artigo mostra como ler e gravar propriedades de metadados de imagem e como geotag arquivos usando a classe de utilitário GeotagHelper .

Propriedades da imagem

A propriedade StorageFile.Properties retorna um objeto StorageItemContentProperties que fornece acesso às informações relacionadas ao conteúdo sobre o arquivo. Obtenha as propriedades específicas da imagem chamando GetImagePropertiesAsync. O objeto retornado ImageProperties expõe membros que contêm campos de metadados de imagem básicos, como o título da imagem e a data de captura.

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

Para acessar um conjunto maior de metadados do arquivo, use o Windows Property System, um conjunto de propriedades de metadados de arquivo que pode ser recuperado com um identificador de cadeia de caracteres exclusivo. Crie uma lista de cadeias de caracteres e adicione o identificador para cada propriedade que você deseja recuperar. O método ImageProperties.RetrievePropertiesAsync usa essa lista de cadeias de caracteres e retorna um dicionário de pares de chave/valor onde a chave é o identificador da propriedade e o valor é o valor da propriedade.

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"];
}
  • Para obter uma lista completa das Propriedades do Windows, incluindo os identificadores e o tipo de cada propriedade, consulte Propriedades do Windows.

  • Algumas propriedades só são suportadas para determinados codecs de imagem e contêineres de arquivos. Para obter uma lista dos metadados de imagem com suporte para cada tipo de imagem, consulte Políticas de Metadados de Fotos.

  • Como as propriedades que não são suportadas podem retornar um valor nulo quando recuperado, sempre verifique para null antes de usar um valor de metadados retornados.

GeotagHelper

GeotagHelper é uma classe de utilitário que facilita a marcação de imagens com dados geográficos usando as APIs Windows.Devices.Geolocation diretamente, sem precisar analisar ou construir manualmente o formato de metadados.

Se você já tiver um objeto Geopoint que representa o local que deseja marcar na imagem, de uma utilização anterior das APIs de geolocalização ou de alguma outra fonte, poderá definir os dados de marca de localização chamando GeotagHelper.SetGeotagAsync e passando StorageFile e o Geopoint.

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

await GeotagHelper.SetGeotagAsync(imageFile, point);

Para definir os dados de marca de localização usando a localização atual do dispositivo, crie um novo objeto Geolocator e chame GeotagHelper.SetGeotagFromGeolocatorAsync passando Geolocator e o arquivo a ser marcado.

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

Para obter um GeoPoint que represente o local de um arquivo de imagem com marca de localização, chame GetGeotagAsync.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

Decodificar e codificar metadados de imagem

A maneira mais avançada de trabalhar com dados de imagem é ler e gravar as propriedades no nível do fluxo usando um BitmapDecoder ou um BitmapEncoder. Para essas operações, você pode usar Propriedades do Windows para especificar os dados que está lendo ou gravando, mas também pode usar a linguagem de consulta de metadados fornecida pelo Windows Imaging Component (WIC) para especificar o caminho para uma propriedade solicitada.

Ler metadados de imagem usando essa técnica exige que você tenha um BitmapDecoder que foi criado com o fluxo de arquivo de imagem de origem. Para obter informações sobre como fazer isso, consulte Imagens.

Assim que você tiver o decodificador, crie uma lista de cadeias de caracteres e adicione uma nova entrada para cada propriedade de metadados que deseja recuperar usando a cadeia de caracteres de identificador da Propriedade do Windows ou uma consulta de metadados do WIC. Chame o método BitmapPropertiesView.GetPropertiesAsync no membro BitmapProperties do decodificador para solicitar as propriedades especificadas. As propriedades são retornadas em um dicionário de pares de chave/valor que contém o nome ou caminho da propriedade e o valor da propriedade.

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;
        }
    }
}
  • Para obter informações sobre a linguagem de consulta de metadados do WIC e as propriedades com suporte, consulte Consultas de metadados nativos de formato de imagem do WIC.

  • Muitas propriedades de metadados são suportadas apenas por um subconjunto de tipos de imagem. GetPropertiesAsync falhará com o código de erro 0x88982F41 se não houver suporte para uma das propriedades solicitadas pela imagem associada ao decodificador e 0x88982F81 se a imagem não der suporte a metadados. As constantes associadas a esses códigos de erro são WINCODEC_ERR_PROPERTYNOTSUPPORTED e WINCODEC_ERR_UNSUPPORTEDOPERATION e são definidas no arquivo de cabeçalho winerror.h.

  • Como uma imagem pode ou não conter um valor de uma propriedade específica, use o IDictionary.ContainsKey para verificar se uma propriedade está presente nos resultados antes de tentar acessá-la.

Gravar metadados de imagem no fluxo requer um BitmapEncoder associado ao arquivo de saída da imagem.

Crie um objeto BitmapPropertySet para conter os valores de propriedade que você deseja definir. Crie um objeto BitmapTypedValue para representar o valor da propriedade. Esse objeto usa um object como o valor e o membro da enumeração PropertyType que define o tipo do valor. Adicione BitmapTypedValue a BitmapPropertySet e, em seguida, chame BitmapProperties.SetPropertiesAsync para fazer com que o codificador grave as propriedades no fluxo.

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