Skip to content

Commit

Permalink
added doc
Browse files Browse the repository at this point in the history
  • Loading branch information
lichtkind committed Apr 7, 2024
1 parent 1147a52 commit 6460d11
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 40 deletions.
6 changes: 3 additions & 3 deletions lib/Graphics/Toolkit/Color.pm
Original file line number Diff line number Diff line change
Expand Up @@ -594,11 +594,11 @@ It takes three named arguments, only the first is required.
is I<in>.
# a little more silver than $color in the mix
$color->blend( with => 'silver', pos => 0.6 );
$color->blend({ with => 'silver', pos => 0.6 }); # works too!
$color->blend( to => 'silver', pos => 0.6 );
$color->blend({ to => 'silver', pos => 0.6 }); # works too!
$blue->blend( with => {H => 240, S =>100, L => 50}, in => 'RGB' ); # teal
Instead of I<with> one could also use the alias I<to>, as in other methods.
Instead of I<to> one could also use the alias I<with>, which sounds more english.
=head1 COLOR SETS
Expand Down
54 changes: 38 additions & 16 deletions lib/Graphics/Toolkit/Color/Space/Hub.pm
Original file line number Diff line number Diff line change
Expand Up @@ -143,32 +143,35 @@ Color space names can be written in any combination of upper and lower case.
=head2 RGB
has three integer values: B<red> (0 .. 255), B<green> (0 .. 255) and
B<blue> (0 .. 255).
has three integer values: B<red> (short I<r>) range: 0 .. 255, B<green>
(short I<g>) range: 0 .. 255 and B<blue> (short I<b>) range: 0 .. 255.
All are scaling from no (0) to very much (255) light of that color,
so that (0,0,0) is black, (255,255,255) is white and (0,0,255) is blue.
=head2 CMY
is the inverse of RGB but with the range: 0 .. 1. B<cyan> is the inverse
value of I<red>, B<magenta> is inverse green and B<yellow> is inverse of
I<blue>. Inverse meaning when a color has the maximal I<red> value,
it has to have the minimal I<cyan> value.
is the inverse of RGB but with the real value range: 0 .. 1.
B<cyan> (short I<c>) is the inverse value of I<red>,
B<magenta> (short I<m> ) is inverse to I<green> and
B<yellow> (short I<y>) is inverse of I<blue>.
Inverse meaning when a color has the maximal I<red> value, it has to
have the minimal I<cyan> value.
=head2 CMYK
is an extension of CMY with a fourth value named B<key> (also 0 .. 1),
is an extension of CMY with a fourth value named B<key> (short I<k>) (also 0 .. 1),
which is basically the amount of black mixed into the CMY color.
=head2 HSL
has three integer values: B<hue> (0 .. 359), B<saturation> (0 .. 100)
and B<lightness> (0 .. 100). Hue stands for a color on a rainbow: 0 = red,
15 approximates orange, 60 - yellow 120 - green, 180 - cyan, 240 - blue,
270 - violet, 300 - magenta, 330 - pink. 0 and 360 point to the same
coordinate. This module only outputs 0, even if accepting 360 as input.
I<saturation> ranges from 0 = gray to 100 - clearest color set by hue.
I<lightness> ranges from 0 = black to 50 (hue or gray) to 100 = white.
and B<lightness> (0 .. 100). Hue (short I<h>) stands for a color on
a rainbow: 0 = red, 15 approximates orange, 60 - yellow 120 - green,
180 - cyan, 240 - blue, 270 - violet, 300 - magenta, 330 - pink.
0 and 360 points to the same coordinate. This module only outputs 0,
even if accepting 360 as input.
I<saturation> (short I<s>) ranges from 0 (gray) to 100 (clearest color set by hue).
I<lightness> (short I<l>) ranges from 0 (black) over 50 (hue or gray) to 100 (white).
=head2 HSV
Expand All @@ -193,18 +196,37 @@ leads to pure white and I<blackness> of 100 always leads to pure black.
=head2 YIQ
Has the linear dimensions I<luminance> (sort of brightness, range 0..1),
I<in-phase> (cyan - orange - balance, range -0.5959 .. 0.5959)
and I<quadrature> (magenta - green - balance, range: -0.5227 .. 0.5227).
Has three linear dimensions:
B<luminance> (short I<y>) (sort of brightness with real range of 0 .. 1),
B<in-phase> (short I<i>) (cyan - orange - balance, range -0.5959 .. 0.5959) and
B<quadrature> (short I<q>) (magenta - green - balance, range: -0.5227 .. 0.5227).
=head2 CIEXYZ
Has three real valued dimension named X, Y and Z, (short names are the same),
which aim to reflect the chemical activity of the three type of
colored light receptors in the human eye. Their ranges span from zero to
0.95047, 1 and 1.08883.
=head2 CIELAB
Has three real valued dimension named L, A and B, (short names are the same),
=head2 CIELUV
=head2 CIEHCL
=head1 RANGES
As pointed out in the previous paragraph, each dimension of color space has
its default range. However, one can demand custom value ranges, if the method
accepts a range decriptor as argument. If so, the following values are accepted:
'normal' real value range from 0 .. 1
number range from zero to that number
[min max] range from min .. max
If both limits are integer (except 0 .. 1),
the resulting range will contain only integer values.
=head1 FORMATS
Expand Down
29 changes: 28 additions & 1 deletion lib/Graphics/Toolkit/Color/Space/Instance/LAB.pm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use v5.12;
use warnings;

