【PowerShell】画像ファイルのExif情報を任意の日付に編集する

Code

はじまり

リサちゃん
リサちゃん

うーん、Googleフォトでいちいち写真の日付を変えるのが面倒だな・・・。

135ml
135ml

じゃあ一括で変えられるようにしよう。

Googleフォトの写真の日付設定を楽にしたい!

というのが、今回の記事の主旨です。

Googleフォトで写真の日付を設定できますよね。

Googleフォトで画像や写真の情報を表示すると、その画像の日付を設定することが出来ます。

でも、この設定をする作業が大変なのだ。

しかしながら、LINEなどで友人・知人から共有された(Exif情報が付加されていない)写真は、Googleフォト上のタイムライン内で、自分が撮った写真とは全然違う時系列で表示されてしまいがちです。

例えば、自分が「2024-06-10 13:23:25」に撮った浅草寺雷門の写真と、同じ時間帯に友人が撮ってその翌日の夜にLINEでアルバムにアップロードされた浅草寺雷門の写真は、「2024-06-10 13:23:25」と「(例えば)2024-06-11 20:41:59」の日時の写真としてバラけて表示されてしまいます。

それは、Googleフォトがアップロードされた画像の日付を設定する際に参照している情報が不足していることが原因で発生します。

この設定項目で1枚ずつ日付を設定していくことが出来るのですが、その作業には骨が折れます・・・。(まあ、昔は愚直に500枚ぐらい編集していた時もありましたが・・・うわぁもうあんな事やってられませんわ。鳥肌が立つッ。)

Exifを編集して、日付設定を楽にしよう。

そこで今回は、1枚ずつ設定するなんてことはしないで、一度の入力でおおよその日付(時間)を設定するためのコマンドを練っていきます。

このコマンドを使うことで、LINEなどで友人・知人から共有された(Exif情報が付加されていない)写真を、Googleフォト上のタイムライン内で適切な時系列で表示できるようになります。

また、以前にExif情報から画像ファイルをリネームして、その画像をjpgやpngからwebpに変換して、このwebp画像に再びExif情報を反映するツールを作りました。

しかし、この時は自分のスマホやカメラで撮っていない写真にExif情報を反映する機能を作らなかったので、今回はその機能を作るためのコマンドの知見を深めていきたいと思います。

Googleフォトの日付は、Exif情報によって初期設定される。

Googleフォトにアップロードした画像の日付は、まあ大体こんな感じでデフォルト設定されます。

  1. Exifタグの「CreateDate」などを参照する。(厳密にどのタグを参照しているかは詳しくは調べていません。)
  2. そのExifタグに該当する日付の情報があったら、その日時を設定する。
  3. そのExifタグに該当する日付の情報がなかったら、ファイルの作成日時を日付として設定する。

その3番目の状態で画像の日付が設定されるので、後で見返しづらいGoogleフォトになってしまうわけです。

そして・・・、「『Exif』とは何ぞや?」となります。

「Exif」とは、画像ファイルに付加できるメタ情報のことで、その情報には、撮影したカメラの機種名、ISO、レンズなどの情報が格納されています。

このExifでは、撮影した位置情報なども扱えるので、Web上に画像をアップロードする際には、Exif情報の取り扱いにも注意ですね。まあ、そういった個人情報を隠すために一般的なSNSではアップロードされると、Exif情報が消える仕様になっているのかもしれません。

Exiftoolというライブラリを使う。

多彩なタグを扱える、多才なExiftoolくん。

今回も、Exif情報を編集するために「Exiftool」というライブラリを使っていきたいと思います。

ExifTool by Phil Harvey
A command-line application and Perl library for reading and writing EXIF, GPS, IPTC, XMP, makernotes and other meta info...

「Exiftool」はスゴイですね。Exifタグ以外にも、色々なタグを編集できるみたいです。

EXIF Tags

PDFとか、Quicktimeとか、9割ぐらいは何に使うのか分からないぐらいコアです・・・。

下記のPDF資料に載っています。

https://exiftool.org/TagNames.pdf

それでは早速、Exiftoolを使う。

Exiftoolを使ったPowershellコマンドがこちらになります。

Powershell

$number = 1
$date_formatted = Get-Date -Format "yyyyMMddHH"
$year_this = Get-Date -UFormat "%Y"
$year_last = Get-Date (Get-Date).AddYears(-1) -UFormat "%Y"
$is_correct = $false

function getUnitOfDatetime([string]$numStr){
    $num = [int]$numStr;
    return [string]$num
}

function getZeroPaddedUnit4([string]$numStr){
    return [string]"{0:0000}" -f [int]$numStr
}

function getZeroPaddedUnit2([string]$numStr){
    return [string]"{0:00}" -f [int]$numStr
}

