edu.uci.qa.performancedriver.util.PaletteGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of performancedriver Show documentation
Show all versions of performancedriver Show documentation
A performance measuring API with high performance and portability
The newest version!
package edu.uci.qa.performancedriver.util;
import java.util.function.Function;
public final class PaletteGenerator {
public static Integer[] generate(int colorCount) {
return generate(colorCount, c -> {
Color out = new Color();
ColorConversions.RGBtoLCH(c, out);
return out.getZ() >= 0 && out.getZ() <= 360 && out.getY() >= 30 && out.getY() <= 80
&& out.getX() >= 35 && out.getX() <= 80;
});
}
public static Integer[] generate(int colorCount, Function checker) {
// TODO: K-Means should be the default setting.
return generate(colorCount, checker, true, 50, false, Type.DEFAULT);
}
public static Integer[] generate(int colorCount, Function checker,
boolean forceMode, int quality, boolean ultraPrecision, Type distanceType) {
if (colorCount <= 0) {
colorCount = 8;
}
if (checker == null) {
checker = c -> true;
}
if (quality <= 0) {
quality = 50;
}
forceMode = true; // TODO: Implement k-means mode
if (forceMode) {
Double[][] colors = new Double[colorCount][3];
for (int i = 0; i < colorCount; i++) {
Double[] color = null;
do {
color = new Double[] {100 * Math.random(), 100 * (2 * Math.random() - 1),
100 * (2 * Math.random() - 1)};
} while (!checkLab(color, checker));
colors[i] = color;
}
int repulsion = 100;
int speed = 100;
int steps = quality * 20;
Vector[] vectors = new Vector[colors.length];
while (steps-- > 0) {
for (int i = 0; i < colors.length; i++) {
vectors[i] = new Vector(0, 0, 0);
}
for (int i = 0; i < colors.length; i++) {
Double[] colorA = colors[i];
for (int j = 0; j < i; j++) {
Double[] colorB = colors[j];
double dl = colorA[0] - colorB[0];
double da = colorA[1] - colorB[1];
double db = colorA[2] - colorB[2];
double d = getColorDistance(colorA, colorB, distanceType);
if(d > 0) {
double force = repulsion / Math.pow(d, 2);
vectors[i].dl += dl * force / d;
vectors[i].da += da * force / d;
vectors[i].db += db * force / d;
vectors[j].dl -= dl * force / d;
vectors[j].da -= da * force / d;
vectors[j].db -= db * force / d;
} else {
vectors[j].dl += 2 - 4 * Math.random();
vectors[j].da += 2 - 4 * Math.random();
vectors[j].db += 2 - 4 * Math.random();
}
}
}
for (int i = 0; i < colors.length; i++) {
Double[] color = colors[i];
double displacement = speed * Math.sqrt(Math.pow(vectors[i].dl, 2) + Math.pow(vectors[i].da, 2) + Math.pow(vectors[i].db, 2));
if (displacement > 0) {
double ratio = speed * Math.min(0.1, displacement) / displacement;
Double[] candidateLab = new Double[] {
color[0] + vectors[i].dl * ratio,
color[1] + vectors[i].da * ratio,
color[2] + vectors[i].db * ratio
};
if (checkLab(candidateLab, checker)) {
colors[i] = candidateLab;
}
}
}
}
Integer[] out = new Integer[colors.length];
for (int i = 0; i < colors.length; i++) {
out[i] = new LAB(colors[i][0], colors[i][1], colors[i][2]).rgb();
}
return out;
}
return null;
}
private static boolean checkLab(Double[] lab, Function checkColor) {
return LAB.isInRGBGamut(lab[0], lab[1], lab[2])
&& checkColor.apply(Color.HEX(new LAB(lab[0], lab[1], lab[2]).rgb()));
}
private static double getColorDistance(Double[] labA, Double[] labB, Type type) {
switch (type) {
case DEFAULT:
case EUCLIDIAN:
return euclidianDistance(labA, labB);
case CMC:
return cmcDistance(labA, labB, 2, 1);
case COMPROMISE:
return compromiseDistance(labA, labB);
default:
return distanceColorblind(labA, labB);
}
}
private static double euclidianDistance(Double[] labA, Double[] labB) {
return Math.sqrt(Math.pow(labA[0] - labB[0], 2) + Math.pow(labA[1] - labB[1], 2) + Math.pow(labA[2] - labB[2], 2));
}
private static double cmcDistance(Double[] labA, Double[] labB, int l, int c) {
return 0;
}
private static double compromiseDistance(Double[] labA, Double[] labB) {
return 0;
}
private static double distanceColorblind(Double[] labA, Double[] labB) {
return 0;
}
public enum Type {
DEFAULT,
EUCLIDIAN,
CMC,
COMPROMISE,
COLORBLIND
}
private static class Vector {
double dl, da, db;
public Vector(double dl, double da, double db) {
this.dl = dl;
this.da = da;
this.db = db;
}
}
}