Каков наилучший способ проверки только непрозрачных пикселей на изображениях в Silverlight?

В соответствии с msdn в Silverlight изображения можно тестировать по их областям отображения изображения / мультимедиа, в основном по их высоте и ширине. Прозрачные / полные альфа-пиксели в файле изображения по-прежнему можно проверить. Теперь мой вопрос: как лучше всего проверить попадание только непрозрачных пикселей в изображения в Silverlight?


person cfroehlich    schedule 20.10.2010    source источник


Ответы (1)


Это невозможно при использовании обычной возможности проверки попаданий, как вы узнали из ссылки MSDN.

Единственная идея, которая у меня была, заключалась в том, чтобы преобразовать ваш образ в WritableBitmap и используйте класс Pixels для тестирования попадания в альфа-канал. Я на самом деле не пробовал это, и я не могу представить, что это тривиально, но в теории это должно работать.

Пиксели представляют собой один большой int[] с 4 байтами каждого целого числа, соответствующего ARGB. Он использует предварительно умноженный формат ARGB32, поэтому, если есть какая-либо альфа-прозрачность, кроме полных 255, другие значения RGB масштабируются соответствующим образом. Я предполагаю, что вы хотите, чтобы все НЕ полная альфа-версия считалась "попаданием", чтобы вы могли просто проверить альфа-байт, чтобы увидеть, равен ли он 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;
}

Вы, вероятно, захотите сделать некоторые оптимизации, например, не создавать WritableBitmap для каждого события MouseMove, но это всего лишь доказательство концепции, показывающее, что это работает.

person Dan Auclair    schedule 20.10.2010
comment
Я думал о том, чтобы сделать что-то подобное, но это казалось излишне сложным, поэтому я хочу убедиться, что нет более простого решения. Другой подход, с которым я столкнулся, пытался использовать контуры объекта для создания геометрии пути, а затем проверять, был ли щелчок мыши внутри или нет. Это также сработало бы в моем приложении, но снова показалось слишком сложным для такой простой проблемы. - person cfroehlich; 20.10.2010
comment
Есть несколько PNG или только один? Я не думаю, что это было бы так уж плохо, я предполагаю, что вы тестируете попадание в событие MouseMove, поэтому у вас есть только одна точка для преобразования в координаты изображения, а затем сверяйте X и Y со строкой и столбцом пикселей. Геометрия пути кажется мне более сложной. - person Dan Auclair; 20.10.2010
comment
Спасибо за пример кода. Вы, кажется, должны перепутать x и y. (x=столбец и y=строка). работает достаточно хорошо, но по-прежнему кажется пустой тратой памяти иметь копию каждого изображения, которое я использую ^^ - person cfroehlich; 25.10.2010