2010-12-12 53 views
4

J'ai mis en place un code pour couvrir aléatoirement un bitmap 2 couleurs différentes, 7 sur 10 fois la couleur serait bleue, et 3 fois sur 10, la couleur serait verte. Cependant, quand c'est fait, il semble très peu aléatoire, comme il a décidé de mettre plusieurs fois 7 pixels bleus, puis 3 pixels verts et ainsi de suite.
Exemple:
alt text Mon code est:Pourquoi la couleur de pixel aléatoire n'est-elle pas si aléatoire dans mon application C#?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace FourEx 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      Bitmap bmp = new Bitmap(canvas.Image); 
      System.Drawing.Imaging.BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, 800, 600), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 
      unsafe 
      { 
       int tempy = 0; 
       while (tempy < 600) 
       { 
        byte* row = (byte*)bmpdata.Scan0 + (tempy * bmpdata.Stride); 
        for (int x = 0; x <= 800; x++) 
        { 
         Random rand = new Random(); 
         if (rand.Next(1,10) <= 7) 
         { 
          row[x * 4] = 255; 
         } 
         else 
         { 
          row[(x * 4) + 1] = 255; 
         } 
        } 
        tempy++; 
       } 
      } 
      bmp.UnlockBits(bmpdata); 
      canvas.Image = bmp; 
     } 
    } 
} 

Si vous avez besoin d'un complément d'information, laissez-moi savoir.

+1

Utilise 'LockBits' et' unsafe' une optimisation des performances? Il semble que vous pourriez le faire beaucoup plus facilement en utilisant ['Bitmap.SetPixel'] (http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.setpixel.aspx). –

+0

@Code Gray: La performance de Get/SetPixel est vraiment mauvaise pour faire de la manipulation d'image, c'est une méthode assez courante pour obtenir des performances acceptables pour la génération d'image à grande échelle où la couleur pixel par pixel est importante. –

+1

@Chris: Je suis au courant. J'ai demandé si cela avait été fait pour des raisons de performance ou parce qu'il ne connaissait pas l'alternative plus simple. J'ai fait les deux dans les applications, selon comment, comme vous le dites, "à grande échelle" cette manipulation d'image que je dois faire est. Si vous créez une image aléatoire une seule fois (comme dans votre événement 'Form.Load'), il n'est probablement pas nécessaire d'en extraire toutes les performances possibles. –

Répondre

11

déplacer cette ligne:

Random rand = new Random(); 

à la portée extérieure. Si vous les créez rapidement, beaucoup recevront le même temps (en raison de la précision de l'horloge) et généreront la même séquence "aléatoire". De plus, vous n'avez vraiment besoin que d'une instance aléatoire ...

private void Form1_Load(object sender, EventArgs e) 
{ 
    Bitmap bmp = new Bitmap(canvas.Image); 
    System.Drawing.Imaging.BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, 800, 600), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 

    Random rand = new Random(); 

    unsafe 
    { 
    // .... 
+0

Merci, je ne pense pas que cela affecte. Fonctionne parfaitement :). – GunnarJ

+0

Pourquoi sommes-nous (développeurs d'applications) destinés à créer des instances de départ aléatoires du tout alors? Pourquoi ne pas simplement déplacer cela vers la portée la plus externe de la bibliothèque standard elle-même ou quelque chose comme ça? Je me suis posé la question depuis environ 20 ans, depuis que j'ai rencontré ce modèle (dans QuickBasic pour DOS autant que je me souvienne). En fait, il y a un système global '/ dev/random' dans les OS Unix, pourquoi n'y a-t-il pas d'alternatives multiplateformes en C# et dans d'autres langages? – Ivan