2010-02-27 2 views
5

Ich versuche eine Funktion zu schreiben, mit der ich eine Bitmap rotverschieben oder blau verschieben kann, während die Gesamthelligkeit des Bildes erhalten bleibt. Im Grunde würde eine vollständig rotverschobene Bitmap die gleiche Helligkeit wie das Original haben, aber gründlich rot getönt sein (d. H. Die G- und B-Werte wären für alle Pixel gleich). Gleiches gilt für Blau-Tönung (aber mit R und G gleich). Der Grad der Spektrumverschiebung muss von 0 bis 1 variieren.Ändern der Tönung einer Bitmap unter Beibehaltung der Gesamthelligkeit

Vielen Dank im Voraus.

+1

Würde die Änderung der Farbraum HSV und dann verschiebt sich der Farbton tun, was Sie suchen? –

+0

HSV würde irgendwie arbeiten, aber nicht genau. – MusiGenesis

+1

Klingt wie, was Sie wollen, ist ein "Graustufen" -Bild in einer bestimmten Farbe, ist das richtig? –

Antwort

4

ist der Effekt, den ich suchte (crappy JPEG, sorry):

alt text http://www.freeimagehosting.net/uploads/d15ff241ca.jpg

Das Bild in der Mitte ist das Original und die Seiten Bilder sind völlig rotverschobenen, teilweise rot- verschoben, teilweise blauverschoben bzw. vollständig blauverschoben.

Und hier ist die Funktion, die diesen Effekt erzeugt:

public void RedBlueShift(Bitmap bmp, double factor) 
{ 
    byte R = 0; 
    byte G = 0; 
    byte B = 0; 
    byte Rmax = 0; 
    byte Gmax = 0; 
    byte Bmax = 0; 
    double avg = 0; 
    double normal = 0; 
    if (factor > 1) 
    { 
     factor = 1; 
    } 
    else if (factor < -1) 
    { 
     factor = -1; 
    } 
    for (int x = 0; x < bmp.Width; x++) 
    { 
     for (int y = 0; y < bmp.Height; y++) 
     { 
      Color color = bmp.GetPixel(x, y); 
      R = color.R; 
      G = color.G; 
      B = color.B; 
      avg = (double)(R + G + B)/3; 
      normal = avg/255.0; // to preserve overall intensity 
      if (factor < 0) // red-tinted: 
      { 
       if (normal < .5) 
       { 
        Rmax = (byte)((normal/.5) * 255); 
        Gmax = 0; 
        Bmax = 0; 
       } 
       else 
       { 
        Rmax = 255; 
        Gmax = (byte)(((normal - .5) * 2) * 255); 
        Bmax = Gmax; 
       } 
       R = (byte)((double)R - ((double)(R - Rmax) * -factor)); 
       G = (byte)((double)G - ((double)(G - Gmax) * -factor)); 
       B = (byte)((double)B - ((double)(B - Bmax) * -factor)); 
      } 
      else if (factor > 0) // blue-tinted: 
      { 
       if (normal < .5) 
       { 
        Rmax = 0; 
        Gmax = 0; 
        Bmax = (byte)((normal/.5) * 255); 
       } 
       else 
       { 
        Rmax = (byte)(((normal - .5) * 2) * 255); 
        Gmax = Rmax; 
        Bmax = 255; 
       } 
       R = (byte)((double)R - ((double)(R - Rmax) * factor)); 
       G = (byte)((double)G - ((double)(G - Gmax) * factor)); 
       B = (byte)((double)B - ((double)(B - Bmax) * factor)); 
      } 
      color = Color.FromArgb(R, G, B); 
      bmp.SetPixel(x, y, color); 
     } 
    } 
} 
+0

Huh? Warum sollte jemand diese Antwort abstimmen? – MusiGenesis

+0

Ich könnte mir vorstellen, dass dieser Code sehr langsam ist, da er pro Pixel Operationen verwendet. Ich würde in die ColorMatrix-Klasse schauen, wie Hans Passant vorgeschlagen hat. –

+0

@Will Kru: Ja, mein Code wie gepostet wäre super-duper-langsam dank 'GetPixel' und' SetPixel'. Allerdings funktioniert ColorMatrix nicht für mich, da meine "Bitmaps" nicht wirklich .NET Bitmaps sind - sie sind 2D 'int' Arrays. Meine enthaltene Funktion verwendet .NET Bitmaps und GetPixel/SetPixel, so dass es für andere nützlich ist. – MusiGenesis

3

Sie würden die ColorMatrix-Klasse dafür verwenden. Es gibt ein gutes Tutorial in this project. Hier