Error value in Processing color()?
Description of this creative coding.
It's a creative coding art work made with Processing on Java programming language.
I had a problem with deciding which colors should I use? I want to do everything automatically. So I tried to use color scheme generator web service. And I found colormind API.
Colormind is a color scheme generator that uses deep learning.
http://colormind.io/
I use this API and draw Archimedes's spiral with these colors.
This code does not display any images on the screen but generates image files in frames directory.
Error value in Processing color()?
Colormind give me 5 colors. I choose darker 2 colors as the background color.
So I should sort by brightness. Colormind color format was RGB. So I thought I should translate it to HSB and get brightness.
Then I found it...
colorMode(HSB, 360.0, 100.0, 100.0);
color c = color(10.0, 10.0, 10.0);
println(hue(c), saturation(c), brightness(c))
19.999998 12.0 9.803922
What the heck! It must be "10.0 10.0 10.0"!
Processing inside seems to have color data as RGB. These RGB values seems to be 0-255 in integer. And the decimal point may be suppressed!
HSB(10.0, 10.0, 10.0)
-> To be exact RGB(25.500, 23.375, 22.950)
-> Inside Processing RGB(25, 23, 22)
Let me try to calculate RGB -> HSB.
60.000 * ((23.375 - 22.950) / (25.500 - 22.950)) = 9.999999996
60.000 * ((23.000 - 22.000) / (25.000 - 22.000)) = 19.999999998
These results supports my thought.
Thanks to ryotako for giving me a splendid insight.
追加情報です! colorMode(HSB, 360, 100, 100) にしたときの color(10, 10, 10) が表す色のRGB値(255段階)は (25.5, 23.375, 22.95) になるはずが、内部的に端数切捨てで (25, 23, 22) になってるっぽいですね...— ryotako (@ryotakob) October 27, 2019
この端数切捨て分をもとに戻せないのでHSB値に戻せない... ということかもです pic.twitter.com/z84LwensDn
By the way, p5.js returns like this.
c = color(10.0, 10.0, 10.0);
console.log(hue(c) + "\t" + saturation(c) + "\t" + brightness(c));
9.999999999999986 9.999999999999995 10
Processing code example.
Please feel free to use this example code of Processing under the terms of the GPL.
To see other works based on my code is my pleasure. And my honor.
Shell script.
#!/bin/bash
# colormind API
ifsBackup=$IFS
IFS=$'\n'
prmcolor=($(curl 'http://colormind.io/api/' --data '{"model":"default"}' | awk -F ':' '{ print $2 }' | tr -d []}))
IFS=${ifsBackup}
# run processing sketch
processing-java --force --sketch=./Bad_Moon_Rising/ --run ${prmcolor}
Processing.
/**
* Big Ten Inch Record.
* get RGB color code from args and draw Archimedes's spiral with these.
*
* @author @deconbatch
* @version 0.1
* Processing 3.2.1
* created : 19.11.03
*/
void setup() {
size(980, 980);
rectMode(CENTER);
smooth();
noStroke();
noLoop();
}
void draw() {
int frameMax = 3; // draw 3 images
int pointMax = 5000;
float spiralGap = 2.0;
FetchColor fc = new FetchColor();
// I'll use 5 colors as 2 background and 3 foreground.
color[][] bgColor = new color[3][2];
color[][] fgColor = new color[3][3];
for (int i = 0; i < 2; i++) {
bgColor[0][i] = fc.getColor(i);
}
for (int i = 0; i < 3; i++) {
fgColor[0][i] = fc.getColor(i + 2);
}
// make 2 addtion color BGR, BRG
for (int i = 0; i < 2; i++) {
bgColor[1][i] = color(blue(bgColor[0][i]), green(bgColor[0][i]), red(bgColor[0][i]));
bgColor[2][i] = color(green(bgColor[0][i]), blue(bgColor[0][i]), red(bgColor[0][i]));
}
for (int i = 0; i < 3; i++) {
fgColor[1][i] = color(blue(fgColor[0][i]), green(fgColor[0][i]), red(fgColor[0][i]));
fgColor[2][i] = color(green(fgColor[0][i]), blue(fgColor[0][i]), red(fgColor[0][i]));
}
colorMode(RGB, 255, 255, 255, 100);
blendMode(BLEND);
translate(width / 2, height / 2);
for (int frameCnt = 0; frameCnt < frameMax; ++frameCnt) {
float startFgc = random(1.0);
float startAlp = random(1.0);
float startSiz = random(1.0);
int bgIndex = frameCnt % 2;
int fgIndex = frameCnt % 3;
background(
red(bgColor[frameCnt][bgIndex]),
green(bgColor[frameCnt][bgIndex]),
blue(bgColor[frameCnt][bgIndex]),
100.0
);
noStroke();
rotate(HALF_PI);
for (int pointCnt = 0; pointCnt < pointMax; ++pointCnt) {
float pointRatio = map(pointCnt, 0, pointMax, 0.0, 1.0);
float divRotate = sqrt(pointCnt) * 2.0;
float radian = TWO_PI / divRotate * pointCnt;
float pX = spiralGap * radian * cos(radian);
float pY = spiralGap * radian * sin(radian);
int fgcIndex = (fgIndex + floor(map(sin(TWO_PI * (startFgc + pointRatio * spiralGap * 20.0)), -1.0, 1.0, 0.0, 2.9))) % 3;
float pointAlp = map(sin(TWO_PI * (startAlp + pointRatio * spiralGap * 40.0)), -1.0, 1.0, 30.0, 100.0);
float pointSiz = map(sin(TWO_PI * (startSiz + pointRatio * spiralGap * 15.0)), -1.0, 1.0, 0.5, 1.0) * spiralGap * 4.5;
fill(
red(fgColor[frameCnt][fgcIndex]),
green(fgColor[frameCnt][fgcIndex]),
blue(fgColor[frameCnt][fgcIndex]),
pointAlp
);
ellipse(pX, pY, pointSiz, pointSiz);
}
casing();
saveFrame("frames/" + String.format("%04d", frameCnt) + ".png");
}
exit();
}
/**
* casing : draw fancy casing
*/
private void casing() {
fill(0.0, 0.0, 0.0, 0.0);
strokeWeight(54.0);
stroke(0.0, 0.0, 0.0, 100.0);
rect(0.0, 0.0, width, height);
strokeWeight(50.0);
stroke(255.0, 255.0, 255.0, 100.0);
rect(0.0, 0.0, width, height);
noStroke();
noFill();
}
/**
* FetchColor : get 5 RGB color infomation from args and sort descending them by brightness.
*
*/
import java.util.Arrays;
import java.util.Comparator;
class FetchColor {
int colorCnt = 5;
color[] colorAry = new color[colorCnt];
FetchColor() {
colorMode(RGB, 255);
for (int i = 0; i < colorCnt; i++) {
colorAry[i] = color(255, 255, 255);
}
// get 5 RGB color infomation from args.
// and translate RGB to HSB
color[] argColor = new color[colorCnt];
float[] baseHue = new float[colorCnt];
float[] baseSat = new float[colorCnt];
float[] baseBri = new float[colorCnt];
if (args == null) {
for (int i = 0; i < colorCnt; i++) {
colorMode(HSB, 360, 100, 100, 100);
baseHue[i] = random(360.0);
baseSat[i] = 40.0;
baseBri[i] = 10.0 + i * 10.0;
argColor[i] = color(baseHue[i], baseSat[i], baseBri[i], 100.0);
}
} else {
int cnt = 0;
int i = 0;
float r = 0.0;
float g = 0.0;
float b = 0.0;
for (String s : args[0].split(",", 0)) {
if (cnt % 3 == 0) r = float(s);
if (cnt % 3 == 1) g = float(s);
if (cnt % 3 == 2) {
b = float(s);
colorMode(RGB, 255);
argColor[i] = color(r, g, b);
colorMode(HSB, 360, 100, 100, 100);
baseHue[i] = hue(argColor[i]);
baseSat[i] = saturation(argColor[i]);
baseBri[i] = brightness(argColor[i]);
i++;
}
cnt++;
}
}
// sort descending by brightness
colorMode(RGB, 255);
float[][] sortBri = new float[colorCnt][2];
for (int i = 0; i < colorCnt; i++) {
sortBri[i][0] = baseBri[i];
sortBri[i][1] = i;
}
Arrays.sort(sortBri, new Comparator<float[]>() {
@Override
public int compare(float[] a, float[] b) {
if(a[0] > b[0]) {
return 1;
} else if(a[0] < b[0]) {
return -1;
}
return 0;
}
}
);
for (int i = 0; i < colorCnt; i++) {
colorAry[i] = argColor[int(sortBri[i][1])];
}
}
color getColor(int i) {
return colorAry[i];
}
}
/*
Copyright (C) 2019- deconbatch
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 3 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, see <http://www.gnu.org/licenses/>
*/