Partilhar via


Metadados de imagem

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

Propriedades da imagem

A propriedade StorageFile.Properties retorna um objeto StorageItemContentProperties que fornece acesso a informações relacionadas ao conteúdo sobre o arquivo. Obtenha as propriedades específicas da imagem chamando GetImagePropertiesAsync. O objeto ImageProperties retornado expõe membros que contêm campos básicos de metadados de imagem, 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 de arquivo, use o Sistema de Propriedades do Windows, um conjunto de propriedades de metadados de arquivo que podem ser recuperadas com um identificador de cadeia de caracteres exclusivo. Crie uma lista de strings 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 chave/valor em que a chave é o identificador de 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 de Propriedades do Windows, incluindo os identificadores e o tipo de cada propriedade, consulte Propriedades do Windows.

  • Algumas propriedades só têm suporte para determinados contêineres de arquivos e codecs de imagem. 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 sem suporte podem retornar um valor nulo quando recuperadas, sempre verifique se há nulo antes de usar um valor de metadados retornado.

Auxiliar de geotag

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 representando o local que deseja marcar na imagem, seja de um uso anterior das APIs de geolocalização ou de alguma outra fonte, poderá definir os dados de geotag chamando GeotagHelper.SetGeotagAsync e passando um 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 geolocalização usando a localização atual do dispositivo, crie um novo objeto Geolocator e chame GeotagHelper.SetGeotagFromGeolocatorAsync passando o 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 representa o local com marcação geográfica de um arquivo de imagem, 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 as 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 WIC (Windows Imaging Component) para especificar o caminho para uma propriedade solicitada.

A leitura de metadados de imagem usando essa técnica requer 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.

Depois de ter o decodificador, crie uma lista de cadeias de caracteres e adicione uma nova entrada para cada propriedade de metadados que você deseja recuperar, usando a cadeia de caracteres do identificador de Propriedade do Windows ou uma consulta de metadados 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 do formato de imagem 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 uma das propriedades solicitadas não for compatível com a 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 para uma propriedade específica, use IDictionary.ContainsKey para verificar se uma propriedade está presente nos resultados antes de tentar acessá-la.

A gravação de 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 objeto como o valor e o membro da enumeração PropertyType que define o tipo do valor. Adicione o BitmapTypedValue ao BitmapPropertySet e 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;
        }
    }
}