So, my program uses a few windows api's to read pixel colors from the monitor. I made a function to get the color of 1 pixel, and to get an area defined by a rectangle. Accidently I re-wrote the 'get an area' code, both versions worked..1 is obviously better, or so I thought.
Code:
Public Function modPublic.GetPixelColor(ByVal x As Int32, ByVal y As Int32) As Color
Dim hWnd As IntPtr
Dim hDC As IntPtr
hWnd = GetDesktopWindow()
hDC = GetWindowDC(hWnd)
Dim lColor As Int32 = GetPixel(hDC, x, y)
ReleaseDC(hWnd, hDC)
Return ColorTranslator.FromWin32(lColor)
End Function
So, that's the code to get 1 specific pixel --> and when I wrote the first version of 'GetRectArea' ..I just called GetPixelColor() a bunch of times --> it works, but it makes LOTS of calls to GetDesktopWindow and GetWindowDC + ReleaseDC.
Here is the bad version of the 'getRegion' func.
Code:
Public Shared Function GetScreenArea(ByVal topLeft As Point, ByVal bottomRight As Point) As Bitmap
Dim boxWidth As Int32 = bottomRight.X - topLeft.X ' no error checkecking: assumes br.x is > tl.x && br.y is > tl.y
Dim boxHeight As Int32 = bottomRight.Y - topLeft.Y
Dim rtnBmp As New Bitmap(boxWidth, boxHeight)
''scans vertically: top-to-bottom, left-to-right
For column As Int32 = 0 To boxWidth - 1
For row As Int32 = 0 To boxHeight - 1
rtnBmp.SetPixel(column, row, modPublic.GetPixelColor(topLeft.X + column, topLeft.Y + row))
Next
Next
Return rtnBmp
End Function
again..it works, but modPublic.GetPixColor keeps calling the api's when we don't need to (This is because GetArea is functionally different than GetPixel) so..I re-wrote GetArea w/ a..I hate to re-write code, but it's essentially the GetPixel code, w/ a loop - but it doesn't release the ptrs (and therefor doesn't have to call the api's over and over again) until it's done.
Code:
Public Function GetPixelArea(ByVal tl As Point, ByVal br As Point) As Bitmap
Dim hWnd As IntPtr
Dim hDC As IntPtr
hWnd = GetDesktopWindow
hDC = GetWindowDC(hWnd)
Dim tmpColor As Color
'''''''''''''''''''''''''''''''''''''
Dim areaWidth As Int32 = br.X - tl.X
Dim areaHeight As Int32 = br.Y - tl.Y
Dim rtnBtmp As New Bitmap(areaWidth, areaHeight)
'scans top-to-bottom, left-to-right
For xx As Int32 = 0 To areaWidth - 1
For yy As Int32 = 0 To areaHeight - 1
tmpColor = ColorTranslator.FromWin32(GetPixel(hDC, tl.X + xx, tl.Y + yy))
rtnBtmp.SetPixel(xx, yy, tmpColor)
Next
Next
ReleaseDC(hWnd, hDC)
Return rtnBtmp
End Function
If you had to pick a function..you'd think GetPixelArea would be faster than GetScreenArea ..but it's not :S I don't understand..it's virtually the exact same code...except the 'slower' version makes less api calls :S so..this truly confuses me..any advice would be greatly appreciated.
I added some timing code to see how much slower/faster they are:
1:57:43 PM->modPublic.ImageScan: 390ms 'Should only call GetWindow etc 1x
1:57:57 PM->wowGUI.GetScreenArea : 265ms 'Should call GetWindow etc proportional to img size: 300,300 = 90,000x!
2:00:55 PM->modPublic.ImageScan: 328ms
2:01:06 PM->wowGUI.GetScreenArea : 500ms
2:02:18 PM->modPublic.ImageScan: 656ms
2:02:28 PM->wowGUI.GetScreenArea : 406ms
I'm guessing they change so much because I'm only on a Pentium4 2.7 w/ 1gb ram - wow,msvs,movie running..so ram is kinda tight :P
Eithor way GetScreenArea is on average a little faster than GetPixelArea -- i would have NEVER expected that..what could be causing?