375 lines
11 KiB
Java
375 lines
11 KiB
Java
package speiger.src.coreengine.math.misc;
|
|
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.FloatBuffer;
|
|
|
|
import speiger.src.collections.floats.lists.FloatList;
|
|
import speiger.src.coreengine.math.MathUtils;
|
|
|
|
public class ColorUtils
|
|
{
|
|
static final float DEVIDER = 1F / 255F;
|
|
public static final int R = 0xFF << 16;
|
|
public static final int G = 0xFF << 8;
|
|
public static final int B = 0xFF;
|
|
public static final int A = 0xFF << 24;
|
|
public static final long SIGN = 0x00000000FFFFFFFFL;
|
|
static final int ALL = 0xFFFFFFFF;
|
|
|
|
public static final int WHITE = rgb(255, 255, 255);
|
|
public static final int LIGHT_GRAY = rgb(192, 192, 192);
|
|
public static final int GRAY = rgb(128, 128, 128);
|
|
public static final int DARK_GRAY = rgb(64, 64, 64);
|
|
public static final int BLACK = rgb(0, 0, 0);
|
|
public static final int RED = rgb(255, 0, 0);
|
|
public static final int PINK = rgb(255, 175, 175);
|
|
public static final int PURPLE = rgb(106, 13, 173);
|
|
public static final int ORANGE = rgb(255, 200, 0);
|
|
public static final int YELLOW = rgb(255, 255, 0);
|
|
public static final int GREEN = rgb(0, 255, 0);
|
|
public static final int DARK_GREEN = rgb(7, 161, 0);
|
|
public static final int MAGENTA = rgb(255, 0, 255);
|
|
public static final int CYAN = rgb(0, 255, 255);
|
|
public static final int BLUE = rgb(0, 0, 255);
|
|
public static final int LIGHT_BLUE = rgb(0, 150, 255);
|
|
|
|
//Specialized Components that get reused
|
|
public static final int INVISIBLE = rgb(0, 0, 0, 0);
|
|
public static final int TEXT_DEFAULT_BACKGROUND = rgb(80, 80, 80, 144);
|
|
public static final int WINDOW_DEFAULT_BACKGROUND = rgb(64, 64, 64, 128);
|
|
public static final int POPUP_DEFAULT_BACKGROUND = rgb(85, 85, 85);
|
|
public static final int DESTRUCTION = rgb(255, 0, 0, 128);
|
|
|
|
public static byte[] toByteArray(int color, boolean alpha)
|
|
{
|
|
byte[] data = new byte[alpha ? 4 : 3];
|
|
data[0] = (byte)((color >> 16) & 0xFF);
|
|
data[1] = (byte)((color >> 8) & 0xFF);
|
|
data[2] = (byte)(color & 0xFF);
|
|
if(alpha) data[3] = (byte)((color >> 24) & 0xFF);
|
|
return data;
|
|
}
|
|
|
|
public static void write(int color, boolean alpha, ByteBuffer buffer)
|
|
{
|
|
buffer.put((byte)((color >> 16) & 0xFF)).put((byte)((color >> 8) & 0xFF)).put((byte)(color & 0xFF));
|
|
if(alpha)
|
|
{
|
|
buffer.put((byte)((color >> 24) & 0xFF));
|
|
}
|
|
}
|
|
|
|
public static void write(int index, int color, boolean alpha, ByteBuffer buffer)
|
|
{
|
|
buffer.put(index, (byte)((color >> 16) & 0xFF)).put(index + 1, (byte)((color >> 8) & 0xFF)).put(index + 2, (byte)(color & 0xFF));
|
|
if(alpha)
|
|
{
|
|
buffer.put(index + 3, (byte)((color >> 24) & 0xFF));
|
|
}
|
|
}
|
|
|
|
public static void writeFloat(int color, boolean alpha, ByteBuffer buffer)
|
|
{
|
|
buffer.putFloat(((color >> 16) & 0xFF) * DEVIDER).putFloat(((color >> 8) & 0xFF) * DEVIDER).putFloat((color & 0xFF) * DEVIDER);
|
|
if(alpha)
|
|
{
|
|
buffer.putFloat(((color >> 24) & 0xFF) * DEVIDER);
|
|
}
|
|
}
|
|
|
|
public static void writeFloat(int index, int color, boolean alpha, ByteBuffer buffer)
|
|
{
|
|
buffer.putFloat(index, ((color >> 16) & 0xFF) * DEVIDER).putFloat(index + 1, ((color >> 8) & 0xFF) * DEVIDER).putFloat(index + 2, (color & 0xFF) * DEVIDER);
|
|
if(alpha)
|
|
{
|
|
buffer.putFloat(index + 3, ((color >> 24) & 0xFF) * DEVIDER);
|
|
}
|
|
}
|
|
|
|
public static void write(int color, boolean alpha, FloatBuffer buffer)
|
|
{
|
|
buffer.put(((color >> 16) & 0xFF) * DEVIDER).put(((color >> 8) & 0xFF) * DEVIDER).put((color & 0xFF) * DEVIDER);
|
|
if(alpha)
|
|
{
|
|
buffer.put(((color >> 24) & 0xFF) * DEVIDER);
|
|
}
|
|
}
|
|
|
|
public static void write(int index, int color, boolean alpha, FloatBuffer buffer)
|
|
{
|
|
buffer.put(index, ((color >> 16) & 0xFF) * DEVIDER).put(index + 1, ((color >> 8) & 0xFF) * DEVIDER).put(index + 2, (color & 0xFF) * DEVIDER);
|
|
if(alpha)
|
|
{
|
|
buffer.put(index + 3, ((color >> 24) & 0xFF) * DEVIDER);
|
|
}
|
|
}
|
|
|
|
public static void write(int color, boolean alpha, FloatList list)
|
|
{
|
|
list.add(((color >> 16) & 0xFF) * DEVIDER);
|
|
list.add(((color >> 8) & 0xFF) * DEVIDER);
|
|
list.add((color & 0xFF) * DEVIDER);
|
|
if(alpha)
|
|
{
|
|
list.add(((color >> 24) & 0xFF) * DEVIDER);
|
|
}
|
|
}
|
|
|
|
public static int read(ByteBuffer buffer, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.get(), buffer.get(), buffer.get()) : rgb(buffer.get(), buffer.get(), buffer.get(), buffer.get());
|
|
}
|
|
|
|
public static int read(ByteBuffer buffer, int index, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.get(index), buffer.get(index+1), buffer.get(index+2)) : rgb(buffer.get(index), buffer.get(index+1), buffer.get(index+2), buffer.get(index+3));
|
|
}
|
|
|
|
public static int readFloat(ByteBuffer buffer, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.getFloat(), buffer.getFloat(), buffer.getFloat()) : rgb(buffer.getFloat(), buffer.getFloat(), buffer.getFloat(), buffer.getFloat());
|
|
}
|
|
|
|
public static int readFloat(ByteBuffer buffer, int index, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.getFloat(index), buffer.getFloat(index+1), buffer.getFloat(index+2)) : rgb(buffer.getFloat(index), buffer.getFloat(index+1), buffer.getFloat(index+2), buffer.getFloat(index+3));
|
|
}
|
|
|
|
public static int read(FloatBuffer buffer, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.get(), buffer.get(), buffer.get()) : rgb(buffer.get(), buffer.get(), buffer.get(), buffer.get());
|
|
}
|
|
|
|
public static int read(FloatBuffer buffer, int index, boolean alpha)
|
|
{
|
|
return alpha ? rgb(buffer.get(index), buffer.get(index+1), buffer.get(index+2)) : rgb(buffer.get(index), buffer.get(index+1), buffer.get(index+2), buffer.get(index+3));
|
|
}
|
|
|
|
public static boolean needsDarkColor(int rgba)
|
|
{
|
|
return getBrightness(rgba) >= 130;
|
|
}
|
|
|
|
public static int getBrightness(int rgba)
|
|
{
|
|
return getBrightness((rgba >> 16) & 0xFF, (rgba >> 8) & 0xFF, rgba & 0xFF);
|
|
}
|
|
|
|
public static int getBrightness(int r, int g, int b)
|
|
{
|
|
return (int)Math.sqrt((r * r * 0.241F) + (g * g * 0.691F) + (b * b * 0.068F));
|
|
}
|
|
|
|
public static int mix(int from, int to, float factor)
|
|
{
|
|
float weight0 = (1F - factor);
|
|
float weight1 = factor;
|
|
int r = (int)((((from >> 16) & 0xFF) * weight0) + (((to >> 16) & 0xFF) * weight1));
|
|
int g = (int)((((from >> 8) & 0xFF) * weight0) + (((to >> 8) & 0xFF) * weight1));
|
|
int b = (int)(((from & 0xFF) * weight0) + ((to & 0xFF) * weight1));
|
|
int a = (int)((((from >> 24) & 0xFF) * weight0) + (((to >> 24) & 0xFF) * weight1));
|
|
return ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | b & 0xFF;
|
|
}
|
|
|
|
public static int darker(int color)
|
|
{
|
|
return darker(color, 0.7F);
|
|
}
|
|
|
|
public static int darker(int color, float factor)
|
|
{
|
|
int r = Math.max(0, (int)(((color >> 16) & 0xFF) * factor));
|
|
int g = Math.max(0, (int)(((color >> 8) & 0xFF) * factor));
|
|
int b = Math.max(0, (int)((color & 0xFF) * factor));
|
|
return (color & A) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
|
}
|
|
|
|
public static int brighter(int color)
|
|
{
|
|
return brighter(color, 0.7F);
|
|
}
|
|
|
|
public static int brighter(int color, float factor)
|
|
{
|
|
int r = (color >> 16) & 0xFF;
|
|
int g = (color >> 8) & 0xFF;
|
|
int b = color & 0xFF;
|
|
int i = (int)(1.0 / (1.0 - factor));
|
|
if(r == 0 && g == 0 && b == 0)
|
|
{
|
|
return (color & A) | ((i & 0xFF) << 16) | ((i & 0xFF) << 8) | (i & 0xFF);
|
|
}
|
|
if(r > 0 && r < i) r = i;
|
|
if(g > 0 && g < i) g = i;
|
|
if(b > 0 && b < i) b = i;
|
|
return (color & A) | Math.min(255, (int)(r / factor)) << 16 | Math.min(255, (int)(g / factor)) << 8 | Math.min(255, (int)(b / factor));
|
|
}
|
|
|
|
public static int toRGB(float hue, float saturation, float brightness)
|
|
{
|
|
if (saturation == 0)
|
|
{
|
|
int result = (int)(brightness * 255F + 0.5F);
|
|
return rgb(result, result, result);
|
|
}
|
|
float h = (hue - MathUtils.floor(hue)) * 6F;
|
|
float f = h - MathUtils.floor(h);
|
|
float p = brightness * (1F - saturation);
|
|
float q = brightness * (1F - saturation * f);
|
|
float t = brightness * (1F - (saturation * (1F - f)));
|
|
switch ((int)h) {
|
|
case 0: return rgb(brightness, t, p);
|
|
case 1: return rgb(q, brightness, p);
|
|
case 2: return rgb(p, brightness, t);
|
|
case 3: return rgb(p, q, brightness);
|
|
case 4: return rgb(t, p, brightness);
|
|
case 5: return rgb(brightness, p, q);
|
|
default: return BLACK;
|
|
}
|
|
}
|
|
|
|
public static float[] toHue(int rgba)
|
|
{
|
|
int r = getR(rgba);
|
|
int g = getG(rgba);
|
|
int b = getB(rgba);
|
|
int cmax = (r > g) ? r : g;
|
|
if (b > cmax) cmax = b;
|
|
int cmin = (r < g) ? r : g;
|
|
if (b < cmin) cmin = b;
|
|
float length = cmax - cmin;
|
|
|
|
float[] result = new float[3];
|
|
result[1] = cmax == 0 ? 0F : length / cmax;
|
|
result[2] = cmax * DEVIDER;
|
|
float hue = 0F;
|
|
if(result[1] != 0F) {
|
|
float redc = (cmax - r) / length;
|
|
float greenc = (cmax - g) / length;
|
|
float bluec = (cmax - b) / length;
|
|
if (r == cmax) hue = bluec - greenc;
|
|
else if (g == cmax) hue = 2F + redc - bluec;
|
|
else hue = 4F + greenc - redc;
|
|
hue /= 6F;
|
|
if (hue < 0) hue += 1F;
|
|
}
|
|
result[0] = hue;
|
|
return result;
|
|
}
|
|
|
|
public static int rgb(int rgb)
|
|
{
|
|
return rgb | (255 << 24);
|
|
}
|
|
|
|
public static int rgb(int r, int g, int b)
|
|
{
|
|
return A | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
|
}
|
|
|
|
public static int rgb(float r, float g, float b)
|
|
{
|
|
return rgb((int)(r * 255F + 0.5F), (int)(g * 255F + 0.5F), (int)(b * 255F + 0.5F));
|
|
}
|
|
|
|
public static int rgb(int r, int g, int b, int a)
|
|
{
|
|
return ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
|
|
}
|
|
|
|
public static int rgb(float r, float g, float b, float a)
|
|
{
|
|
return rgb((int)(r * 255F + 0.5F), (int)(g * 255F + 0.5F), (int)(b * 255F + 0.5F), (int)(b * 255F + 0.5F));
|
|
}
|
|
|
|
public static int setR(int rgba, int r)
|
|
{
|
|
return rgba & ~R | ((r & 0xFF) << 16);
|
|
}
|
|
|
|
public static int setR(int rgba, float r)
|
|
{
|
|
return rgba & ~R | (((int)(r * 255F + 0.5F)) << 16);
|
|
}
|
|
|
|
public static int setG(int rgba, int g)
|
|
{
|
|
return rgba & ~G | ((g & 0xFF) << 8);
|
|
}
|
|
|
|
public static int setG(int rgba, float g)
|
|
{
|
|
return rgba & ~G | (((int)(g * 255F + 0.5F)) << 8);
|
|
}
|
|
|
|
public static int setB(int rgba, int b)
|
|
{
|
|
return rgba & ~B | (b & 0xFF);
|
|
}
|
|
|
|
public static int setB(int rgba, float b)
|
|
{
|
|
return rgba & ~B | ((int)(b * 255F + 0.5F));
|
|
}
|
|
|
|
public static int setA(int rgba, int a)
|
|
{
|
|
return rgba & ~A | ((a & 0xFF) << 24);
|
|
}
|
|
|
|
public static int setA(int rgba, float a)
|
|
{
|
|
return rgba & ~A | (((int)(a * 255F + 0.5F)) << 24);
|
|
}
|
|
|
|
public static int getR(int rgba)
|
|
{
|
|
return (rgba >> 16) & 0xFF;
|
|
}
|
|
|
|
public static float getRF(int rgba)
|
|
{
|
|
return ((rgba >> 16) & 0xFF) * DEVIDER;
|
|
}
|
|
|
|
public static int getG(int rgba)
|
|
{
|
|
return (rgba >> 8) & 0xFF;
|
|
}
|
|
|
|
public static float getGF(int rgba)
|
|
{
|
|
return ((rgba >> 8) & 0xFF) * DEVIDER;
|
|
}
|
|
|
|
public static int getB(int rgba)
|
|
{
|
|
return rgba & 0xFF;
|
|
}
|
|
|
|
public static float getBF(int rgba)
|
|
{
|
|
return (rgba & 0xFF) * DEVIDER;
|
|
}
|
|
|
|
public static int getA(int rgba)
|
|
{
|
|
return (rgba >> 24) & 0xFF;
|
|
}
|
|
|
|
public static float getAF(int rgba)
|
|
{
|
|
return ((rgba >> 24) & 0xFF) * DEVIDER;
|
|
}
|
|
|
|
public static String getHexCode(int rgba, boolean alpha)
|
|
{
|
|
return "0x"+(alpha ? Long.toHexString(1 << 32 | rgba & SIGN) : Integer.toHexString((1 << 24) | (rgba & ~A))).substring(1);
|
|
}
|
|
|
|
public static String getHTMLCode(int rgba, boolean alpha)
|
|
{
|
|
return "#"+(alpha ? Long.toHexString(1 << 32 | rgba & SIGN) : Integer.toHexString((1 << 24) | (rgba & ~A))).substring(1);
|
|
}
|
|
}
|