algorithm - hacer - longitud de onda de la luz visible
Valores RGB del espectro visible (8)
Creo que las respuestas no abordan un problema con la pregunta real.
Los valores RGB generalmente se derivan del espacio de color XYZ, que es la combinación de una función de observador humano estándar, una iluminación y la potencia relativa de la muestra en cada longitud de onda en el rango de ~ 360-830.
No estoy seguro de lo que está tratando de lograr aquí, pero sería posible calcular un valor RGB relativamente "preciso" para una muestra en la que cada banda discreta del espectro @ digamos 10nm estaba completamente saturada. La transformación se parece a este Espectro ->XYZ->RGB
. Visite el sitio de Bruce Lindbloom para las matemáticas. Desde el XYZ también puede calcular fácilmente valores de hue
, chroma
o colorimetric
como L*a*b*
.
Necesito un algoritmo o función para mapear cada longitud de onda del rango visible del espectro a sus valores RGB equivalentes. ¿Hay alguna relación estructural entre el sistema RGB y la longitud de onda de una luz? como esta imagen: alt text http://www1.appstate.edu/~kms/classes/psy3203/Color/spectrum5.gif lo siento si esto fue irrelevante: -]
El código de VBA se deriva de los "Valores aproximados de RGB para longitudes de onda visibles" por Dan Bruton ([email protected]). Enlace a su código Fortran original: http://www.physics.sfasu.edu/astro/color/spectra.html Programa Spectra: http://www.efg2.com/Lab/ScienceAndEngineering/Spectra.htm
Sub Wavelength_To_RGB()
''Purpose: Loop thru the wavelengths in the visible spectrum of light
'' and output the RGB values and colors to a worksheet.
'' Wavelength range: 380nm and 780nm
Dim j As Long, CellRow As Long
Dim R As Double, G As Double, B As Double
Dim iR As Integer, iG As Integer, iB As Integer
Dim WL As Double
Dim Gamma As Double
Dim SSS As Double
Gamma = 0.8
CellRow = 1
For j = 380 To 780
WL = j
Select Case WL
Case 380 To 440
R = -(WL - 440#) / (440# - 380#)
G = 0#
B = 1#
Case 440 To 490
R = 0#
G = ((WL - 440#) / (490# - 440#))
B = 1#
Case 490 To 510
R = 0#
G = 1#
B = (-(WL - 510#) / (510# - 490#))
Case 510 To 580
R = ((WL - 510#) / (580# - 510#))
G = 1#
B = 0#
Case 580 To 645
R = 1#
G = (-(WL - 645#) / (645# - 580#))
B = 0#
Case 645 To 780
R = 1#
G = 0#
B = 0#
Case Else
R = 0#
G = 0#
B = 0#
End Select
''LET THE INTENSITY SSS FALL OFF NEAR THE VISION LIMITS
If WL > 700 Then
SSS = 0.3 + 0.7 * (780# - WL) / (780# - 700#)
ElseIf WL < 420 Then
SSS = 0.3 + 0.7 * (WL - 380#) / (420# - 380#)
Else
SSS = 1#
End If
''GAMMA ADJUST
R = (SSS * R) ^ Gamma
G = (SSS * G) ^ Gamma
B = (SSS * B) ^ Gamma
''Multiply by 255
R = R * 255
G = G * 255
B = B * 255
''Change RGB data type from Double to Integer.
iR = CInt(R)
iG = CInt(G)
iB = CInt(B)
''Output to worksheet
Cells(CellRow, 1).Interior.Color = RGB(iR, iG, iB)
Cells(CellRow, 2) = WL
Cells(CellRow, 3) = "(" & iR & "," & iG & "," & iB & ")"
CellRow = CellRow + 1
Next j
End Sub
Esto es más de lo que tratan los perfiles de color . Básicamente, para un dispositivo determinado (escáner, cámara, monitor, impresora, etc.), un perfil de color indica qué colores reales de luz generará un conjunto específico de entradas.
También tenga en cuenta que para la mayoría de los dispositivos reales, solo maneja unas pocas longitudes de onda de luz discretas, y los colores intermedios se producen no produciendo esa longitud de onda directamente, sino mezclando cantidades variables de las dos longitudes de onda contiguas disponibles. Dado que percibimos el color de la misma manera, eso no es realmente un problema, pero dependiendo de por qué te importa, puede valer la pena saberlo de todos modos.
Sin un perfil de color (o información equivalente), no tiene la información necesaria para asignar el valor RGB a los colores. Un valor RGB de rojo puro normalmente se asignará al color más rojo que el dispositivo sea capaz de producir / detectar (y del mismo modo, azul puro al color azul), pero que "rojo" o "azul" puede variar (ampliamente) basado en el dispositivo.
Existe una relación entre la frecuencia y lo que se conoce como Hue, pero por razones complicadas de percepción, gama de monitores y calibración, lo mejor que se puede lograr fuera del costoso equipo de laboratorio es una aproximación aproximada.
Vea http://en.wikipedia.org/wiki/HSL_and_HSV para las matemáticas, y tenga en cuenta que tendrá que llegar a su mejor estimación para el mapeo de Hue ⇔ Frequency. Espero que este mapeo empírico sea cualquier cosa menos lineal.
Parcial "Valores aproximados de RGB para longitudes de onda visibles"
Crédito: Dan Bruton - Ciencia del color
Código FORTRAN original @ ( http://www.physics.sfasu.edu/astro/color/spectra.html )
Devolverá un espectro suave (continuo), pesado en el lado rojo.
w - longitud de onda, R, G y B - componentes de color
Ignorando las hojas simples gamma e intensidad:
if w >= 380 and w < 440:
R = -(w - 440.) / (440. - 380.)
G = 0.0
B = 1.0
elif w >= 440 and w < 490:
R = 0.0
G = (w - 440.) / (490. - 440.)
B = 1.0
elif w >= 490 and w < 510:
R = 0.0
G = 1.0
B = -(w - 510.) / (510. - 490.)
elif w >= 510 and w < 580:
R = (w - 510.) / (580. - 510.)
G = 1.0
B = 0.0
elif w >= 580 and w < 645:
R = 1.0
G = -(w - 645.) / (645. - 580.)
B = 0.0
elif w >= 645 and w <= 780:
R = 1.0
G = 0.0
B = 0.0
else:
R = 0.0
G = 0.0
B = 0.0
Patapom tiene casi razón: para cada longitud de onda calcula los valores de CIE XYZ, luego conviértalos a (digamos) sRGB usando fórmulas estándar (si tiene suerte, encontrará el código que puede usar para hacer esta conversión). Entonces, el paso clave es obtener los valores XYZ. Afortunadamente, para la luz de longitud de onda única esto es fácil: las funciones de coincidencia de color XYZ son simplemente tablas que enumeran los valores XYZ para una longitud de onda dada. Así que solo búscalo. Si tuvieras luz con un espectro más complicado, tal vez un cuerpo negro, entonces tendrías que promediar las respuestas XYZ por la cantidad de cada longitud de onda en la luz.
Recientemente descubrí que mis colores espectrales no funcionan correctamente porque se basaban en datos no lineales y modificados. Así que investigué poco y recopilé datos y descubrí que la mayoría de las imágenes de espectro que existen son incorrectas. Además, los rangos de color no coinciden entre sí, por lo que utilicé a partir de este punto solo datos de espectroscopia real linealizados como este
Aquí está la salida rectificada de la mía:
- el primer espectro es el mejor espectro renderizado que encontré, pero aún muy lejos del real
- el segundo es espectro linealizado de nuestro Sol tomado de la Tierra
- el último es mi salida de color actual
A continuación se muestran los gráficos RGB:
Esta es la combinación de ambos gráficos:
Ahora el código:
void spectral_color(double &r,double &g,double &b,double l) // RGB <0,1> <- lambda l <400,700> [nm]
{
double t; r=0.0; g=0.0; b=0.0;
if ((l>=400.0)&&(l<410.0)) { t=(l-400.0)/(410.0-400.0); r= +(0.33*t)-(0.20*t*t); }
else if ((l>=410.0)&&(l<475.0)) { t=(l-410.0)/(475.0-410.0); r=0.14 -(0.13*t*t); }
else if ((l>=545.0)&&(l<595.0)) { t=(l-545.0)/(595.0-545.0); r= +(1.98*t)-( t*t); }
else if ((l>=595.0)&&(l<650.0)) { t=(l-595.0)/(650.0-595.0); r=0.98+(0.06*t)-(0.40*t*t); }
else if ((l>=650.0)&&(l<700.0)) { t=(l-650.0)/(700.0-650.0); r=0.65-(0.84*t)+(0.20*t*t); }
if ((l>=415.0)&&(l<475.0)) { t=(l-415.0)/(475.0-415.0); g= +(0.80*t*t); }
else if ((l>=475.0)&&(l<590.0)) { t=(l-475.0)/(590.0-475.0); g=0.8 +(0.76*t)-(0.80*t*t); }
else if ((l>=585.0)&&(l<639.0)) { t=(l-585.0)/(639.0-585.0); g=0.84-(0.84*t) ; }
if ((l>=400.0)&&(l<475.0)) { t=(l-400.0)/(475.0-400.0); b= +(2.20*t)-(1.50*t*t); }
else if ((l>=475.0)&&(l<560.0)) { t=(l-475.0)/(560.0-475.0); b=0.7 -( t)+(0.30*t*t); }
}
//--------------------------------------------------------------------------
Dónde
-
l
es la longitud de onda en [nm] los valores utilizables sonl = < 400.0 , 700.0 >
-
r,g,b
devuelven componentes de color en el rango< 0.0 , 1.0 >
Si desea una coincidencia exacta, entonces la única solución es realizar una convolución de las funciones de concordancia de color x, y, z con sus valores espectrales para que finalmente obtenga una representación de color XYZ (independiente del dispositivo) que luego pueda convertir en (dispositivo -dependiente) RGB.
Esto se describe aquí: http://www.cs.rit.edu/~ncs/color/t_spectr.html
Puede encontrar la función de coincidencia de color x, y, z para convolución aquí: http://cvrl.ioo.ucl.ac.uk/cmfs.htm