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


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 フォトにアップロードした画像の日付は、まあ大体こんな感じでデフォルト設定されます。
- Exif タグの
CreateDateなどを参照する。(厳密にどのタグを参照しているかは詳しくは調べていません。) - その Exif タグに該当する日付の情報があったら、その日時を設定する。
- その Exif タグに該当する日付の情報がなかったら、ファイルの作成日時を日付として設定する。
その 3 番目の状態で画像の日付が設定されるので、後で見返しづらい Google フォトになってしまうわけです。

そして・・・、「『Exif』とは何ぞや?」となります。
「Exif」とは、画像ファイルに付加できるメタ情報のことで、その情報には、撮影したカメラの機種名、ISO、レンズなどの情報が格納されています。
この Exif では、撮影した位置情報なども扱えるので、 Web 上に画像をアップロードする際には、 Exif 情報の取り扱いにも注意ですね。まあ、そういった個人情報を隠すために一般的な SNS ではアップロードされると、Exif情報が消える仕様になっているのかもしれません。
Exiftoolというライブラリを使う。
多彩なタグを扱える、多才なExiftoolくん。
今回も、Exif情報を編集するために「Exiftool」というライブラリを使っていきたいと思います。
「Exiftool」はスゴイですね。Exifタグ以外にも、色々なタグを編集できるみたいです。
PDFとか、Quicktimeとか、9割ぐらいは何に使うのか分からないぐらいコアです・・・。 下記のPDF資料に載っています。
それでは早速、Exiftoolを使う。
Exiftoolを使った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 枚ぐらい送られて来ても怖くない!
おしまい


以上になります!
記事を共有
この記事が役に立ったなら、ぜひ他の人と共有してください!