在 Silverlight 中仅对图像中的非透明像素命中进行测试的最佳方法是什么?

发布于 2024-09-28 11:13:49 字数 140 浏览 6 评论 0原文

根据 Silverlight 中的 msdn,图像在其图像/媒体显示区域(基本上是其高度和宽度)上可进行命中测试。图像文件中的透明/全 Alpha 像素仍然可进行测试。 我现在的问题是,在 Silverlight 中仅让图像中的非透明像素命中可测试的最佳方法是什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜未央樱花落 2024-10-05 11:13:49

正如您在 MSDN 参考中发现的那样,使用普通的命中测试功能是不可能实现这一点的。

我唯一的想法是将您的图像转换为 WritableBitmap 类并使用 Pixels 属性进行 Alpha 通道命中测试。我还没有真正尝试过这个,我无法想象这样做是微不足道的,但理论上它应该有效。

像素是一个大的 int[],每个整数的 4 个字节对应于 ARGB。它使用预乘的 ARGB32 格式,因此如果除了完整的 255 之外还有任何 alpha 透明度,其他 RGB 值也会相应缩放。我假设您希望任何完整 alpha 被视为“命中”,因此您只需检查 alpha 字节以查看它是否为 255。

您将访问您正在查找的行/列像素通过数组索引进行检查,如下所示:

int pixel = myBitmap.Pixels[row * myBitmap.PixelWidth + col];

查看 这篇文章以获得更多想法。

编辑:

我进行了一个快速测试,它有效并且非常简单:

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.Pixels[row * writableBitmap.PixelWidth + col];
    byte[] pixelBytes = BitConverter.GetBytes(pixel);

    if (pixelBytes[0] != 0x00)
        return true;
    else
        return false;
}

您可能想要进行一些优化,例如不在每个 MouseMove 事件上创建 WritableBitmap,但这只是一个要展示的概念证明它有效。

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.Pixels[row * 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.Pixels[row * writableBitmap.PixelWidth + col];
    byte[] pixelBytes = BitConverter.GetBytes(pixel);

    if (pixelBytes[0] != 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文