怎么把Color Wavelength转换为RGB或HSL?

时间:2019-06-29 20:33:14

标签: fortran

我正在研究一个项目,该项目的一部分需要从颜色波长转换为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代码,所以我不知道它是如何工作的。有人可以帮我吗?

3 个答案:

答案 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.11.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