イメージ メタデータ

この記事では、画像メタデータ プロパティの読み取りと書き込み方法、および 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 dateTaken = props.DateTaken;
}

より大きなファイル メタデータ セットにアクセスするには、Windows プロパティ システム (一意の文字列識別子を使用して取得できるファイル メタデータ プロパティのセット) を使用します。 文字列の一覧を作成し、取得する各プロパティの識別子を追加します。 ImageProperties.RetrievePropertiesAsync メソッドは、この文字列の一覧を取得し、キーがプロパティ識別子であり、値がプロパティ値であるキーと値のペアのディクショナリを返します。

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"];
    }
}
  • 各プロパティの識別子と型など、Windows プロパティの完全な一覧については、「Windows Properties」を参照してください。

  • 一部のプロパティは、特定のファイル コンテナーとイメージ コーデックでのみサポートされます。 各画像の種類でサポートされている画像メタデータの一覧については、「 写真メタデータ ポリシー」を参照してください。

  • サポートされていないプロパティは取得時に null 値を返す可能性があるため、返されるメタデータ値を使用する前に必ず null を確認してください。

ジオタグ ヘルパー

GeotagHelper は、Windows を使用して、画像に地理データを簡単にタグ付けできるようにするユーティリティ クラスです。Devices.Geolocation API を直接使用します。メタデータ形式を手動で解析または構築する必要はありません。

画像にタグを付ける場所を表す Geopoint オブジェクトが既にある場合は、 ジオロケーション API またはその他のソースの以前の使用から、geotag データを設定するには、GeotagHelper.SetGeotagAsync を呼び出し、StorageFileGeopoint

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

    await GeotagHelper.SetGeotagAsync(imageFile, point);
}

デバイスの現在の位置を使用してジオタグ データを設定するには、新しい Geolocator オブジェクトを作成し、Geolocator とタグ付けする対象のファイルを渡して GeotagHelper.SetGeotagFromGeolocatorAsync を呼び出します。

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);
    }
}
  • SetGeotagFromGeolocatorAsync API を使用するには、アプリ マニフェストに場所デバイス機能を含める必要があります。

  • SetGeotagFromGeolocatorAsync を呼び出す前に RequestAccessAsync を呼び出して、ユーザーが自分の場所を使用するアクセス許可をアプリに付与していることを確認する必要があります。

  • 位置情報 API とマップ API の詳細については、「 マップ コントロール」を参照してください。

画像ファイルのジオタグ付き場所を表す GeoPoint を取得するには、 GetGeotagAsync を呼び出します。

private async void GetGeoData(StorageFile imageFile)
{
    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;
        }
    }
}
  • WIC メタデータ クエリ言語とサポートされているプロパティについては、 WIC イメージ形式のネイティブ メタデータ クエリを参照してください。

  • 多くのメタデータ プロパティは、イメージの種類のサブセットでのみサポートされます。 GetPropertiesAsync は、要求されたプロパティのいずれかがデコーダーに関連付けられているイメージでサポートされていない場合はエラー コード 0x88982F41で失敗し、イメージがメタデータをまったくサポートしていない場合は0x88982F81。 これらのエラー コードに関連付けられている定数は WINCODEC_ERR_PROPERTYNOTSUPPORTED と WINCODEC_ERR_UNSUPPORTEDOPERATION であり、winerror.h ヘッダー ファイルで定義されています。

  • イメージに特定のプロパティの値が含まれている場合と含まれていない場合があるため、 IDictionary.ContainsKey を使用して、アクセスを試みる前にプロパティが結果に存在することを確認します。

ストリームにイメージ メタデータを書き込むには、イメージ出力ファイルに関連付けられている BitmapEncoder が必要です。

BitmapPropertySet オブジェクトを作成して、設定するプロパティ値を格納します。 プロパティ値を表す BitmapTypedValue オブジェクトを作成します。 このオブジェクトは、object を、値の型を定義する PropertyType 列挙型の値とメンバーとして使用します。 BitmapTypedValueBitmapPropertySet に追加し、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;
        }
    }
}