我需要一个算法或函数来将可见光谱的每个波长映射到对应的RGB值。 RGB系统和光的波长之间是否存在结构关系?像这张图片一样: ![alt text](https://istack.dev59.com/fJ0uO.gif)
(来源:kms at www1.appstate.edu)
![alt text](https://istack.dev59.com/fJ0uO.gif)
(来源:kms at www1.appstate.edu)
如果这是无关的,我很抱歉 :-]
如果这是无关的,我很抱歉 :-]
VBA代码源自Dan Bruton(astro@tamu.edu)的“可见波长的近似RGB值”。 他原始Fortran代码的链接:http://www.physics.sfasu.edu/astro/color/spectra.html 光谱程序: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
一个基于流行答案的可运行示例:
function spectrogram() {
var svgns = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(svgns, 'svg');
var defs = document.createElementNS(svgns, 'defs');
var gradient = document.createElementNS(svgns, 'linearGradient');
var rect = document.createElementNS(svgns, 'rect');
var stops = spectral_gradient( 400, 700, 3 );
for( var i = 0, length = stops.length; i < length; i++ ) {
var stop = document.createElementNS(svgns, 'stop');
stop.setAttribute('offset', stops[i].offset);
stop.setAttribute('stop-color', stops[i].color);
gradient.appendChild(stop);
}
// Apply the <lineargradient> to <defs>
gradient.id = 'Gradient';
gradient.setAttribute('x1', '0');
gradient.setAttribute('x2', '1');
gradient.setAttribute('y1', '0');
gradient.setAttribute('y2', '0');
defs.appendChild(gradient);
// Setup the <rect> element.
rect.setAttribute('fill', 'url(#Gradient)');
rect.setAttribute('width', '100%');
rect.setAttribute('height', '100%');
// Assign an id, classname, width and height
svg.setAttribute('width', '100%');
svg.setAttribute('height', '100%')
svg.setAttribute('version', '1.1');
svg.setAttribute('xmlns', svgns);
// Add the <defs> and <rect> elements to <svg>
svg.appendChild(defs);
svg.appendChild(rect);
// Add the <svg> element to <body>
document.body.appendChild(svg);
}
function spectral_gradient( wl1, wl2, steps ) {
var stops = [];
var delta = Math.abs( wl2 - wl1 );
for( var wl = wl1; wl <= wl2; wl += steps ) {
var offset = Math.round( (1 - Math.abs( wl2 - wl ) / delta) * 100 );
stops.push({
"color": wavelength2hex( wl ),
"offset": offset + "%"
});
}
return stops;
}
function wavelength2hex( l ) {
var wl = wavelength2rgb( l );
var rgb = {
"r": Math.round( wl.r * 255 ),
"g": Math.round( wl.g * 255 ),
"b": Math.round( wl.b * 255 )
};
return rgb2hex( rgb.r, rgb.g, rgb.b );
}
function wavelength2rgb( l ) {
var t;
var r = 0.0;
var g = 0.0;
var 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);
}
return {"r": r, "g": g, "b": b};
}
function rgb2hex( r, g, b ) {
return "#" + hex( r ) + hex( g ) + hex( b );
}
function hex( v ) {
return v.toString( 16 ).padStart( 2, "0" );
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="js/spectrum.js"></script>
</head>
<body onload="spectrogram();">
</body>
</html>