指定した位置の画素(ピクセル)の色RGBの取得にかかる時間を短縮したい
【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を使っていますが、ビットマップなどの画像を扱うわけではありません。ディスプレイ上のどの点の位置でも自由に色を読み取れるようにしています。
以下がソースコードです。作りかけのプログラムなので一部無意味なプロシージャなどがありますが気にしないでください。
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
コンパイルエラーや実行時エラーは一切ありませんが、ピクセルの色を取得するのにかなり時間がかかってしまいます。
プロシージャ Timer1_Tick
が1秒間に9回ほどしか実行されません。
(Label koushinsokudo
に Timer1_Tick
が1秒間に何回実行されたかを表示しています。)
For n = 1 To 6
Call 画素の色を取得(ポインタ位置X, ポインタ位置Y)
Next
の部分についてですが、同じ処理を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回程度になる方法でも構いません。