PowerShell

PowerShellで作る画像一括縮小ツール|GUI・ImageMagick対応・EXIF回転修正・WebP変換もできる実用スクリプト

PowerShellで作る画像一括縮小ツール|GUI・ImageMagick対応・EXIF回転修正・WebP変換もできる実用スクリプトアイキャッチ

はじめに

スマホやデジカメで撮影した写真は、1枚あたり5MB〜10MBになることも珍しくありません。

ブログにアップするにも、メールで送るにも、共有フォルダに置くにもサイズが大きすぎて困る。。。

そんな経験はありませんか?

市販のツールやWebサービスもありますが、

  • EXIF回転が反映されず画像が横向きになる
  • 一括処理が遅い
  • WebPに変換したい
  • GUIで簡単に使いたい
  • 処理を途中で中断したい
  • さらに高圧縮したい(ImageMagick利用)

といったニーズを完全に満たすものはなかなかありません。

そこで今回、自分が本当に使いたい機能だけをまとめた「PowerShell 画像縮小GUIツール」を作成しました。

このツールでできること

本ツールは PowerShell の標準機能と ImageMagick を組み合わせた、高機能かつ実用性の高い画像変換ツールです。

機能説明
画像のドラッグ&ドロップ複数ファイル・フォルダどちらもOK
一括縮小(60〜10%)ボタン1つで簡単縮小
JPEG品質調整(40〜90)画質と容量を最適に調整
EXIF自動回転横向き・逆さま防止
メタデータ削除(strip)撮影場所情報などを除去
WebP変換次世代フォーマットに対応
進行状況バー大量処理でも安心
中断ボタン処理を途中で止められる
ImageMagick 対応高画質・高圧縮モード
バッチファイル起動可能ダブルクリックで使えるアプリ化

ブログ用の画像調整、共有フォルダへの保存、メール添付前の圧縮など、普段使いの作業を圧倒的に効率化できます。

完成イメージ

ツールを起動すると、次のようなGUI画面が表示されます。

  • 上部:ドラッグ&ドロップで画像を追加
  • 中央:縮小率ボタン(Windows標準/ImageMagick)
  • 右側:メタデータ削除・WebP変換などオプション
  • 下部:進捗バーとステータス表示

直感的に操作できるため、PowerShellがわからない人にも使いやすい構成です。

使用している技術とポイント

1. Windowsフォームを使ったGUI化

PowerShell でも Windows.Forms を使えば、GUIアプリを作成できます。

  • ListBox にドラッグ&ドロップ
  • TrackBar(スライダー)で品質調整
  • FlowLayoutPanel に縮小ボタンを整列
  • プログレスバーで進行状況表示

業務ツールのような自然なUIに仕上がっています。

2. EXIF Orientation対応(画像の向きを正す)

スマホ写真は EXIF に「向き」が記録されているため、縮小時にその情報を反映しないと横向きになってしまいます。

本ツールでは、

switch ($orientation) {
    3 { Rotate180 }
    6 { Rotate90 }
    8 { Rotate270 }
}

といった処理で正しい向きへ補正しています。

3. ImageMagickとの連携

ImageMagick が PC に入っていれば自動検出し専用ボタン(IM版縮小ボタン)が有効化されます。

IM版は次のような高度な処理が可能です:

  • -auto-orient 向き調整
  • -strip メタデータ削除
  • -quality JPEG品質指定
  • -sampling-factor 4:2:0 圧縮効率の最適化

結果として Windows標準モードよりも 画質が良いまま容量を大幅に削減できます。

4. 中断ボタンによるキャンセル

大量のファイルを処理している途中で止めたい場合があります。
そのため $script:cancelRequested フラグを用意し、ループごとにチェックしています。

if ($script:cancelRequested) {
    break
}

ユーザー体験がかなり良くなるポイントです。

5. 進捗バーと DoEvents