while($is_correct -eq $false){
  $date_formatted = Read-Host "Input prefix of pictures (yyyyMMddHH)"
	if($date_formatted.length -eq 10 -and $date_formatted -like "${year_this}*" -or $date_formatted -like "${year_last}*"){
		$is_correct = $true
	}
  $y = getZeroPaddedUnit4(getUnitOfDatetime($date_formatted.Substring(0, 4)));
  $m = getZeroPaddedUnit2(getUnitOfDatetime($date_formatted.Substring(4, 2)));
  $d = getZeroPaddedUnit2(getUnitOfDatetime($date_formatted.Substring(6, 2)));
  $h = getZeroPaddedUnit2(getUnitOfDatetime($date_formatted.Substring(8, 2)));
  $new_create_date = "{0}-{1}-{2} {3}:00:00" -f $y, $m, $d, $h;
  Write-Host $new_create_date;
}

Get-ChildItem -Path . -File | ForEach-Object {
  if($_ -notlike "${year_this}*" -and $_ -notlike "${year_last}*" -and $_ -notlike "*.exe" -and $_ -isnot [System.IO.DirectoryInfo]){
		Write-Host "LOG-INFO" $_.GetType() "true" $_.Name

    # Exif
    $jpgFilePath = $_.FullName;
		./exiftool.exe -AllDates="$new_create_date" "$jpgFilePath"

    # Rename
    $number_zeropadded = "{0:0000}" -f $number
		$ext = [System.IO.Path]::GetExtension($_)
		$newName = "${date_formatted}${number_zeropadded}${ext}"
		Write-Host "LOG-INFO" $newName
		Rename-Item -Path ".\${_}" -NewName $newName

		$number++
  }else{
		Write-Host "LOG-INFO" $_.GetType() "false" $_.Name
	}
}
Write-Output("Exif info of {0} images are fixed with prompted dates." -f [string]($number-1));

これを実行すると、以下のように元画像は「.jpg_original」のファイルとなり、「.jpg」にExif情報が設定されたファイルが出来上がります。

今回のコマンドの解説

「# Rename」でコメントしている部分は今回の内容とは関係ないので説明は省きます。以下の記事をご参考下さい。

「# Exif」でコメントしている部分の説明に入ります。$_.FullNameの部分で、繰り返しているファイル群から1つのファイルの絶対パスを取得して、そのパスをexiftoolの引数に渡しています。

$jpgFilePath = $_.FullName;

そして、-AllDatesオプションを指定することで、CreateDate、ModifyDate、DateTimeOriginalの3つのExifタグを編集できるようです。(ソースはこちら。)

./exiftool.exe -AllDates="$new_create_date" "$jpgFilePath"

ちなみに、$new_create_dateを以下のように記述していますが、こちらは「”{0}-{1}-{2} {3}:00:00″」ではなく「”{0}:{1}:{2} {3}:00:00″」と記述しても日付がちゃんと反映されます。

$new_create_date = "{0}-{1}-{2} {3}:00:00" -f $y, $m, $d, $h;

$new_create_date変数に使う、$date_formatted変数を宣言する際に、指定する日付はPowershellコンソール内で入力させるようになっています。

$date_formatted = Read-Host "Input prefix of pictures (yyyyMMddHH)";

今回のコマンドの効果

このようなコマンドを作ることで、例えば、自分が「2024-06-10 13:23:25」に撮った浅草寺雷門の写真と、同じ時間帯に友人が撮ってその翌日の夜にLINEでアルバムにアップロードされた浅草寺雷門の写真を、「2024061013」と指定してExifを編集することで、ほぼ同じ時間帯の写真としてGoogleフォト上で表示させることが出来ます。

例えば、先程のこの写真を「2024061420」と打ち込んでExifを編集することで・・・、

右側にある日付の情報を見比べると分かります。「2024-06-15 21:00」から「2024-06-14 20:00」に設定し直されていることが確認できます。

これで、Googleフォト上で1枚ずつ写真の日付を設定し直す必要が無くなりました!

まとめ

本記事のまとめです。

Googleフォトの日付設定の問題点およびExif情報:

  • Googleフォトで手動で日付を変更するのは手間がかかる。
  • GoogleフォトではExif情報がないと、共有された写真の日付が正味の値として反映されない。
  • Exif情報とは画像ファイルに付加されたメタ情報のことで、カメラの機種や撮影日時などを含む。

Exiftoolの利用:

  • Exiftoolとは、Exif情報を編集するためのツールである。
  • Exiftoolで一括でExif情報を編集する、PowerShellスクリプトを作った。
  • PowerShellコンソールで日付を入力して設定する。
  • -AllDatesオプションを使って、CreateDate、ModifyDate、DateTimeOriginalの3つのタグを編集する。

これでもう、友人から写真が100枚ぐらい送られて来ても怖くない!

おしまい

リサちゃん
リサちゃん

これでテンキーのキーボードが要らなくなるワァ。

135ml
135ml

後で思い出の写真が見返しやすくなるな。

以上になります!

コメント

タイトルとURLをコピーしました