2010-02-10 13 views
0

J'ai deux bitmaps 8bpp. Je veux faire un ET bit à bit de l'un à l'autre, mais je ne vois aucune façon évidente de le faire dans .NET. Est-il possible de le faire sans utiliser les méthodes non-NET? Merci!Opération bitmap booléenne dans .NET?

+0

Est-ce que 8bpp est indexé? Cela signifie qu'il y a 256 couleurs, mais/which/they sont spécifiées dans une table distincte dans laquelle chaque pixel est indexé. .NET appelle ceci Format8bppIndexed. –

+0

Non, ce n'est qu'un canal extrait d'une image plus profonde. – user20493

+0

Hmm, je ne suis pas sûr que ce soit l'une des valeurs PixelFormat supportées. –

Répondre

3

Je pense que vous êtes à la recherche Bitmap.LockBits.

+0

Je peux devoir recourir à ceci si je ne peux pas trouver une méthode de bibliothèque qui le fait. Malheureusement, la boucle en C# s'exécutera probablement plus lentement. – user20493

1

Si les performances ne sont pas importantes, utilisez Bitmap.GetPixel et Bitmap.SetPixel

+0

Malheureusement, ceux-ci sont très lents dans .NET. – user20493

3

Vous pouvez essayer de convertir le bitmap à un tableau d'octets et boucle à travers les octets anding-les ensemble

Edit: a publié un test de temps sur l'idée de la boucle:

Exemple de code:

DateTime StartTime = DateTime.Now; 
Image Image1 = Image.FromFile("C:\\Image1.bmp"); 
Image Image2 = Image.FromFile("C:\\Image2.bmp"); 
DateTime AfterLoad = DateTime.Now; 
MemoryStream S = new MemoryStream(); 
Image1.Save(S, System.Drawing.Imaging.ImageFormat.Bmp); 
Byte[] I1 = S.ToArray(); 
Image2.Save(S, System.Drawing.Imaging.ImageFormat.Bmp); 
Byte[] I2 = S.ToArray(); 
DateTime AfterConvert = DateTime.Now; 
DateTime AfterLoop = DateTime.Now; 
if (I1.Length == I2.Length) 
{ 
    Byte[] I3 = new Byte[I1.Length]; 
    for (int i = 0; i < I1.Length; i++) 
     I3[i] = Convert.ToByte(I1[i] & I2[i]); 
    AfterLoop = DateTime.Now; 
    FileStream F = new FileStream("C:\\Users\\jamesb\\desktop\\Image3.bmp", FileMode.OpenOrCreate); 
    F.Write(I3, 0, I3.Length); 
    F.Close(); 
} 
DateTime Finished = DateTime.Now; 
MessageBox.Show("Load Time: " + (AfterLoad - StartTime).TotalMilliseconds.ToString() + " ms" + "\r\n" + 
       "Convert Time: " + (AfterConvert - AfterLoad).TotalMilliseconds.ToString() + " ms"+ "\r\n" + 
       "Loop Time: " + (AfterLoop - AfterConvert).TotalMilliseconds.ToString() + " ms"+ "\r\n" + 
       "Save Time: " + (Finished - AfterLoop).TotalMilliseconds.ToString() + " ms"+ "\r\n" + 
       "Total Time: " + (Finished - StartTime).TotalMilliseconds.ToString() + " ms"); 

avec les résultats suivants:

Load Time: 30.003 ms 
Convert Time: 94.0094 ms 
Loop Time: 128.0128 ms 
Save Time: 177.0177 ms 
Total Time: 429.0429 ms 

Les images « Image1 » et « Image2 » étaient 4000 x 2250 (à partir d'un appareil photo numérique converti en 8 bits bmp)

+0

Une approche intéressante. Malheureusement, la mise en boucle est lente en C#. – user20493

1

Vous pouvez utiliser la fonction « BitBlt », dans lequel vous pouvez et la source et la destination (SRCAND), la signature pinvoke est here.

Voici un article sur Codeproject qui utilise un wrapper BitBlt here.

Espérons que cela aide, Cordialement, Tom.

+0

Il a demandé de le faire sans utiliser de méthodes non-NET. –

+0

@Matthew ... malheureusement ... il ya une dépendance sur pinvoke pour faire des choses que .NET ne peut pas faire .... – t0mm13b

+0

Il n'y a aucune raison .NET ne peut pas faire cela. –