Open1

PowerShellで System.Drawing.Bitmap.Save するとEXIF情報がエクスプローラーから見えなくなる

halthalt

ファイルの更新日をEXIFの撮影日時としたくてChatGPTに聞きながらPowerShellのコードを書いた。
撮影日時の書き込みはできるようになったんだけど、書き込みを行うと、もともとあったユーザーコメントなどの情報がエクスプローラーから表示できなくなってしまう。

コードをコメントアウトしながら何が原因か調べていたらどうもSaveメソッドを使うとEXIFが消えるっぽい?というわけで、元あったユーザーコメントを明示的に書き込むようにしてみたが状況は改善せず。

EXIFを読むプログラムをPowerShellで書いて調べたところ、Saveメソッドで作った画像ファイル、エクスプローラーからはEXIF読めないけど、EXIFデータは存在するっぽい。

もうどうしたらいいのかわからないのでお手上げ。

write_exif.ps1
Add-Type -AssemblyName System.Drawing

$baseFolder = "C:\test"

# 撮影日時のタグ
$DateTimeOriginalIndex = 0x9003
$DateTimeDegitizedIndex = 0x9004
$UserCommentIndex = 0x9286

$jpegFiles = Get-ChildItem -Path $baseFolder -Filter "*.jpg" -File

foreach ($file in $jpegFiles) {
    $image = New-Object System.Drawing.Bitmap($file.FullName)
    $propertyItems = $image.PropertyItems

    # ファイル更新日を取得 (作成日はコピペで更新されるので更新日がよさそう)
    $creationDate = $file.LastWriteTime

    # 撮影日時を取得。EXIFデータが存在するならSkip
    Try {
        $exifDateTakenProperty = $image.GetPropertyItem($DateTimeOriginalIndex)
        $image.Dispose()
        Write-Output("Skip: " + $file.Name)
        continue
    }
    Catch {
        $item = $image.PropertyItems | Select-Object -Last 1

        # Id:9003 原画像データの生成日時
        $item.Id = $DateTimeOriginalIndex
        $item.Len = 20
        $item.Type = 2
        $item.Value = [System.Text.Encoding]::ASCII.GetBytes($creationDate.ToString("yyyy:MM:dd HH:mm:ss`0"))
        $image.SetPropertyItem($item)

        # Id:9004 Digitalデータの生成日時
        $item.Id = $DateTimeDegitizedIndex
        $image.SetPropertyItem($item)

        $item.Id = 0x0132
        $image.SetPropertyItem($item)

        $item.Id = 0x0131
        $item.Value = [System.Text.Encoding]::ASCII.GetBytes("Stable Diffusion")
        $image.SetPropertyItem($item)
    }

    #$exifDateTakenProperty.Value = [System.Text.Encoding]::ASCII.GetBytes($creationDate.ToString("yyyy:MM:dd HH:mm:ss`0"))
    #$image.SetPropertyItem($exifDateTakenProperty)

    # なぜかコメントが消えてしまうので、プロパティアイテムの中からJPEGコメントを検索
    $comment = $propertyItems | Where-Object { $_.Id -eq $UserCommentIndex }
    Write-Output([System.Text.Encoding]::Unicode.GetString($comment.Value))
    $image.SetPropertyItem($comment)

    # 更新した画像を保存
    $bufKey = "_m_write_exif_m_"
    $newFilePath = $baseFolder + "\" + $bufKey + $file.Name
    $image.Save($newFilePath, [System.Drawing.Imaging.ImageFormat]::Jpeg)
    $image.Dispose()

    Move-Item $newFilePath $file.FullName -Force
    Write-Output("Move: " + $file.Name)

}