package Colour;
# Colour conversion to/from RGB/HSV
use strict;
=head1 NAME
Colour - Colour conversion RGB <=> HSV
=head1 SYNOPSIS
use Colour;
my @rgb = (255,153,102); # Pale Brown
@rgb = map {$_ /= 255 } @rgb; # Convert to values from 0 to 1
print "HSV values: ", (join ",", RGBtoHSV(@rgb)), "\n";
my @hsv = (20, 0.6, 1); # Pale Brown
print "RGB values: ", (join ",", HSVtoRGB(@hsv)), "\n";
=head1 DESCRIPTION
The purpose of this module is to easily convert between RGB and
HSV (or HSB) values. The main interest in doing so is that
the HSV system is more user-friendly than the RGB.
The Hue is the 'tone' of the color. It's the most awkward parameter
to set since you're not supposed to know that values around 240 are
for blues or values around 60 are for yellows. A 'circle of color'
is not very hard to find though...
The Saturation value is the 'amount' of color you want, ranging from
white (no color) to the full color.
The Value (or Brightness) is the 'lightness' of the color. A low
value makes the color black whereas high value makes
the color brighter.
This module is stolen from
http://www.cs.rit.edu/~ncs/color/t_convert.html
thanks to [merlyn] and [Rudif] for pointing me to the URL.
=cut
use v5.6.0; # not too hard to tweak otherwise :)
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(RGBtoHSV HSVtoRGB);
our $VERSION = 0.1;
#use POSIX;
=head1 DESCRIPTION
=head2 RGBtoHSV($r, $g, $b)
The three RGB values ranges from 0 to 1. The function returns a
three element array with the HSV values in it.
=cut
sub RGBtoHSV {
my ($r, $g, $b) = @_;
my ($h, $s, $v);
my ($min, $max, $delta);
($min, undef, $max) = sort ($r, $g, $b);
$v = $max;
$delta = $max - $min;
if( $max != 0 ){
$s = $delta / $max;
}
else {
# $r = $g = $b = 0 # $s = 0, $v is undef
$s = 0;
$h = -1;
return ($h, $s, $v);
}
if( $r == $max ){
$h = ( $g - $b ) / $delta; # between yellow & magenta
}
elsif( $g == $max ){
$h = 2 + ( $b - $r ) / $delta; # between cyan & yellow
}
else {
$h = 4 + ( $r - $g ) / $delta; # between magenta & cyan
}
$h *= 60; # degrees
if( $h < 0 ){
$h += 360;
}
return ($h, $s, $v);
}
=head2 HSVtoRGB ($h, $s, $v)
The $h (hue) is in degrees, ranging from 0 to 360. The two
other values, $s (saturation) and $v (value, brightness) are
ranging from 0 to 1.
If the saturation is set to 0, the colour resulting will be
in grayscale (each RGB value being the same).
=cut
sub HSVtoRGB {
my ($h, $s, $v) = @_;
my ($r, $g, $b);
my($i, $f, $p, $q, $t);
if( $s == 0 ) {
# achromatic (grey)
$r = $g = $b = $v;
return ($r, $g, $b);
}
$h /= 60; # sector 0 to 5
#$i = floor( $h );
$i = $h =~ /^(\d+)\./; # substitute for POSIX::floor function?
$f = $h - $i; # factorial part of h
$p = $v * ( 1 - $s );
$q = $v * ( 1 - $s * $f );
$t = $v * ( 1 - $s * ( 1 - $f ) );
if ($i == 0){ ($r, $g, $b) = ($v, $t, $p)}
elsif ($i == 1){ ($r, $g, $b) = ($q, $v, $p)}
elsif ($i == 2){ ($r, $g, $b) = ($p, $v, $t)}
elsif ($i == 3){ ($r, $g, $b) = ($p, $q, $v)}
elsif ($i == 4){ ($r, $g, $b) = ($t, $p, $v)}
else { ($r, $g, $b) = ($v, $p, $q)} # if 5
}
=head1 EXPORTS
Both functions are exported.
=cut
"She comes in color everywhere";
|