themes: convert colorscheme.c to Perl

This commit is contained in:
Lucas 2020-12-06 15:08:37 +00:00
parent e71a6eb321
commit 54a7ab5e6e
3 changed files with 183 additions and 210 deletions

View File

@ -1,5 +1,5 @@
# env # env
# Written in 2019 by Lucas # Written in 2019-2020 by Lucas
# CC0 1.0 Universal/Public domain - No rights reserved # CC0 1.0 Universal/Public domain - No rights reserved
# #
# To the extent possible under law, the author(s) have dedicated all # To the extent possible under law, the author(s) have dedicated all
@ -10,25 +10,21 @@
# <http://creativecommons.org/publicdomain/zero/1.0/>. # <http://creativecommons.org/publicdomain/zero/1.0/>.
.POSIX: .POSIX:
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .c .in .txt .png .SUFFIXES: .in .txt .png
LDLIBS= -lm
THEMES= blueie brightie brightie2 brightie3 brightie4 THEMES= blueie brightie brightie2 brightie3 brightie4
.c:
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
.in.txt: .in.txt:
./colorscheme <"$<" >"$@" perl colorscheme.pl <"$<" >"$@"
.in.png: .in.png:
./colorscheme -i <"$<" | pnmtopng >"$@" perl colorscheme.pl -i <"$<" | pnmtopng >"$@"
all: colorscheme all: colorscheme.pl
clean: clean:
rm -f colorscheme $(THEMES:=.png) $(THEMES:=.txt) rm -f $(THEMES:=.png) $(THEMES:=.txt)
show: $(THEMES:=.png) $(THEMES:=.txt) show: $(THEMES:=.txt) $(THEMES:=.png)
$(THEMES:=.png) $(THEMES:=.txt): all $(THEMES:=.txt) $(THEMES:=.png): all

View File