PowerShell の GUI で進行状況をリアルタイム更新するには内部で DoEvents() を使用します。

[System.Windows.Forms.Application]::DoEvents()

これによりUIが固まらず、実用的なアプリに仕上がります。

ソースコード(全文)

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

[System.Windows.Forms.Application]::EnableVisualStyles()

# 対象拡張子
$supportedExtensions = @(".jpg", ".jpeg", ".png", ".bmp", ".gif")

# 中断フラグ
$script:cancelRequested = $false

# ------------------------------------------------------------
# ImageMagick 検出関数
# ------------------------------------------------------------
function Find-ImageMagick {
    try {
        $cmd = Get-Command magick.exe -ErrorAction SilentlyContinue
        if ($cmd) { return $cmd.Path }
    } catch {}

    $searchBases = @(
        "C:\Program Files",
        "C:\Program Files (x86)"
    )

    foreach ($base in $searchBases) {
        if (-not (Test-Path $base)) { continue }
        try {
            $imDirs = Get-ChildItem -Path $base -Directory -Filter "ImageMagick*" -ErrorAction SilentlyContinue
            foreach ($d in $imDirs) {
                $mag = Join-Path $d.FullName "magick.exe"
                if (Test-Path $mag) { return $mag }
            }
        } catch {}
    }

    return $null
}

$magickPath  = Find-ImageMagick
$hasMagick   = -not [string]::IsNullOrEmpty($magickPath)

# ------------------------------------------------------------
# フォーム作成
# ------------------------------------------------------------
$form                = New-Object System.Windows.Forms.Form
$form.Text           = "画像一括縮小ツール"
$form.Width          = 900
$form.Height         = 680
$form.StartPosition  = "CenterScreen"

$label               = New-Object System.Windows.Forms.Label
$label.Text          = "ここに画像ファイル(またはフォルダ)をドラッグ&ドロップしてください。"
$label.AutoSize      = $true
$label.Top           = 10
$label.Left          = 10

$listBox             = New-Object System.Windows.Forms.ListBox
$listBox.Top         = 40
$listBox.Left        = 10
$listBox.Width       = 860
$listBox.Height      = 280
$listBox.AllowDrop   = $true

# オプションパネル(品質・メタデータ・WebP・クリア・中断・終了)
$optionsPanel              = New-Object System.Windows.Forms.Panel
$optionsPanel.Top          = 330
$optionsPanel.Left         = 10
$optionsPanel.Width        = 860
$optionsPanel.Height       = 80

# 品質ラベル
$qualityLabel              = New-Object System.Windows.Forms.Label
$qualityLabel.Text         = "品質 (40~90):"
$qualityLabel.AutoSize     = $true
$qualityLabel.Top          = 10
$qualityLabel.Left         = 10

# 品質スライダー
$qualityTrackBar           = New-Object System.Windows.Forms.TrackBar
$qualityTrackBar.Minimum   = 40
$qualityTrackBar.Maximum   = 90
$qualityTrackBar.Value     = 75
$qualityTrackBar.TickFrequency = 5
$qualityTrackBar.SmallChange   = 1
$qualityTrackBar.LargeChange   = 5
$qualityTrackBar.Top       = 5
$qualityTrackBar.Left      = 120
$qualityTrackBar.Width     = 250

# 品質テキストボックス
$qualityTextBox            = New-Object System.Windows.Forms.TextBox
$qualityTextBox.Top        = 10
$qualityTextBox.Left       = 380
$qualityTextBox.Width      = 40
$qualityTextBox.Text       = $qualityTrackBar.Value.ToString()

# メタデータ削除チェック
$stripMetadataCheck        = New-Object System.Windows.Forms.CheckBox
$stripMetadataCheck.Text   = "メタデータ削除(strip)"
$stripMetadataCheck.AutoSize = $true
$stripMetadataCheck.Top    = 10
$stripMetadataCheck.Left   = 440
$stripMetadataCheck.Checked = $true

