Skip to content

Instantly share code, notes, and snippets.

@hageldave
Created October 3, 2016 22:10
Show Gist options
  • Save hageldave/b6ad662a475474fdcf04af816b4b31ed to your computer and use it in GitHub Desktop.
Save hageldave/b6ad662a475474fdcf04af816b4b31ed to your computer and use it in GitHub Desktop.
demo app showing the RGB representable colors of LAB
public static void main(String[] args) throws IOException {
Img[] gammut = new Img[256];
Consumer<Pixel> lab2rgb = (px)->{px.setValue(transformLAB2RGB(px.getValue()));};
for(int l = 0; l < 256; l++){
int L = l;
Img img = new Img(256, 256);
img.forEach(px->{px.setRGB(L, px.getX(), px.getY());});
img.forEach(lab2rgb);
gammut[l] = img;
}
int[] current = {0};
ImageFrame frame = new ImageFrame();
frame.setTitle("L="+current[0]);
ImagePanel panel = frame.getPanel();
panel.setImg(gammut[current[0]]);
panel.addMouseWheelListener(e->{
int plus = e.getWheelRotation();
current[0] = (current[0] + 256 + plus) % 256;
panel.setImg(gammut[current[0]]);
frame.setTitle("L="+current[0]);
});
panel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "UP");
panel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "DOWN");
panel.getActionMap().put("UP", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
current[0] = (current[0] + 256 + 1) % 256;
panel.setImg(gammut[current[0]]);
frame.setTitle("L="+current[0]);
}
});
panel.getActionMap().put("DOWN", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
current[0] = (current[0] + 256 -1) % 256;
panel.setImg(gammut[current[0]]);
frame.setTitle("L="+current[0]);
}
});
frame.setVisible(true);
}
static int transformLAB2RGB(int val){
float L = (Pixel.r_normalized(val) )*100;
float A = ((Pixel.g(val)-127)/254.0f)*200;
float B = ((Pixel.b(val)-127)/254.0f)*200;
// LAB to XYZ
float temp = (L+16)/116;
float x = LAB.Xn*LAB.funcInv(temp + (A/500));
float y = LAB.Yn*LAB.funcInv(temp);
float z = LAB.Zn*LAB.funcInv(temp - (B/200));
int r = Math.round(( 3.2404542f*x -1.5371385f*y -0.4985314f*z)*0xff );
int g = Math.round((-0.9692660f*x +1.8760108f*y +0.0415560f*z)*0xff );
int b = Math.round(( 0.0556434f*x -0.2040259f*y +1.0572252f*z)*0xff );
int a = 255;
if(isOut(r)||isOut(g)||isOut(b)){
a = 0;
}
return Pixel.argb_bounded(a, r, g, b);
}
static boolean isOut(int val){
return (val&0xff) != val;
}
private static final class LAB {
static final float Xn = 0.95047f;
static final float Yn = 1.00000f;
static final float Zn = 1.08883f;
static final float lab6_29 = 6.0f/29.0f;
static final float lab6_29_3 = lab6_29*lab6_29*lab6_29;
static final float lab1_3_29_6_2 = (1.0f/3.0f) * (29.0f/6.0f) * (29.0f/6.0f);
static float func(float q){
return q > lab6_29_3 ? (float)Math.cbrt(q):lab1_3_29_6_2*q + (4.0f/29.0f);
// return (float)Math.cbrt(q);
}
static float funcInv(float q){
return q > lab6_29 ? q*q*q : 3*lab6_29*lab6_29*(q-(4.0f/29.0f));
// return q*q*q;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment