def rgb2lrgb(rgb: np.ndarray, *, rgbs: RgbSpecification = None) -> np.ndarray: """ Convert companded RGB to linear RGB :param rgb: :param rgbs: :return: """ if rgbs is None: rgbs = get_default_rgb_specification() return rgbs.inverse_compand(rgb)
def __init__( self, data: ArrayLike, *, axis: int = None, illuminant: Illuminant = get_default_illuminant(), observer: Observer = get_default_observer(), rgbs: RgbSpecification = get_default_rgb_specification(), caa: ChromaticAdaptationAlgorithm = get_default_chromatic_adaptation_algorithm( ), is_scaled: bool = False): """ :param data: the color space data to contain :param axis: the axis along which the color data lies. If `axis` is not specified, then it will be determined automatically by finding the last dimension with the required size. :param illuminant: the illuminant :param observer: the observer :param rgbs: the rgb specification :param caa: the chromatic adaptation algorithm :param is_scaled: Whether or not the data is scaled """ if is_scaled: self._data = np.array(data, copy=True) / self.scale_factor else: self._data = np.array(data, copy=True) self._data.flags.writeable = False self._axis = (axis if axis is not None else get_matching_axis( self._data.shape, 3)) self._illuminant = (illuminant if illuminant is not None else get_default_illuminant()) self._observer = (observer if observer is not None else get_default_observer()) self._rgbs = (rgbs if rgbs is not None else get_default_rgb_specification()) self._caa = (caa if caa is not None else get_default_chromatic_adaptation_algorithm()) self._is_scaled = is_scaled
def xyz2lrgb(xyz: np.ndarray, *, axis: int = None, illuminant: Illuminant = None, observer: Observer = None, rgbs: RgbSpecification = None, caa: ChromaticAdaptationAlgorithm = None) -> np.ndarray: """ Convert XYZ to linear RGB :param xyz: :param axis: :param illuminant: :param observer: :param rgbs: :param caa: :return: """ if axis is None: axis = get_matching_axis(xyz.shape, 3) if illuminant is None: illuminant = get_default_illuminant() if observer is None: observer = get_default_observer() if rgbs is None: rgbs = get_default_rgb_specification() if caa is None: caa = get_default_chromatic_adaptation_algorithm() # If the white points are not equal, we will need to convert to the # RGB white point source_white_point = illuminant.get_white_point(observer) destination_white_point = rgbs.white_point if not np.allclose( source_white_point, destination_white_point, rtol=1e-5, atol=1e-14): xyz = xyz2xyz(xyz, source_white_point, destination_white_point, axis, caa) # Get the XYZ values into the correct shape for matrix multiplication n_dims = xyz.ndim new_dims = list(range(n_dims)) if axis != n_dims - 1: new_dims[-1] = axis new_dims[axis] = n_dims - 1 xyz = xyz.transpose(new_dims) input_shape = xyz.shape xyz_is_not_matrix = xyz.ndim != 2 if xyz_is_not_matrix: xyz = xyz.reshape((-1, 3)) # Convert to linear RGB m = rgbs.linear_transformation lrgb = np.linalg.solve(m.T, xyz.T).T # Transform the destination data back to the original shape if xyz_is_not_matrix: lrgb = lrgb.reshape(input_shape) return lrgb.transpose(new_dims)
def lrgb2xyz(lrgb: np.ndarray, *, axis: int = None, illuminant: Illuminant = None, observer: Observer = None, rgbs: RgbSpecification = None, caa: ChromaticAdaptationAlgorithm = None) -> np.ndarray: """ Convert from linear RGB to XYZ :param lrgb: :param axis: :param illuminant: :param observer: :param rgbs: :param caa: :return: """ if axis is None: axis = get_matching_axis(lrgb.shape, 3) if illuminant is None: illuminant = get_default_illuminant() if observer is None: observer = get_default_observer() if rgbs is None: rgbs = get_default_rgb_specification() if caa is None: caa = get_default_chromatic_adaptation_algorithm() # Get the XYZ values into the correct shape for matrix multiplication n_dims = lrgb.ndim new_dims = list(range(n_dims)) if axis != n_dims - 1: new_dims[-1] = axis new_dims[axis] = n_dims - 1 lrgb = lrgb.transpose(new_dims) input_shape = lrgb.shape lrgb_is_not_matrix = n_dims != 2 if lrgb_is_not_matrix: lrgb = lrgb.reshape((-1, 3)) # Do the transformation m = rgbs.linear_transformation xyz = lrgb.dot(m) # Transform back to the original shape if lrgb_is_not_matrix: xyz = xyz.reshape(input_shape) if axis != n_dims - 1: xyz = xyz.transpose(new_dims) source_white_point = rgbs.white_point destination_white_point = illuminant.get_white_point(observer) if not np.allclose( source_white_point, destination_white_point, rtol=1e-5, atol=1e-14): return xyz2xyz(xyz, source_white_point, destination_white_point, axis, caa) else: return xyz