Add a basic color palette generator
This commit is contained in:
parent
03a8ae9a24
commit
c49b042b62
2
slop/palette/.gitignore
vendored
Normal file
2
slop/palette/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
palette.png
|
184
slop/palette/index.mjs
Normal file
184
slop/palette/index.mjs
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import Color from "colorjs.io/dist/color.js";
|
||||||
|
import {PNG} from "pngjs";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
function generateColors() {
|
||||||
|
let pad = function(n) {
|
||||||
|
while (colors.length < n) {
|
||||||
|
colors.push(new Color("slategray"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let band = function(colors) {
|
||||||
|
return function(point, shimmer) {
|
||||||
|
point += shimmer;
|
||||||
|
var ix2 = point * colors.length;
|
||||||
|
while (ix2 < 0) { ix2 += colors.length; }
|
||||||
|
|
||||||
|
return colors[Math.floor(ix2) % colors.length].mix(
|
||||||
|
colors[Math.floor(ix2 + 1) % colors.length],
|
||||||
|
ix2 % 1,
|
||||||
|
{"space": "oklch", "outputSpace": "oklab"}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ramp = function(start, c0, c1, c2) {
|
||||||
|
// deep base -> center -> pastel
|
||||||
|
var r01 = c0.range(c1, {space: "oklab", outputSpace: "oklch"});
|
||||||
|
var r12 = c1.range(c2, {space: "oklab", outputSpace: "oklch"});
|
||||||
|
var n = 5;
|
||||||
|
var i = 0;
|
||||||
|
for (var amt = 0; amt < n; amt++) {
|
||||||
|
colors[start + i * 8] = r01(amt/(n - 1));
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
n = 3;
|
||||||
|
for (var amt = 1; amt < n; amt++) {
|
||||||
|
colors[start + i * 8] = r12(amt/(n - 1));
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var colors = [];
|
||||||
|
|
||||||
|
// we were originally appending these
|
||||||
|
// but for now, just prefill all the slots
|
||||||
|
pad(64); // so the slots are filled and we can replace them
|
||||||
|
|
||||||
|
// system colors
|
||||||
|
colors[0] = new Color("#000000");
|
||||||
|
colors[1] = new Color("#0000ff");
|
||||||
|
colors[2] = new Color("#00ff00");
|
||||||
|
colors[3] = new Color("#00ffff");
|
||||||
|
colors[4] = new Color("#ff0000");
|
||||||
|
colors[5] = new Color("#ff00ff");
|
||||||
|
colors[6] = new Color("#ffff00");
|
||||||
|
colors[7] = new Color("#ffffff");
|
||||||
|
|
||||||
|
for (var i = 0; i < 8; i++) {
|
||||||
|
// colors[i].hsv.h += 135.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lowBand = band([
|
||||||
|
new Color("oklch(11.2% 0.0744 268.04)"),
|
||||||
|
new Color("oklch(15.55% 0.0782 310.39)"),
|
||||||
|
new Color("oklch(21.51% 0.0864 357.28)"),
|
||||||
|
new Color("oklch(22.74% 0.0755 43.16)"),
|
||||||
|
new Color("oklch(23.84% 0.0733 145.59)"),
|
||||||
|
new Color("oklch(27.4% 0.0444 171.2)"), // NOTE: This reproduces terribly
|
||||||
|
new Color("oklch(19.1% 0.0396 233.51)"), // NOTE: This reproduces terribly
|
||||||
|
new Color("oklch(18.63% 0.0575 259.12)"), // NOTE: This reproduces terribly
|
||||||
|
]);
|
||||||
|
|
||||||
|
let middleBand = band([
|
||||||
|
new Color("oklch(55.34% 0.241 291.34)"),
|
||||||
|
new Color("oklch(58.54% 0.1994 330.82)"),
|
||||||
|
new Color("oklch(63.2% 0.2135 20.28)"),
|
||||||
|
new Color("oklch(80.34% 0.16 70.47)"),
|
||||||
|
new Color("oklch(91.95% 0.23681720512967358 126.89394948265881)"),
|
||||||
|
new Color("oklch(87.99% 0.2353 147.34)"),
|
||||||
|
new Color("oklch(86.44% 0.1505 187.42)"),
|
||||||
|
new Color("oklch(74.91% 0.1505 235.22)"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let highBand = band([
|
||||||
|
new Color("oklch(92.3% 0.041 317.16)"),
|
||||||
|
new Color("oklch(94.93% 0.0217 358.04)"),
|
||||||
|
new Color("oklch(95.21% 0.0101 7.31)"),
|
||||||
|
new Color("oklch(98.41% 0.0172 88.4)"),
|
||||||
|
new Color("oklch(99.58% 0.00969628196819721 125.6732391579389)"),
|
||||||
|
new Color("oklch(97.53% 0.0584 127.22)"),
|
||||||
|
new Color("oklch(96.38% 0.0465 167.45)"),
|
||||||
|
new Color("oklch(95.21% 0.0475 214.73)"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
var lowRampIx = (i - 0.25) / 4;
|
||||||
|
var low = lowBand(lowRampIx, -0.3);
|
||||||
|
var middle = middleBand(lowRampIx, 0.0);
|
||||||
|
colors[8 + i * 2] = low.mix(middle, 0.2/4.0, {space: "oklab"})
|
||||||
|
colors[8 + i * 2 + 1] = low.mix(middle, 0.8/4.0, {space: "oklab"})
|
||||||
|
colors[8 + i * 2].oklch.c *= 0.4;
|
||||||
|
colors[8 + i * 2 + 1].oklch.c *= 0.5;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
for (var c = 1; c < 3; c++) {
|
||||||
|
var lowRampIx = (i - 0.25) / 4;
|
||||||
|
var low = lowBand(lowRampIx, -0.3);
|
||||||
|
var middle = middleBand(lowRampIx, 0.0);
|
||||||
|
var cbase = low.mix(middle, ([2.1, 3.1, 4.0][c - 1])/4, {space: "oklab"})
|
||||||
|
colors[8 + i * 2 + c * 8] = cbase
|
||||||
|
var color2 = low.mix(middle, ([1.7, 2.7, 3.5][c - 1])/4, {space: "oklab"})
|
||||||
|
color2.oklch.c *= 0.6
|
||||||
|
colors[8 + i * 2 + 1 + c * 8] = color2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 8; i++) {
|
||||||
|
colors[32 + i] = middleBand((i - 1) / 8, 0.0);
|
||||||
|
colors[32 + i + 8] =
|
||||||
|
middleBand((i - 1) / 8, 0.0).mix(highBand((i - 1) / 8, 0.15), 1.5/5, {space: "oklch"})
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
var highRampIx = (i - 0.25) / 4;
|
||||||
|
colors[48 + i * 2] =
|
||||||
|
middleBand(highRampIx, 0.0).mix(highBand(highRampIx, 0.15), 2.4/5, {space: "oklch"})
|
||||||
|
colors[48 + i * 2 + 1] =
|
||||||
|
middleBand(highRampIx, 0.0).mix(highBand(highRampIx, 0.15), 3.4/5, {space: "oklch"})
|
||||||
|
colors[48 + i * 2 + 1].lch.c *= 0.7
|
||||||
|
}
|
||||||
|
for (var i = 0; i < 4; i++) {
|
||||||
|
var highRampIx = (i - 0.25) / 4;
|
||||||
|
colors[56 + i * 2] =
|
||||||
|
middleBand(highRampIx, 0.0).mix(highBand(highRampIx, 0.15), 4.3/5, {space: "oklch"})
|
||||||
|
colors[56 + i * 2].lch.c *= 0.6
|
||||||
|
colors[56 + i * 2 + 1] =
|
||||||
|
middleBand(highRampIx, 0.0).mix(highBand(highRampIx, 0.1), 5/5, {space: "oklch"})
|
||||||
|
colors[56 + i * 2 + 1].lch.c *= 0.4
|
||||||
|
colors[56 + i * 2].lch.l =
|
||||||
|
colors[56 + i * 2].lch.l * 0.25 +
|
||||||
|
colors[56 + i * 2 + 1].lch.l * 0.75
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for (var i = 0; i < 8; i++) {
|
||||||
|
colors[8 + i] = middleBand(i/8.0);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function dump(fname, colors, width, height, scalar) {
|
||||||
|
if (colors.length != width * height) {
|
||||||
|
throw new Error("wrong number of colors: " + colors.length);
|
||||||
|
}
|
||||||
|
let pngdata = [];
|
||||||
|
|
||||||
|
let clamp = function(x) {
|
||||||
|
if (x < 0.0) { return 0.0; }
|
||||||
|
if (x > 255.0) { return 255.0; }
|
||||||
|
return Math.round(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var y = 0; y < height * scalar; y++) {
|
||||||
|
for (var x = 0; x < width * scalar; x++) {
|
||||||
|
let i = Math.floor(y / scalar) * width + Math.floor(x / scalar);
|
||||||
|
|
||||||
|
pngdata.push(clamp(255 * colors[i].srgb.r));
|
||||||
|
pngdata.push(clamp(255 * colors[i].srgb.g));
|
||||||
|
pngdata.push(clamp(255 * colors[i].srgb.b));
|
||||||
|
pngdata.push(255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var png = new PNG({
|
||||||
|
width: width * scalar,
|
||||||
|
height: height * scalar
|
||||||
|
});
|
||||||
|
png.data = pngdata;
|
||||||
|
png.pack().pipe(fs.createWriteStream(fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
dump("palette.png", generateColors(), 8, 8, 64);
|
30
slop/palette/package-lock.json
generated
Normal file
30
slop/palette/package-lock.json
generated
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "palette",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "palette",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"colorjs.io": "^0.5.0",
|
||||||
|
"pngjs": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/colorjs.io": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-qekjTiBLM3F/sXKks/ih5aWaHIGu+Ftel0yKEvmpbKvmxpNOhojKgha5uiWEUOqEpRjC1Tq3nJRT7WgdBOxIGg=="
|
||||||
|
},
|
||||||
|
"node_modules/pngjs": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.19.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
slop/palette/package.json
Normal file
16
slop/palette/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "palette",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"main": "node index.mjs",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"colorjs.io": "^0.5.0",
|
||||||
|
"pngjs": "^7.0.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user