A short Google search turned up some very informative sites and among them was the algorithm for nanometer to RGB conversion. What seems to be the oldest search result is a conversion algorithm written by Dan Bruton in FORTRAN. You may also be interested in the Color Science site from the same author. As I was a bit confused by the FORTRAN code, I also used what appears to be a translation of this code into C#. I know C# about as much as FORTRAN but the syntax was more understandable to me. My only contribution was a literal translation of the algorithm into Python.

The function takes a value in nanometers and returns a list of [R, G, B] values. Although a PIL putpixel function requires a tuple, I found a list more flexible in case you want to change the values e.g. according to measured intensity. So, here is the code:

def wav2RGB(wavelength):

w = int(wavelength)

# colour

if w >= 380 and w < 440:

R = -(w - 440.) / (440. - 350.)

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

# intensity correction

if w >= 380 and w < 420:

SSS = 0.3 + 0.7*(w - 350) / (420 - 350)

elif w >= 420 and w <= 700:

SSS = 1.0

elif w > 700 and w <= 780:

SSS = 0.3 + 0.7*(780 - w) / (780 - 700)

else:

SSS = 0.0

SSS *= 255

return [int(SSS*R), int(SSS*G), int(SSS*B)]

The output value's range is 0 -- 255. The code could use some streamlining, but even in this form it is fast enough for an occasional image.

Here is whole visible spectrum as made by this function:

... and a line spectrum of our decades-old mercury vapour lamp:

Finally, in case you want to read more about computer colour science:

Rendering spectra

Colour Rendering of Spectra