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}