NAME
    Graphics::Toolkit::Color - calculate color (sets), IO many spaces and
    formats

SYNOPSIS
        use Graphics::Toolkit::Color qw/color is_in_gamut/;

        my $red = Graphics::Toolkit::Color->new('red');  # create color object
        say $red->add_value( 'blue' => 255 )->name;      # red + blue = 'magenta'
        my @blue = color( 0, 0, 255)->values('HSL');     # 240, 100, 50 = blue
        if (is_in_gamut('oklab(14, -106, 3)')) { ..      # check if valid
        $red->mix( to => [HSL => 0,0,80], by => 0.1);     # mix red with a little grey
        $red->gradient( to => '#0000FF', steps => 10);   # 10 colors from red to blue
        my @base_triadic = $red->complement( 3 );        # get fitting red green and blue
        my @reds = $red->cluster( r => 1.1, min_d => 1 );# 13 shades of red

DESCRIPTION
    Graphics::Toolkit::Color, for short GTC, is the top level API of this
    library and the only package a regular user should be concerned with.
    Its main purpose is the creation of related colors or sets of them, such
    as gradients, complements and more. But if you want to convert,
    quantize, round or reformat color definitions or translate from and to
    color names, it can be helpful too.

    This page will give you a quick overview of all GTC methods. The Manual
    contains deeper explanations and describes every argument and topic of
    interest in detail. Therefore each chapter here starts with a link to
    the appropriate paragraph of a manual page.

    While this module can understand and output color values of many (33)
    color spaces, RGB is the internal and primary one for input and output,
    because GTC is about colors that can be shown on the screen, and these
    are usually encoded in *RGB* (nonlinear standard RGB). However, many
    color calculations are operating by default in *OKLAB* or *OKHSL* to
    give perceptually uniform results.

    Each GTC object represents one color and is read-only. It has no runtime
    dependencies. Only Test::Simple and Test::Warn are needed for testing.
    The behavior of error messages can be chosen, but defaults to using
    Carp.

DEPRECATION
    The next API cleanup will come with version 3.0. Please see which syntax
    is on the way out.

CONSTRUCTOR
    new is the universal constructor to create a GTC object that takes the
    arguments: color (color definition), raw (defaults to false, which
    clamps values into range), range (min. and max. values) and in (color
    space name). "color" is the only required argument and the default
    argument (can be provided as the only positional argument).

    The importable method color is a short alias for calling "new" just with
    the argument "color".

        use Graphics::Toolkit::Color qw/color/;

        my $color = Graphics::Toolkit::Color->new( 'Emerald' ); # X11 constant
        my $green = Graphics::Toolkit::Color->new( 'SVG:green');# SVG constant (explicit with full name)
        my $navy  = color( 'navy' );                            # just a shortcut, X11 constant
    
        color(  r => 255, g => 0, b => 0 );                     # red (RGB)
        color( {r => 255, g => 0, b => 0});                     # red in char_hash format (RGB)
        color( Red => 255, Green => 0, Blue => 0);              # red in hash format (RGB)
        color( Hue => 0, Saturation => 1, Lightness => .5 );    # red in OKHSL
        color( hue => 0, whiteness => 0, blackness => 0 );      # red in OKHWB

        color(  255, 0, 0 );                # list format, no space name -> RGB
        color( [255, 0, 0] );               # array format, RGB only (as input)
        color( 'RGB',   255, 0, 0  );       # named list format
        color(  RGB =>  255, 0, 0  );       # with fat comma
        color( [RGB =>  255, 0, 0] );       # named_array
        color(  RGB => [255, 0, 0] );       # tuple under named key
        color( [RGB => [255, 0, 0]]);       # nested_array

        color( 'rgb: 255, 0, 0' );          # named string format, commas are not optional
        color( 'HSV: 240, 100, 100' );      # space name is case insensitive
        color( 'hsv(240, 100, 100)' );      # css_string format
        color( 'hsv(240, 100%, 100%)' );    # value suffix is optional
        color( 'rgb(255 0 0)' );            # commas are optional
                                                                            
        color( '#FF0000' );                 # hex_string format, RGB only
        color( '#f00' );                    # hex_string format, short form

        # color is far outside the RGB16 range, but will be read as is, unclamped
        Graphics::Toolkit::Color->new( color => [100_000,0,0], range => 2**16-1, raw => 1 );

GETTER
    These methods provide information about color(s), but not a GTC object.

  is_in_gamut
    is_in_gamut returns a perlish pseudo boolean that answers the question:
    is this color inside the value range of a color space (gamut). It can be
    used as a method or an importable subroutine. In method mode it takes
    one optional positional argument, which is a color space name (like in).
    The color will be converted into that space, before a check is
    performed. If no space name is provided, the check happens in the color
    space the original values (when the object was created) were defined in.

    When used as a subroutine, it requires only one positional argument,
    that has to be a color definition (like with the "color" routine). This
    check will be performed in the color space the color is defined in. For
    color names this would be RGB, which makes the result always true (1).

        $color->is_in_gamut( 'okLab');               # is current color inside OKLAB?

        use Graphics::Toolkit::Color qw/is_in_gamut/;
        is_in_gamut('rgb: 0, 0, 300');               # false, SRGB ranges span up to 255
        is_in_gamut('#000000');                      # true, black is always included

  values
    values returns the numeric values of the color, held by the object and
    accepts six optional, named arguments: in (color space), "as" ( format),
    range (min. and max. values), "precision", "suffix" and raw (defaults to
    false, which clamps values into range). "in" is the default argument
    (used as only positional) and if no arguments are provided, the method
    will return a list with RGB values.

        $blue->values();                                        #  0, 0, 255
        $blue->values( in => 'RGB', as => 'list');              #  0, 0, 255  # explicit arguments
        $blue->values(              as => 'array');             # [0, 0, 255] - RGB only
        $blue->values( in => 'RGB', as => 'named_array');       # ['RGB', 0, 0, 255]
        $blue->values( in => 'RGB', as => 'hash');              # { red => 0, green => 0, blue => 255}
        $blue->values( in => 'RGB', as => 'char_hash');         # { r => 0, g => 0, b => 255}
        $blue->values( in => 'RGB', as => 'named_string');      # 'rgb: 0, 0, 255'
        $blue->values( in => 'RGB', as => 'css_string');        # 'rgb( 0, 0, 255)'
        $blue->values(              as => 'hex_string');        # '#0000ff' - RGB only
        $blue->values(           range => 2**16-1 );            # 0, 0, 65535
        $blue->values('HSL');                                   # 240, 100, 50 # HSL is only argument
        $blue->values( in => 'HSL',suffix => ['', '%','%']);    # 240, '100%', '50%'
        $blue->values( in => 'HSB',  as => 'hash')->{'hue'};    # 240
       ($blue->values( 'HSB'))[0];                              # 240
        $blue->values( in => 'XYZ', range => 1, precision => 2);# normalized, 2 decimals max.

  name
    name returns the normalized name of the current color, if it (converted
    to RGB) is part of a color scheme. It has four optional named arguments:
    from (scheme name), "all" (allows to return more names), "full" (include
    scheme name in color name) and "distance" (all colors within distance).
    The default argument is "from" which defaults to the default scheme. All
    other arguments default to zero.

        $blue->name();                                   # 'blue'
        $blue->name('SVG');                              # 'blue'
        $blue->name( from => [qw/CSS X/], all => 1);     # 'blue', 'blue1'
        $blue->name( from => 'CSS', full => 1);          # 'CSS:blue'
        $blue->name( distance => 3, all => 1);           # all names within the distance

  closest_name
    closest_name (almost) always returns a normalized color name (unlike
    name). In list context it also returns the "distance" between the
    current color and the color belonging to the returned name. It has three
    optional, named arguments: "from", "all", "full" which work the same way
    as in "name".

        my $name = $red_like->closest_name;              # closest name in default scheme
        my $name = $red_like->closest_name('HTML');      # closest HTML constant
        ($name, $distance) = $color->closest_name( from => 'Pantone', all => 1 );

  distance
    distance returns a numeric value, the Euclidean distance between two
    colors in some color space, which works even in cylindrical spaces. It
    accepts four named arguments: to, range, only and in. Only the "to" is
    required and can be provided as the only positional argument.

        my $d = $blue->distance( 'lapisblue' );                        # how close is blue to lapisblue?
        $d = $blue->distance( to => 'airyblue', only => 'b');          # do they have the same amount of blue?
        $d = $color->distance( to => $c2, only => 'hue', in => 'HSL' );# same hue?
        $d = $color->distance( to => $c2, range => 'normal' );         # distance with values in 0 .. 1 range
        $d = $color->distance( to => $c2, only => [qw/r g b b/]);      # double the weight of blue value differences

SINGLE COLOR
    These methods create one GTC object with a color that is related to the
    current one. They can be divided into the simpler, high level
    convenience methods on the one side (*lighten*, *darken*, *saturate*,
    *desaturate*, *tint*, *shade*, *tone*) and the more powerful low level
    operations on the other (*apply*, *set_value*, *add_value*, *mix*,
    *invert*).

    The signature of the high level methods is always the same. It
    understands 2 named arguments: "by" and "in". The first is the required
    one, which can be provided as a positional argument, if it is the only
    one. "by" needs a floating point number between 0 and 1. Usually the
    method produces the same color again when 0 is provided and a fixed
    predictable outcome when the argument is 1. The attribute in is as
    always the color space the method is computed in, which defaults here to
    *OKHSL*. The first 4 methods can only operate in a space of the *HSL*
    family.

  lighten
    lighten increases the lightness by an absolute amount, but does not
    touch saturation. The result will be clamped, so lighten(1) will always
    return *white*.

  darken
    darken decreases the lightness by an absolute amount, but does not touch
    saturation. The result will be clamped, so darken(1) will always return
    *black*.

  saturate
    saturate increases the saturation by an absolute amount, but does not
    touch lightness. The result will be clamped, so saturate(1) will always
    return the purest possible color.

  desaturate
    desaturate decreases the saturation by an absolute amount, but does not
    touch lightness. The result will be clamped, so desaturate(1) will
    always return a shade of grey with the same lightness as the given
    color.

  tint
    tint mixes ("mix") a color with *white* by the given percentage (0.2 =
    20% white, 80% given color). That lightens and desaturates at once. The
    result of tint(1) will always be *white*.

  tone
    tone mixes ("mix") a color with mid gray (*gray50*) by the given
    percentage (0.2 = 20% gray50, 80% given color). That darkens or lightens
    and desaturates at once. The result of tone(1) will always be *gray50*.

  shade
    shade mixes ("mix") a color with *black* by the given percentage (0.2 =
    20% black, 80% given color). That darkens and desaturates at once. The
    result of shade(1) will always be *black*.

  tone_curve
    tone_curve computes a gamma correction. It has two named arguments:
    "gamma" and in, the first one being required and the default argument.
    "in" defaults here to *LinearRGB*.

        my $c = $blue->tone_curve( gamma => 2.2 );                          # is the same as :
        my $c = $blue->tone_curve( gamma => {r => 2.2, g =>2.2, b => 2.2}, in => 'LinearRGB' );

  set_value
    set_value returns a color that differs in some chosen values from the
    current one. Its arguments have to be short or long axis names from one
    selected color space. You may additionally provide the color space in
    mind with the argument in if the axis names alone are too ambiguous.

        my $blue = $black->set_value( blue => 255 );                    # same as #0000ff
        my $color = $blue->set_value( saturation => 50, in => 'HSV' );  # would otherwise use OKHSL

  add_value
    Works exactly as "set_value" with only one difference: the provided axis
    values will be added to the current ones and not exchanged.

        my $darkblue = $blue->add_value( Lightness => -25 );    # get a darker tone
        my $blue3 = $blue->add_value( l => 10, in => 'LAB' );   # lighter color according to CIELAB

  mix
    mix computes a color that is a blend between two or more other colors.
    It has three named arguments: to, by and in. The first one is the only
    required and also the default argument. "by" defaults to a 50:50 blend
    and "in" to *OKLAB*.

        $blue->mix( $silver );                                     # 50% silver, 50% blue
        $blue->mix( to => 'silver', by => .6 );                    # 60% silver, 40% blue
        $blue->mix( to => [qw/silver green/], by => [.1, .2]);     # 10% silver, 20% green, 70% blue

  invert
    invert computes a color with opposite properties (values). It has two
    named, optional arguments: only (select axes) and in (color space name,
    defaults to *OKHSL*).

        my $still_gray = $gray->invert();                 # got same color back
        my $blue = $yellow->invert('hue');                # invert hue in 'OKHSL'
        $yellow->invert( in => 'OKHSL', only => 'hue' );  # same in long form, same result as $yellow->complement();

COLOR SETS
    These methods create sets of colors which are currently just a list of
    GTC objects.

  complement
    complement computes colors that form a circle of complementary colors.
    This can only work in cylindrical spaces of the *HSL* family. It
    understands five named arguments: steps (color count), tilt, "target",
    "skew" and in (color space name, defaults to *OKHSL*). With no argument
    given it computes THE complementary color.

        my @colors = $c->complement( 4 );                       # 'quadratic' colors
        my @colors = $c->complement( steps => 4, tilt => 1.5 ); # split-complementary colors
        my @colors = $c->complement( steps => 3, tilt => 2, target => { l => -10 } );
        my @colors = $c->complement( steps => 3, tilt => 2, target => { h => 20, s=> -5, l => -10 });

  analogous
    analogous creates a list of colors that differ from each other the same
    way as the two given colors. It accepts four named arguments: to (next
    color), steps (max. color count, default 4), "tilt" and in (color space
    name, defaults to *OKHSL*). Only "to" is required and also the default
    argument.

        my @colors = $darkblue->analogous( to => $midblue, steps => 5);     # 5 shades of blue
        @colors = $c->analogous( to => [14,10,222], steps => 3, tilt => 0.2, in => 'RGB' );

  gradient
    gradient creates a list of colors that are a gradual blend between two
    or more given colors. It accepts four named arguments: to, steps (color
    count), "tilt" and in (color space name, defaults to *OKLAB*). Only "to"
    is required and also the default argument.

        my @colors = $c->gradient( to => $grey, steps => 5);       # we turn to grey
        @colors = $c1->gradient( to => [14,10,222], steps => 10, tilt => 1, in => 'HSL' );

  cluster
    cluster creates a list of GTC color objects that look similar to the
    calling color but distinctly different. It accepts three named
    arguments: "radius", "minimal_distance" and in (color space name,
    defaults to *OKLAB*). "radius", "minimal_distance" are required and can
    be written "r" and "min_d".

        my @blues = $blue->cluster( radius => 4, minimal_distance => 0.3 ); # ball shapes cluster
        my @c = $color->cluster( r => [2,2,3], min_d => 0.4, in => 'YUV' ); # box shaped cluster

SEE ALSO
    *   PDL::Transform::Color

    *   PDL::Graphics::ColorSpace

    *   Color::Scheme

    *   Graphics::ColorUtils

    *   Color::Fade

    *   Graphics::Color

    *   Graphics::ColorObject

    *   Color::Calc

    *   Convert::Color

    *   Color::Similarity

ACKNOWLEDGEMENT
    These people contributed by providing patches, bug reports and useful
    comments:

    *   Petr Pisar (ppisar)

    *   Slaven Rezic (srezic)

    *   Gabor Szabo (szabgab)

    *   Gene Boggs (GENE)

    *   Stefan Reddig (sreagle)

AUTHOR
    Herbert Breunung, <lichtkind@cpan.org>

COPYRIGHT
    Copyright 2022-2026 Herbert Breunung.

LICENSE
    This program is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

