#!/usr/bin/env perl # colorscheme.pl # # Written in 2020 by Lucas # # To the extent possible under law, the author(s) have dedicated all # copyright and related and neighboring rights to this software to the # public domain worldwide. This software is distributed without any # warranty. # # You should have received a copy of the CC0 Public Domain Dedication # along with this software. If not, see # . use v5.12; use strict; use warnings; use Getopt::Std; use POSIX qw(fmod); use constant { LENGTH => 50, }; my $progname = $0; $progname =~ s@.*/@@; sub err (@) { say STDERR "$progname: @_"; exit 1; } sub usage () { say STDERR "Usage: $progname [-i]"; exit 1; } sub validhsv ($$$) { my ($h, $s, $v) = @_; return $h >= 0.0 && $h <= 360.0 && $s >= 0.0 && $s <= 1.0 && $v >= 0.0 && $v <= 1.0; } sub validhsl ($$$) { my ($h, $s, $l) = @_; return $h >= 0.0 && $h <= 360.0 && $s >= 0.0 && $s <= 1.0 && $l >= 0.0 && $l <= 1.0; } sub validrgb ($$$) { my ($r, $g, $b) = @_; return $r >= 0 && $r <= 255 && $g >= 0 && $g <= 255 && $b >= 0 && $b <= 255; } sub validrgbhex ($$$) { my ($r, $g, $b) = @_; return $r =~ /^[0-9A-Fa-f]{2}$/ && $g =~ /^[0-9A-Fa-f]{2}$/ && $b =~ /^[0-9A-Fa-f]{2}$/; } sub hsvtorgb ($$$) { my ($h, $s, $v) = @_; my $c = $s * $v; my $hh = $h == 360.0 ? 0.0 : $h / 60.0; my $x = $c * (1.0 - abs(fmod($hh, 2.0) - 1.0)); my ($r, $g, $b); for (int($hh)) { ($r, $g, $b) = ($c, $x, 0) if $_ == 0; ($r, $g, $b) = ($x, $c, 0) if $_ == 1; ($r, $g, $b) = (0, $c, $x) if $_ == 2; ($r, $g, $b) = (0, $x, $c) if $_ == 3; ($r, $g, $b) = ($x, 0, $c) if $_ == 4; ($r, $g, $b) = ($c, 0, $x) if $_ == 5; } my $m = $v - $c; return map {255 * ($_ + $m)} $r, $g, $b; } sub hsltorgb ($$$) { my ($h, $s, $l) = @_; my $c = (1.0 - abs(2.0 * $l - 1.0)) * $s; my $hh = $h == 360.0 ? 0.0 : $h / 60.0; my $x = $c * (1.0 - abs(fmod($hh, 2.0) - 1.0)); my ($r, $g, $b); for (int($hh)) { ($r, $g, $b) = ($c, $x, 0) if $_ == 0; ($r, $g, $b) = ($x, $c, 0) if $_ == 1; ($r, $g, $b) = (0, $c, $x) if $_ == 2; ($r, $g, $b) = (0, $x, $c) if $_ == 3; ($r, $g, $b) = ($x, 0, $c) if $_ == 4; ($r, $g, $b) = ($c, 0, $x) if $_ == 5; } my $m = $l - $c / 2.0; return map {255 * ($_ + $m)} $r, $g, $b; } sub parseinput () { my @colors; while (my $line = ) { chomp $line; next if $line =~ /^#|^$/; my ($t, $x, $y, $z, undef) = split(/\s+/, $line, 5); my @v; if ($t eq "hsv") { die "invalid input: $line" unless validhsv($x, $y, $z); @v = map {int} hsvtorgb($x, $y, $z); } elsif ($t eq "hsl") { die "invalid input: $line" unless validhsl($x, $y, $z); @v = map {int} hsltorgb($x, $y, $z); } elsif ($t eq "rgb") { die "invalid input: $line" unless validrgb($x, $y, $z); @v = map {int} ($x, $y, $z); } elsif ($t eq "rgbhex") { die "invalid input: $line" unless validrgbhex($x, $y, $z); @v = map {hex} ($x, $y, $z); } else { die "invalid input: $line"; } push(@colors, \@v); } return @colors; } sub main () { my %opts; getopts("i", \%opts) or usage; my @colors = parseinput(); if (defined($opts{"i"})) { err "Colorscheme doesn't have 18 colors" if scalar(@colors) != 18; printf "P6\n%u %u 255\n", 9 * LENGTH, 2 * LENGTH; for (0..LENGTH - 1) { for (0..8) { print pack("CCC", @{$colors[$_]}) x LENGTH; } } for (0..LENGTH - 1) { for (9..17) { print pack("CCC", @{$colors[$_]}) x LENGTH; } } } else { foreach (@colors) { say "#", (map {sprintf "%02x", $_} @$_); } } } main();