# -*- coding: utf-8 -*-
# =============================================================================
# Copyright (c) 2020, Lawrence Livermore National Security, LLC.
# Produced at the Lawrence Livermore National Laboratory.
# Written by Saransh Singh <saransh1@llnl.gov> and others.
# LLNL-CODE-529294.
# All rights reserved.
#
# This file is part of HEXRD. For details on dowloading the source,
# see the file COPYING.
#
# Please also see the file LICENSE.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License (as published by the Free
# Software Foundation) version 2.1 dated February 1999.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the terms and conditions of the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program (see file LICENSE); if not, write to
# the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA or visit <http://www.gnu.org/licenses/>.
# =============================================================================
from hexrd import constants
import numpy as np
eps = constants.sqrt_epsf
[docs]def hsl2rgb(hsl):
'''
>> @AUTHOR: Saransh Singh, Lawrence Livermore National Lab, saransh1@llnl.gov
>> @DATE: 10/29/2020 SS 1.0 original
>> @DETAILS: routines to convert between hsl to rgb representations, the
input and output will have all components in the range [0,1]
'''
'''
first check the shape of the hsl array. it has to be nx3 array
it is assumed that the hsl array has values in [0,1] for the
different components
'''
hsl = np.atleast_2d(hsl)
hsl[np.abs(hsl) < eps] = 0.
hsl[np.abs(hsl - np.ones(hsl.shape)) < eps] = 1.
if( (hsl.min() < 0.) or (hsl.max() > 1.)):
raise RuntimeError("value of not in range [0,1]. normalizing before conversion")
if(hsl.ndim != 2):
raise RuntimeError("hsl_rgb: shape of hsl array is invalid.")
rgb = np.zeros(hsl.shape)
'''
calculate the different factors needed for the conversion
'''
H = hsl[:, 0]
S = hsl[:, 1]
L = hsl[:, 2]
C = (1.0 - np.abs(2.*L - 1.)) * S
X = (1.0 - np.abs(np.mod(6*H, 2) - 1.0)) * C
m = L - C/2.
case = np.floor(6.*H).astype(np.int32)
'''
depending on the range of H, the rgb definition changes. see
https://www.rapidtables.com/convert/color/hsl-to-rgb.html
for the detailed formula
'''
Cp = np.atleast_2d(C+m).T
Xp = np.atleast_2d(X+m).T
Zp = np.atleast_2d(m).T
mask = np.logical_or((case == 0), (case == 6))
rgb[mask, :] = np.hstack((Cp[mask, :], Xp[mask, :], Zp[mask, :]))
mask = case == 1
rgb[mask, :] = np.hstack((Xp[mask, :], Cp[mask, :], Zp[mask, :]))
mask = case == 2
rgb[mask, :] = np.hstack((Zp[mask, :], Cp[mask, :], Xp[mask, :]))
mask = case == 3
rgb[mask, :] = np.hstack((Zp[mask, :], Xp[mask, :], Cp[mask, :]))
mask = case == 4
rgb[mask, :] = np.hstack((Xp[mask, :], Zp[mask, :], Cp[mask, :]))
mask = case == 5
rgb[mask, :] = np.hstack((Cp[mask, :], Zp[mask, :], Xp[mask, :]))
'''
catch all cases where rgb values are out of [0,1] bounds
'''
rgb[rgb < 0.] = 0.
rgb[rgb > 1.] = 1.
return rgb
[docs]def rgb2hsl(rgb):
'''
>> @AUTHOR: Saransh Singh, Lawrence Livermore National Lab, saransh1@llnl.gov
>> @DATE: 10/29/2020 SS 1.0 original
>> @DETAILS: routines to convert between rgb to hsl representations, the
input and output will have all components in the range [0,1]
'''
'''
first check the shape of the rgb array. it has to be nx3 array
it is assumed that the hsl array has values in [0,1] for the
different components
'''
rgb = np.atleast_2d(rgb)
if(rgb.ndim != 2):
raise RuntimeError("hsl_rgb: shape of hsl array is invalid.")
hsl = np.zeros(rgb.shape)
'''
calculate different factors needed for the conversion
'''
Cmax = rgb.max(axis=1)
Cmin = rgb.min(axis=1)
delta = Cmax - Cmin
L = 0.5 * (Cmax + Cmin)
# catching cases where delta is close to zero
zmask = np.abs(delta) < eps
hsl[zmask, 1] = 0.0
# depending on whether r,g or b is maximum, the hue is
# assigned different values, we will deal with those cases here
rmask = rgb[:, 0] == Cmax
rmask = np.logical_and(rmask, np.logical_not(zmask))
hsl[rmask, 0] = np.mod(
(rgb[rmask, 1] - rgb[rmask, 2])/delta[rmask], 6) / 6.
gmask = rgb[:, 1] == Cmax
gmask = np.logical_and(gmask, np.logical_not(zmask))
hsl[gmask, 0] = np.mod(
(rgb[gmask, 2] - rgb[gmask, 0])/delta[gmask] + 2., 6) / 6.
bmask = rgb[:, 2] == Cmax
bmask = np.logical_and(bmask, np.logical_not(zmask))
hsl[bmask, 0] = np.mod(
(rgb[bmask, 0] - rgb[bmask, 1])/delta[bmask] + 4., 6) / 6.
hsl[np.logical_not(zmask), 1] = delta[np.logical_not(
zmask)] / (1. - np.abs(2 * L[np.logical_not(zmask)] - 1.))
hsl[:,2] = L
'''
catch cases where hsl is out of [0,1] bounds
'''
hsl[hsl < 0.] = 0.
hsl[hsl > 1.] = 1.
return hsl