# LAB color space specific code
# LAB color space specific code based on XYZ

package Graphics::Toolkit::Color::Space::Instance::LAB;
use Graphics::Toolkit::Color::Space;
Expand Down Expand Up @@ -35,3 +35,30 @@ sub to_rgb {
}

$lab_def;

__END__
sub from_rgb {
my ($r, $g, $b) = @_;
$r = ( $r > 0.04045 ) ? ((($r + 0.055) / 1.055 ) ** 2.4) : ($r / 12.92);
$g = ( $g > 0.04045 ) ? ((($g + 0.055) / 1.055 ) ** 2.4) : ($g / 12.92);
$b = ( $b > 0.04045 ) ? ((($b + 0.055) / 1.055 ) ** 2.4) : ($b / 12.92);
my $x = (0.4124564 * $r) + ( 0.3575761 * $g) + ( 0.1804375 * $b);
my $y = (0.2126729 * $r) + ( 0.7151522 * $g) + ( 0.0721750 * $b);
my $z = (0.0193339 * $r) + ( 0.1191920 * $g) + ( 0.9503041 * $b);
return ($x, $y, $z);
}
sub to_rgb {
my ($x, $y, $z) = @_;
my $r = ( 3.2404542 * $x) + (-1.5371385 * $y) + (-0.4985314 * $z);
my $g = (-0.9692660 * $x) + ( 1.8760108 * $y) + ( 0.0415560 * $z);
my $b = ( 0.0556434 * $x) + (-0.2040259 * $y) + ( 1.0572252 * $z);
$r = ($r > 0.003131) ? ((($r**0.416666) * 1.055) - 0.055) : $r * 12.92;
$g = ($g > 0.003131) ? ((($g**0.416666) * 1.055) - 0.055) : $g * 12.92;
$b = ($b > 0.003131) ? ((($b**0.416666) * 1.055) - 0.055) : $b * 12.92;
return ($r, $g, $b);
}
46 changes: 26 additions & 20 deletions lib/Graphics/Toolkit/Color/Space/Instance/XYZ.pm
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
use v5.12;
use warnings;

# XYZ color space specific code for D65 ans
# XYZ color space specific code for Illuminant D65 and Observer

package Graphics::Toolkit::Color::Space::Instance::XYZ;
use Graphics::Toolkit::Color::Space;

