Background:
I wanted to detect if a click on a Canvas was on an icon that I’ve painted into it so I started looking at techniques to do just using RGBSurface or something that would allow be to detect a click on a non-transparent pixel.
Something odd happened (i.e. I didn’t expect it).
I’ve some PNG graphic files that I’ve dragged into an Image in my project. I’ve added x1 and x2 resolutions to support HDPI. The PNG’s have a transparent background and are displayed correctly on my window (it’s a Mac Desktop project by the way).
If I pause the project and take a look at my picture object I see;
HasAlphaChannel: False
RGBSurface: Nil
If I check the Contents of the picture in the debugger as well I see my image in the Picture (oddly displayed in the debugger with a white background) and Mask is a X (i.e. no mask).
Nothing in debugger hints at this picture having a mask or a transparent background but it does and it’s drawn perfectly in the canvas if I simply set the Backdrop property in code.
I noticed also that if I do this…
// ImageNormal has the transparent picture in it…
ImageTest = new Picture(ImageNormal.Width, ImageNormal.Height, 32)
ImageTest.Graphics.DrawPicture(ImageNormal, 0, 0)
Window1.Canvas1.backdrop = ImageTest
Window1.Canvas1 show the image with a white background.
Q1: In all the years of using RealBASIC and the Xojo I’ve never had to do this but something isn’t adding up here. Can anyone explain the behaviour I am seeing? What am I missing in terms of using PNG files… Years ago I used to save icons / graphics and then save a mask image that I’d load and apply separately but that stopped being a thing I had to do when transparent image file formats started to be support. Confused
Q2: Assuming there is a logical explanation to the above.
How am I analyse the picture data to work out if a click is on a transparent pixel. RGBSurface isn’t available for my images? Any other ideas or pointers?
I think images dragged into a project are now loaded as immutable bitmaps which means you probably have to copy the content into a new picture to access RGBSurface.
Another problem you may run into is that pictures on some Xojo targets store the pixels in a premultiplied format which means you could get different results based on the target.
We prefer to bypass Xojo’s built-in image handling and use plugins from MBS & Einhuger.
In that event, you get the Click location in x,y.
If the user click in x > 10 and x < 30 and y > 10 and y < 30 then the click in in the rectable “play Beethoven”… for example.
Hi Emile.
Thanks for your reply. I can already detect a click within a rectangle thank you again.
My problem is where I wanted to actually detect if the click was within the irregular icon boundaries… so I can be sure the actual graphic is clicked and not just a click in the rectangle boundary.
Hence the idea of checking the pixel that’s been clicked to see if it’s transparent.
Update first…
OK I am back on track… No longer quite as bewildered as I was when I wrote the original post.
My initial problem with weird HasAlphaChannel: False and RGBSurface: nil has been solved.
I should have been testing against Image.ImageAt(0) or (1)…
If I do that then I get the HasAlphaChannel = true and I can now interrogate the RGBSurface using the click coordinates from the MouseDown event.
This is kind of working for me…
Canvas.MouseDown event
// me.backdrop already has the image set..
dim bestImage As Picture
// Get the images that is being displayed on screen...
bestImage = me.Backdrop.BestRepresentation(me.Width, me.Height, self.ScaleFactor)
if bestImage.HasAlphaChannel then
rgb = bestImage.RGBSurface
pixelColor = rgb.Pixel(X * self.ScaleFactor, Y * self.ScaleFactor)
if pixelColor.Alpha = 255 then
// transparent pixel was clicked...
Window1.whichColour.Visible = false
else
// just display the color for now - so you can verify the pixel
Window1.whichColour.Visible = true
Window1.whichColour.FillColor = pixelColor
end if
end if