001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009package imagingbook.pub.color.image;
010
011/**
012 * Methods for converting between RGB and HLS color spaces.
013 * @author W. Burger
014 * @version 2013-12-25
015*/
016public class HlsConverter {
017
018        public float[] RGBtoHLS (int[] RGB) {
019                int R = RGB[0], G = RGB[1], B = RGB[2]; // R, G, B assumed to be in [0,255]
020                int cHi = Math.max(R, Math.max(G, B)); // highest component value
021                int cLo = Math.min(R, Math.min(G, B)); // lowest component value
022                int cRng = cHi - cLo;                               // component range
023                
024                // Calculate lightness L
025                float L = ((cHi + cLo) / 255f) / 2;
026                
027                // Calculate saturation S               
028                float S = 0;
029                if (0 < L && L < 1) {
030                        float d = (L <= 0.5f) ? L : (1 - L);
031                        S = 0.5f * (cRng / 255f) / d;
032                }
033                
034                // Calculate hue H (same as in HSV)
035                float H = 0;    
036                if (cHi > 0 && cRng > 0) {        // a color pixel
037                        float r = (float)(cHi - R) / cRng;
038                        float g = (float)(cHi - G) / cRng;
039                        float b = (float)(cHi - B) / cRng;
040                        float h;
041                        if (R == cHi)                      // R is largest component
042                                h = b - g;
043                        else if (G == cHi)                 // G is largest component
044                                h = r - b + 2.0f;
045                        else                               // B is largest component
046                                h = g - r + 4.0f;
047                        if (h < 0)
048                          h = h + 6;
049                        H = h / 6;
050                }
051                return new float[] {H, L, S};
052        }
053        
054        
055        public int[] HLStoRGB (float[] HLS) {
056                float H = HLS[0], L = HLS[1], S = HLS[2]; // H,L,S in [0,1]
057                float r = 0, g = 0, b = 0;      
058                if (L <= 0)                             // black
059                        r = g = b = 0;
060                else if (L >= 1)                // white
061                        r = g = b = 1;
062                else {
063                        float hh = (6 * H) % 6;
064                        int   c1 = (int) hh;
065                        float c2 = hh - c1;
066                        float d = (L <= 0.5f) ? (S * L) : (S * (1 - L));
067                        float w = L + d;
068                        float x = L - d;
069                        float y = w - (w - x) * c2;
070                        float z = x + (w - x) * c2;
071                        switch (c1) {
072                                case 0: r = w; g = z; b = x; break;
073                                case 1: r = y; g = w; b = x; break;
074                                case 2: r = x; g = w; b = z; break;
075                                case 3: r = x; g = y; b = w; break;
076                                case 4: r = z; g = x; b = w; break;
077                                case 5: r = w; g = x; b = y; break;
078                        }                       
079                }       // r, g, b in [0,1]
080                int R = Math.min(Math.round(r * 255), 255);
081                int G = Math.min(Math.round(g * 255), 255);
082                int B = Math.min(Math.round(b * 255), 255);
083                return new int[] {R, G, B};
084        }
085
086}