What is the best way to have only non-transparent pixel hit testable in images in Silverlight? – Education Career Blog

According to msdn in Silverlight images are hit testable over their image/media display areas, basically their Height and Width. Transparent / full alpha pixels in the image file are still hit testable.
My question is now, what is the best way to have only non-transparent pixel hit testable in images in Silverlight?

,

This is not going to be possible using the normal hit testing capability, as you found out with the MSDN reference.

The only idea I had was to convert your image to the WritableBitmap class and use the Pixels property to do alpha channel hit testing. I have not actually tried this and I can’t imagine it’s trivial to do, but it should work in theory.

The pixels are one large int with the 4 bytes of each integer corresponding to ARGB. It uses the premultiplied ARGB32 format, so if there is any alpha transparency besides full 255 the other RGB values are scaled accordingly. I am assuming you want anything NOT full alpha to be considered a “hit” so you could just check against the alpha byte to see if it is 255.

You would access the row/col pixel you are looking to check by array index like this:

int pixel = myBitmap.Pixelsrow * myBitmap.PixelWidth + col;

Check out this post for some more ideas.

EDIT:

I threw together a quick test, it works and it’s pretty straightforward:

public MainPage()
{
    InitializeComponent();

    this.image = new BitmapImage(new Uri("my_tranny_image.png", UriKind.Relative));
    this.MyImage.Source = image;

    this.LayoutRoot.MouseMove += (sender, e) =>
    {
        bool isHit = ImageHitTest(image, e.GetPosition(this.MyImage));
        this.Result.Text = string.Format("Hit Test Result: {0}", isHit);
    };
}

bool ImageHitTest(BitmapSource image, Point point)
{
    var writableBitmap = new WriteableBitmap(image);

    // check bounds
    if (point.X < 0.0 || point.X > writableBitmap.PixelWidth - 1 ||
        point.Y < 0.0 || point.Y > writableBitmap.PixelHeight - 1)
        return false;

    int row = (int)Math.Floor(point.Y);
    int col = (int)Math.Floor(point.X);

    int pixel = writableBitmap.Pixelsrow * writableBitmap.PixelWidth + col;
    byte pixelBytes = BitConverter.GetBytes(pixel);

    if (pixelBytes0 != 0x00)
        return true;
    else
        return false;
}

You would probably want to make some optimizations like not create the WritableBitmap on every MouseMove event but this is just a proof of concept to show that it works.

Leave a Comment