图像元数据
本文介绍如何读写图像元数据属性以及如何使用 GeotagHelper 实用程序类标注文件。
映像属性
StorageFile.Properties 属性返回对关于文件的相关内容信息提供访问的 StorageItemContentProperties 对象。 通过调用 GetImagePropertiesAsync 获取特定于图像的属性。 返回的 ImageProperties 对象公开包含基本图像元数据字段(如图像的标题和捕获日期)的成员。
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
}
}
若要访问较大的文件元数据集,请使用 Windows 属性系统,一组可以使用唯一的字符串标识符进行检索的文件元数据。 创建字符串列表,并为想要检索的每个属性添加标识符。 ImageProperties.RetrievePropertiesAsync 方法采用此字符串列表,并返回键/值对的字典,其中键是属性标识符,值是属性值。
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"];
}
有关 Windows 属性的完整列表(包括标识符和每个属性的类型),请参阅 Windows 属性。
某些属性仅适用于某些文件容器和图像编解码器。 有关每种图像类型支持的图像元数据的列表,请参阅照片元数据策略。
由于不受支持的属性在检索时可能会返回 Null 值,因此在使用返回的元数据值之前,始终检查 Null。
地理标签帮助程序
GeotagHelper 是一个实用工具类,可以方便地直接使用 Windows.Devices.Geolocation API 标记带有地理数据的图像,而不必手动分析或构建元数据格式。
如果你已拥有表示要在图像(来自先前使用的地理位置 API 或某些其他源)中标记的位置的 Geopoint 对象,你可以通过调用 GeotagHelper.SetGeotagAsync 并传入 StorageFile 和 Geopoint 来设置地理标签数据。
var point = new Geopoint(
new BasicGeoposition
{
Latitude = 48.8567,
Longitude = 2.3508,
});
await GeotagHelper.SetGeotagAsync(imageFile, point);
若要使用设备的当前位置设置地理标签数据,则创建一个新的 Geolocator 对象,并调用传入 Geolocator 和要标记文件的 GeotagHelper.SetGeotagFromGeolocatorAsync。
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);
}
必须在应用部件清单中包含 location 设备功能,以便使用 SetGeotagFromGeolocatorAsync API。
你必须在调用 SetGeotagFromGeolocatorAsync 之前调用 RequestAccessAsync,以确保用户已授予你的应用使用他们的位置的权限。
有关地理位置 API 的详细信息,请参阅地图和位置。
若要获取表示图像文件的已加注地理标签位置的 GeoPoint,请调用 GetGeotagAsync。
Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);
解码和编码图像元数据
使用图像数据的最先进方式是使用 BitmapDecoder 或 BitmapEncoder 在流级别上读写属性。 对于这些操作,你可以使用 Windows 属性来指定正在读写的数据,但你也可以使用由 Windows 图像处理组件 (WIC) 提供的元数据查询语言为请求的属性指定路径。
使用此技术读取图像元数据要求你拥有使用源图像文件流创建的 BitmapDecoder。 有关如何执行此操作的详细信息,请参阅图像处理。
安装解码器后,创建一个字符串列表,并为要使用 Windows 属性标识符字符串或 WIC 元数据查询进行检索的每个元数据属性添加一个新项。 调用解码器的 BitmapProperties 成员上的 BitmapPropertiesView.GetPropertiesAsync 方法以请求指定的属性。 在包含属性名称或路径和属性值的键/值对的字典中将返回属性。
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;
}
}
}
有关 WIC 元数据查询语言和支持的属性的信息,请参阅 WIC 图像格式本机元数据查询。
许多元数据属性仅受图形类型的一个子集支持。 如果请求的属性中的某一个属性不受与解码器关联的图像支持,GetPropertiesAsync 将失败,错误代码为 0x88982F41;如果图像完全不支持元数据,错误代码为 0x88982F81。 与这些错误代码相关联的常量是 WINCODEC_ERR_PROPERTYNOTSUPPORTED 和 WINCODEC_ERR_UNSUPPORTEDOPERATION,它们在 winerror.h 标头文件中定义。
由于不确定图像是否包含特定属性的值,在尝试访问它之前,请使用 IDictionary.ContainsKey 来验证属性是否出现在结果中。
将图像元数据写入流需要与图像输出文件关联的 BitmapEncoder。
创建 BitmapPropertySet 对象以包含要设置的属性值。 创建 BitmapTypedValue 对象以表示属性值。 此对象将 object 用作值和定义值类型的 PropertyType 枚举的成员。 将 BitmapTypedValue 添加到 BitmapPropertySet,然后调用 BitmapProperties.SetPropertiesAsync 会导致编码器将属性写入流中。
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;
}
}
}
有关图像文件类型支持的属性的详细信息,请参阅 Windows 属性、照片元数据策略和 WIC 图像格式本机元数据查询。
如果请求的属性之一不受与编码器关联的图像支持,SetPropertiesAsync 将失败,错误代码为 0x88982F41。
相关主题