# cyan-orange balance, magenta-green balance
my $xyz_def = Graphics::Toolkit::Color::Space->new( axis => [qw/X Y Z/],
my $xyz_def = Graphics::Toolkit::Color::Space->new( axis => [qw/X Y Z/], #
prefix => 'CIE',
range => [0.95047, 1, 1.08883] );

$xyz_def->add_converter('RGB', \&to_rgb, \&from_rgb );

sub from_rgb {
my ($r, $g, $b) = @_;
$r = ( $r > 0.04045 ) ? ((($r + 0.055) / 1.055 ) ** 2.4) : ($r / 12.92);
$g = ( $g > 0.04045 ) ? ((($g + 0.055) / 1.055 ) ** 2.4) : ($g / 12.92);
$b = ( $b > 0.04045 ) ? ((($b + 0.055) / 1.055 ) ** 2.4) : ($b / 12.92);

my $x = (0.4124564 * $r) + ( 0.3575761 * $g) + ( 0.1804375 * $b);
my $y = (0.2126729 * $r) + ( 0.7151522 * $g) + ( 0.0721750 * $b);
my $z = (0.0193339 * $r) + ( 0.1191920 * $g) + ( 0.9503041 * $b);
return ($x, $y, $z);
return mult_matrix([[0.4124564, 0.2126729, 0.0193339],
[0.3575761, 0.7151522, 0.1191920],
[0.1804375, 0.0721750, 0.9503041]], apply_d65( $r ), apply_d65( $g ), apply_d65( $b ));
}


sub to_rgb {
my ($x, $y, $z) = @_;
my $r = ( 3.2404542 * $x) + (-1.5371385 * $y) + (-0.4985314 * $z);
my $g = (-0.9692660 * $x) + ( 1.8760108 * $y) + ( 0.0415560 * $z);
my $b = ( 0.0556434 * $x) + (-0.2040259 * $y) + ( 1.0572252 * $z);

$r = ($r > 0.003131) ? ((($r**0.416666) * 1.055) - 0.055) : $r * 12.92;
$g = ($g > 0.003131) ? ((($g**0.416666) * 1.055) - 0.055) : $g * 12.92;
$b = ($b > 0.003131) ? ((($b**0.416666) * 1.055) - 0.055) : $b * 12.92;
return ($r, $g, $b);
my ($r, $g, $b) = mult_matrix([[ 3.2404542, -1.5371385, -0.4985314],
[-0.9692660, 1.8760108, 0.0415560],
[ 0.0556434, -0.2040259, 1.0572252]], $x, $y, $z);

#~ my $r = ( 3.2404542 * $x) + (-1.5371385 * $y) + (-0.4985314 * $z);
#~ my $g = (-0.9692660 * $x) + ( 1.8760108 * $y) + ( 0.0415560 * $z);
#~ my $b = ( 0.0556434 * $x) + (-0.2040259 * $y) + ( 1.0572252 * $z);

return ( remove_d65($r), remove_d65($g), remove_d65($b));
}

sub apply_d65 { $_[0] > 0.04045 ? ((($_[0] + 0.055) / 1.055 ) ** 2.4) : ($_[0] / 12.92) }
sub remove_d65 { $_[0] > 0.003131 ? ((($_[0]**(1/2.4)) * 1.055) - 0.055) : ($_[0] * 12.92) }
sub mult_matrix {
my ($mat, $v1, $v2, $v3) = @_;
return unless ref $mat eq 'ARRAY' and defined $v3;
return ($v1 * $mat->[0][0] + $v2 * $mat->[1][0] + $v3 * $mat->[2][0]) ,
($v1 * $mat->[0][1] + $v2 * $mat->[1][1] + $v3 * $mat->[2][1]) ,
($v1 * $mat->[0][2] + $v2 * $mat->[1][2] + $v3 * $mat->[2][2]) ;
}

$xyz_def;

__END__
3 changes: 3 additions & 0 deletions t/18_xyz_space.t
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ is( close_enough($rgb[0], 0.5), 1, 'right red value');
is( close_enough($rgb[1], 0.5), 1, 'right green value');
is( close_enough($rgb[2], 0.5), 1, 'right blue value');

say "@rgb";


@rgb = $def->convert( [0.95047, 1, 1.08883], 'RGB');
is( int @rgb, 3, 'converted back gray with 3 values');
is( close_enough($rgb[0], 1), 1, 'right red value');
Expand Down

0 comments on commit 6460d11

Please sign in to comment.