本文中の "$" は半角で読み替えること。
Googleフォトにアップした際、時刻が-9時間される問題、とりあえずの回避策としてExif情報の撮影日時を付加するように、前回作成したスクリプトに機能を追加する。
変更点としては、
・第2引数に出力先パスを追加
・第1引数で指定したパス内のJPEGファイルにEXIF情報(撮影日時)を付加し、第2引数のパスに出力。
・これまで通り更新日時の更新も行うが、この更新は第2引数で指定したファイルに対して行う。
PeopertyItemオブジェクトの取得
参考:PowerShellでExif情報を書き込むには? #1
上記サンプルでは、PropertyItemを追加するため、既存のPropertyItemの先頭項目を取得していた。
しかし、追加しようとするIdが既にPeopertyItemsに存在する場合はどうするか?を考えると、
・登録したいIdを指定しProperyItemを取得
・見つからなければ先頭のPropertyItemを取得
とした方が良いのかもしれない。
→ と思ったが、この方法だと、取得したPropertyItemに値をセットしSetPropertyItemを行う時に、既にIdが存在しているのに、そのIdでSetPropertyItemを行ってしまいダメな気がする。
ということで、以下の方法に変更
・登録したいIdを指定しProperyItemを取得
・取得できたら RemovePropertyItem でアイテムを削除
・先頭のPropertyItemを取得
これらを踏まえ以下の関数を作成する。引数$imageは対象画像ファイルのBitmapオブジェクトである。
上記サンプルでは、PropertyItemを追加するため、既存のPropertyItemの先頭項目を取得していた。
しかし、追加しようとするIdが既にPeopertyItemsに存在する場合はどうするか?を考えると、
・登録したいIdを指定しProperyItemを取得
・見つからなければ先頭のPropertyItemを取得
とした方が良いのかもしれない。
→ と思ったが、この方法だと、取得したPropertyItemに値をセットしSetPropertyItemを行う時に、既にIdが存在しているのに、そのIdでSetPropertyItemを行ってしまいダメな気がする。
ということで、以下の方法に変更
・登録したいIdを指定しProperyItemを取得
・取得できたら RemovePropertyItem でアイテムを削除
・先頭のPropertyItemを取得
これらを踏まえ以下の関数を作成する。引数$imageは対象画像ファイルのBitmapオブジェクトである。
function GetPropertyItem($image, $id) { $item = $image.PropertyItems | Where-Object { $_.Id -eq $id } if($item -ne $null) { $image.RemovePropertyItem($id) } return $image.PropertyItems | Select-Object -First 1 }
PropertyItemオブジェクトの登録
ExifVersionや撮影日時などのPropertyItemを登録する汎用的な関数を作成。
引数として$image(Bitmapオブジェクト)、設定するId,Len,Type,Valueは引数より取得する。
ベースとなるPropertyItemオブジェクトは、先ほど作成したGetPropertyItem関数を使用。
引数として$image(Bitmapオブジェクト)、設定するId,Len,Type,Valueは引数より取得する。
ベースとなるPropertyItemオブジェクトは、先ほど作成したGetPropertyItem関数を使用。
function SetPropertyItem($image, $id, $len, $type, $value) { $item = GetPropertyItem -image $image -id $id $item.Id = $id $item.Len = $len $item.Type = $type $item.Value = $value $image.SetPropertyItem($item) }
ExifVersionの登録
作成したSetPropertyItem関数を使いExifVersion(Id:9000)を登録する。
登録するバージョンは"0210"固定(ASCIIコードでは 48,50,49,48)とする。
登録するバージョンは"0210"固定(ASCIIコードでは 48,50,49,48)とする。
function SetExifVersion($image) { SetPropertyItem -image $image -id 0x9000 -len 4 -type 7 -value @(48,50,49,48) }
撮影日時データの取得
前回のスクリプトで、ファイル名より取得した日時は、日付型変数 $fileDate にセットしていた。
この変数値よりExif情報用の撮影日時(書式は "yyyy:MM:dd HH:mm:ss")を取得しASCII文字配列へ変換する。
この処理を行う関数 getDateTimeValue を追加する。
この変数値よりExif情報用の撮影日時(書式は "yyyy:MM:dd HH:mm:ss")を取得しASCII文字配列へ変換する。
この処理を行う関数 getDateTimeValue を追加する。
function getDateTimeValue($dateTime) { $chars = $dateTime.ToString("yyyy:MM:dd HH:mm:ss").ToCharArray() $ascii = @() foreach($char in $chars) { $ascii += [Byte][Char]$char } $ascii += 0 return $ascii }
撮影日時の登録
getDateTimeValue関数で撮影日時のASCIIコードデータを作成、その値を Id:9003とId:90004 に登録する。
function SetDateTime($image, $dateTime) { $value = getDateTimeValue -dateTime $dateTime SetPropertyItem -image $image -id 0x9003 -len 20 -type 2 -value $value SetPropertyItem -image $image -id 0x9004 -len 20 -type 2 -value $value }
画像ファイルにExif情報を設定し別ファイルとして保存
(2020.09.17改版) 変数名ルール:"~Path"でなく"~Dir"へ統一 → $outputPath → $outputDirとする
(2020.09.17改版) バグ修正:関数1行目の"$inputFile"だけの行を削除
$inputFileで指定した画像ファイルをオープン、$dateTimeで指定した撮影日時を設定し、設定した画像ファイルを$outpubDirで指定したディレクトリ保存する関数を作成する。
関数戻り値として、出力した画像ファイルのフルパスを返す。
(2020.09.17改版) バグ修正:関数1行目の"$inputFile"だけの行を削除
$inputFileで指定した画像ファイルをオープン、$dateTimeで指定した撮影日時を設定し、設定した画像ファイルを$outpubDirで指定したディレクトリ保存する関数を作成する。
関数戻り値として、出力した画像ファイルのフルパスを返す。
function SetExifInfo($inputFile, $outputDir, $dateTime) { $image = New-Object System.Drawing.Bitmap($inputFile) SetExifVersion -image $image SetDateTime -image $image -dateTime $dateTime $outputFile = Join-Path $outputDir (Split-Path $inputFile -Leaf) $image.Save($outputFile) $image.Dispose() return $outputFile }
メイン処理の修正
(2020.09.17改版) 拡張子は "jpeg" または "jpg" どちらでも可能とするように修正
引数で取得したパス内の画像ファイルを取得し、SetExifInfo関数を呼び出しExif情報を付加する。
SetExifInfo関数は設定した画像ファイルのフルパスを戻り値として返すので、このファイルに対して更新日時の設定を行う。
引数で取得したパス内の画像ファイルを取得し、SetExifInfo関数を呼び出しExif情報を付加する。
SetExifInfo関数は設定した画像ファイルのフルパスを戻り値として返すので、このファイルに対して更新日時の設定を行う。
$files = Get-ChildItem -Path $inputDir | Where-Object {$_.Name -Match "^\d{8}_\d{4}_[^.]*\.(jpeg|jpg)"} foreach ($file in $files) { try { $fileDate = [DateTime]::ParseExact($file.Name.Substring(0, 13), "yyyyMMdd_HHmm", $null) $outputFile = SetExifInfo -inputFile $file.FullName -outputDir $outputDir -dateTime $fileDate Set-ItemProperty $outputFile -Name LastWriteTime -Value $fileDate Write-Host( "[OK] " + $file.Name) } catch { Write-Host( "[ER] " + $file.Name + "`r`n" + $_) } }
#6 へ続く
自作プログラム, PowerShell, Exif
2020.09.17改版
2020.09.17改版
0 件のコメント:
コメントを投稿