📷
ImageMagicで画像の一括リサイズ
高解像度の写真がオンプレのファイルSVの容量を圧迫していたので、条件指定したものをリサイズする方法を考えてみた。
使ったもの
- ImageMagic
ダウンロードはこちら
https://imagemagick.org/script/download.php
実行する環境を汚したくないので、Portable版を今回は利用
処理の内容
PowerShellとImageMagicのコマンドを使って実装
- リサイズしたい画像があるフォルダを指定
- 指定したパスがあるか確認
- 指定したフォルダは以下で、対象となるファイルを検索して抽出
※スクリプト例では、1MB以上のサイズかつ拡張子が「jpg」を指定 - 画像データの撮影日時を取得 or 更新日時を取得(撮影日時がない場合の対応)
- ImageMagicでリサイズ
※縦か横が"1280"になるように指定している - リサイズ時にファイル更新日時が更新されてしまうので、撮影日時(リサイズ前の更新日時)に修正
スクリプト
ImageResize.ps1
Add-Type -AssemblyName System.Drawing
$Input = Read-Host "リサイズしたい画像があるフォルダを指定"
if (Test-Path $Input) {
# ImageMagickのディレクトリを指定
Set-Location ".\ImageMagick"
# 指定したフォルダ配下で1MB以上かつjpgのファイル抽出
Get-ChildItem -Path "$Input" -Recurse |
Where-Object { $_.Length -gt 1MB -and $_.Extension -eq ".jpg" } |
ForEach-Object {
# 対象画像ファイルを読み込み
$Img = New-Object Drawing.Bitmap($_.FileName)
# 画像ファイルの撮影日時を取得(バイト配列)
$ByteAry = ($Img.PropertyItems | Where-Object{$_.Id -eq 36867}).Value
# IsNullOrWhiteSpaceメソッドで空文字・空白のみ・Nullと「0000:00:00 00:00:00」チェック
if(([System.String]::IsNullOrWhiteSpace($ByteAry)) -or ($ByteAry[0] = 48)) {
# NULLなら更新日時を取得
$BateStr = (Get-ItemProperty $_.FileName).LastWriteTime
} else {
# yyyy:mm:dd hh:mm:ss → yyyy/mm/dd hh:mm:ss に変換
$ByteAry[4] = 47
$ByteAry[7] = 47
# バイト配列を文字列に変換
$DateStr = [System.Text.Encoding]::ASCII.GetString($ByteAry)
}
# ファイルの読み込みの解放
$Img.Dispose()
$Img = $null
# ImageMagickでリサイズ
.\magick.exe mogrify -quality 100 -resize "1280x1280>" $_.FilellName
# ファイル更新日時を撮影日時 or リサイズ前の更新日時に指定
Set-ItemProperty $_.FileName -name LastWriteTime -value $DateStr
}
} else {
Write-Host "フォルダはありません"
}
BatからPowerShellを起動する場合はこんな感じで。
Start_ImageResize.bat
powershell -ExecutionPolicy RemoteSigned -File %~dp0ImageResize.ps1 > resize_error.log 2>&1
画像ファイルによってはエラーがでる場合もあるので、適宜調整していく。
補足
PropertyItem.Id プロパティ
Discussion