Dragging images with transparent background in Silverlight
===

I have a Canvas (Puzzle) and a list of child png images (PuzzleParts) with transparent background. I need to drag these image only if mouse over non-transparent part of image. So, my implementation looks like this:

    public class Puzzle : Canvas
        {
            public Puzzle()
            {
                Background = new SolidColorBrush(Colors.Transparent);
                MouseLeftButtonDown += Puzzle_MouseLeftButtonDown;
            }

            public void Load(PuzzleSettings settings)
            {
                foreach (var child in Children)
                {
                    //child.MouseLeftButtonDown -= OnMouseLeftButtonDown;
                    child.MouseLeftButtonUp -= OnMouseLeftButtonUp;
                    child.MouseMove -= OnMouseMove;
                }
                Children.Clear();

                foreach (var part in settings.Parts)
                {
                    var puzzlePart = new PuzzlePart(part);
                    //puzzlePart.MouseLeftButtonDown += OnMouseLeftButtonDown;
                    puzzlePart.MouseLeftButtonUp += OnMouseLeftButtonUp;
                    puzzlePart.MouseMove += OnMouseMove;
                
                    Children.Add(puzzlePart);
                }
            }
    
            /// Finds all PuzzleParts under mouse pointer and first of them with non-
            /// transparent pixel (dragging PuzzlePart)
            private void Puzzle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                var elements = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(null), this);
    
                foreach (var element in elements)
                {
    
                    if (!(element is PuzzlePart))
                        continue;
    
                    var part = element as PuzzlePart;
    
                    if (!IsTransparentPixel(part, e.GetPosition(part)))
                    {
                        OnMouseLeftButtonDown(part, e);
                    }
                }
            }
            
            /// Checks if specific pixel of PuzzlePart is transparent
            private bool IsTransparentPixel(PuzzlePart part, Point point)
            {
                var uri = new Uri(part.Settings.ImagePath, UriKind.Relative);
                var bitmapImage = new BitmapImage {CreateOptions = BitmapCreateOptions.None, UriSource = uri};
                var writableBitmap = new WriteableBitmap(bitmapImage);
    
                // check bounds
                if (point.X < 0.0 || point.X > writableBitmap.PixelWidth - 1 ||
                    point.Y < 0.0 || point.Y > writableBitmap.PixelHeight - 1)
                    return false;
    
                var row = (int)Math.Floor(point.Y);
                var 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;
    
                return false;
            }
    
            private bool _isDragging;
    
            private Point _lastPosition;
    
            private double _offsetX;
    
            private double _offsetY;
    
            private int _lastZIndex;
    
            #region Puzzle part dragging
    
            /// Performs PuzzlePart dragging
            private void OnMouseMove(object sender, MouseEventArgs e)
            {
                if (_isDragging)
                {
                    var puzzlePart = (PuzzlePart) sender;
    
                    Point p = e.GetPosition(this);
                    double x = p.X - _offsetX;
                    double y = p.Y - _offsetY;
    
                    var displacementX = puzzlePart.Settings.ControlPoint.Position.X - x;
                    var displacementY = puzzlePart.Settings.ControlPoint.Position.Y - y;
    
                    if (Math.Sqrt(displacementX * displacementX + displacementY * displacementY) < _sensivity)
                    {
                        x = puzzlePart.Settings.ControlPoint.Position.X;
                        y = puzzlePart.Settings.ControlPoint.Position.Y;
                    }
    
                    // Set the new position for the puzzle part control.
                    puzzlePart.SetValue(LeftProperty, x);
                    puzzlePart.SetValue(TopProperty, y);
                }
            }
            
            /// Ends drag operation
            private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
            {
                var element = (UIElement)sender; 
    
                _isDragging = false;
                element.ReleaseMouseCapture();
                _lastPuzzlePart = (PuzzlePart) element;
            }
    
            /// Begins drag operation
            private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
    
                var puzzlePart = (PuzzlePart) sender;
                puzzlePart.CaptureMouse();
                _isDragging = true;
                SetZIndex(puzzlePart, _lastZIndex++);
                _lastPosition = e.GetPosition(puzzlePart);
                _offsetX = _lastPosition.X;
                _offsetY = _lastPosition.Y;
            }
    
            #endregion
        }

It works good when the PuzzlePart is on top of the Canvas, but I have performance problem with dragging when the PuzzlePart is not on top and it need to find dragging image by inspecting mouse over pixels. I don't understand what problem is.