LoginSignup
4
4

More than 5 years have passed since last update.

【WPF】C#でjpgのExif情報を読み込む

Last updated at Posted at 2019-03-11

概要

C#(WPF)で、jpg画像の中のEXIF情報を取り出し/書き込みする。
読み書きには、BitmapMetadataクラスのGetQuery/SetQueryを使用する。

読み出し

流れは下記のようにする。

  • ファイルパスからBitmapFrameクラスのインスタンスを作成(画像を読み込み)。
  • BitmapMetadataクラスで、EXIF情報を含むMetadataを取り出し。
  • 取り出したMetadataから、GetQueryメソッドを使って必要なデータを取り出す。

具体的には、下記のようにする。

// ファイル/Metadata読み込み
Uri uri = new Uri(tb_FileName.Text, UriKind.Absolute);
BitmapFrame frame = BitmapFrame.Create(uri);
BitmapMetadata metadata = frame.Metadata as BitmapMetadata;

// GetQueryしてエラーになる場合、
// クエリの中の型(「ushort」の部分)が間違っているかもしれない。
// その時は、「読み込み位置の指定(クエリ)の実験」で行ったMetadataの列挙のところで
// 出力される型を確認する。(画像ファイルによって、型が異なる?)

// varの型が実際何かは、デバッグ実行して、この下でとめて、ウォッチの「種類」欄で帰ってきた値の型を見る。
var GPSLatitudeRef = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=1}");  // 北緯or南緯
var GPSLatitude = metadata.GetQuery("/app1/ifd/gps/subifd:{ushort=2}");     // 緯度
var GPSLongitudeRef = metadata.GetQuery("/app1/ifd/gps/{ushort=3}");        // 東経or西経
var GPSLongitude = metadata.GetQuery("/app1/ifd/gps/{ushort=4}");           // 経度

var Maker = metadata.GetQuery("/app1/ifd/{ushort=271}");                    // メーカー名
var Model = metadata.GetQuery("/app1/ifd/{ushort=272}");                    // モデル名

var MakerExif = metadata.GetQuery("/app1/ifd/exif/{ushort=34864}");         // Exifバージョン

metadata.GetQuery()で各idの値をとれるが、何の型で帰ってくるのか、がよくわからなかった。
結果、ソース中にも書いているが、帰ってきたところでbreakで止めて、ウォッチで中身の型を見て判定した。

読み出し(実験)

GetQueryに引数として渡すクエリは、
"/app1/ifd/exif" のように名前?で指定もできるし、
"/app1/ifd/{ushort=34665}"のようにIDで指定もできる。
 ※IDが何かは、規格資料(参考資料参照)の中に書いてある。
  /app1/ifd/{ushort=34665}は、下の「Exifタグ」のところのIDを使う。
image.png

名前を使った場合と、IDを使った場合の例は、下記の通り。


// ファイル/Metadata読み込み
Uri uri = new Uri(tb_FileName.Text, UriKind.Absolute);
BitmapFrame frame = BitmapFrame.Create(uri);
BitmapMetadata metadata = frame.Metadata as BitmapMetadata;

BitmapMetadata metadata2 = (BitmapMetadata)metadata.GetQuery("/app1");
Debug.WriteLine("Metadataを列挙 /app1");
foreach (string str in metadata2)
{
    Debug.WriteLine(str);
}

#if true
BitmapMetadata metadata4 = (BitmapMetadata)metadata.GetQuery("/app1/ifd");
Debug.WriteLine("Metadataを列挙 /app1/ifd");
foreach (string str in metadata4)
{
    Debug.WriteLine(str);
}
#else
// 以下は、上の処理と同じ
BitmapMetadata metadata4 = (BitmapMetadata)metadata.GetQuery("/app1/{ushort=0}");
Debug.WriteLine("Metadataを列挙 /app1/{ushort=0}");
#endif

#if true
BitmapMetadata metadata6 = (BitmapMetadata)metadata.GetQuery("/app1/ifd/exif");
Debug.WriteLine("Metadataを列挙 /app1/ifd/exif");
foreach (string str in metadata6)
{
    Debug.WriteLine(str);
}
#else
// 以下は、上の処理と同じ
BitmapMetadata metadata6 = (BitmapMetadata)metadata.GetQuery("/app1/ifd/{ushort=34665}");
Debug.WriteLine("Metadataを列挙 /app1/ifd/{ushort=34665}");
#endif

#if true
BitmapMetadata metadataGPS = (BitmapMetadata)metadata.GetQuery("/app1/ifd/gps");
Debug.WriteLine("Metadataを列挙 /app1/ifd/gps");
foreach (string str in metadataGPS)
{
    Debug.WriteLine(str);
}
#else
// 以下は、上の処理と同じ
BitmapMetadata metadataGPS = (BitmapMetadata)metadata.GetQuery("/app1/ifd/{ushort=34853}");
Debug.WriteLine("Metadataを列挙 /app1/ifd/{ushort=34853}");
#endif

それぞれ「Debug.WriteLine(str);」で、そのIDにぶら下がっている項目が一覧表示される。

コード

参考

EXIF規格
http://www.cipa.jp/std/documents/j/DC-008-2012_J.pdf

わかりやすいEXIFの規格のイメージ(図がわかりやすい)
http://dsas.blog.klab.org/archives/52123322.html

書き込みのサンプル
http://puni-o.hatenablog.com/entry/2017/12/15/113053

読み込みのサンプル
http://funct.hatenablog.com/entry/20151007/1444231916

4
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4