try gradients in Lab space, add pref to use them

This commit is contained in:
Ben Fry
2022-08-05 18:44:31 -04:00
parent 9f7f37bffa
commit 361a0393cd
3 changed files with 184 additions and 8 deletions
+161
View File
@@ -202,6 +202,15 @@ public class Theme {
static public Image makeGradient(String attribute, int wide, int high) {
if ("lab".equals(Preferences.get("theme.gradient.method"))) {
return makeGradientLab(attribute, wide, high);
} else { // otherwise go with the default
return makeGradientRGB(attribute, wide, high);
}
}
static private Image makeGradientRGB(String attribute, int wide, int high) {
int top = getColor(attribute + ".gradient.top").getRGB();
int bot = getColor(attribute + ".gradient.bottom").getRGB();
@@ -216,4 +225,156 @@ public class Theme {
}
return outgoing;
}
static private Image makeGradientLab(String attribute, int wide, int high) {
double[] top = xyzToLab(rgbToXyz(getColor(attribute + ".gradient.top")));
double[] bot = xyzToLab(rgbToXyz(getColor(attribute + ".gradient.bottom")));
double diffL = bot[0] - top[0];
double diffA = bot[1] - top[1];
double diffB = bot[2] - top[2];
BufferedImage outgoing =
new BufferedImage(wide, high, BufferedImage.TYPE_INT_RGB);
int[] row = new int[wide];
WritableRaster wr = outgoing.getRaster();
for (int i = 0; i < high; i++) {
double amt = i / (high - 1.0);
double el = top[0] + amt * diffL;
double ay = top[1] + amt * diffA;
double be = top[2] + amt * diffB;
int rgb = argb(xzyToRgb(labToXyz(el, ay, be)));
Arrays.fill(row, rgb);
wr.setDataElements(0, i, wide, 1, row);
}
return outgoing;
}
// https://web.archive.org/web/20060213080500/http://www.easyrgb.com/math.php?MATH=M2#text2
// Observer= 2°, Illuminant= D65;
static final double REF_X = 95.047;
static final double REF_Y = 100.0;
static final double REF_Z = 108.883;
static private double[] rgbToXyz(Color color) {
double var_R = color.getRed() / 255.0;
double var_G = color.getGreen() / 255.0;
double var_B = color.getBlue() / 255.0;
var_R = 100 * ((var_R > 0.04045) ?
Math.pow((var_R + 0.055) / 1.055, 2.4) : var_R / 12.92);
var_G = 100 * ((var_G > 0.04045) ?
Math.pow((var_G + 0.055) / 1.055, 2.4) : var_G / 12.92);
var_B = 100 * ((var_B > 0.04045) ?
Math.pow((var_B + 0.055) / 1.055, 2.4) : var_B / 12.92);
// Observer = 2°, Illuminant = D65
return new double[] {
var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805,
var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722,
var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
};
}
static private double[] xyzToLab(double[] xyz) {
double var_X = xyz[0] / REF_X; // Observer= 2°, Illuminant= D65
double var_Y = xyz[1] / REF_Y;
double var_Z = xyz[2] / REF_Z;
var_X = (var_X > 0.008856) ?
Math.pow(var_X, 1/3.0) : (7.787*var_X + 16/116.0);
var_Y = (var_Y > 0.008856) ?
Math.pow(var_Y, 1/3.0) : (7.787*var_Y + 16/116.0);
var_Z = (var_Z > 0.008856) ?
Math.pow(var_Z, 1/3.0) : (7.787*var_Z + 16/116.0);
return new double[] {
(116 * var_Y) - 16,
500 * (var_X - var_Y),
200 * (var_Y - var_Z)
};
}
// static private double[] labToXyz(double[] lab) {
// double var_Y = (lab[0] + 16) / 116.0;
// double var_X = lab[1] / 500 + var_Y;
// double var_Z = var_Y - lab[2] / 200.0;
static private double[] labToXyz(double el, double ay, double be) {
double var_Y = (el + 16) / 116;
double var_X = ay / 500 + var_Y;
double var_Z = var_Y - be / 200;
// if ( var_Y^3 > 0.008856 ) var_Y = var_Y^3
// else var_Y = ( var_Y - 16 / 116 ) / 7.787
// if ( var_X^3 > 0.008856 ) var_X = var_X^3
// else var_X = ( var_X - 16 / 116 ) / 7.787
// if ( var_Z^3 > 0.008856 ) var_Z = var_Z^3
// else var_Z = ( var_Z - 16 / 116 ) / 7.787
final double amt = Math.pow(0.008856, 1/3.0);
var_Y = (var_Y > amt) ?
Math.pow(var_Y, 3) : (var_Y - 16/116.0) / 7.787;
var_X = (var_X > amt) ?
Math.pow(var_X, 3) : (var_X - 16/116.0) / 7.787;
var_Z = (var_Z > amt) ?
Math.pow(var_Z, 3) : (var_Z - 16/116.0) / 7.787;
// X = ref_X * var_X //ref_X = 95.047 Observer= 2°, Illuminant= D65
// Y = ref_Y * var_Y //ref_Y = 100.000
// Z = ref_Z * var_Z //ref_Z = 108.883
return new double[] {
REF_X * var_X,
REF_Y * var_Y,
REF_Z * var_Z
};
}
static private double[] xzyToRgb(double[] xyz) {
double var_X = xyz[0] / 100; // Where X = 0 ÷ 95.047
double var_Y = xyz[1] / 100; // Where Y = 0 ÷ 100.000
double var_Z = xyz[2] / 100; // Where Z = 0 ÷ 108.883
double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986;
double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415;
double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570;
// if ( var_R > 0.0031308 ) var_R = 1.055 * ( var_R ^ ( 1 / 2.4 ) ) - 0.055
// else var_R = 12.92 * var_R
// if ( var_G > 0.0031308 ) var_G = 1.055 * ( var_G ^ ( 1 / 2.4 ) ) - 0.055
// else var_G = 12.92 * var_G
// if ( var_B > 0.0031308 ) var_B = 1.055 * ( var_B ^ ( 1 / 2.4 ) ) - 0.055
// else var_B = 12.92 * var_B
var_R = (var_R > 0.0031308) ?
1.055 * Math.pow(var_R, 1/2.4) - 0.055 : 12.92 * var_R;
var_G = (var_G > 0.0031308) ?
1.055 * Math.pow(var_G, 1/2.4) - 0.055 : 12.92 * var_G;
var_B = (var_B > 0.0031308) ?
1.055 * Math.pow(var_B, 1/2.4) - 0.055 : 12.92 * var_B;
return new double[] {
var_R * 255,
var_G * 255,
var_B * 255
};
}
static private int bounded(double amount) {
return Math.max(0, Math.min((int) Math.round(amount), 255));
}
static private int argb(double[] rgb) {
return 0xff000000 |
bounded(rgb[0]) << 16 | bounded(rgb[1]) << 8 | bounded(rgb[2]);
}
}
+4
View File
@@ -81,6 +81,9 @@ chooser.files.native = true
# https://github.com/processing/processing4/issues/77
#chooser.files.native.macos = false
# set to 'lab' to interpolate theme gradients using L*a*b* color space
theme.gradient.method = rgb
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -93,6 +96,7 @@ update.check = true
# on windows, automatically associate .pde files with processing.exe
platform.auto_file_type_associations = true
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# default font used for UI elements (no longer in use as of beta 9)
+19 -8
View File
@@ -1,6 +1,18 @@
1285 (4.0?)
X try gradients in Lab space
X not an obvious win, so set as a pref and come back to it later
docs
X update theme instructions
X https://github.com/processing/processing4/wiki/Themes
X update the platforms page
X https://github.com/processing/processing4/wiki/Supported-Platforms
o rename to 'platforms'?
cleaning
X the gradient.top and gradient.bottom lines are used by makeGradient(),
X so search for makeGradient() calls to see whether they're still in use.
X having brought back some gradient themes for beta 9, we'll keep this in place
known issues
@@ -169,17 +181,13 @@ _ theme_selector.combo_box.enabled.bgcolor
_ theme_selector.combo_box.enabled.bgcolor
_ dont update dynamically unless you (a) select Minerals or Alloys
_ or (b) open, then close the dropdown
_ build new welcome/examples screen for startup
_ implement document icons on Windows
_ implement document icons on Linux
_ add notes about params to the wiki
_ the gradient.top and gradient.bottom lines are used by makeGradient(),
_ so search for makeGradient() calls to see whether they're still in use.
4.0
_ how to handle contrib manager download/retry/etc and showing progress
_ do gradients in Lab space
_ adding a file to an untitled sketch should require a save
_ Cannot type quotes with an international keyboard on MacOS
_ fixed by turning on "Enable complex text input"
@@ -195,19 +203,22 @@ _ really a drag for version control
_ https://github.com/processing/processing/issues/5848
_ or at least avoid the multiple
_ https://github.com/processing/processing4/issues/330
_ update the platforms page
_ https://github.com/processing/processing4/wiki/Supported-Platforms
_ if error in the code during export, it's just saying "error during export"
_ is this still the case?
_ chars[] array is never used in ascii video example
_ ui scaling in the PDE is important for classes/seeing at a distance
_ Export to Application was broken with OpenGL (Casey)
_ add a version of this to the 4.x repo
_ https://github.com/processing/processing/wiki/troubleshooting
_ and update the Help menu to link to it
_ and maybe the FAQ too?
4.0 / with Casey
_ Export to Application was broken with OpenGL (Casey)
_ resolution for the About screen
_ examples still coming from processing-docs repo
_ chars[] array is never used in ascii video example
4.0 / movie maker
_ break Movie Maker out to its own library?
_ another big leap in file size reduction for the PDE download