Now I understand why you wanted findClosestPaletteColor() to be a regular instance method: You’ve got rid of its 1st parameter!
Instead the previous parameter became a clone of the current C3 instance.
Just so you know, you can keep both static
& non-static
versions for findClosestPaletteColor().
And those new r(), g() & b() helper functions can be converted to static
inside C3Base:
static abstract class C3Base {
static final color r(final color c) {
return c >> 020 & 0xff;
}
static final color g(final color c) {
return c >> 010 & 0xff;
}
static final color b(final color c) {
return c & 0xff;
}
static final C3 findClosestPaletteColor(final C3 c, final C3[] palette) {
C3 closest = null;
int dif = MAX_INT;
for (final C3 n : palette) if (n.diff(c) < dif) dif = (closest = n).diff(c);
return closest;
}
}
Notice now that I’ve got rid of class PGraph & its corresponding static
pg field in C3Base.
In its place I’m using this formula: b | g << 010 | r << 020 | PImage.ALPHA_MASK
.
Here’s latest version for class C3 w/ even more cool features:
class C3 extends C3Base implements Comparable<C3>, Cloneable {
color r, g, b;
C3(final color c) {
r = r(c);
g = g(c);
b = b(c);
}
C3(final color r, final color g, final color b) {
set(r, g, b);
}
C3 set(final color x, final color y, final color z) {
r = x;
g = y;
b = z;
return clamp();
}
C3 add(final C3 c) {
return new C3(r + c.r, g + c.g, b + c.b);
}
C3 sub(final C3 c) {
return new C3(r - c.r, g - c.g, b - c.b);
}
C3 mul(final int d) {
return new C3(d * r, d * g, d * b);
}
C3 mul(final float d) {
return new C3((int) (d * r), (int) (d * g), (int) (d * b));
}
int diff(final C3 c) {
final color
rDiff = c.r - r,
gDiff = c.g - g,
bDiff = c.b - b;
return rDiff * rDiff + gDiff * gDiff + bDiff * bDiff;
}
final C3 findClosestPaletteColor(final C3... palette) {
return findClosestPaletteColor(this, palette);
}
C3 clone() {
try {
return (C3) super.clone();
}
catch (final CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
C3 clamp() {
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
return this;
}
color toColor() {
return clamp().hashCode();
}
int hashCode() {
return b | g << 010 | r << 020 | PImage.ALPHA_MASK;
}
boolean equals(final Object o) {
return o instanceof C3? o.hashCode() == hashCode() : false;
}
int compareTo(final C3 c) {
return
(hashCode() & ~PImage.ALPHA_MASK) -
(c.hashCode() & ~PImage.ALPHA_MASK);
}
String toString() {
return '#' + hex(hashCode(), 6) + ": [ " + r + ", " + g + ", " + b + " ]";
}
}
Edit 1: changed: return C3.findClosestPaletteColor(clone(), palette);
to just: return C3.findClosestPaletteColor(this, palette);
No need to use clone() for this operation, given neither passed object arguments are mutated in anyway inside static
method findClosestPaletteColor().
Edit 2: Created a set() method and changed 2nd constructor to use that:
C3(final color r, final color g, final color b) {
set(r, g, b);
}
C3 set(final color x, final color y, final color z) {
r = x;
g = y;
b = z;
return clamp();
}
Edit 3: No need to prefix w/ C3 at return C3.findClosestPaletteColor(this, palette);
:
return findClosestPaletteColor(this, palette);