# WebP変換チェック
$webpCheck                 = New-Object System.Windows.Forms.CheckBox
$webpCheck.Text            = "WebP へ変換"
$webpCheck.AutoSize        = $true
$webpCheck.Top             = 40
$webpCheck.Left            = 440
$webpCheck.Checked         = $false

# クリアボタン(オプションパネル内)
$clearBtn = New-Object System.Windows.Forms.Button
$clearBtn.Width  = 80
$clearBtn.Height = 30
$clearBtn.Text   = "クリア"
$clearBtn.Top    = 10
$clearBtn.Left   = 600

# 中断ボタン(クリアの右)
$cancelBtn = New-Object System.Windows.Forms.Button
$cancelBtn.Width  = 80
$cancelBtn.Height = 30
$cancelBtn.Text   = "中断"
$cancelBtn.Top    = 10
$cancelBtn.Left   = 690

# 終了ボタン(その右)
$exitBtn = New-Object System.Windows.Forms.Button
$exitBtn.Width  = 80
$exitBtn.Height = 30
$exitBtn.Text   = "終了"
$exitBtn.Top    = 10
$exitBtn.Left   = 780

$optionsPanel.Controls.Add($qualityLabel)
$optionsPanel.Controls.Add($qualityTrackBar)
$optionsPanel.Controls.Add($qualityTextBox)
$optionsPanel.Controls.Add($stripMetadataCheck)
$optionsPanel.Controls.Add($webpCheck)
$optionsPanel.Controls.Add($clearBtn)
$optionsPanel.Controls.Add($cancelBtn)
$optionsPanel.Controls.Add($exitBtn)

# ステータスラベル
$statusLabel         = New-Object System.Windows.Forms.Label
$statusLabel.Text    = "準備完了"
$statusLabel.AutoSize= $true
$statusLabel.Top     = 420
$statusLabel.Left    = 10

# Windows標準機能グループ
$winGroupLabel              = New-Object System.Windows.Forms.Label
$winGroupLabel.Text         = "Windows標準機能:"
$winGroupLabel.AutoSize     = $true
$winGroupLabel.Top          = 450
$winGroupLabel.Left         = 10

$winButtonPanel             = New-Object System.Windows.Forms.FlowLayoutPanel
$winButtonPanel.Top         = 470
$winButtonPanel.Left        = 10
$winButtonPanel.Width       = 860
$winButtonPanel.Height      = 40
$winButtonPanel.WrapContents = $false
$winButtonPanel.AutoScroll   = $false

# ImageMagickグループ
$imGroupLabel               = New-Object System.Windows.Forms.Label
if ($hasMagick) {
    $imGroupLabel.Text      = "ImageMagick(検出済み):"
} else {
    $imGroupLabel.Text      = "ImageMagick(未検出):"
}
$imGroupLabel.AutoSize      = $true
$imGroupLabel.Top           = 515
$imGroupLabel.Left          = 10

$imButtonPanel              = New-Object System.Windows.Forms.FlowLayoutPanel
$imButtonPanel.Top          = 535
$imButtonPanel.Left         = 10
$imButtonPanel.Width        = 860
$imButtonPanel.Height       = 40
$imButtonPanel.WrapContents = $false
$imButtonPanel.AutoScroll   = $false

# 進行バー(いちばん下)
$progressBar                = New-Object System.Windows.Forms.ProgressBar
$progressBar.Top            = 585
$progressBar.Left           = 10
$progressBar.Width          = 860
$progressBar.Height         = 20
$progressBar.Minimum        = 0
$progressBar.Step           = 1

# フォームに追加
$form.Controls.Add($label)
$form.Controls.Add($listBox)
$form.Controls.Add($optionsPanel)
$form.Controls.Add($statusLabel)
$form.Controls.Add($winGroupLabel)
$form.Controls.Add($winButtonPanel)
$form.Controls.Add($imGroupLabel)
$form.Controls.Add($imButtonPanel)
$form.Controls.Add($progressBar)

