interpolating rgb values
Code:
public void fillGradientTriangleRGB(int x0, int y0, int rgb0, int x1, int y1, int rgb1, int x2, int y2, int rgb2) {
if (y2 < y0) {
int tmp = x0;
x0 = x2;
x2 = tmp;
tmp = y0;
y0 = y2;
y2 = tmp;
tmp = rgb0;
rgb0 = rgb2;
rgb2 = tmp;
}
if (y1 < y0) {
int tmp = x0;
x0 = x1;
x1 = tmp;
tmp = y0;
y0 = y1;
y1 = tmp;
tmp = rgb0;
rgb0 = rgb1;
rgb1 = tmp;
}
if (y2 < y1) {
int tmp = x1;
x1 = x2;
x2 = tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
tmp = rgb1;
rgb1 = rgb2;
rgb2 = tmp;
}
if (y0 >= height) return;
int r0 = (rgb0 >> 16) & 0xFF;
int g0 = (rgb0 >> 8) & 0xFF;
int b0 = rgb0 & 0xFF;
int r1 = (rgb1 >> 16) & 0xFF;
int g1 = (rgb1 >> 8) & 0xFF;
int b1 = rgb1 & 0xFF;
int r2 = (rgb2 >> 16) & 0xFF;
int g2 = (rgb2 >> 8) & 0xFF;
int b2 = rgb2 & 0xFF;
int mx0 = 0, mr0 = 0, mg0 = 0, mb0 = 0;
int mx1 = 0, mr1 = 0, mg1 = 0, mb1 = 0;
int mx2 = 0, mr2 = 0, mg2 = 0, mb2 = 0;
if (y0 != y1) {
int denom = y1 - y0;
mx0 = ((x1 - x0) << 16) / denom;
mr0 = ((r1 - r0) << 16) / denom;
mg0 = ((g1 - g0) << 16) / denom;
mb0 = ((b1 - b0) << 16) / denom;
}
if (y1 != y2) {
int denom = y2 - y1;
mx1 = ((x2 - x1) << 16) / denom;
mr1 = ((r2 - r1) << 16) / denom;
mg1 = ((g2 - g1) << 16) / denom;
mb1 = ((b2 - b1) << 16) / denom;
}
if (y2 != y0) {
int denom = y2 - y0;
mx2 = ((x2 - x0) << 16) / denom;
mr2 = ((r2 - r0) << 16) / denom;
mg2 = ((g2 - g0) << 16) / denom;
mb2 = ((b2 - b0) << 16) / denom;
}
x0 <<= 16;
r0 <<= 16;
g0 <<= 16;
b0 <<= 16;
x2 = x1 << 16;
r2 = r1 << 16;
g2 = g1 << 16;
b2 = b1 << 16;
x1 = x0;
r1 = r0;
g1 = g0;
b1 = b0;
if (y0 < 0) {
x0 -= mx2 * y0;
r0 -= mr2 * y0;
g0 -= mg2 * y0;
b0 -= mb2 * y0;
x1 -= mx0 * y0;
r1 -= mr0 * y0;
g1 -= mg0 * y0;
b1 -= mb0 * y0;
y0 = 0;
}
if (y1 < 0) {
x2 -= mx1 * y1;
r2 -= mr1 * y1;
g2 -= mg1 * y1;
b2 -= mb1 * y1;
y1 = 0;
}
int remaining = y1 - y0;
int offset = offsets[y0];
while (remaining-- > 0) {
if(y0++ >= height) return;
drawGradientScanlineRGB(offset, x0 >> 16, r0, g0, b0, x1 >> 16, r1, g1, b1);
x0 += mx2;
r0 += mr2;
g0 += mg2;
b0 += mb2;
x1 += mx0;
r1 += mr0;
g1 += mg0;
b1 += mb0;
offset += width;
}
remaining = y2 - y1;
while (remaining-- > 0) {
if(y0++ >= height) return;
drawGradientScanlineRGB(offset, x0 >> 16, r0, g0, b0, x2 >> 16, r2, g2, b2);
x0 += mx2;
r0 += mr2;
g0 += mg2;
b0 += mb2;
x2 += mx1;
r2 += mr1;
g2 += mg1;
b2 += mb1;
offset += width;
}
}
private void drawGradientScanlineRGB(int offset, int x0, int r0, int g0, int b0, int x1, int r1, int g1, int b1) {
if (x0 == x1) return;
if (x0 > x1) {
int tmp = x0;
x0 = x1;
x1 = tmp;
tmp = r0;
r0 = r1;
r1 = tmp;
tmp = g0;
g0 = g1;
g1 = tmp;
tmp = b0;
b0 = b1;
b1 = tmp;
}
int len = x1 - x0;
int mr = (r1 - r0) / len;
int mg = (g1 - g0) / len;
int mb = (b1 - b0) / len;
if (x0 < 0) {
r0 -= x0 * mr;
g0 -= x0 * mg;
b0 -= x0 * mb;
x0 = 0;
}
if (x1 > width) x1 = width - 1;
len = x1 - x0;
offset += x0;
while (len-- > 0) {
data[offset] = (r0 & 0xFF0000) | ((g0 >> 8) & 0xFF00) | (b0 >> 16);
r0 += mr;
g0 += mg;
b0 += mb;
offset++;
}
}
creating that hsl lookup table of any size
Code:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.IOException;
public final class Palette {
public static void main(String[] args) throws IOException {
BufferedImage image = new BufferedImage(512, 2048, BufferedImage.TYPE_INT_RGB);
create(((DataBufferInt) image.getRaster().getDataBuffer()).getData(), 512, 2048, 64);
ImageIO.write(image, "png", new File("palette.png"));
}
public static double getValue(double value, double a, double b) {
if ((6.0 * value) < 1.0) return b + ((a - b) * 6.0 * value);
if (2.0 * value < 1.0) return a;
if (3.0 * value < 2.0) return b + ((a - b) * ((2.0 / 3.0) - value) * 6.0);
return b;
}
public static int[] create(int width, int height) {
return create(null, width, height, 64); // the color channel normally generated has 64 hues
}
public static int[] create(int[] dst, int width, int height, int hueCount) {
int offset = 0;
int hueHeight = height / hueCount;
if (dst == null) dst = new int[width * height];
for (int y = 0; y < height; y++) {
double fGreen = (y / hueHeight) / (double) hueCount;
double saturation = (y & (hueHeight - 1)) / (double) hueHeight;
for (int x = 0; x < width; x++) {
double lightness = x / (double) width;
double red = lightness;
double green = lightness;
double blue = lightness;
if (saturation != 0.0) {
double valueA;
if (lightness < 0.5) {
valueA = lightness * (1.0 + saturation);
} else {
valueA = (lightness + saturation) - (lightness * saturation);
}
double valueB = (2.0 * lightness) - valueA;
double fRed = fGreen + (1.0 / 3.0);
double fBlue = fGreen - (1.0 / 3.0);
if (fRed > 1.0) fRed--;
if (fBlue < 0.0) fBlue++;
red = getValue(fRed, valueA, valueB);
green = getValue(fGreen, valueA, valueB);
blue = getValue(fBlue, valueA, valueB);
}
dst[offset++] = ((int) (red * 256.0) << 16) | ((int) (green * 256.0) << 8) | (int) (blue * 256.0);
}
}
return dst;
}
}
512x2048: