2010-10-06 4 views
0

Le problème consiste à inverser les couleurs d'un élément Silverlight Image.Silverlight Image: comment inverser ou annuler les couleurs de l'image?

Il existe une image avec un fichier JPG en tant que source. Cliquez sur un bouton pour inverser les couleurs. Cela semble simple, pas vrai. Prenez chaque pixel, puis modifiez sa valeur par une valeur de 255 pixels. Mais quand j'ai essayé WritableBitmap chargé avec la source d'image, j'ai obtenu l'exception de sécurité interdisant l'accès au pixel. Voici mon code:

  if (MainLeftImage.Source != null) 
      { 
       WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)MainLeftImage.Source); 
       byte[] pixels = new byte[bitmap.Pixels.Length]; 

       int size = pixels.Count(); 
       for (int i = 0; i < size; i++) 
        pixels[i] = (byte)(255 - pixels[i]); 

       bitmap.Invalidate();//redraw and then plug it back on 

       MainLeftImage.Source = bitmap; 
      } 
     } 
     catch (Exception ex) 
     { 
     } 

Attend que WritableBitmap est pas une solution, non? Toute aide appréciée. Merci les gars.

Répondre

3

façon d'inverser Easiest une image serait d'appliquer un effet de pixel shader. Je crois qu'il y a un pixel shader de couleurs inversées dans le WPF Pixel Shader Effects Library.

La raison pour laquelle vous utilisez l'exception de sécurité est que WriteableBitmap empêche l'accès aux pixels au contenu inter-domaines. Pour comprendre pourquoi cela est important, vous pouvez voir mon explication de la nécessité des fichiers de stratégie d'accès client dans this answer. Pour comprendre le point pour les images, remplacez "secretaccountdetails.html" par "myPrivatePhoto.jpg" dans l'exemple.

Si vous souhaitez vraiment utiliser un WriteableBitmap pour accéder aux pixels d'une image, vous devez:
1. Assurez-vous que la source de l'image provient du même domaine que l'application.
ou
2. Assurez-vous que le serveur à partir duquel l'image est diffusée fournit un client access policy approprié et télécharge le fichier image en tant que flux. Utilisez BitmapSource.SetSource (Stream) pour définir la source de l'image au lieu de la définir sur l'URL de l'image.

Dans les deux cas ci-dessus, vous serez en mesure d'accéder aux pixels d'une image dans un WriteableBitmap.

+0

Je vois, merci Keith. J'ai eu le problème avec l'accès interdomaines, ce qui est mon cas. Je vais essayer le shader d'abord. À votre santé. – val

+0

Salut Keith, j'ai essayé les pix shaders et ils ont l'air bien pour les effets, mais ils ne modifient pas Image.Source dont j'ai besoin aussi. En ce qui concerne mon exception d'accès de sécurité: quelle est la place pour le fichier xml de la politique interdomaines exactement? Devrait-il être dans la racine de mon répertoire virtuel d'image sur le serveur? ou avec l'application web SL? Merci. – val

+0

Le fichier clientaccesspolicy doit aller à la racine du serveur à partir duquel l'image est exposée. Donc, si l'URL de l'image est http://myserver.com/images/myphoto.jpg, l'url du fichier clientaccesspolicy doit être http://myserver.com/clientaccesspolicy.xml. Plus d'informations [ici] (http://msdn.microsoft.com/en-us/library/cc645032%28v=VS.95%29.aspx). – KeithMahoney

0

Oui, cela semble être une restriction idiote sur WritableBitmap. Je ne suis pas sûr du scénario qu'ils essayent d'empêcher là. Je crois que cette exception particulière est levée chaque fois que vous accédez à du contenu inter-domaines, et cela peut fonctionner si le fichier JPEG provient de exactement le le même serveur qui héberge l'application Silverlight. Voir ici:

http://forums.silverlight.net/forums/t/118030.aspx

Mais je suis honnêtement pas sûr de toutes les causes possibles. Une option consisterait à utiliser la bibliothèque FJCore pour décoder l'image JPEG en bitmap, faire pivoter le pixel sur le bitmap décodé, puis charger le bitmap résultant directement dans une image.

http://code.google.com/p/fjcore/

+0

Merci Ken. Ce qui me dérange, ce sont des exemples où ils montrent comment manipuler les pixels WritableBitmap dans des scénarios stupides comme ici http://www.silverlight.net/learn/videos/all/how-do-i-create-a-bitmap-using-writeablebitmap/ – val

0

Vous devez résoudre l'accès inter-domaines comme les autres réponses proposées. Mais il y a aussi une erreur dans votre algorithme. Le tableau WriteableBitmap.Pixels stocke chaque pixel en tant que valeur entière. Les 4 octets de l'int représentent les composantes alpha, rouge, verte et bleue du pixel (ARGB). Vous devez mettre en œuvre comme ceci:

int[] pixels = bitmap.Pixels; 
int size = pixels.Length; 
for (int i = 0; i < size; i++) 
{ 
     // Extract color components 
     var c = pixels[i]; 
     var a = 0x000000FF & (c >> 24); 
     var r = 0x000000FF & (c >> 16); 
     var g = 0x000000FF & (c >> 8); 
     var b = 0x000000FF & (c); 

     // Invert 
     r = 0x000000FF & (0xFF - r); 
     g = 0x000000FF & (0xFF - g); 
     b = 0x000000FF & (0xFF - b); 

     // Set result color 
     pixels[i] = (a << 24) | (r << 16) | (g << 8) | b; 
} 

Comme d'autres ont proposé, vous pouvez utiliser un effet de pixel shader au lieu. Mais vous devrez montrer l'image dans un contrôle Image afin d'y appliquer un shader. Après cela, vous pouvez rendre le résultat dans WriteableBitmap.

var wb = new WriteableBitmap(myImageUiElement, null); 
+0

René, merci beaucoup d'avoir signalé une erreur dans mon inversion algorigthm. Tu as raison. Savez-vous comment résoudre l'accès inter-domaine? Où exactement le fichier XML de domaine croisé doit être placé? – val

Questions connexes