我正在研究一个项目,该项目的一部分需要从颜色波长转换为RGB / HSL / HSV(其中的任何一个),所以我找到了此页面:http://www.physics.sfasu.edu/astro/color/spectra.html,我有点理解,但是我需要它作为Javascript函数。
我试图在Hue值和波长之间做一个简单的标度,但是感觉不对。问题是我发现的代码是在Fortran上完成的:
可见波的RGB值,Dan Bruton(astro@tamu.edu)
该程序可以在以下位置找到
http://www.physics.sfasu.edu/astro/color.html
最后更新于1996年2月20日。
该程序将创建频谱的ppm(便携式像素图)图像。
使用可见光的近似RGB值生成光谱
波长在380 nm至780 nm之间。
NetPBM的ppmtogif可用于转换ppm图像
到gif。红色,绿色和蓝色值(RGB)为
假定随波长线性变化(对于GAMMA = 1)。
NetPBM软件:ftp://ftp.cs.ubc.ca/ftp/archive/netpbm/
IMPLICIT REAL*8 (a-h,o-z)
REAL*8 CV(500,500,3)
图像信息-宽度,高度,深度,伽玛值
M=400
N=50
MAX=255
GAMMA=.80
将输出写入PPM文件
OPEN(UNIT=20,FILE='temp.ppm',STATUS='UNKNOWN')
FORMAT(A10)
WRITE(20,1) 'P3 '
WRITE(20,1) '# temp.ppm'
WRITE(20,*) M,N
WRITE(20,*) MAX
DO J=1,N
DO I=1,M
WAVELENGTH = WL
WL = 380. + REAL(I * 400. / M)
IF ((WL.GE.380.).AND.(WL.LE.440.)) THEN
R = -1.*(WL-440.)/(440.-380.)
G = 0.
B = 1.
ENDIF
IF ((WL.GE.440.).AND.(WL.LE.490.)) THEN
R = 0.
G = (WL-440.)/(490.-440.)
B = 1.
ENDIF
IF ((WL.GE.490.).AND.(WL.LE.510.)) THEN
R = 0.
G = 1.
B = -1.*(WL-510.)/(510.-490.)
ENDIF
IF ((WL.GE.510.).AND.(WL.LE.580.)) THEN
R = (WL-510.)/(580.-510.)
G = 1.
B = 0.
ENDIF
IF ((WL.GE.580.).AND.(WL.LE.645.)) THEN
R = 1.
G = -1.*(WL-645.)/(645.-580.)
B = 0.
ENDIF
IF ((WL.GE.645.).AND.(WL.LE.780.)) THEN
R = 1.
G = 0.
B = 0.
ENDIF
在视觉极限附近让强度SSS下降
IF (WL.GT.700.) THEN
SSS=.3+.7* (780.-WL)/(780.-700.)
ELSE IF (WL.LT.420.) THEN
SSS=.3+.7*(WL-380.)/(420.-380.)
ELSE
SSS=1.
ENDIF
GAMMA调整图像并将其写入阵列
CV(I,J,1)=(SSS*R)**GAMMA
CV(I,J,2)=(SSS*G)**GAMMA
CV(I,J,3)=(SSS*B)**GAMMA
ENDDO
ENDDO
将图像写入PPM文件
DO J=1,N
DO I=1,M
WL = 380. + REAL(I * 400. / M)
IR=INT(MAX*CV(I,J,1))
IG=INT(MAX*CV(I,J,2))
IB=INT(MAX*CV(I,J,3))
ITYPE=1 - PLAIN SPECTUM
ITYPE=2 - MARK SPECTRUM AT 100 nm INTEVALS
ITYPE=3 - HYDROGEN BALMER EMISSION SPECTRA
ITYPE=4 - HYDROGEN BALMER ABSORPTION SPECTRA
ITYPE=4
IF (ITYPE.EQ.2) THEN
DO K=400,700,100
IF ((ABS(INT(WL)-K).LT.1).AND.(J.LE.20)) THEN
IR=MAX
IG=MAX
IB=MAX
ENDIF
ENDDO
ELSEIF (ITYPE.EQ.3) THEN
IF ((ABS(WL-656.).GT.1.).and.(ABS(WL-486.).GT.1.).and.
* (ABS(WL-433.).GT.1.).and.(ABS(WL-410.).GT.1.)
* .AND.(ABS(WL-396.).GT.1.)) THEN
IR = 0
IG = 0
IB = 0
ENDIF
ELSEIF (ITYPE.EQ.4) THEN
IF ((ABS(WL-656.).LT.1.1).or.(ABS(WL-486.).LT.1.1).or.
* (ABS(WL-433.).LT.1.1).or.(ABS(WL-410.).LT.1.1)
* .or.(ABS(WL-396.).LT.1.1)) THEN
IR = 0
IG = 0
IB = 0
ENDIF
ENDIF
WRITE(20,*) IR, IG, IB
ENDDO
ENDDO
STOP
END
好吧,我什至从未听说过Fortran代码,所以我不知道它是如何工作的。有人可以帮我吗?
答案 0 :(得分:0)
如果知道的话,代码很容易阅读
.GT. = greater than
.GE. = greater than or equal to
.LT. = less than
.LE. = less than or equal to
1. = 1.000
1.1 = 1.1000
.1 = 0.1000
1.1.GT.1
与1.1 > 1
相同。进一步
!this is a comment
IMPLICIT REAL*8 (a-h,o-z) !variables starting with a,b,...h and o,..,z are double scalars
REAL*8 CV(500,500,3) ! this is an array of doubles
现在编写JavaScript。
答案 1 :(得分:0)
为了免除以后遇到的麻烦,这是转换为javascript的fortran代码:
const wl2rgb_pregamma = wl => {
if (wl >= 380 && wl < 440) {
const s = wl < 420 ? 0.3 + (0.7 * (wl - 380.0)) / (420.0 - 380.0) : 1.0;
return [(s * -1 * (wl - 440)) / (440 - 380), 0, s];
}
if (wl >= 440 && wl < 490) {
return [0, (wl - 440) / (490 - 440), 1];
}
if (wl >= 490 && wl < 510) {
return [0, 1, (-1 * (wl - 510)) / (510 - 490)];
}
if (wl >= 510 && wl < 580) {
return [(wl - 510) / (580 - 510), 1.0, 0.0];
}
if (wl >= 580 && wl < 645) {
return [1, (-1 * (wl - 645)) / (645 - 580), 0];
}
if (wl > 700) {
return [0.3 + (0.7 * (780 - wl)) / (780 - 700), 0, 0];
}
return [1, 0, 0];
};
const wl2rgb = wl => {
const gamma = 0.8;
const [r, g, b] = wl2rgb_pregamma(wl);
return [Math.pow(r, gamma), Math.pow(g, gamma), Math.pow(b, gamma)];
};
并在画布上尝试一下:
var ctx = canvas.getContext("2d");
for (var i = 380; i < 780; i++) {
const [r,g,b] = wl2rgb(i);
ctx.fillStyle = `rgb(${r*255}, ${g*255}, ${b*255})`;
ctx.fillRect(i - 380, 0, 1, 50);
}
答案 2 :(得分:0)
波长只能转换为色调。
公式为(如果 w = 波长和 h = 色调): h =(40/27)w 或 w =(27h)/ 40 。
图表位于https://www.desmos.com/calculator/8unmqnujio(色相为 x ,波长(以nm为单位)为 y 。
请注意,如果波长小于400或大于650,则可能需要在色相中添加360,直到波长大于400且小于650。
w = 0;
h = input('Hue: ');
def hw():
w = 27 * int(h);
w /= 40;
while w > 650 or w < 400:
hw()
print(w);
w = input('Wavelength in nm: ')
h = 40 / 27
h *= w