2010-10-20 28 views
2

Selon msdn dans Silverlight, les images peuvent être testées sur leurs zones d'affichage image/média, essentiellement leur hauteur et leur largeur. Les pixels alpha transparents/entiers dans le fichier image sont toujours testables. Ma question est maintenant, quelle est la meilleure façon d'avoir seulement pixel hit non transparent testable dans les images dans Silverlight?Quelle est la meilleure façon de ne tester que les pixels non transparents dans les images dans Silverlight?

Répondre

1

Cela ne va pas être possible en utilisant la fonctionnalité de test d'atteinte normale, comme vous l'avez découvert avec la référence MSDN. La seule idée que j'avais était de convertir votre image à la classe WritableBitmap et d'utiliser la propriété Pixels pour effectuer des tests de succès de canal alpha. Je n'ai pas réellement essayé cela et je ne peux pas imaginer que ce soit trivial à faire, mais cela devrait fonctionner en théorie.

Les pixels ont un grand int [] avec les 4 octets de chaque entier correspondant à ARGB. Il utilise le format ARGB32 prémultiplié, donc s'il y a une transparence alpha en plus de 255, les autres valeurs RVB sont mises à l'échelle en conséquence. Je suppose que vous voulez tout non alpha alpha complet pour être considéré comme un "hit" de sorte que vous pouvez simplement vérifier par rapport à l'octet alpha pour voir si c'est 255.

Vous souhaitez accéder à la rangée/col pixel que vous cherchez à vérifier par index de tableau comme celui-ci:

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

Découvrez this post pour plus d'idées.

EDIT:

j'ai jeté ensemble un test rapide, il fonctionne et il est assez simple:

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; 
} 

Vous auriez probablement eu envie de faire quelques optimisations comme créer pas le WritableBitmap sur chaque événement MouseMove mais ceci est juste une preuve de concept pour montrer que cela fonctionne.

+0

J'ai pensé à faire quelque chose comme ça, mais cela semblait inutilement compliqué, donc je veux m'assurer qu'il n'y a pas de solution plus facile. Une autre approche que j'ai trouvée a essayé d'utiliser les contours de l'objet pour créer une géométrie de chemin et ensuite vérifier si le clic de souris était dedans ou non. Cela fonctionnerait également dans ma demande, mais encore une fois semblait trop compliqué pour un problème aussi fondamental. – cfroehlich

+0

Y a-t-il plusieurs fichiers PNG ou seulement un? Je ne pense pas que ce serait si mauvais, je devine que vous êtes touché sur l'événement MouseMove, donc vous n'avez qu'un point à traduire aux coordonnées de l'image, puis vérifiez X et Y par rapport à la ligne et la colonne de pixels. La géométrie du chemin me semble plus compliquée. –

+0

Édité ma réponse avec un exemple de code. –