C#で JPEG の Exifデータ にある GPS情報(位置情報)を更新します。前回 と同じく今回も下記の4つの値を使用します。
| タグ名称 | タグ番号 | Field Name | タイプ |
| 北緯(N)or 南緯(S) | 1 | GPSLatitudeRef | ASCII |
| 緯度(数値) | 2 | GPSLatitude | RATIONAL |
| 東経(E)or 西経(W) | 3 | GPSLongitudeRef | ASCII |
| 経度(数値) | 4 | GPSLongitude | RATIONAL |
※RATIONAL : 最初の数値が分子、2個目のL数値が分母を表す 32 ビット符号なし整数が2個
Exifの詳しい仕様については下記をご覧ください。
デジタルスチルカメラ用画像ファイルフォーマット規格
http://it.jeita.or.jp/document/publica/standard/exif/japanese/jeida49ja.htm
Bitmap クラス オブジェクトを作成し、タグ番号(Id)の配列を取得します。
string inFn = @"元画像のパス";
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(inFn);
緯度の南北の PropertyItem(ID:1)を取得し、SetPropertyItem を使用して値を更新します。
System.Drawing.Imaging.PropertyItem gpsLatitudeRef =
bmp.PropertyItems[Array.IndexOf(ids, 0x0001)];
byte[] latRef = System.Text.Encoding.Unicode.GetBytes("N");
bmp.SetPropertyItem(gpsLatitudeRef);
緯度の PropertyItem(ID:2)を取得し、SetPropertyItem を使用して値を更新します。
※緯度 35度39分31.05秒に更新する場合
byte[] lat = new byte[24];
Array.Copy(BitConverter.GetBytes(35), 0, lat, 0, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lat, 4, 4);
Array.Copy(BitConverter.GetBytes(39), 0, lat, 8, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lat, 12, 4);
Array.Copy(BitConverter.GetBytes(310500), 0, lat, 16, 4);
Array.Copy(BitConverter.GetBytes(10000), 0, lat, 20, 4);
gpsLatitude.Value = lat;
bmp.SetPropertyItem(gpsLatitude);
新しいファイル名を指定して保存します。
string outFn = @"更新後の画像パス";
bmp.Save(outFn, System.Drawing.Imaging.ImageFormat.Jpeg);
東経(E)or 西経(W), 経度も同様に更新することができます。
尚、PropertyItem クラスには、定義済みのパブリック コンストラクターがありません。
そのため、更新ではなく新規で位置情報などの PropertyItem を追加したい場合は、
別の画像から PropertyItem オブジェクトを取得して、SetPropertyItem で指定すれば、新に項目が追加されます。
サンプルコード(緯度 35度39分31.05秒, 経度 139度44分43.494秒に更新)
using System;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
string inFn = @"入力ファイル";
string outFn = @"出力ファイル";
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(inFn);
int[] ids = bmp.PropertyIdList;
// 緯度の南北(タグ番号 1.GPSLatitudeRef)を取得・設定
System.Drawing.Imaging.PropertyItem gpsLatitudeRef = bmp.PropertyItems[Array.IndexOf(ids, 0x0001)];
byte[] latRef = System.Text.Encoding.Unicode.GetBytes("N");
bmp.SetPropertyItem(gpsLatitudeRef);
// 緯度(タグ番号 2.GPSLatitude)を取得
System.Drawing.Imaging.PropertyItem gpsLatitude = bmp.PropertyItems[Array.IndexOf(ids, 0x0002)];
// 緯度 35度39分31.05秒 を設定
byte[] lat = new byte[24];
Array.Copy(BitConverter.GetBytes(35), 0, lat, 0, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lat, 4, 4);
Array.Copy(BitConverter.GetBytes(39), 0, lat, 8, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lat, 12, 4);
Array.Copy(BitConverter.GetBytes(310500), 0, lat, 16, 4);
Array.Copy(BitConverter.GetBytes(10000), 0, lat, 20, 4);
gpsLatitude.Value = lat;
bmp.SetPropertyItem(gpsLatitude);
// 経度の東西(タグ番号 3.GPSLongitudeRef)を取得・設定
System.Drawing.Imaging.PropertyItem gpsLongitudeRef = bmp.PropertyItems[Array.IndexOf(ids, 0x0003)];
byte[] lonRef = System.Text.Encoding.Unicode.GetBytes("E");
// 経度(タグ番号 4.GPSLongitude)を取得
System.Drawing.Imaging.PropertyItem gpsLongitude = bmp.PropertyItems[Array.IndexOf(ids, 0x0004)];
// 経度 139度44分43.494秒 を設定
byte[] lon = new byte[24];
Array.Copy(BitConverter.GetBytes(139), 0, lon, 0, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lon, 4, 4);
Array.Copy(BitConverter.GetBytes(44), 0, lon, 8, 4);
Array.Copy(BitConverter.GetBytes(1), 0, lon, 12, 4);
Array.Copy(BitConverter.GetBytes(434940), 0, lon, 16, 4);
Array.Copy(BitConverter.GetBytes(10000), 0, lon, 20, 4);
gpsLongitude.Value = lon;
bmp.SetPropertyItem(gpsLongitude);
// 保存
bmp.Save(outFn, System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
}
public Form1()
{
InitializeComponent();
}
}
}