Module:Sandbox/AlexNB/nmColor

local p = {}

local redvalue = 0
local greenvalue = 0
local bluevalue = 0
 
local function nm2RGB(wavelength, IFcorrect)
-- code based on an algorithm from Dan Bruton's Color Science Page: http://www.physics.sfasu.edu/astro/color/spectra.html
-- calculating RGB color components
    if (wavelength >= 380) and (wavelength < 440) then
        redvalue = (440 - wavelength) / 90
        greenvalue = 0
        bluevalue = 1
    elseif (wavelength >= 440) and (wavelength < 490) then
        redvalue = 0
        greenvalue = (wavelength - 440) / 50
        bluevalue = 1
    elseif (wavelength >= 490) and (wavelength < 510) then
        redvalue = 0
        greenvalue = 1
        bluevalue = (510 - wavelength) / 20
    elseif (wavelength >= 510) and (wavelength < 580) then
        redvalue = (wavelength - 510) / 70
        greenvalue = 1
        bluevalue = 0
    elseif (wavelength >= 580) and (wavelength < 645) then
        redvalue = 1
        greenvalue = (645 - wavelength) / 65
        bluevalue = 0
    elseif (wavelength >= 645) and (wavelength <= 780) then
        redvalue = 1
        greenvalue = 0
        bluevalue = 0
    end
-- calculating intensity correction factor
    if IFcorrect then
    local intensityfactor = 0
    if (wavelength >= 380) and (wavelength < 420) then
        intensityfactor = 0.3 + 0.7*(wavelength - 350) / 70
    elseif (wavelength >= 420) and (wavelength <= 700) then
        intensityfactor = 1
    elseif (wavelength > 700) and (wavelength <= 780) then
        intensityfactor = 0.3 + 0.7*(780 - wavelength) / 80
    end
    redvalue = redvalue * intensityfactor
    greenvalue = greenvalue * intensityfactor
    bluevalue = bluevalue * intensityfactor
    end
end

function p.emission(frame)
-- this function returns the string "#RRGGBB" with approximate RGB value for a wavelength passed as a first argument
    local wavelength = tonumber(frame.args[1])
    nm2RGB(wavelength, true)
    local result='#' .. string.format("%.2X%.2X%.2X", 255*redvalue, 255*greenvalue, 255*bluevalue) 
    return result
end

local function absorption_to_visible(wavelength_abs)
-- code based on a color wheel drawn at: http://www2.chemistry.msu.edu/faculty/reusch/virttxtjml/spectrpy/uv-vis/spectrum.htm
   local wavelength_vis
   local minVioletIndigo = 380 -- originally, it was 400
   local maxVioletIndigo = 430
   local widthVioletIndigo = maxVioletIndigo - minVioletIndigo
   local minBlue = 430
   local maxBlue = 490
   local widthBlue = maxBlue - minBlue
   local minGreen = 490
   local maxGreen = 560
   local widthGreen = maxGreen - minGreen
   local minYellow = 560
   local maxYellow = 580
   local widthYellow = maxYellow - minYellow
   local minOrange = 580
   local maxOrange = 650 -- originally, it was 620
   local widthOrange = maxOrange - minOrange
   local minRed = 650 -- originally, it was 620
   local maxRed = 780 -- originally, it was 800
   local widthRed = maxRed - minRed
   if (wavelength_abs>=minVioletIndigo) and (wavelength_abs<=maxVioletIndigo) then
      wavelength_vis = (wavelength_abs - minVioletIndigo)*widthYellow/widthVioletIndigo + minYellow
   elseif (wavelength_abs>minBlue) and (wavelength_abs<=maxBlue) then
      wavelength_vis = (wavelength_abs - minBlue)*widthOrange/widthBlue + minOrange
   elseif (wavelength_abs>minGreen) and (wavelength_abs<=maxGreen) then
      wavelength_vis = (wavelength_abs - minGreen)*widthRed/widthGreen + minRed
   elseif (wavelength_abs>minYellow) and (wavelength_abs<=maxYellow) then
      wavelength_vis = (wavelength_abs - minYellow)*widthVioletIndigo/widthYellow + minVioletIndigo
   elseif (wavelength_abs>minOrange) and (wavelength_abs<=maxOrange) then
      wavelength_vis = (wavelength_abs - minOrange)*widthBlue/widthOrange + minBlue
   elseif (wavelength_abs>minRed) and (wavelength_abs<=maxRed) then
      wavelength_vis = (wavelength_abs - minRed)*widthGreen/(widthRed + 20) + minGreen
-- one of the "corrected" versions: wavelength_vis = (wavelength_abs - minRed - 30)*widthGreen/widthRed + minGreen
   end
   return wavelength_vis
end

local minAntiMagenta = 550
local maxAntiMagenta = 570

local function process_magenta(wavelength_abs)
   local redvalue_RED
   local bluevalue_RED
   local greenvalue_RED
   local redvalue_BLUE
   local bluevalue_BLUE
   local greenvalue_BLUE
   local widthAntiMagenta = maxAntiMagenta - minAntiMagenta
   local bias_BLUE = (wavelength_abs - minAntiMagenta)/widthAntiMagenta
   local bias_RED = (maxAntiMagenta - wavelength_abs)/widthAntiMagenta
   nm2RGB(700, false)
   redvalue_RED = redvalue*bias_RED
   bluevalue_RED = bluevalue*bias_RED
   greenvalue_RED = greenvalue*bias_RED
   nm2RGB(400, false)
   redvalue_BLUE = redvalue*bias_BLUE
   bluevalue_BLUE = bluevalue*bias_BLUE
   greenvalue_BLUE = greenvalue*bias_BLUE
   redvalue = 0.6+ 0.4*(redvalue_RED + redvalue_BLUE)
   bluevalue = 0.7 + 0.3*(bluevalue_RED + bluevalue_BLUE)
   greenvalue = greenvalue_RED + greenvalue_BLUE
end

function p.absorption(frame)
-- this function returns the string "#RRGGBB" with approximate RGB value for a complementary color (reflection) to a color, defined as a wavelength passed as a first argument
    local wavelength = tonumber(frame.args[1])
-- adding magentas to smoothen red->blue transition. Trying 540..570 nm
    if (wavelength>=minAntiMagenta) and (wavelength<=maxAntiMagenta) then
       process_magenta(wavelength)
       else nm2RGB(absorption_to_visible(wavelength), false)
    end
    local result='#' .. string.format("%.2X%.2X%.2X", 255*redvalue, 255*greenvalue, 255*bluevalue) 
    return result
end


return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.