Hello.
I am sure this is very straight forward but I haven’t found a solution a I am a bit new to this. I am trying to make a very simple color picker to get the color at a mouse down event (this will be with a Raspberry pi and a touch screen). I have an image scaled into a canvas and can get the color with the mouse down event but the color returned is from the non scaled image, not the actual color where the mouse is clicked. Can someone help me out? Do I really have to take a screenshot and get the color from that as I have read and will this work on a Pi, or is there a simpler way?
This always happens. I spend ages trying to figure it out, post a question and then immediately find my answer. imgColour is my canvas with the scaled image and in the mousdown event I have found this works:
dim pickimage as new Picture(imgColour.Width, imgColour.Height,32)
imgColour.DrawInto pickimage.Graphics, 0, 0
Var surf As RGBSurface = pickimage.RGBSurface
dim f as color= surf.Pixel(x,y)
'Messagebox(str(f.red))
RectCol.FillColor=f
rem canvas1 Mousedown img_0577 = picture
Var scale As Double = scalefaktor (0.5 - 2)
Var fx2 As Double = img_0577.Width/(canvas1.Width*scale)
Var fy2 As Double = img_0577.height/(canvas1.height*scale)
Var c As Color = img_0577.RGBSurface.pixel(x*fx2,y*fy2)
mycolor.FillColor = c
A few problems with your code. First, there’s no indication that you are scaling your pic to the dimensions of the Canvas. I’m imagining you have something like this in your Canvas.Paint event:
g.DrawPicture displayedPicture, 0, 0, g.width-1, g.height-1, 0, 0, displayedPicture.Width, displayedPicture.Height
That will take displayedPicture and stretch it to fill the Canvas - note that it will not be scaled proportionally for this example. Then, to get the color underneath the pointer upon MouseDown, you need to do this in the MouseDown event handler:
dim scaledPicture as picture
scaledPicture=New Picture(me.Width, me.Height)
scaledPicture.Graphics.DrawPicture displayedPicture, 0, 0, scaledPicture.width-1, scaledPicture.height-1, 0, 0, displayedPicture.width, displayedPicture.height
dim colorAtMouseCoordinates as color
colorAtMouseCoordinates=scaledPicture.RGBSurface.Pixel(x, y)
(Of course you could cache scaledPicture
for future use instead of redrawing it every time, which would make a big difference in performance!)
This is all well and good and will produce reasonable results in most situations. However, this is a big ‘gotcha’ here: if your picture is relatively small compared to your Canvas, the operating system may interpolate your picture when drawing it. This will produce colors that are not in the original picture, which may not be what you want. For example, if you had a very low resolution image with black and white pixels (no grays), if you stretch it to fill a larger area, many operating systems will interpolate gray values in between the black and white pixels in the original image.
A similar issue can happen when shrinking a picture to fit: the colors shown on the screen may represent the combined colors of several pixels that are compressed down in the drawing process and you’ll end up with a color that is displayed on the screen but isn’t in the original image. This may be acceptable depending on your usage model.
To get around this, you can see if interpolation can be turned off; or, as another poster noted, use a mathematical transformation to turn screen coordinates into picture coordinates and read the color that way. Each approach has its advantages and disadvantages.
i just made a example a few days ago for web.
Thanks for all the help. Very informative.