Grafiker-Gurus gerufen! 🙂
Folgendes: ich habe ein Bild mit z.B. blauem Hintergrund. Jetzt will ich das Bitmap so "maskieren", dass alles, was nicht blau (nicht Hintergrund) ist, auf schwarz gesetzt wird.
hat jemand eine klevere Idee, als Pixel für Pixel, die Farbe zu ändern?
Wenn b dein Bitmap ist:
using System.Drawing;
//...
Color c = b.GetPixel(50, 50);
if (c != Color.Blue)
b.SetPixel(50, 50, Color.Black);
Musst halt nur über sämtliche Pixel iterieren.
Windows Server Advanced Power Management
Erweitertes Energie-Management unter Windows
Gibt es keine Eigenschaft namens Transparent Color oder so, die man dann verändern kann?
ich habe jetzt in einer schleife gemacht und zwar so:
...
private Bitmap CreateMask(Image originalImage)
{
int mcol = Color.Magenta.ToArgb();
Bitmap bmp = new Bitmap(originalImage);
Rectangle rect = new Rectangle(new Point(0, 0), bmp.Size);
BitmapData bmpdata = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
unsafe
{
uint* ptr = (uint*)bmpdata.Scan0;
for (int i = 0, j = bmp.Width * bmp.Height; i < j; i++)
{
if (mcol != (int)*ptr)
*ptr = 0;
ptr++;
}
}
bmp.UnlockBits(bmpdata);
return bmp;
}
warum unsafe? damit es schneller läuft.
Trotzdem etwas umständlich, oder?
Läuft das von der Performance her wirklich so viel besser?
Windows Server Advanced Power Management
Erweitertes Energie-Management unter Windows
Oh, ja. Bis zu 27 mal schneller ist keine Seltenheit:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp11152001.asp
Gernot Melichar
Original von exec
Läuft das von der Performance her wirklich so viel besser?
jeder kann sich selbst überzeugen
diese test anvendung konvertiert ein Farb-Bild in Graustuffen
.NET 2.0 Beta 2
umständlich. - ja, leider gibt GDI+ nicht mehr her.
Gegenüber getPixel ist die angegebene Methode ungleich schneller(getpixel ist so ziemlich das langsamste was möglich ist). Optimierungsmöglichkeiten in C# sind nur bei Kenntnis der Farbtiefe der Bitmap möglich. Ansonsten(für weitere Optimierungen) bleibt noch der Weg über C++ & GDI(bei sehr guten Kenntnissen, lässt sich die C#- Methode noch etwas optimieren ca 10-15% / ziemlicher Aufwand).
Damit sich die "Umständlichkeit" in Grenzen hält, lohnt es sich die Methode in einer Helperklasse zu kapseln(Wiederverwendbarkeit)
Ich hätte eine Idee wie man das Problem mit dem System.Drawing.Imaging-Namespace lösen kann. Ist nicht ganz ausgegoren, wahrscheinlich geht es anders noch besser.
Drei Arbeitsschritte, man erstellt eine ColorMatrix, die alle Farben, ausser den Blau-Kanal auf 0 runtersetzt. Dann ändert man die Hintergrundfarbe von blau in grün und setzt auch den Blau-Kanal auf 0 runter. Übrig bleibt eine schwarze Sillouette mit grünem Hintergrund.
Msdn: GDI+ Recoloring
Die ColorMatrix ist ja eine 5x5-Matrix, die Farbtransformationen im ARGB(W)-Raum ausführt. Gibt es vielleicht eine Matrix, die das gleiche Ergebnis in einem Schritt erreicht?
Gruss
Pulpapex
hm..
ich habe jetzt nach Pulpapex-"Anleitung" folgendes zusammen gestellt:
float[][] cl = new float[][]{
new float[]{255, 0, 0, 0, 1},
new float[]{255, 0, 0, 255, 1},
new float[]{255, 0, 255, 0, 1},
new float[]{255, 0, 0, 0, 1},
new float[]{255, 0, 0, 0, 1}};
ColorMatrix cmx = new ColorMatrix(cl);
ImageAttributes iat = new ImageAttributes();
iat.SetColorMatrix(cmx);
Bitmap bmp = new Bitmap(16, 16);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(pictureBox1.Image, new Rectangle(0, 0, 16, 16), 0, 0, 16, 16, GraphicsUnit.Pixel, iat);
ColorMap[] cmp = new ColorMap[2]{new ColorMap(),new ColorMap()};
cmp[0].OldColor = Color.Magenta;
cmp[0].NewColor = Color.Black;
cmp[1].OldColor = Color.FromArgb(0, 0, 0, 0);
cmp[1].NewColor = Color.Magenta;
ia = new ImageAttributes();
ia.SetRemapTable(cmp);
g.DrawImage(bmp, new Rectangle(0, 0, 16, 16), 0, 0, 16, 16, GraphicsUnit.Pixel, iat);
pictureBox1.Image = bmp;
als Hintergrundfarbe wird Magenta verwendet.
das finde ich noch umständlicher als mit unsafe. ob diese methode schneller ist als mit pointer? hat jemand lust das zu testen?
Ich zeichne ein Grafikobjekt auf eine Bitmap, doch leider ist der Hintergrund des Bitmaps standardmäßig blau - komischer Weise. Habe schon (meine Bitmap = bmp) bmp.MakeTransparent() und
img = Image.FromHbitmap(bmp.GetHbitmap(Color.White));
ausprobiert. Wenn ich bei GetHbitmap(Color.Green) einstelle wird der Hintergrund sogar Schwarz. Was kann ich tun damit der Hintergrund wirklich Weiss ist?
glücklicherweise gibts ja aber im Unterforum Komponenten noch die Klasse RoBitmap, deren Methoden Get-/SetPixel die von Bitmap von Haus aus um Faktor 800 (Angaben des Autors) schlagen, wodurch das Iterieren doch wieder interessant wird...
Hallo!
Ich habe die RoBitmap-Klasse selbst mal ausprobiert, sie ist wirklich um einiges schneller.
Nobody is perfect. I'm sad, i'm not nobody 🙁
So habe die Antwort woanders gefunden, die Lösung für mein obiges Problem lautet Graphics.Clear()...
Indirekt Danke an Herbivore, es stand in einem anderen Thread...