#できること
1.フォルダー選択画面をGUIで出して
2.選択したフォルダにある.jpgファイルを
3.縦横比を維持して横幅640Pixにして
4.選択したフォルダ直下へサブフォルダ作成しそちらに出力します。
#環境
PowerShellの2.0もしくは3.0で動作させましたが後方互換は問題ないと思います
一応条件分岐でps1ファイルから実行できるようにコード入れました
Win7以降で動作すると思います。.Netも必要?偉い人に聞いてください、普通の会社では人権的に配備されているかと思います…きっと
1~2行目までのポリシーの部分は単独でファイル作成して実行する必要がある?これも偉い人に聞いてください。
#改善余地
画像品質を60~80くらいに設定するオプション入れてさらに圧縮できるようにしたいです。キュービックやらなんやらが良くわからないです。
ネットワークドライブに対しては環境によっては実施できないのは他のもそうだし説明は割愛。でも動かしたいところ
#コード本文
下記を.ps1形式で保存して使用してください。ポリシー解除は自己責任でお願いします。
#ポリシー有効化(当該セッションのみ)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
#ApartmentStateにてSTAモードのチェック(.NET Frameworkオブジェクトを利用する前提)
$reRun = $false;
Switch($host.Runspace.ApartmentState){
'STA' {
#何もしない
}
'MTA' {
#MTAモードの場合は、STAモードを指定して再実行
$reRun = $true;
}
default {
#STAモードでもMTAモードでもない場合はUnknown(デフォルト)
If($PSVersionTable.PSVersion.Major -eq "2"){
#PowerShell2.0の場合、デフォルトがMTAモードなのでSTAモードを指定して再実行
$reRun = $true;
}
}
}
If($reRun){
$ScriptPath = $MyInvocation.MyCommand.Path;
Start-Process PowerShell.exe -ArgumentList "-sta $ScriptPath";
Exit;
}
# System.Windows.Formsアセンブリを有効化
[void][System.Reflection.Assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")
# ディレクトリのダイアログ呼び出し
Set-StrictMode -version Latest
#.NET Frameworkのダイアログ関連オブジェクトの取り込み
Add-Type -AssemblyName System.Windows.Forms;
#ディレクトリ選択ダイアログのオブジェクト取得
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog;
#ダイアログへ説明を追加
$dialog.Description = "画像フォルダディレクトリを選択";
#新規ディレクトリ作成のボタンを非表示
$dialog.ShowNewFolderButton = $false;
#デフォルト選択ディレクトリの設定
$dialog.SelectedPath = "C:\";
If($dialog.ShowDialog() -eq "OK"){
$dialog.SelectedPath;
}Else{
"選択なし";
}
# 設定項目
[string]$画像の保存されているフォルダ = $dialog.SelectedPath
[string]$縮小した画像の保存先 = '{0}\圧縮画像' -f $画像の保存されているフォルダ
[int]$画像の横幅 = 640 #px
[string]$元の画像の拡張子 = '*.jpg'
# 画像操作に必要なライブラリ読み込み
#Add-Type -AssemblyName System.Drawing
[void][reflection.assembly]::LoadWithPartialName("System.Drawing")
[void][reflection.assembly]::LoadWithPartialName("System.Drawing.Imaging")
[Drawing.Imaging.ImageFormat]$縮小後画像の形式 = [Drawing.Imaging.ImageFormat]::JPEG
# 出力先のフォルダを作成(すでにある場合は何もしない)
[IO.Directory]::CreateDirectory( $縮小した画像の保存先 ) > $null
# $画像の保存されているフォルダ の中から、$元の画像の拡張子 でフィルターしたものを探す
Get-ChildItem -LiteralPath $画像の保存されているフォルダ -Filter $元の画像の拡張子 |
%{
# 見つかったものそれぞれに対して処理 ( $_ -is [IO.FileInfo] )
# 品質修正したデータを渡す
# 元となる画像読み込み
[Drawing.Bitmap]$srcBmp = [Drawing.Bitmap]::FromFile($_.FullName)
# 画像のメタデータ(撮影日時など)取得
[Drawing.Imaging.PropertyItem[]]$props = $srcBmp.PropertyItems
# 新しい画像の大きさを計算
[int]$newWidth = $画像の横幅
[int]$newHeight = [int]( ($srcBmp.Height / $srcBmp.Width) * $newWidth )
# 縮小した画像を作成(メモリ内)
[Drawing.Bitmap]$destBmp =
New-Object -TypeName Drawing.Bitmap -ArgumentList $srcBmp, $newWidth, $newHeight
# 画像のメタデータ(撮影日時など)設定
$props | %{ $destBmp.SetPropertyItem( $_ ) <# $_ -is [Drawing.Imaging.PropertyItem] #> }
# 縮小した画像の保存先
[string]$destPath = [IO.Path]::Combine(
$縮小した画像の保存先,
[IO.Path]::ChangeExtension($_.Name, $縮小後画像の形式.ToString()))
# ファイルの存在確認
if ( Test-Path -LiteralPath $destPath ) {
Write-Host ('「{0}」はすでに存在しています。' -f [IO.Path]::GetFileName($destPath))
} else {
# $縮小後画像の形式 で保存
$destBmp.Save($destPath, $縮小後画像の形式)
Write-Host ('「{0}」を「{1}」として保存しました。' -f $_.Name, [IO.Path]::GetFileName($destPath))
}
# リソース解放
$destBmp.Dispose()
$srcBmp.Dispose()
}
# 保存したフォルダを開く
explorer.exe $縮小した画像の保存先
#参考
MS Paintで画像を一括、あるいは自動で圧縮したい
https://teratail.com/questions/120216
//画像をリサイズする周りのプログラムを参考
.NETダイアログが表示されずスクリプトが止まる問題の対策
http://funcs.org/907
//ps1ファイルにして実行する際に実行できない対策に参考
PowerShellでダイアログを表示し入力結果を取得
http://funcs.org/895
//ダイアログからPATHデータを入手するのに使用
HIRO's.NET 09.画像ファイルをリサイズする
http://hiros-dot.net/PowerShell/myfunction/myfunction09.htm
//画像品質回りの設定方法を参考(予定)
##書いた人について
ずぶの素人なので詳しいことはよくわかりません
多分、動くと思います。技術不足のためリサイズまでしかできていません。
品質圧縮に関しては勉強中です。見通しは立っていますが教えていただければありがたいです
#経緯
ローカル環境、管理者権限確保できない社内PCで鯖を圧迫する画像を圧縮しろと言われたので 某ソフト入れさせてくれと申請したら 真心こめて手作業でやれ と言われたので作ろうと思い立ちました
個人的には自由度の高いCUIでやりたいところですが世間的にはGUIの方が分かりやすいので何とか食い込ませようとしています。