이미지 메타데이터

이 문서에서는 이미지 메타데이터 속성을 읽고 쓰는 방법과 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를 호출하고 StorageFileGeopoint를 전달하여 지오태그 데이터를 설정할 수 있습니다.

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

이미지 파일의 지리적 태그가 지정된 위치를 나타내는 GeoPoint를 얻으려면 GetGeotagAsync를 호출합니다.

Geopoint geoPoint = await GeotagHelper.GetGeotagAsync(imageFile);

이미지 메타데이터 디코딩 및 인코딩

이미지 데이터를 사용하는 가장 고급 방법은 BitmapDecoder 또는 BitmapEncoder를 사용하여 스트림 수준에서 속성을 읽고 쓰는 것입니다. 이러한 작업의 경우 Windows 속성을 사용하여 읽거나 쓰는 데이터를 지정할 수 있지만 WIC(Windows 이미징 구성 요소)에서 제공하는 메타데이터 쿼리 언어를 사용하여 요청된 속성의 경로를 지정할 수도 있습니다.

이 기술을 사용하여 이미지 메타데이터를 읽으려면 원본 이미지 파일 스트림을 사용하여 만든 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 개체를 만듭니다. 이 개체는 값의 형식을 정의하는 PropertyType 열거형의 값 및 멤버로 개체를 사용합니다. BitmapPropertySetBitmapTypedValue를 추가한 다음, 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;
        }
    }
}