2010-02-27 9 views
5

Sto provando a scrivere una funzione che mi consentirà di spostare in rosso o in blu una bitmap mantenendo la luminosità complessiva dell'immagine. Fondamentalmente, una bitmap completamente a rosso potrebbe avere la stessa luminosità dell'originale, ma essere completamente colorata di rosso (cioè i valori G e B sarebbero uguali per tutti i pixel). Lo stesso vale per la colorazione blu (ma con R e G uguali). Il grado di spostamento dello spettro deve variare da 0 a 1.Cambiare la tonalità di una bitmap mantenendo la luminosità complessiva

Grazie in anticipo.

+1

Sarebbe cambiare lo spazio colore da HSV e poi spostando la tonalità fare quello che stai cercando? –

+0

HSV avrebbe funzionato, ma non esattamente. – MusiGenesis

+1

Sembra che quello che vuoi sia un'immagine di "scala di grigi" in un colore particolare, è corretto? –

risposta

4

Ecco l'effetto che cercavo (scadente JPEG, sorry):

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

L'immagine al centro è l'originale, e le immagini laterali sono completamente spostata verso il rosso, in parte red- spostato, parzialmente spostato verso il blu e completamente spostato verso il blu, rispettivamente.

E qui è la funzione che produce questo effetto:

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

Eh? Perché qualcuno dovrebbe votare questa risposta? – MusiGenesis

+0

Potrei immaginare che questo codice sia molto lento poiché utilizza le operazioni per pixel. Vorrei esaminare la classe ColorMatrix come suggerito da Hans Passant. –

+0

@Will Kru: sì, il mio codice come postato sarebbe super-duper-lento grazie a 'GetPixel' e' SetPixel'. Tuttavia, ColorMatrix non funzionerà per me dato che i miei "Bitmap" non sono realmente bitmap .NET, sono array di 'int' 2D. La mia funzione inclusa utilizza bitmap .NET e GetPixel/SetPixel in modo che sia più utile per gli altri. – MusiGenesis

3

Si utilizzerà la classe ColorMatrix per questo. C'è un buon tutorial disponibile in this project.

Problemi correlati