概要
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を使う。
名前を使った場合と、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