📍

Exif の位置情報に謎の値が入っていた

2023/09/13に公開

ラブグラフエンジニアの水瀬ひろです!

Exif の位置情報を利用したくて調べると、見たことの無い形で保存されていたので
lat, lng で扱える形に変換する方法をまとめておきます。

位置情報に関連する Exif

僕が旅行先で撮影した写真から Exif を読み取ったんですが、以下の値が入っていました。

GPSLatitudeRef: [24, 2435671/50000, 0]
GPSLongitudeRef: [125, 849567/50000, 0]

これを見てどう扱えばいいか分かりますか...??
僕は分かりませんでした。

よく見る値に変換する

実はこれ60進数で表現されているらしく、10進数に変換すると

  • 24.8118903333
  • 125.283189

のようなよく見る緯度経度になります。
変換方法を見ていきましょう。

60進数を10進数に変換する公式

[度] + [分 ÷ 60] + [秒 ÷ 3600]

なので、実際の計算手順は以下。
緯度と経度それぞれに同じことをやるのでメソッド化してみました。

/// Exif から取得できる緯度経度が60進数なので10進数に変換
/// 引数の例: [24, 2435671/50000, 0]
/// 返り値の例: 24.8118903333
/// 公式: [度] + [分 ÷ 60] + [秒 ÷ 3600]
double Convert60DecimalNumberToDecimalNumber(strFrom60Decimal) {
  final List<String> split60DecimalArray = strFrom60Decimal.replaceAll("[", "").replaceAll("]", "").split(",");

  final double degree = double.parse(split60DecimalArray[0]);
  final List<String> minuteSplitArray = split60DecimalArray[1].split("/");
  final double minute = (int.parse(minuteSplitArray[0]) / int.parse(minuteSplitArray[1])) / 60;
  final double second = double.parse(split60DecimalArray[2]) / 3600;

  return degree + minute + second;
}

このメソッドを通すことで
[24, 2435671/50000, 0] を 24.8118903333 に
[125, 849567/50000, 0] を 125.283189 に
それぞれ変換できるようになりました。

これで扱えそうですがもうひとつやる事があります...!!

北緯・南緯・西経・東経の判定

位置情報に関連する Exif のなかでまだ使っていないものがあります。

GPSLatitudeRef: N
GPSLongitudeRef: E

これは縦軸・横軸それぞれどこに位置するのかを示しています。

GPSLatitudeRef には N か S が入ります。
N なら North なので北緯、 S なら South なので南緯を表しています。

同じように GPSLongitudeRef には E か W が入ります。
E なら East なので東経、 W なら West なので西経となりますね。

実際の使い方としては
GPSLatitudeRef が S なら GPSLatitudeRef が負の数に。
GPSLongitudeRef が W なら GPSLongitudeRef が負の数になります。

今回のケースでは N と E だったのでどちらも正の数となり、 lat: 24.8118903333, lng: 125.283189 が導かれるので、宮古島で撮影された写真であることが分かりました🎉
座標を Google Map で検索

まとめ

これで、アップロードされた写真をマップにプロットしていくような機能が必要になっても、対応できるようになりましたね!
スマホで撮る写真には基本的に位置情報が含まれているので、どう扱うのかを今回知れてよかったです。

お読みいただきありがとうございました!

ラブグラフのエンジニアブログ

Discussion