001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019/**
020 * A class for calulating the colors of the spectrum.
021 */
022public class Spectrum {
023
024        private static int adjust(float color, float factor, float gamma) {
025                if (color == 0.0)
026                        return 0;
027                return (int)Math.round(255 * Math.pow(color * factor, gamma));
028        }
029        
030        /**
031     * Convert a wavelength to an RGB value.
032         * @param wavelength wavelength in nanometres
033     * @return the RGB value
034         */
035        public static int wavelengthToRGB(float wavelength) {
036                float gamma = 0.80f;
037                float r, g, b, factor;
038
039                int w = (int)wavelength;
040                if (w < 380) {
041                        r = 0.0f;
042                        g = 0.0f;
043                        b = 0.0f;
044                } else if (w < 440) {
045                        r = -(wavelength - 440) / (440 - 380);
046                        g = 0.0f;
047                        b = 1.0f;
048                } else if (w < 490) {
049                        r = 0.0f;
050                        g = (wavelength - 440) / (490 - 440);
051                        b = 1.0f;
052                } else if (w < 510) {
053                        r = 0.0f;
054                        g = 1.0f;
055                        b = -(wavelength - 510) / (510 - 490);
056                } else if (w < 580) {
057                        r = (wavelength - 510) / (580 - 510);
058                        g = 1.0f;
059                        b = 0.0f;
060                } else if (w < 645) {
061                        r = 1.0f;
062                        g = -(wavelength - 645) / (645 - 580);
063                        b = 0.0f;
064                } else if (w <= 780) {
065                        r = 1.0f;
066                        g = 0.0f;
067                        b = 0.0f;
068                } else {
069                        r = 0.0f;
070                        g = 0.0f;
071                        b = 0.0f;
072                }
073
074                // Let the intensity fall off near the vision limits
075                if (380 <= w && w <= 419)
076                        factor = 0.3f + 0.7f*(wavelength - 380) / (420 - 380);
077                else if (420 <= w && w <= 700)
078                        factor = 1.0f;
079                else if (701 <= w && w <= 780)
080                        factor = 0.3f + 0.7f*(780 - wavelength) / (780 - 700);
081                else
082                        factor = 0.0f;
083
084                int ir = adjust(r, factor, gamma);
085                int ig = adjust(g, factor, gamma);
086                int ib = adjust(b, factor, gamma);
087
088                return 0xff000000 | (ir << 16) | (ig << 8) | ib;
089        }
090
091}