2

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

4

1 回答 1

1

正如您在 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,但这只是证明它有效的概念证明。

于 2010-10-20T15:32:29.530 回答