GetPixelColour with mouse magnifier

Developed or developing a new product in PureBasic? Tell the world about it.
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

GetPixelColour with mouse magnifier

Post by infratec »

Hi,

from a small coding question I was inspired to make this:

Code: Select all

; Samplecode to get the color of a Pixel on the Desktop
; by PureLust for PureBasic-Forum - 18.09.2009 (with thanks to netmaestro)  ;)
; extended by infratec
; windows Vista problem solved by srod (GetPixel() is to slow in Vista ~40ms !!!)
; now works also with 7 (GetDC() and ReleaseDC() now inside the loop)
; fix for multi screen environment added
; now multi screens should really work correct
; cursor movements are now correct (relative moves goes through the driver and his acceleration)


#MOUSEEVENTF_VIRTUALDESK = $4000

Global Mag = 5
Global ImageDim
NewMag = 5
#BoxPlusMinus = 10


Procedure SetMag(NewMag.i)
 Mag = NewMag
 ImageDim = #BoxPlusMinus * 2 * Mag
 CreateImage(0, ImageDim, ImageDim)
 If ImageDim < 100
  WinDim = 100
 Else
  WinDim = ImageDim
 EndIf
 ResizeWindow(0, #PB_Ignore, #PB_Ignore, 100 + WinDim, 70 + WinDim)
 TextGadget(1, 0, 45 + WinDim, 100 + WinDim, 20, "", #PB_Text_Center)
EndProcedure



Dim SendInputData.INPUT(0)

SendInputData(0)\Type = #INPUT_MOUSE
SendInputData(0)\mi\time = 0
SendInputData(0)\mi\dwExtraInfo = 0
SendInputData(0)\mi\mouseData = 0



OpenWindow(0, 0, 0, 200, 170, "", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered|#PB_Window_Minimize)

ImageGadget(0, 46, 20, 105, 105, 0, #PB_Image_Border)
TextGadget(1, 0, 145, 200, 20, "", #PB_Text_Center)
TrackBarGadget(2, 10, 20, 20, 105, 1, 9, #PB_TrackBar_Vertical)
SetGadgetState(2, 1)

BoxDim = #BoxPlusMinus * 2
ImageDim = #BoxPlusMinus * 2 * Mag

CreateImage(0, ImageDim, ImageDim)


ShortCuts = 0

Repeat
 Event = WaitWindowEvent(100)

 x.l = DesktopMouseX()
 y.l = DesktopMouseY()

 hDC.l = GetDC_(0)
 PointColor = GetPixel_(hDC, x, y)
 Red = Red(PointColor)
 Green = Green(PointColor)
 Blue = Blue(PointColor)
 PixelColour$ = RSet(Hex(Red), 2, "0") + RSet(Hex(Green), 2, "0") + RSet(Hex(Blue), 2, "0")
 
 If WindowHeight(0) > 10
 
  If ShortCuts = 0
   AddKeyboardShortcut(0, #PB_Shortcut_Left, 1)
   AddKeyboardShortcut(0, #PB_Shortcut_Up, 2)
   AddKeyboardShortcut(0, #PB_Shortcut_Right, 3)
   AddKeyboardShortcut(0, #PB_Shortcut_Down, 4)
   AddKeyboardShortcut(0, #PB_Shortcut_Add, 5)
   AddKeyboardShortcut(0, #PB_Shortcut_Subtract, 6)
   AddKeyboardShortcut(0, #PB_Shortcut_F1, 7)
   SetWindowTitle(0, "GetPixelColour")
   ShortCuts = 1
  EndIf
 
  SetGadgetText(1, "Colour at " + Str(x) + ","+ Str(y) +" is: " + PixelColour$)
 
  SD = StartDrawing(ImageOutput(0))
 
  If SD
   
   ; find out the correct screensize
   If GetSystemMetrics_(#SM_CMONITORS) = 1
    DeskWidth.l = GetSystemMetrics_(#SM_CXSCREEN)
    DeskHeight.l = GetSystemMetrics_(#SM_CYSCREEN)
    dwFlags.q = #MOUSEEVENTF_ABSOLUTE + #MOUSEEVENTF_MOVE
   Else
    DeskWidth.l = GetSystemMetrics_(#SM_CXVIRTUALSCREEN)
    DeskHeight.l = GetSystemMetrics_(#SM_CYVIRTUALSCREEN)
    dwFlags.q = #MOUSEEVENTF_ABSOLUTE + #MOUSEEVENTF_MOVE + #MOUSEEVENTF_VIRTUALDESK
   EndIf
   
   ; calculations for the 'borders'
   If x - #BoxPlusMinus < 0
    ScreenX1 = 0
    ImageX1 = (#BoxPlusMinus - x) * Mag
   Else
    ScreenX1 = x - #BoxPlusMinus
    ImageX1 = 0
   EndIf
   
   If x + #BoxPlusMinus > DeskWidth
    ImageX2 = (#BoxPlusMinus * 2 - (x + #BoxPlusMinus - DeskWidth)) * Mag
   Else
    ImageX2 = ImageDim
   EndIf
   
   If y - #BoxPlusMinus < 0
    ScreenY1 = 0
    ImageY1 = (#BoxPlusMinus - y) * Mag
   Else
    ScreenY1 = y - #BoxPlusMinus
    ImageY1 = 0
   EndIf
   
   If y + #BoxPlusMinus > DeskHeight
    ImageY2 = (#BoxPlusMinus * 2 - (y + #BoxPlusMinus - DeskHeight)) * Mag
   Else
    ImageY2 = ImageDim
   EndIf
   
   ; do the magnification
   StretchBlt_(SD, ImageX1, ImageY1, ImageDim, ImageDim, hDC, ScreenX1, ScreenY1, BoxDim, BoxDim, #SRCCOPY)
   
   ; fill the borders if neccessary
   If ImageX1 > 0
    Box(0, 0, ImageX1, ImageDim, 0)
   EndIf
   
   If ImageY1 > 0
    Box(0, 0, ImageDim, ImageY1, 0)
   EndIf
   
   If ImageX2 < ImageDim
    Box(ImageX2, 0, ImageDim - ImageX2, ImageDim, 0)
   EndIf
   
   If ImageY2 < ImageDim
    Box(0, ImageY2, ImageDim, ImageDim - ImageY2, 0)
   EndIf
   
   
   ; draw the crosshairs
CompilerIf #PB_Compiler_Version >= 440
   Line((ImageDim + Mag) / 2, 0, 1, ImageDim + Mag , ~PointColor)
   Line(0, (ImageDim + Mag) / 2, ImageDim + Mag, 1 , ~PointColor)
CompilerElse
   PointColor = $FFFFFF - PointColor
   Line((ImageDim + Mag) / 2, 0, 0, ImageDim + Mag , PointColor)
   Line(0, (ImageDim + Mag) / 2, ImageDim + Mag, 0 , PointColor)
CompilerEndIf

   StopDrawing()
   SetGadgetState(0, ImageID(0))
  EndIf
 
  If Event = #PB_Event_Gadget
   If EventGadget() = 2
    NewMag = 4 + (GetGadgetState(2) * 2 - 1)
    If Mag <> NewMag
     SetMag(NewMag)
    EndIf
   EndIf
  EndIf
 
  If Event = #PB_Event_Menu
   
   SendInputData(0)\mi\dwFlags = dwFlags
   
   Select EventMenu()
    Case 1:
;     mouse_event_(1, -1, 0, 0, 0)
     SendInputData(0)\mi\dx = Round((65536.0 * (x - 1) / DeskWidth), #PB_Round_Up)
     SendInputData(0)\mi\dy = Round((65536.0 * y) / DeskHeight, #PB_Round_Up)
     SendInput_(1, SendInputData(0), SizeOf(INPUT))
    Case 2:
     ;mouse_event_(1, 0, -1, 0, 0)
     SendInputData(0)\mi\dx = Round((65536.0 * x) / DeskWidth, #PB_Round_Up)
     SendInputData(0)\mi\dy = Round((65536.0 * (y - 1)) / DeskHeight, #PB_Round_Up)
     SendInput_(1, SendInputData(0), SizeOf(INPUT))
    Case 3:
     ;mouse_event_(1, 1, 0, 0, 0)
     SendInputData(0)\mi\dx = Round((65536.0 * (x + 1)) / DeskWidth, #PB_Round_Up)
     SendInputData(0)\mi\dy = Round((65536.0 * y) / DeskHeight, #PB_Round_Up)
     SendInput_(1, SendInputData(0), SizeOf(INPUT))
    Case 4:
     ;mouse_event_(1, 0, 1, 0, 0)
     SendInputData(0)\mi\dx = Round((65536.0 * x) / DeskWidth, #PB_Round_Up)
     SendInputData(0)\mi\dy = Round((65536.0 * (y + 1)) / DeskHeight, #PB_Round_Up)
     SendInput_(1, SendInputData(0), SizeOf(INPUT))
    Case 5:     
     If Mag < 21
      Mag + 2
      SetMag(Mag)
      SetGadgetState(2, (Mag - 3) / 2 )
     EndIf     
    Case 6:
     If Mag > 5
      Mag - 2
      SetMag(Mag)
      SetGadgetState(2, (Mag - 3) / 2 )
     EndIf
    Case 7:
     Text$ = "                  Getpixelcolour" + Chr(13)
     Text$ + Chr(13)
     Text$ + "                 2009 by Infratec" + Chr(13)
     Text$ + Chr(13)
     Text$ + "Use the cursor keys for fine adjustment" + Chr(13)
     Text$ + "Plus and minus to set the magnification" + Chr(13)
     Text$ + Chr(13)
     Text$ + "                      Have fun!"
     MessageRequester("Info", Text$)
   EndSelect
  EndIf
 
 Else
  SetWindowTitle(0, PixelColour$)
  If ShortCuts = 1
   RemoveKeyboardShortcut(0, #PB_Shortcut_All)
   ShortCuts = 0
  EndIf
 EndIf

 ReleaseDC_(0,hDC)

Until Event = #PB_Event_CloseWindow
I hope all bugs are fixed.

I found it usefull, since I have often to do some html stuff,
and all other solutions are much bigger in size.

Bernd
Last edited by infratec on Wed Dec 02, 2009 4:06 pm, edited 9 times in total.
+18
Enthusiast
Enthusiast
Posts: 228
Joined: Fri Oct 24, 2008 2:07 pm

Re: GetPixelColour with mouse magnifier

Post by +18 »

Very cool, merci :D
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: GetPixelColour with mouse magnifier

Post by netmaestro »

Very nice little handy tool. Now a little challenge for you: It would be easier to use if it had keyboard control as well, so that one press of the up arrow would move your mouse pointer exactly one pixel and same for the other 3 directions. This would give you finetuned control when you're close to what you want.
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: GetPixelColour with mouse magnifier

Post by srod »

Crashes here on Vista if I activate the window and then try and close it.
I may look like a mule, but I'm not a complete ass.
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GetPixelColour with mouse magnifier

Post by infratec »

@netmaestro
since christmas is near, I fullfilled your wish.
Now you can use the cursorkeys for fine tuning.


@srod
Hm, at the moment I have no access to Vista.
But I'll test it asap. At the moment I have no idea what can be the reason.

Bernd
User avatar
Arctic Fox
Enthusiast
Enthusiast
Posts: 609
Joined: Sun Dec 21, 2008 5:02 pm
Location: Aarhus, Denmark

Re: GetPixelColour with mouse magnifier

Post by Arctic Fox »

I think the problem lies in Color = GetPixel_(hDC, x1, y1) on line number 45. No problems occur here on Vista when commenting it out.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: GetPixelColour with mouse magnifier

Post by srod »

Yes, GetPixel_() is horrendously slow when working with a desktop DC on Vista and the problem is that it is all 'backing up'. Simple tests have confirmed this. Switch to a normal window DC and everything runs much better.

If I were you I would dump a copy of the desktop to a memory DC holding an image and then work with that - or find some other way.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: GetPixelColour with mouse magnifier

Post by srod »

@infratec : here's something which I knocked up in a couple of minutes and which works fine here on Vista. You might want to play with it?

Code: Select all

OpenWindow(0, 0, 0, 200, 170, "", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)

ImageGadget(0, 46, 20, 105, 105, 0, #PB_Image_Border)
TextGadget(1, 0, 145, 200, 20, "", #PB_Text_Center)

CreateImage(0, 105, 105)

HDC = GetDC_(0)

AddWindowTimer(0, 100, 10)

Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Timer And EventTimer() = 100
    x = DesktopMouseX()
    y = DesktopMouseY()
    PointColor = GetPixel_(hDC, x, y)
    SetWindowTitle(0, Hex(PointColor))
    hdcImage = StartDrawing(ImageOutput(0))
    If hdcImage
      x - 10
      If x < 0 : x = 0 : EndIf
      y - 10
      If y < 0 : y = 0 : EndIf
      StretchBlt_(hdcImage, 0, 0, 105, 105, hdc, x, y, 20, 20, #SRCCOPY)
      StopDrawing()
      SetGadgetState(0, ImageID(0))
    EndIf
  EndIf 
Until Event = #PB_Event_CloseWindow

ReleaseDC_(0,HDC)
I may look like a mule, but I'm not a complete ass.
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GetPixelColour with mouse magnifier

Post by infratec »

It's right.

With XP it takes 0 ms for one GetPixel(),
with Vista it takes between 30 and 40 ms.

With 20 by 20 requests, this takes 16s :!:

What a m...!

I try to solve this.

Bernd
Last edited by infratec on Mon Nov 30, 2009 8:29 am, edited 1 time in total.
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GetPixelColour with mouse magnifier

Post by infratec »

@srod

Thank's, I'll try it.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: GetPixelColour with mouse magnifier

Post by Kwai chang caine »

Very usefull !!!
Thanks at you two 8)

You have always somme code for open my eyes like that :shock:
ImageThe happiness is a road...
Not a destination
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GetPixelColour with mouse magnifier

Post by infratec »

Hi together,

I don't like wind... :!:

And normally I avoid all that API stuff, so I say thank you to srod for his hint.
He also pointed out an other problem of my program:
The 'border' problem.

This was a hard work for my brain, but now it is fixed.
So now you can also investigate the borders.

Also with Vista and maybe also with 7 (not tested, since I have no 7)

Have fun,

Bernd

P.S.: It is already prepared for a slider where you can change the magnification.
the next step of the evolution :mrgreen:
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: GetPixelColour with mouse magnifier

Post by infratec »

Hi,

now also with a magnification slider :mrgreen: :mrgreen: :mrgreen:

Bernd
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Re: GetPixelColour with mouse magnifier

Post by srod »

Works well infratec; very nice. 8)
I may look like a mule, but I'm not a complete ass.
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: GetPixelColour with mouse magnifier

Post by Rook Zimbabwe »

Extermely cool! 8)
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Post Reply