25static decltype(
auto) assert_nonnull(T &&t)
28 return std::forward<T>(t);
40Color::Color(
Space::Type space_type, std::vector<double> values)
41 :
Color(assert_nonnull(
Manager::get().find(space_type)),
std::move(values))
47Color::Color(uint32_t rgba,
bool opacity)
60Color::Color(std::shared_ptr<Space::AnySpace> space, std::vector<double> colors)
61 : _values(
std::move(colors))
62 , _space(
std::move(space))
73bool Color::operator==(
Color const &other)
const
87double Color::get(
unsigned index)
const
106std::string Color::toString(
bool opacity)
const
117uint32_t Color::toRGBA(
double opacity)
const
125uint32_t Color::toARGB(
double opacity)
const
127 auto value =
toRGBA(opacity);
128 return (value >> 8) | ((value & 0xff) << 24);
134uint32_t Color::toABGR(
double opacity)
const
136 auto value =
toRGBA(opacity);
137 return (value << 24) | ((value << 8) & 0x00ff0000) | ((value >> 8) & 0x0000ff00) | (value >> 24);
145bool Color::convert(
Color const &other)
159bool Color::convert(std::shared_ptr<Space::AnySpace> to_space)
161 if (!to_space || !to_space->isValid()) {
167 _space = std::move(to_space);
189std::optional<Color> Color::converted(
Color const &other)
const
192 if (copy.convert(other)) {
201std::optional<Color> Color::converted(std::shared_ptr<Space::AnySpace> to_space)
const
204 if (copy.convert(std::move(to_space))) {
218 if (copy.convert(type)) {
230void Color::setValues(std::vector<double> values)
249bool Color::set(
Color const &other,
bool keep_space)
256 if (
set(other,
false)) {
263 }
else if (*
this != other) {
281bool Color::set(std::string
const &parsable,
bool keep_space)
283 if (
auto color = Color::parse(parsable)) {
284 return set(*color, keep_space);
292bool Color::_isnear(std::vector<double>
const &other,
double epsilon)
const
294 bool is_near =
_values.size() == other.size();
295 for (
size_t i = 0; is_near && i <
_values.size(); i++) {
296 is_near &= std::abs(
_values[i] - other[i]) < epsilon;
304std::optional<Color> Color::parse(
char const *value)
309 return parse(std::string(value));
315std::optional<Color> Color::parse(std::string
const &value)
318 std::string cms_name;
319 std::vector<double> values;
320 std::vector<double> fallback;
322 return ifValid(space_type, std::move(values));
331std::optional<Color> Color::ifValid(
Space::Type space_type, std::vector<double> values)
334 if (space->isValidData(values)) {
335 return std::make_optional<Color>(std::move(space), std::move(values));
350bool Color::set(
unsigned int index,
double value)
356 auto const changed = std::abs(
_values[
index] - value) >= 0.001;
369bool Color::set(uint32_t rgba,
bool opacity)
374 }
else if (rgba ==
toRGBA(opacity)) {
385void Color::enableOpacity(
bool enable)
388 if (enable && !has_opacity) {
390 }
else if (!enable && has_opacity) {
398bool Color::hasOpacity()
const
407double Color::getOpacity()
const
417double Color::stealOpacity()
427unsigned int Color::getOpacityChannel()
const
429 return _space->getComponentCount();
436unsigned int Color::getPin(
unsigned int channel)
const
444bool Color::setOpacity(
double opacity)
447 if (opacity ==
_values.back()) {
460void Color::normalize()
483void Color::invert(
unsigned int pin)
485 for (
unsigned int i = 0; i <
_values.size(); i++) {
486 if (pin & (1 << i)) {
499void Color::jitter(
double force,
unsigned int pin)
501 for (
unsigned int i = 0; i <
_values.size(); i++) {
502 if (pin & (1 << i)) {
506 double r = (
static_cast<double>(std::rand()) / RAND_MAX - 0.5);
517void Color::compose(
Color const &other)
521 [alpha](
auto &value,
auto otherValue) { value = value * (1.0 - alpha) + otherValue * alpha; });
544void Color::average(
Color const &other,
double pos,
unsigned int pin)
547 [pos](
auto &value,
auto otherValue) { value = value * (1 - pos) + otherValue * pos; });
559 copy.average(other, pos);
566double Color::difference(
Color const &other)
const
569 if (
auto copy = other.
converted(*
this)) {
570 for (
unsigned int i = 0; i <
_values.size(); i++) {
571 ret += std::pow(
_values[i] - (*copy)[i], 2);
583bool Color::isClose(
Color const &other,
double epsilon)
const
586 for (
unsigned int i = 0; match && i <
_values.size(); i++) {
599bool Color::isSimilar(
Color const &other,
double epsilon)
const
603 return isClose(*copy, epsilon);
607 return isClose(other, epsilon);
615bool Color::isOutOfGamut(std::shared_ptr<Space::AnySpace> other)
const
623bool Color::isOverInked()
const
629template <
typename Func>
630void Color::_color_mutate_inplace(
Color const &other,
unsigned int pin, Func func)
634 if (
auto copy = other.
converted(*
this)) {
641 for (
unsigned int i = 0; i <
_values.size(); i++) {
642 if (pin & (1 << i)) {
bool convert(Color const &other)
Convert to the same format as the other color.
static std::optional< Color > ifValid(Space::Type space_type, std::vector< double > values)
Construct a color from the space type and values, if the values are valid.
bool _isnear(std::vector< double > const &other, double epsilon=0.001) const
Returns true if the values are near to the other values.
unsigned int getOpacityChannel() const
Get the opacity channel index.
void _color_mutate_inplace(Color const &other, unsigned int pin, Func avgFunc)
uint32_t toRGBA(double opacity=1.0) const
Return an sRGB conversion of the color in RGBA int32 format.
bool setOpacity(double opacity)
Set the opacity of this color object.
bool isClose(Color const &other, double epsilon=EPSILON) const
Find out if a color is a close match to another color of the same type.
void enableOpacity(bool enabled)
Enables or disables the opacity channel.
std::optional< Color > converted(Color const &other) const
Return a copy of this color converted to the same format as the other color.
void normalize()
Make sure the values for this color are within acceptable ranges.
std::vector< double > _values
unsigned int getPin(unsigned int channel) const
Return the pin number (pow2) of the channel index to pin that channel in a mutation.
std::shared_ptr< Space::AnySpace > _space
static std::optional< Color > parse(char const *value)
Create an optional color if value is valid.
bool hasOpacity() const
Returns true if there is an opacity channel in this color.
double getOpacity() const
Get the opacity in this color, if it's stored.
A set of useful color modifying functions which do not fit as generic methods on the color class itse...
std::vector< double > rgba_to_values(uint32_t rgba, bool opacity)
Convert a 32bit unsigned int into a set of 3 or 4 double values for rgba.