How to analyse the pixels in an Picture

Hi all.
Two part question here I think.

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 :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?

Much appreciated.

Dave

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.

https://documentation.xojo.com/topics/user_interface/desktop/desktop_controls/canvas.html#canvas-mousedown

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 :+1:t2: 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.

I hope that clarifies the scenario.

can you upload your icon?

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

That is when the image was dropped into the project.

Things will be different if the image is dropped into the Canvas by the user or if you load the image say in the Open Event.