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.
my $c = $mint->lighten( 0.1 ); # is the same as :
my $c = $mint->lighten( by => 0.1, in => 'OKHSL' );
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 (to) is the only required one 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 where values of neighbours 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
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.