2010-02-27 13 views
5

Próbuję napisać funkcję, która pozwoli mi przesunąć czerwoną lub niebieską zmianę mapy bitowej przy zachowaniu całkowitej jasności obrazu. Zasadniczo, w pełni przesunięta na czerwono bitmapa będzie miała taką samą jasność jak oryginał, ale będzie całkowicie zabarwiona na czerwono (to znaczy wartości G i B będą równe dla wszystkich pikseli). To samo dotyczy zabarwienia na niebiesko (ale z równymi R i G). Stopień przesunięcia widma musi wynosić od 0 do 1.Zmiana odcienia mapy bitowej przy zachowaniu całkowitej jasności

Z góry dziękuję.

+1

Czy zmieniającą się przestrzeń kolorów HSV, a następnie przesunięcie odcień zrobić to, czego szukasz? –

+0

HSV byłby rodzajem pracy, ale nie do końca. – MusiGenesis

+1

Wygląda na to, że to, co chcesz, to obraz w skali szarości w określonym kolorze, czy to prawda? –

Odpowiedz

4

Oto efekt szukałem (brzydko JPEG, przepraszam):

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

Obraz w środku jest oryginalny, a obrazy boczne są całkowicie przesunięte ku czerwieni, częściowo red- przesunięte, częściowo przesunięte na niebiesko i odpowiednio przesunięte na niebiesko.

I tu jest funkcja, która wywołuje ten efekt:

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? Dlaczego ktoś miałby głosować na tę odpowiedź? – MusiGenesis

+0

Mogę sobie wyobrazić, że ten kod jest bardzo wolny, ponieważ używa operacji na pikselach. Zajrzałbym do klasy ColorMatrix, jak zasugerował Hans Passant. –

+0

@Will Kru: Tak, mój kod jako wysłany byłby super-duper-slow dzięki 'GetPixel' i' SetPixel'. Jednak ColorMatrix nie będzie dla mnie działał, ponieważ moje "bitmapy" nie są mapami bitowymi .NET - są to tablice 2D 'int'. Moja dołączona funkcja wykorzystuje mapy bitowe .NET i GetPixel/SetPixel, dzięki czemu jest bardziej przydatna dla innych. – MusiGenesis

3

Do tego celu należy użyć klasy ColorMatrix. W this project dostępny jest dobry samouczek.

Powiązane problemy