JavaScirptだけで画像のExif情報から位置情報を取得

2022年12月23日金曜日

Javascirpt

t f B! P L

enter image description here

JPEG、PNGなどの写真ファイルにはEXIF(エグジフ)規格があり、スマホで写真を撮ると自動で画像データと共に撮影日時やGPSの位置情報(ジオタグ)などが写真ファイルに付与されます。

今回は「Exif.js」というライブラリを使用して、JavaScriptだけでEXIF情報を取得する方法を紹介します。

スポンサーリンク

インストール

npmでインストールか、CDN経由で使用する。

npmでインストールする場合

npm install exif-js --save   

CDN経由で使用する場合

<script src="https://cdn.jsdelivr.net/npm/exif-js"></script>  

■「Exif.js」の Githubリポジトリ
Exif.js

サンプルコード

選択された画像から、EXIF情報を取得して位置情報(緯度・軽度)を取得するサンプルコードを作ってみます。

まず、ファイル選択の入力コントロールを置いた HTMLを用意します。

【HTML】

<div>
  <input id="file" type="file" />
</div>

【JavaScirpt】
画面でファイルが選択された際に、FileReaderを使って画像ファイルを Data URLに変換し、変換した URLを引数に後述する getExif 関数を呼び出す処理を作る。

const input = document.getElementById("file")

//ファイルを選択した時のイベントを登録
input.addEventListener("change", (e) => {
  if (input.files.length == 0) return
  
  //選択したファイルを Data URLに変換して、緯度・軽度を取得する getExif()関数を呼ぶ
  const reader = new FileReader()
  reader.addEventListener("load", () => {
    getExif(reader.result as string)
  }, false)
  reader.readAsDataURL(input.files[0])
})

次に、選択された画像の Data URLから「Exif.js」の関数を使って、緯度・軽度を取得する getExif を作成する。

/**
 * EXIF情報から緯度・軽度を取得する
 * @param url 画像のData URL
 */
function getExif(url) {

  //Data URLから Imageを作成
  const image = new Image()
  image.src = url
  image.onload = function () {

    EXIF.getData(image, function () {
      //EXIF情報の緯度・経度タグを取得
      const gpsLatitude = EXIF.getTag(image, 'GPSLatitude')
      const gpgLongitude = EXIF.getTag(image, 'GPSLongitude')

      //[度,分,秒]の値を10進数に変換
      const lat = gpsLatitude[0]/1 + gpsLatitude[1]/60 + gpsLatitude[2]/3600
      const lon = gpgLongitude[0]/1 + gpgLongitude[1]/60 + gpgLongitude[2]/3600
      console.log(`緯度=${lat}`)
      console.log(`経度=${lon}`)
    });
  }
}

補足

「Exif.js」から取得できるEXIFの位置情報(緯度・経度)は、次のような形式となっている。

{
    "GPSLatitude": [
        34,
        49,
        16.43
    ],
    "GPSLongitude": [
        137,
        22,
        5.91
    ],
}

上記のように、GPSLatitude(緯度)、GPSLongitude(経度)のタグには [度, 分, 秒]の形式でデータが格納されている。そのため、今回のサンプルコードでは以下の部分で、「度分秒」の値を10進数の緯度・経度に変換している。

//[度,分,秒]の値を10進数に変換
const lat = gpsLatitude[0]/1 + gpsLatitude[1]/60 + gpsLatitude[2]/3600
const lon = gpgLongitude[0]/1 + gpgLongitude[1]/60 + gpgLongitude[2]/3600

スポンサーリンク

Reactで実装する方法

ついでに、React(TypeScript)で作った場合のコードも紹介する。基本は上の JavaScirptと実装方法は同じである。

import EXIF from 'exif-js'
import React, { useCallback, useRef } from 'react'

function Sample() {

  const inputRef = useRef<HTMLInputElement>(null)

  /**
   * ファイル選択時の処理
   */
  const onChange = useCallback(
    () => {
      if (inputRef.current?.files 
        && inputRef.current.files.length > 0) {

        //選択したファイルを Data URLに変換して、緯度・軽度を取得する getExif()関数を呼ぶ
        const reader = new FileReader()
        reader.addEventListener("load", () => {
          getExif(reader.result as string)
        }, false);
        reader.readAsDataURL(inputRef.current.files[0]);
      }
    }, 
    []
  )
  
  /**
   * EXIF情報から緯度・軽度を取得する
   * @param url 画像のData URL
   */
  function getExif(url: string) {

    //Data URLから Imageを作成
    const image = new Image()
    image.src = url
    image.onload = function () {

      EXIF.getData(image as any, function () {
        //EXIF情報の緯度・経度タグを取得
        const gpsLatitude = EXIF.getTag(image, 'GPSLatitude')
        const gpgLongitude = EXIF.getTag(image, 'GPSLongitude')

        //度分秒を10進数に変換
        const lat = gpsLatitude[0]/1 + gpsLatitude[1]/60 + gpsLatitude[2]/3600
        const lon = gpgLongitude[0]/1 + gpgLongitude[1]/60 + gpgLongitude[2]/3600
        console.log(`緯度=${lat}`)
        console.log(`経度=${lon}`)
      });
    }
  }

  return (
    <div>
      <input ref={inputRef} onChange={onChange} type="file" />
    </div>
  )
}

export default Sample

まとめ

「Exif.js」を使って、画像ファイルの EXIF情報から位置情報(緯度・経度)を取得する方法を紹介しました。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