

【Visual Studio, VB】指定した位置の画素(ピクセル)の色RGBの取得にかかる時間を短縮したい

Visual Studio 2017 Community で Windowsフォームアプリケーションを作成しています。

マウスのポインタの位置にある画素(ピクセル)の色をPictureBox `shutsuryoku`
の背景色に設定し、さらにR(0～255)、G(0～255)、B(0～255)をそれぞれLabel `ontei`, `onryou`, `joutai`
に表示しています。

PictureBoxを使っていますが、ビットマップなどの画像を扱うわけではありません。ディスプレイ上のどの点の位置でも自由に色を読み取れるようにしています。

以下がソースコードです。作りかけのプログラムなので一部無意味なプロシージャなどがありますが気にしないでください。

* * *
[code]

    Public Class Form1
    
        '■API関数の宣言
        Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Integer)
    
        'Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Long) As Long
    
        Declare Function GetTickCount Lib "kernel32" () As Long
    
        Declare Function GetPixel Lib "gdi32" Alias "GetPixel" _
            (ByVal hdc As IntPtr, ByVal x As Integer, ByVal y As Integer) As UInt32
    
        Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Integer) As Integer
    
        Declare Function ReleaseDC Lib "user32" (ByVal hwnd As _
            IntPtr, ByVal hdc As IntPtr) As UInt32
    
        Declare Function GetDesktopWindow Lib "user32" () As Long
    
        '■変数の宣言
        Private i As Long
        Private j As Long
        Private n As Long
        Private tick As Long
        Private window As Long
        Private hdc As Long
        Private ピクセルの色 As Color
        Private 速度更新時刻 As Long
        Private ポインタ位置X As Long
        Private ポインタ位置Y As Long
    
        Private 出力の色 As Color
    
        'フォームを読み込んだときに実行する処理
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            'デスクトップのウィンドウハンドルを取得
            window = GetDesktopWindow
    
            'DCのハンドルを取得
            hdc = GetDC(window)
    
    
            tick = 0
            速度更新時刻 = GetTickCount
    
        End Sub
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    
            '■tick数をカウント
            tick = tick + 1
    
            '■更新速度を表示
            If tick Mod 10 = 0 Then
                If GetTickCount - 速度更新時刻 > 0 Then
                    koushinsokudo.Text = Int(1 / ((GetTickCount - 速度更新時刻) / 10 / 1000))
                End If
                速度更新時刻 = GetTickCount
            End If
    
            '■ポインタ位置を取得
            ポインタ位置X = System.Windows.Forms.Cursor.Position.X
            ポインタ位置Y = System.Windows.Forms.Cursor.Position.Y
    
            '表示
            pX.Text = ポインタ位置X
            pY.Text = ポインタ位置Y
    
            '■ポインタ位置の色を取得
            For n = 1 To 6
                Call 画素の色を取得(ポインタ位置X, ポインタ位置Y)
            Next
            'RGB値をColor型に変換
            出力の色 = ピクセルの色
    
            '出力
            shutsuryoku.BackColor = 出力の色
    
            'RGB値を表示
            ontei.Text = ピクセルの色.R
            onryou.Text = ピクセルの色.G
            joutai.Text = ピクセルの色.B
    
            'プログレスバーに表示
            '値が増加したときにバーが徐々に伸びるアニメーションの表示を無効化するため
            '大きい値から減少させる
            onteibar.Maximum = 256
            onteibar.Value = 256
            onteibar.Value = ピクセルの色.R
            onteibar.Maximum = 255
    
            onryoubar.Maximum = 256
            onryoubar.Value = 256
            onryoubar.Value = ピクセルの色.G
            onryoubar.Maximum = 255
    
            joutaibar.Maximum = 256
            joutaibar.Value = 256
            joutaibar.Value = ピクセルの色.B
            joutaibar.Maximum = 255
    
        End Sub
        Sub 画素の色を取得(ByVal x As Long, ByVal y As Long)
    
            Dim Color As Long
    
    
            'ピクセルの色を取得
            Color = GetPixel(hdc, x, y)
    
    
    
            'Long型をColor型に変換
            ピクセルの色 = ColorTranslator.FromOle(Color)
    
        End Sub
    
        '「検出位置を探す」ボタンが押されたとき
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
    
    
        End Sub
    
        'フォームを閉じるとき
        Private Sub Form1_FormClosing(ByVal sender As Object,
            ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    
            'DCを解放
            ReleaseDC(window, hdc)
    
        End Sub
    End Class
    
[/code]

* * *

コンパイルエラーや実行時エラーは一切ありませんが、ピクセルの色を取得するのにかなり時間がかかってしまいます。

プロシージャ `Timer1_Tick` が1秒間に9回ほどしか実行されません。  
(Label `koushinsokudo` に `Timer1_Tick` が1秒間に何回実行されたかを表示しています。)

[code]

    For n = 1 To 6
        Call 画素の色を取得(ポインタ位置X, ポインタ位置Y)
    Next
    
[/code]

の部分についてですが、同じ処理を6回繰り返しているのは、このプログラムだと全く意味がありませんが、先述したとおりこのプログラムはまだ作りかけで、完成したときには意味のある「画素の色の取得」を6回行うようにするつもりです。

なので、 `Timer1_Tick` 内で少なくとも「画素の色の取得」を6回実行しなければならなくなるはずなので、このようなプログラムの記述にしています。

ちなみに、`For n = 1 To 6` を `For n = 1 To 1`
に書き換えると1秒間に60回程度になります。なので、色の取得以外の処理の実行に異常に時間がかかっているとは考えられません。

パソコンのスペックは以下のとおりです。  
OS Windows10 Home  
CPU 2.50[GHz] (Core i5-3210M)  
RAM 8[GB]

システムの種類は64ビットオペレーティングシステム, x64ベースプロセッサです。

このプログラムを実行するときは、

  * このプログラム
  * Visual Studio 2017 Community
  * タスクマネージャー

以外のアプリケーションは同時に実行していません。

また、タスクマネージャーでCPU使用率を確認すると、10%以下となっているので、バックグラウンドプロセスがこのプログラムの処理速度を低下させているとは考えられません。

ここで質問ですが、ピクセルの色を取得するのにかかる時間を短縮するにはどうすればよいですか？その方法があれば教えてください。

`Timer1_Tick`
が1秒間に40回以上(色の取得は240回以上)実行されるのが理想的ですが、それはさすがに無理だとしても、1秒間に15回や20回程度になる方法でも構いません。


CC BY-SA 3.0
2017-10-20T13:07:47.790
38912
2019-01-25T05:00:50.117
2017-10-20T14:18:29.807
25835
25835
question
visual-studio vb.net
指定した位置の画素(ピクセル)の色RGBの取得にかかる時間を短縮したい


直接関係ありませんが、[`GetPixel`が非常に低速なためにMFC
Ribbonの表示に支障が出ている](https://developercommunity.visualstudio.com/content/problem/136952/mfc-
ribbon-slow-on-first-loadshow.html)報告がなされています。今後`GetPixel`の速度が改善されるかもしれません。


CC BY-SA 3.0
2017-11-06T00:16:45.560
39319
2017-11-06T00:16:45.560
4236
38912
answer