# ------------------------------------------------------------
# 品質スライダーとテキストボックス同期
# ------------------------------------------------------------
$script:isUpdatingQuality = $false

$qualityTrackBar.Add_ValueChanged({
    if ($script:isUpdatingQuality) { return }
    $script:isUpdatingQuality = $true
    $qualityTextBox.Text = $qualityTrackBar.Value.ToString()
    $script:isUpdatingQuality = $false
})

$qualityTextBox.Add_TextChanged({
    if ($script:isUpdatingQuality) { return }
    $value = 0
    if ([int]::TryParse($qualityTextBox.Text, [ref]$value)) {
        if     ($value -lt 40) { $value = 40 }
        elseif ($value -gt 90) { $value = 90 }
        $script:isUpdatingQuality = $true
        $qualityTrackBar.Value = $value
        $qualityTextBox.Text   = $value.ToString()
        $script:isUpdatingQuality = $false
    }
})

# ------------------------------------------------------------
# Drag & Drop 処理
# ------------------------------------------------------------
$listBox.Add_DragEnter({
    param($sender, $e)
    if ($e.Data.GetDataPresent([System.Windows.Forms.DataFormats]::FileDrop)) {
        $e.Effect = [System.Windows.Forms.DragDropEffects]::Copy
    }
})

$listBox.Add_DragDrop({
    param($sender, $e)
    $paths = $e.Data.GetData([System.Windows.Forms.DataFormats]::FileDrop)

    foreach ($path in $paths) {
        if (-not (Test-Path $path)) { continue }
        $item = Get-Item $path

        if ($item.PSIsContainer) {
            Get-ChildItem $item.FullName -Recurse -File |
                Where-Object { $supportedExtensions -contains $_.Extension.ToLower() } |
                ForEach-Object {
                    if (-not $listBox.Items.Contains($_.FullName)) {
                        [void]$listBox.Items.Add($_.FullName)
                    }
                }
        }
        else {
            $ext = $item.Extension.ToLower()
            if ($supportedExtensions -contains $ext) {
                if (-not $listBox.Items.Contains($item.FullName)) {
                    [void]$listBox.Items.Add($item.FullName)
                }
            }
        }
    }

    $statusLabel.Text = "ファイル数: {0}" -f $listBox.Items.Count
})

