summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/Smokeping/Colorspace.pm148
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/Smokeping/Colorspace.pm b/lib/Smokeping/Colorspace.pm
new file mode 100644
index 0000000..9f58357
--- /dev/null
+++ b/lib/Smokeping/Colorspace.pm
@@ -0,0 +1,148 @@
+# -*- perl -*-
+
+package Smokeping::Colorspace;
+
+=head1 OVERVIEW
+
+This module provides simple colorspace conversion methods, primarily allowing
+conversion from RGB (red, green, blue) to and from HSL (hue, saturation, luminosity).
+
+=head1 COPYRIGHT
+
+Copyright 2006 by Grahame Bowland.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public
+License along with this program; if not, write to the Free
+Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+02139, USA.
+
+=head1 AUTHOR
+
+Grahame Bowland <grahame.bowland@uwa.edu.au>
+
+=cut
+
+sub web_to_rgb {
+ my $web = shift;
+ $web =~ s/^#//;
+ my @rgb = (hex(substr($web, 0, 2)) / 255,
+ hex(substr($web, 2, 2)) / 255,
+ hex(substr($web, 4, 2)) / 255) ;
+ return @rgb;
+}
+
+sub rgb_to_web {
+ my @rgb = @_;
+ return sprintf("#%.2x%.2x%.2x", 255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]);
+}
+
+sub min_max_indexes {
+ my $idx = 0;
+ my ($min_idx, $min, $max_idx, $max);
+ my @l = @_;
+
+ foreach my $i (@l) {
+ if (not defined($min) or ($i < $min)) {
+ $min = $i;
+ $min_idx = $idx;
+ }
+ if (not defined($max) or ($i > $max)) {
+ $max = $i;
+ $max_idx = $idx;
+ }
+ $idx++;
+ }
+ return ($min_idx, $min, $max_idx, $max);
+}
+
+# source for conversion algorithm is:
+# http://www.easyrgb.com/math.php?MATH=M18#text18
+sub rgb_to_hsl {
+ my @rgb = @_;
+ my ($h, $l, $s);
+
+ my ($min_idx, $min, $max_idx, $max) = min_max_indexes(@rgb);
+ my $delta_max = $max - $min;
+ $l = ($max + $min) / 2;
+ if ($delta_max == 0) {
+ my $h = 0;
+ my $s = 0;
+ } else {
+ if ($l < 0.5) {
+ $s = $delta_max / ($max + $min);
+ } else {
+ $s = $delta_max / (2 - $max - $min);
+ }
+ my $delta_r = ((($max - $rgb[0]) / 6) + ($max / 2)) / $delta_max;
+ my $delta_g = ((($max - $rgb[1]) / 6) + ($max / 2)) / $delta_max;
+ my $delta_b = ((($max - $rgb[2]) / 6) + ($max / 2)) / $delta_max;
+ if ($max_idx == 0) {
+ $h = $delta_b - $delta_g;
+ } elsif ($max_idx == 1) {
+ $h = (1/3) + $delta_r - $delta_b;
+ } else {
+ $h = (2/3) + $delta_g - $delta_r;
+ }
+ if ($h < 0) {
+ $h += 1;
+ } elsif ($h > 1) {
+ $h -= 1;
+ }
+ }
+ return ($h, $s, $l);
+}
+
+sub hue_to_rgb {
+ my ($v1, $v2, $vh) = @_;
+ if ($vh < 0) {
+ $vh += 1;
+ } elsif ($vh > 1) {
+ $vh -= 1;
+ }
+ if ($vh * 6 < 1) {
+ return $v1 + ($v2 - $v1) * 6 * $vh;
+ } elsif ($vh * 2 < 1) {
+ return $v2;
+ } elsif ($vh * 3 < 2) {
+ return $v1 + ($v2 - $v1) * ((2/3) - $vh) * 6;
+ } else {
+ return $v1;
+ }
+}
+
+sub hsl_to_rgb {
+ my ($h, $s, $l) = @_;
+ my ($r, $g, $b);
+ if ($s == 0) {
+ $r = $g = $b = $l;
+ } else {
+ my $ls;
+ if ($l < 0.5) {
+ $ls = $l * (1 + $s);
+ } else {
+ $ls = ($l + $s) - ($s * $l);
+ }
+ $l = 2 * $l - $ls;
+ $r = hue_to_rgb($l, $ls, $h + 1/3);
+ $g = hue_to_rgb($l, $ls, $h);
+ $b = hue_to_rgb($l, $ls, $h - (1/3));
+ }
+ return ($r, $g, $b);
+}
+
+1;
+