Dado un valor RGB, ¿cómo creo un tinte (o sombra)?

124

Dado un valor RGB, como 168, 0, 255, ¿cómo creo tintes (lo hago más claro) y sombras (lo hago más oscuro) del color?

DenaliHardtail
fuente

Respuestas:

153

Entre varias opciones para sombrear y teñir:

  • Para tonos, multiplique cada componente por 1/4, 1/2, 3/4, etc., de su valor anterior. Cuanto menor sea el factor, más oscuro será el tono.

  • Para tintes, calcule (255 - valor anterior), multiplique eso por 1/4, 1/2, 3/4, etc. (cuanto mayor sea el factor, más claro será el tinte), y sume eso al valor anterior (asumiendo cada .component es un número entero de 8 bits).

Tenga en cuenta que las manipulaciones de color (como tintes y otros sombreados) deben realizarse en RGB lineal . Sin embargo, es poco probable que los colores RGB especificados en documentos o codificados en imágenes y video estén en RGB lineal, en cuyo caso es necesario aplicar la denominada función de transferencia inversa a cada uno de los componentes del color RGB. Esta función varía con el espacio de color RGB. Por ejemplo, en el espacio de color sRGB (que se puede asumir si se desconoce el espacio de color RGB), esta función es aproximadamente equivalente a elevar cada componente de color sRGB (que va de 0 a 1) a una potencia de 2,2. (Tenga en cuenta que "RGB lineal" no es un espacio de color RGB).

Consulte también el comentario de Violet Giraffe sobre la "corrección de gamma".

Peter O.
fuente
20
Probé esto y funcionó muy bien. Pensé que sería útil escribir ejemplos de las fórmulas. Original (r, g, b); De sombra (RS, GS, BS): rs = r * 0.25, gs = g * 0.25, bs = b * 0.25(que es un tono bastante oscuro); Tint (rt, gt, bt): rt = r + (0.25 * (255 - r)), gt = g + (0.25 * (255 - g)), bt = b + (0.25 * (255 - b))(que es un tinte bastante luz). Lo hice como parte de una variedad genial que creó muchos tonos y funcionó muy bien. Espero que ayude. Gracias Peter.
Thomas
1
Ha cometido un error. Es al revés.
Francesco Menzani
¿Está seguro de que esta manipulación no debe tener en cuenta la corrección de gamma?
Jirafa violeta
1
@VioletGiraffe: Tienes un buen punto con la corrección de gamma. Ver mi edición. (Esto reemplaza un comentario mío eliminado de hace 22 horas.)
Peter O.26 de
97

Algunas definiciones

  • Un tono se produce "oscureciendo" un tono o "agregando negro"
  • Un tinte se produce al "aclarar" un tono o "agregar blanco"

Creando un tinte o un tono

Dependiendo de su modelo de color, existen diferentes métodos para crear un color más oscuro (sombreado) o más claro (teñido):

  • RGB:

    • A la sombra:

      newR = currentR * (1 - shade_factor)
      newG = currentG * (1 - shade_factor)
      newB = currentB * (1 - shade_factor)
      
    • Para teñir:

      newR = currentR + (255 - currentR) * tint_factor
      newG = currentG + (255 - currentG) * tint_factor
      newB = currentB + (255 - currentB) * tint_factor
      
    • De manera más general, el color que resulta en superponer un color RGB(currentR,currentG,currentB)con un color RGBA(aR,aG,aB,alpha)es:

      newR = currentR + (aR - currentR) * alpha
      newG = currentG + (aG - currentG) * alpha
      newB = currentB + (aB - currentB) * alpha
      

    donde (aR,aG,aB) = black = (0,0,0)sombrear y (aR,aG,aB) = white = (255,255,255)teñir

  • HSVo bien HSB:

    • Para sombrear: bajar Value/ Brightnesso aumentar elSaturation
    • Para teñir: bajar Saturationo aumentar Value/Brightness
  • HSL:
    • Para sombrear: baje el Lightness
    • Para teñir: aumente el Lightness

Existen fórmulas para convertir de un modelo de color a otro. Según su pregunta inicial, si está dentro RGBy desea usar el HSVmodelo para sombrear, por ejemplo, puede simplemente convertir a HSV, hacer el sombreado y volver a convertir a RGB. Las fórmulas para convertir no son triviales, pero se pueden encontrar en Internet. Dependiendo de su idioma, también podría estar disponible como función principal:

Comparando los modelos

  • RGB tiene la ventaja de ser realmente simple de implementar, pero:
    • solo puedes sombrear o teñir tu color relativamente
    • no tienes idea si tu color ya está teñido o sombreado
  • HSVo HSBes algo complejo porque necesitas jugar con dos parámetros para obtener lo que quieres ( Saturation& Value/Brightness )
  • HSL es lo mejor desde mi punto de vista:
    • compatible con CSS3 (para aplicaciones web)
    • simple y preciso:
      • 50% significa un tono inalterado
      • >50% significa que el tono es más claro (tinte)
      • <50% significa que el tono es más oscuro (sombra)
    • dado un color, puede determinar si ya está teñido o sombreado
    • puede teñir o matizar un color relativa o absolutamente (simplemente reemplazando la Lightnesspieza)

JBE
fuente
1
Yo creo aquí "Un tono se produce" oscureciendo "un tono" , por tono, te refieres al color. Porque si habla de tono como en HSL / HSV, cambiarlo producirá un color diferente, no un tono / tinte. El tono (0-360 °), por sí solo, no puede oscurecerse / aclararse. Para dar un tono / tinte de color, habría que modificar los valores SL / SV. Esta definición podría inducir a error a alguien a pensar que cambiar el tono producirá un color más oscuro / más claro.
akinuri
La versión de sombra solo funciona para el rango de colores a partir de 0. Agregue la mitad de su rango de color al valor del canal de color, luego haga los cálculos y luego reste ese rango nuevamente. Si su color está firmado y puede hacer el cálculo sin destruir algo debido al desbordamiento, esto funciona según lo previsto.
t0b4cc0
3

Actualmente estoy experimentando con lienzos y píxeles ... Estoy descubriendo que esta lógica me funciona mejor.

  1. Use esto para calcular el gris-ness (luma?)
  2. pero con el valor existente y el nuevo valor de 'tinte'
  3. calcular la diferencia (encontré que no necesitaba multiplicar)
  4. agregar para compensar el valor de 'tinte'

    var grey =  (r + g + b) / 3;    
    var grey2 = (new_r + new_g + new_b) / 3;
    
    var dr =  grey - grey2 * 1;    
    var dg =  grey - grey2 * 1    
    var db =  grey - grey2 * 1;  
    
    tint_r = new_r + dr;    
    tint_g = new_g + dg;   
    tint_b = new_b _ db;
    

o algo así...

Blair
fuente