# ------------------------------------------------------------
# Windows標準機能での縮小処理(EXIF 向き対応+中断対応)
# ------------------------------------------------------------
function Resize-ImagesWindows {
    param(
        [double]$Scale,
        [int]$JpegQuality,
        [System.Windows.Forms.ListBox]$ListBox,
        [System.Windows.Forms.Label]$StatusLabel,
        [System.Windows.Forms.ProgressBar]$ProgressBar,
        [System.Windows.Forms.Form]$Form
    )

    if ($ListBox.Items.Count -eq 0) {
        [System.Windows.Forms.MessageBox]::Show("ファイルが追加されていません。")
        return
    }

    Add-Type -AssemblyName System.Drawing

    $percent = [int]($Scale * 100)
    $StatusLabel.Text = "縮小中...(Windows標準機能 / ${percent}% の縮小処理)"
    $Form.UseWaitCursor = $true
    $script:cancelRequested = $false

    $ProgressBar.Value   = 0
    $ProgressBar.Maximum = $ListBox.Items.Count

    foreach ($path in $ListBox.Items) {
        if ($script:cancelRequested) {
            $StatusLabel.Text = "中断しました(Windows標準機能 / ${percent}% の縮小処理)"
            break
        }

        if (-not (Test-Path $path)) { continue }

        try {
            $file = Get-Item $path
            $img  = [System.Drawing.Image]::FromFile($file.FullName)

            # EXIF Orientation 読み取り・回転
            $orientationId = 0x0112
            if ($img.PropertyIdList -contains $orientationId) {
                $prop        = $img.GetPropertyItem($orientationId)
                $orientation = [BitConverter]::ToInt16($prop.Value, 0)

                switch ($orientation) {
                    3 { $img.RotateFlip([System.Drawing.RotateFlipType]::Rotate180FlipNone) }
                    6 { $img.RotateFlip([System.Drawing.RotateFlipType]::Rotate90FlipNone)  }
                    8 { $img.RotateFlip([System.Drawing.RotateFlipType]::Rotate270FlipNone) }
                }

                try { $img.RemovePropertyItem($orientationId) } catch {}
            }

            $newWidth  = [int]($img.Width  * $Scale)
            $newHeight = [int]($img.Height * $Scale)

            if ($newWidth -lt 1 -or $newHeight -lt 1) {
                $img.Dispose()
                continue
            }

            $bmp   = New-Object System.Drawing.Bitmap $newWidth, $newHeight
            $graph = [System.Drawing.Graphics]::FromImage($bmp)

            $graph.InterpolationMode  = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
            $graph.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality
            $graph.SmoothingMode      = [System.Drawing.Drawing2D.SmoothingMode]::HighQuality
            $graph.PixelOffsetMode    = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality

            $graph.DrawImage($img, 0, 0, $newWidth, $newHeight)

            $dir    = Split-Path $file.FullName -Parent
            $outDir = Join-Path $dir ("Resized_{0}" -f $percent)
            if (-not (Test-Path $outDir)) {
                New-Item -ItemType Directory -Path $outDir | Out-Null
            }

            $outPath = Join-Path $outDir $file.Name
            $ext     = $file.Extension.ToLower()

            if ($ext -eq ".jpg" -or $ext -eq ".jpeg") {
                $codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() |
                         Where-Object { $_.MimeType -eq "image/jpeg" }
                $encoder      = [System.Drawing.Imaging.Encoder]::Quality
                $encoderParms = New-Object System.Drawing.Imaging.EncoderParameters(1)
                $encoderParms.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($encoder, [int64]$JpegQuality)
                $bmp.Save($outPath, $codec, $encoderParms)
            }
            elseif ($ext -eq ".png") {
                $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Png)
            }
            elseif ($ext -eq ".gif") {
                $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Gif)
            }
            elseif ($ext -eq ".bmp") {
                $bmp.Save($outPath, [System.Drawing.Imaging.ImageFormat]::Bmp)
            }
            else {
                $bmp.Save($outPath)
            }

            $graph.Dispose()
            $bmp.Dispose()
            $img.Dispose()
        }
        catch {
            [System.Windows.Forms.MessageBox]::Show("Windows標準機能処理中にエラーが発生しました。`n$path`n`n$($_.Exception.Message)")
        }

        if ($ProgressBar.Value -lt $ProgressBar.Maximum) {
            $ProgressBar.PerformStep()
        }
        [System.Windows.Forms.Application]::DoEvents()
    }

    $Form.UseWaitCursor = $false
    if (-not $script:cancelRequested) {
        $StatusLabel.Text = "完了しました(Windows標準機能 / ${percent}% の縮小処理)"
    }
}

