2010-02-27 7 views
5

Estoy intentando escribir una función que me permita desplazar hacia el rojo o hacia el azul un mapa de bits mientras se preserva el brillo general de la imagen. Básicamente, un mapa de bits totalmente desplazado en rojo tendría el mismo brillo que el original pero se tiñería completamente de rojo (es decir, los valores G y B serían iguales para todos los píxeles). Lo mismo para el teñido azul (pero con R y G iguales). El grado de desplazamiento del espectro debe variar de 0 a 1.Cambiar el tinte de un mapa de bits mientras se conserva el brillo general

Gracias de antemano.

+1

¿Podría cambiar el espacio de color HSV y luego cambiando el matiz hacer lo que estás buscando? –

+0

HSV funcionaría, pero no exactamente. – MusiGenesis

+1

Parece que lo que quieres es una imagen en "escala de grises" en un color en particular, ¿es correcto? –

Respuesta

4

Aquí es el efecto que estaba buscando (JPEG malo, lo siento):

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

La imagen en el medio es el original, y las imágenes laterales son totalmente desplazada al rojo, parcialmente red- desplazado, parcialmente desplazado en azul y totalmente desplazado en azul, respectivamente.

Y aquí es la función que produce este efecto:

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? ¿Por qué alguien podría rechazar esta respuesta? – MusiGenesis

+0

Podría imaginarme que este código es muy lento ya que usa operaciones por píxel. Miraría la clase ColorMatrix como sugirió Hans Passant. –

+0

@Will Kru: sí, mi código como se publicó sería súper lento debido a 'GetPixel' y' SetPixel'. Sin embargo, ColorMatrix no funcionará para mí, ya que mis "Bitmaps" no son realmente mapas de bits .NET, son matrices 2D 'int'. Mi función incluida usa .NET bitmaps y GetPixel/SetPixel para que sea más útil para otros. – MusiGenesis

3

Utilizaría la clase ColorMatrix para esto. Hay un buen tutorial disponible en this project.

Cuestiones relacionadas