前置き
ずっと投稿してなかったけど、なにか書かないと…と思っていたところ、先日、勤め先で「画像の回転を行いたい」という悩み事を解決した。
100枚とかあるとのことで、プログラムを組むしか無いのだが、「フリーソフトとかは入れたくない」とのことで、Windowsで実行できるPowerShellと.NETにやらせるスクリプトを書いた。
TL;DR
生成AIよろしく
PowerShell + .NET の System.Drawing を使って、外部ツールなしで大量の画像を一括回転できるスクリプトを作った。
角度・回転基準・サイズ処理・背景色を対話式で指定可能。
PowerShellスクリプト仕様
回転角度と回転の基準(左上か中央)と回転後元のサイズで切り抜くか外接矩形でサイズアップするか、サイズアップする場合の背景色(白、黒、透明)を入力可能にしてある。
※jpgは透明にはできないが…
このコードをコピペして、「ImageRotate.ps1」とかで保存
※ちなみに勤め先で提供したものはもうちょっとしっかりした作りにしてある別物。
画像回転スクリプト(PowerShell)
Add-Type -AssemblyName System.Drawing
# スクリプトの場所を基準にフォルダを設定
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$inputDir = Join-Path $scriptDir "Input"
$outputDir = Join-Path $scriptDir "Output"
if (!(Test-Path $outputDir)) {
New-Item -ItemType Directory -Path $outputDir | Out-Null
}
# 回転角度の入力
$angle = Read-Host "回転角度を入力してください(例:90)"
# 回転基準の選択
Write-Host "回転の基準を選んでください:"
Write-Host "1: 左上を基準に回転"
Write-Host "2: 画像の中心を基準に回転"
$pivotChoice = Read-Host "番号を入力"
# サイズ処理の選択
Write-Host "回転後のサイズを選んでください:"
Write-Host "1: 元のサイズで切り抜く"
Write-Host "2: 外接矩形にサイズアップする"
$sizeChoice = Read-Host "番号を入力"
# 背景色(外接矩形の場合のみ)
$bgColor = [System.Drawing.Color]::Transparent
if ($sizeChoice -eq "2") {
Write-Host "背景色を選んでください:"
Write-Host "1: 黒"
Write-Host "2: 白"
Write-Host "3: 透明"
$bgChoice = Read-Host "番号を入力"
switch ($bgChoice) {
"1" { $bgColor = [System.Drawing.Color]::Black }
"2" { $bgColor = [System.Drawing.Color]::White }
"3" { $bgColor = [System.Drawing.Color]::Transparent }
default { $bgColor = [System.Drawing.Color]::Transparent }
}
}
# 画像処理
Get-ChildItem $inputDir -File | ForEach-Object {
$img = [System.Drawing.Image]::FromFile($_.FullName)
# 回転角度(ラジアン)
$rad = $angle * [Math]::PI / 180
# 元のサイズ
$w = $img.Width
$h = $img.Height
# 回転後のサイズ計算(外接矩形)
$newW = [Math]::Abs($w * [Math]::Cos($rad)) + [Math]::Abs($h * [Math]::Sin($rad))
$newH = [Math]::Abs($w * [Math]::Sin($rad)) + [Math]::Abs($h * [Math]::Cos($rad))
if ($sizeChoice -eq "1") {
# 元のサイズで切り抜く
$canvasW = $w
$canvasH = $h
} else {
# 外接矩形に拡大
$canvasW = [int][Math]::Ceiling($newW)
$canvasH = [int][Math]::Ceiling($newH)
}
# 新しいビットマップ作成
$bmp = New-Object System.Drawing.Bitmap $canvasW, $canvasH
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.Clear($bgColor)
# 高品質設定
$g.InterpolationMode = "HighQualityBicubic"
$g.PixelOffsetMode = "HighQuality"
$g.SmoothingMode = "HighQuality"
# 回転中心の設定
if ($pivotChoice -eq "1") {
# 左上基準
$pivotX = 0
$pivotY = 0
} else {
# 中心基準
$pivotX = $canvasW / 2
$pivotY = $canvasH / 2
}
# 回転
$g.TranslateTransform($pivotX, $pivotY)
$g.RotateTransform($angle)
$g.TranslateTransform(-$pivotX, -$pivotY)
# 描画位置(中心基準の場合は中央に配置)
$drawX = ($canvasW - $w) / 2
$drawY = ($canvasH - $h) / 2
$g.DrawImage($img, $drawX, $drawY, $w, $h)
# 保存
$outPath = Join-Path $outputDir $_.Name
$bmp.Save($outPath, $img.RawFormat)
# 後処理
$g.Dispose()
$bmp.Dispose()
$img.Dispose()
Write-Host "出力: $($_.Name)"
}
Write-Host "処理が完了しました。"
ちなみに回転の補間の関係で、外接矩形より数ピクセル大きくなることがある。
キャンバスサイズを少し大きめにしないといけない場合がある。
起動用バッチファイル
で、このPowerShellスクリプトだけ渡して「そっちで実行しろ」はユーザーにはハードルが高いので、起動用のバッチファイルを下記のとおりに作成。
「ImageRotate.bat」とかでPowerShellスクリプトと同じ場所に保存する。
@powershell -ExecutionPolicy Bypass -File ImageRotate.ps1
@echo なにかキーを押すと終了します。
@pause >nul
フォルダ構成
ここまでできたら、フォルダ構成をこのようにしておく。
[root]
├ Input/
├ Output/
├ ImageRotate.bat
└ ImageRotate.ps1
使い方
- 回転させたい画像ファイルを「Input」フォルダに入れておく
- 「ImageRotate.bat」を実行する
- 角度を入力
- 回転基準を入力
- 切り抜くかサイズアップを選択
- サイズアップを選択していたら、背景色を選択
- 出来上がるまで待つ
- 「Output」フォルダへ出来上がる
使用感スクリーンショット
締め締め
業務効率化って、こういう小さなことの積み重ねよね。
今回は回転だけど、System.Drawingを使ってるので、リサイズとか反転とか、簡単なことならできるじゃろ。
これがまた誰かの役に立てばヨシヨシ。
Python+統計みたいな話ばっかり投稿してたけど、やっぱりこういうのも作っていて面白い。