# ------------------------------------------------------------
# ImageMagick 縮小処理(auto-orient+中断対応)
# ------------------------------------------------------------
function Resize-ImagesMagick {
    param(
        [double]$Scale,
        [int]$Quality,
        [bool]$StripMetadata,
        [bool]$ConvertWebP,
        [string]$MagickPath,
        [System.Windows.Forms.ListBox]$ListBox,
        [System.Windows.Forms.Label]$StatusLabel,
        [System.Windows.Forms.ProgressBar]$ProgressBar,
        [System.Windows.Forms.Form]$Form
    )

    if (-not (Test-Path $MagickPath)) {
        [System.Windows.Forms.MessageBox]::Show("ImageMagick (magick.exe) が見つかりません。")
        return
    }

    if ($ListBox.Items.Count -eq 0) {
        [System.Windows.Forms.MessageBox]::Show("ファイルが追加されていません。")
        return
    }

    $percent = [int]($Scale * 100)
    $StatusLabel.Text = "縮小中...(ImageMagick / ${percent}% の縮小処理)"
    $Form.UseWaitCursor = $true
    $script:cancelRequested = $false

    $ProgressBar.Value   = 0
    $ProgressBar.Maximum = $ListBox.Items.Count

    foreach ($path in $ListBox.Items) {
        if ($script:cancelRequested) {
            $StatusLabel.Text = "中断しました(ImageMagick / ${percent}% の縮小処理)"
            break
        }

        if (-not (Test-Path $path)) { continue }

        try {
            $file   = Get-Item $path
            $dir    = Split-Path $file.FullName -Parent
            $base   = [System.IO.Path]::GetFileNameWithoutExtension($file.Name)
            $srcExt = [System.IO.Path]::GetExtension($file.Name).ToLower()

            $outDir = Join-Path $dir ("ResizedIM_{0}" -f $percent)
            if (-not (Test-Path $outDir)) {
                New-Item -ItemType Directory -Path $outDir | Out-Null
            }

            if ($ConvertWebP) {
                $destExt  = ".webp"
            } else {
                $destExt  = $srcExt
            }
            $outPath = Join-Path $outDir ($base + $destExt)

            $args = @(
                "`"$($file.FullName)`"",
                "-auto-orient",
                "-resize", "${percent}%",
                "-quality", $Quality.ToString()
            )

            if ($destExt -in @(".jpg", ".jpeg", ".webp")) {
                $args += @("-sampling-factor", "4:2:0")
            }

            if ($StripMetadata) {
                $args += "-strip"
            }

            $args += "`"$outPath`""

            $psi = New-Object System.Diagnostics.ProcessStartInfo
            $psi.FileName = $MagickPath
            $psi.Arguments = $args -join " "
            $psi.CreateNoWindow = $true
            $psi.UseShellExecute = $false
            $psi.RedirectStandardOutput = $true
            $psi.RedirectStandardError  = $true

            $proc = New-Object System.Diagnostics.Process
            $proc.StartInfo = $psi
            [void]$proc.Start()
            $null   = $proc.StandardOutput.ReadToEnd()
            $stderr = $proc.StandardError.ReadToEnd()
            $proc.WaitForExit()

            if ($proc.ExitCode -ne 0) {
                [System.Windows.Forms.MessageBox]::Show("ImageMagick処理中にエラーが発生しました。`n$path`n`n$stderr")
            }
        }
        catch {
            [System.Windows.Forms.MessageBox]::Show("ImageMagick処理中にエラーが発生しました。`n$path`n`n$($_.Exception.Message)")
        }

        if ($ProgressBar.Value -lt $ProgressBar.Maximum) {
            $ProgressBar.PerformStep()
        }
        [System.Windows.Forms.Application]::DoEvents()
    }

    $Form.UseWaitCursor = $false
    if (-not $script:cancelRequested) {
        $StatusLabel.Text = "完了しました(ImageMagick / ${percent}% の縮小処理)"
    }
}

# ------------------------------------------------------------
# ボタン生成(Tag に倍率を入れて sender.Tag から取得)
# ------------------------------------------------------------
$scales = @(60, 50, 40, 30, 20, 10)

# Windows標準機能ボタン
foreach ($p in $scales) {
    $btn = New-Object System.Windows.Forms.Button
    $btn.Width  = 80
    $btn.Height = 30
    $btn.Text   = "{0}%%" -f $p
    $btn.Tag    = $p / 100

    $btn.Add_Click({
        param($sender, $e)
        $scale = [double]$sender.Tag
        $q = $qualityTrackBar.Value
        Resize-ImagesWindows -Scale $scale -JpegQuality $q -ListBox $listBox -StatusLabel $statusLabel -ProgressBar $progressBar -Form $form
    })

    $winButtonPanel.Controls.Add($btn)
}

# ImageMagick ボタン
foreach ($p in $scales) {
    $btnIM = New-Object System.Windows.Forms.Button
    $btnIM.Width  = 80
    $btnIM.Height = 30
    $btnIM.Text   = "{0}%%" -f $p
    $btnIM.Tag    = $p / 100
    $btnIM.Enabled = $hasMagick

    $btnIM.Add_Click({
        param($sender, $e)
        $scale = [double]$sender.Tag
        $q  = $qualityTrackBar.Value
        $st = $stripMetadataCheck.Checked
        $wp = $webpCheck.Checked
        Resize-ImagesMagick -Scale $scale -Quality $q -StripMetadata $st -ConvertWebP $wp -MagickPath $magickPath -ListBox $listBox -StatusLabel $statusLabel -ProgressBar $progressBar -Form $form
    })

    $imButtonPanel.Controls.Add($btnIM)
}

# クリア/中断/終了ボタンの動作
$clearBtn.Add_Click({
    $listBox.Items.Clear()
    $statusLabel.Text = "ファイルがクリアされました。"
    $progressBar.Value = 0
})

$cancelBtn.Add_Click({
    $script:cancelRequested = $true
})

$exitBtn.Add_Click({
    $form.Close()
})

# ------------------------------------------------------------
# フォーム表示
# ------------------------------------------------------------
[void]$form.ShowDialog()

バッチファイルから起動(アプリ化)

次のコードを 起動.bat として保存すると、ダブルクリックで GUI アプリとして起動でき、CMD ウィンドウも残りません。

@echo off
start "" powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0ImageResize-GUI.ps1"
exit

ショートカットをデスクトップに置けば、完全にアプリ感覚で使えます。

ImageMagick を使うとここまで変わる(圧縮比較)

実際の画像で比較すると:

画像ファイルサイズ備考
元画像5.2 MBスマホ撮影
Windows標準 60%1.3 MB画質は十分
ImageMagick 60%310 KB同サイズで圧倒的に軽い
ImageMagick 60% + WebP150 KBWeb使うなら最強

WebPにするとさらに容量を半分以下に抑えることができます。

まとめ

今回紹介した PowerShell 画像縮小ツールは、

  • 縮小
  • 回転補正
  • メタデータ削除
  • WebP変換
  • ImageMagick連携
  • 中断処理
  • 進行バー付きGUI

と、実作業で必要な機能をすべて網羅しています。

PowerShell は「コマンドラインのツール」という印象が強いですが、GUI を組み合わせることで 立派なアプリケーションに進化できます。

ぜひカスタマイズして、自分の作業スタイルに合わせたツール作りにも挑戦してみてください!

【改訂新版】 Windows PowerShell ポケットリファレンス

PowerShell の基本コマンドから応用スクリプトまで、すぐ動くサンプルで学べる実践書です。
ファイル操作・条件分岐・ループ・エラーハンドリングなど、“実際に手を動かす” ことで理解が進みます。
PowerShell の基礎力と応用力を同時に高めたい人におすすめです。

おすすめポイント:

  • 動作するサンプルが豊富で理解が早い
  • 自動化に必要な基礎文法〜実践スクリプトを広くカバー
  • 初級者から中級者へのステップアップに最適

Rakuten

Amazon

Yahoo!ショッピング

  • この記事を書いた人
  • 最新記事

かじ

くまyyの管理人:かじ。 社内SEとして13年勤務、システム企画・開発をしているIT屋さん。 ガジェット好きなので最新ガジェットを追いかけるのが好き。 プログラミングなど自分の知識と経験をいろんな人に役立ってもらえるように記事を更新します!

-PowerShell