@ -1,198 +0,0 @@
/*
* env
* Written in 2019 by Lucas
* CC0 1.0 Universal/Public domain - No rights reserved
*
* 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
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <errno.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 50
#define INRANGE(x, a, b) ((a) <= (x) && (x) <= (b))
static void
hsvtorgb(double hsv[3], uint8_t rgb[3])
{
double c, hh, m, x;
double r, g, b;
c = hsv[2] * hsv[1];
hh = hsv[0] / 60.0;
x = c * (1.0 - fabs(fmod(hh, 2.0) - 1.0));
switch ((int)floor(hh == 6.0 ? 0.0 : hh)) {
case 0: r = c; g = x; b = 0; break;
case 1: r = x; g = c; b = 0; break;
case 2: r = 0; g = c; b = x; break;
case 3: r = 0; g = x; b = c; break;
case 4: r = x; g = 0; b = c; break;
case 5: r = c; g = 0; b = x; break;
}
m = hsv[2] - c;
r += m; g += m; b += m;
rgb[0] = round(255 * r);
rgb[1] = round(255 * g);
rgb[2] = round(255 * b);
}
static void
hsltorgb(double hsl[3], uint8_t rgb[3])
{
double c, hh, m, x;
double r, g, b;
c = (1.0 - fabs(2.0 * hsl[2] - 1.0)) * hsl[1];
hh = hsl[0] / 60.0;
x = c * (1.0 - fabs(fmod(hh, 2.0) - 1.0));
switch ((int)floor(hh == 6.0 ? 0.0 : hh)) {
case 0: r = c; g = x; b = 0; break;
case 1: r = x; g = c; b = 0; break;
case 2: r = 0; g = c; b = x; break;
case 3: r = 0; g = x; b = c; break;
case 4: r = x; g = 0; b = c; break;
case 5: r = c; g = 0; b = x; break;
}
m = hsl[2] - c / 2.0;
r += m; g += m; b += m;
rgb[0] = round(255 * r);
rgb[1] = round(255 * g);
rgb[2] = round(255 * b);
}
static void
parsecolorline(const char *s, size_t n, uint8_t rgb[3])
{
double d[3];
unsigned int u[3];
if (sscanf(s, "hsv %lf %lf %lf", &d[0], &d[1], &d[2]) == 3) {
if (!INRANGE(d[0], 0, 360) || !INRANGE(d[1], 0, 1)
|| !INRANGE(d[2], 0, 1))
goto err;
hsvtorgb(d, rgb);
} else if (sscanf(s, "hsl %lf %lf %lf", &d[0], &d[1], &d[2]) == 3) {
if (!INRANGE(d[0], 0, 360) || !INRANGE(d[1], 0, 1)
|| !INRANGE(d[2], 0, 1))
goto err;
hsltorgb(d, rgb);
} else if (sscanf(s, "rgb %u %u %u", &u[0], &u[1], &u[2]) == 3) {
if (!INRANGE(u[0], 0, 255) || !INRANGE(u[1], 0, 255)
|| !INRANGE(u[2], 0, 255))
goto err;
rgb[0] = u[0]; rgb[1] = u[1]; rgb[2] = u[2];
} else if (sscanf(s, "rgbhex %x %x %x", &u[0], &u[1], &u[2]) == 3) {
if (!INRANGE(u[0], 0, 255) || !INRANGE(u[1], 0, 255)
|| !INRANGE(u[2], 0, 255))
goto err;
rgb[0] = u[0]; rgb[1] = u[1]; rgb[2] = u[2];
} else {
err:
fprintf(stderr, "Invalid input: \"%s\".", s);
exit(1);
}
}
static void
readcolorscheme(uint8_t colorscheme[18][3])
{
char *line = NULL;
size_t linesize = 0;
ssize_t linelen;
int nlines = 0;
while ((linelen = getline(&line, &linesize, stdin)) != -1
&& nlines < 18) {
if (linelen == 0 || line[0] == '\n' || line[0] == '#')
continue;
parsecolorline(line, linelen, colorscheme[nlines]);
nlines++;
}
free(line);
if (ferror(stdin)) {
fputs("Input error.\n", stderr);
exit(1);
}
if (nlines < 18) {
fputs("Not enought colors.\n", stderr);
exit(1);
}
}
static void
writecolor(uint8_t rgb[3], int l)
{
int i;
for (i = 0; i < l; i++) {
if (fwrite(rgb, sizeof(rgb[0]), 3, stdout) != 3) {
fputs("Short write.\n", stderr);
exit(1);
}
}
}
static void
do_image(uint8_t colorscheme[18][3])
{
int i, n;
printf("P6\n%u %u 255\n", 9 * LENGTH, 2 * LENGTH);
for (i = 0; i < LENGTH; i++)
for (n = 0; n < 9; n++)
writecolor(colorscheme[n], LENGTH);
for (i = 0; i < LENGTH; i++)
for (n = 9; n < 18; n++)
writecolor(colorscheme[n], LENGTH);
}
static void
do_colors(uint8_t colorscheme[18][3])
{
int n;
for (n = 0; n < 18; n++)
printf("#%02x%02x%02x\n", colorscheme[n][0],
colorscheme[n][1], colorscheme[n][2]);
}
int
main(int argc, char *argv[])
{
uint8_t colorscheme[18][3];
int iflag = 0;
if (argc > 2)
goto usage;
if (argc == 2) {
if (strncmp(argv[1], "-i", 3) != 0)
goto usage;
iflag = 1;
}
readcolorscheme(colorscheme);
if (iflag)
do_image(colorscheme);
else
do_colors(colorscheme);
return 0;
usage:
fprintf(stderr, "Usage: %s [-i]\n", argv[0]);
return 1;
}

175
themes/colorscheme.pl Normal file
View File

@ -0,0 +1,175 @@
#!/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
# <http://creativecommons.org/publicdomain/zero/1.0/>.
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 = <STDIN>) {
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();