PowerShellでスクリーン上の任意の位置のRGB値を取得する(カラーピッカー)


概要

PowerShell で、マウスカーソルの位置の RGB 値を取得するスクリプトを作りました(カラーピッカー、スポイトツール)。

使い方

  1. スクリプトを起動する。
  2. スクリーン上の RGB 値を取得したい箇所に、マウスカーソルを 3 秒以内に持っていく。
  3. (スクリプトを起動してから 3 秒後時点の)マウスカーソルの位置の RGB 値が、コンソールに出力される。

オプション機能

  • ピックした色をクリップボードにセットできるようにした。
    • スクリプトの最後に「C」キーを押すことで、この機能が動作する。
    • 16x16 サイズの、単色の画像としてセットする。

コード

ColorPikcer.ps1
Add-Type -AssemblyName System.Drawing, System.Windows.Forms

# Bitmap と Graphics オブジェクトを用意しておく (1x1 ピクセル)
$bitmap = New-Object System.Drawing.Bitmap(1, 1)
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)

# 3 秒間の猶予を与える
Write-Host "Move the cursor to the targt position in 3 seconds..."
Start-Sleep 3

# カーソルの位置 (X, Y 座標) を取得
$dpiScaling = 1.0
$positionX = [System.Windows.Forms.Cursor]::Position.X * $dpiScaling
$positionY = [System.Windows.Forms.Cursor]::Position.Y * $dpiScaling

# カーソルの位置のスクリーンの RGB 値を取得
$graphics.CopyFromScreen($positionX, $positionY, 0, 0, $bitmap.Size)
$pixel = $bitmap.GetPixel(0, 0)

# RGB 値をコンソールに表示
$decValue = "RGB({0}, {1}, {2})" -f $pixel.R, $pixel.G, $pixel.B
$hexValue = "#{0:X2}{1:X2}{2:X2}" -f $pixel.R, $pixel.G, $pixel.B
Write-Host "$decValue, $hexValue"

# 「C」キー押下で、取得した色をクリップボードにセット
Write-Host "Press 'C' to copy the color to the clipboard..." -NoNewLine
if ([Console]::ReadKey().KeyChar -eq 'c')
{
    $bitmap16x16 = New-Object System.Drawing.Bitmap(16, 16)
    $graphics16x16 = [System.Drawing.Graphics]::FromImage($bitmap16x16)
    $graphics16x16.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::NearestNeighbor
    $graphics16x16.DrawImage($bitmap, 0, 0, 16*2, 16*2)
    [Windows.Forms.Clipboard]::SetImage($bitmap16x16)
}

実行結果

Move the cursor to the targt position in 3 seconds...
RGB(89, 187, 12), #59BB0C
Press 'C' to copy the color to the clipboard...C

クリップボードにセットされた画像: (#59BB0C)

メモ

  • 動作状況:

    • マルチディスプレイ環境でも動作した。
    • DPI のスケーリング値を 100% より大きい値に設定していると、[System.Windows.Forms.Cursor]::Position の位置がずれてしまう。

      • スクリプト中の変数 $dpiScaling の値を変更することで、このずれを修正できるようにした。

        • 例。スケーリング値を 150% に設定している場合は、以下のように変更する:

          $dpiScaling = 1.5
          
      • WinAPI からこのスケーリング値を取得することもできるらしい(が、面倒そうなので今回はパス……)。

    • 「マルチディスプレイ環境」かつ「DPI のスケーリング値がディスプレイ間で異なる環境」だと上手く動作しない(スケーリング値が合っていないディスプレイで位置ずれが発生する)。

  • 欠点:

    • 「マウスオーバーで動的に表示が切り替わるような箇所」から「切り替わる前の色」をピックすることができない。
  • その他:

    • (大したメモリ量にはならないとは思い今回は省略したが、)Bitmap や Graphics の Dispose() はちゃんと書いたほうがお行儀がいいかもしれない。
    • Write-Host-BackgroundColor オプションを使って、色の見本がコンソールに表示できたら便利だったのだが、このオプションで指定できるのは "magenta""yellow" などの固定の 16 色だけだった。