lygia
/color
/distance
)Perceptual distance between two color according to CIE94 https://en.wikipedia.org/wiki/Color_difference#CIE94
Dependencies:
lygia
/color
/space
/rgb2lab
.glsl
lygia
/color
/space
/rgb2YCbCr
.glsl
lygia
/color
/space
/rgb2YPbPr
.glsl
lygia
/color
/space
/rgb2yuv
.glsl
lygia
/color
/space
/rgb2oklab
.glsl
Use:
colorDistance(<vec3|vec4> rgbA, <vec3|vec4> rgbA)
#ifndef COLORDISTANCE_FNC
#define COLORDISTANCE_FNC colorDistanceLABCIE94
#endif
#ifndef FNC_PERCEPTUALDISTANCE
#define FNC_PERCEPTUALDISTANCE
float colorDistanceLABCIE94(in vec3 rgb1, in vec3 rgb2) {
vec3 lab1 = rgb2lab(rgb1);
vec3 lab2 = rgb2lab(rgb2);
vec3 delta = lab1 - lab2;
float c1 = sqrt(lab1.y * lab1.y + lab1.z * lab1.z);
float c2 = sqrt(lab2.y * lab2.y + lab2.z * lab2.z);
float delta_c = c1 - c2;
float delta_h = delta.x * delta.x + delta.z * delta.z - delta_c * delta_c;
delta_h = mix( 0., sqrt(delta_h), step(0.,delta_h));
float sc = 1. +.045 * c1;
float sh = 1. + .015 * c1;
float delta_ckcsc = delta_c / sc;
float delta_hkhsh = delta_h / sh;
float delta_e = delta.x * delta.x + delta_ckcsc * delta_ckcsc + delta_hkhsh * delta_hkhsh;
return mix( 0., sqrt(delta_e), step(0.,delta_e));
}
float colorDistanceLAB(in vec3 rgb1, in vec3 rgb2) { return distance(rgb2lab(rgb1), rgb2lab(rgb2)); }
float colorDistanceYCbCr(in vec3 rgb1, in vec3 rgb2) { return distance(rgb2YCbCr(rgb1).yz, rgb2YCbCr(rgb2).yz); }
float colorDistanceYPbPr(in vec3 rgb1, in vec3 rgb2) { return distance(rgb2YPbPr(rgb1).yz, rgb2YPbPr(rgb2).yz); }
float colorDistanceYUV(in vec3 rgb1, in vec3 rgb2) { return distance(rgb2yuv(rgb1), rgb2yuv(rgb2)); }
float colorDistanceOKLAB(in vec3 rgb1, in vec3 rgb2) { return distance(rgb2oklab(rgb1), rgb2oklab(rgb2)); }
float colorDistance(in vec3 rgb1, in vec3 rgb2) { return COLORDISTANCE_FNC(rgb1, rgb2); }
float colorDistance(in vec4 rgb1, in vec4 rgb2) { return COLORDISTANCE_FNC(rgb1.rgb, rgb2.rgb); }
#endif
Dependencies:
lygia
/color
/space
/rgb2lab
.glsl
lygia
/color
/space
/rgb2YCbCr
.glsl
lygia
/color
/space
/rgb2YPbPr
.glsl
lygia
/color
/space
/rgb2yuv
.glsl
lygia
/color
/space
/rgb2oklab
.glsl
Use:
colorDistance(<float3|float4> rgbA, <float3|float4> rgbA)
#ifndef COLORDISTANCE_FNC
#define COLORDISTANCE_FNC colorDistanceLABCIE94
#endif
#ifndef FNC_PERCEPTUALDISTANCE
#define FNC_PERCEPTUALDISTANCE
float colorDistanceLABCIE94(in float3 rgb1, in float3 rgb2) {
float3 lab1 = rgb2lab(rgb1);
float3 lab2 = rgb2lab(rgb2);
float3 delta = lab1 - lab2;
float c1 = sqrt(lab1.y * lab1.y + lab1.z * lab1.z);
float c2 = sqrt(lab2.y * lab2.y + lab2.z * lab2.z);
float delta_c = c1 - c2;
float delta_h = delta.x * delta.x + delta.z * delta.z - delta_c * delta_c;
delta_h = lerp( 0., sqrt(delta_h), step(0.,delta_h));
float sc = 1. +.045 * c1;
float sh = 1. + .015 * c1;
float delta_ckcsc = delta_c / sc;
float delta_hkhsh = delta_h / sh;
float delta_e = delta.x * delta.x + delta_ckcsc * delta_ckcsc + delta_hkhsh * delta_hkhsh;
return lerp( 0., sqrt(delta_e), step(0.,delta_e));
}
float colorDistanceLAB(in float3 rgb1, in float3 rgb2) { return distance(rgb2lab(rgb1), rgb2lab(rgb2)); }
float colorDistanceYCbCr(in float3 rgb1, in float3 rgb2) { return distance(rgb2YCbCr(rgb1).yz, rgb2YCbCr(rgb2).yz); }
float colorDistanceYPbPr(in float3 rgb1, in float3 rgb2) { return distance(rgb2YPbPr(rgb1).yz, rgb2YPbPr(rgb2).yz); }
float colorDistanceYUV(in float3 rgb1, in float3 rgb2) { return distance(rgb2yuv(rgb1), rgb2yuv(rgb2)); }
float colorDistanceOKLAB(in float3 rgb1, in float3 rgb2) { return distance(rgb2oklab(rgb1), rgb2oklab(rgb2)); }
float colorDistance(in float3 rgb1, in float3 rgb2) { return COLORDISTANCE_FNC(rgb1, rgb2); }
float colorDistance(in float4 rgb1, in float4 rgb2) { return COLORDISTANCE_FNC(rgb1.rgb, rgb2.rgb); }
#endif
Dependencies:
lygia
/color
/space
/rgb2lab
.glsl
lygia
/color
/space
/rgb2YCbCr
.glsl
lygia
/color
/space
/rgb2YPbPr
.glsl
lygia
/color
/space
/rgb2yuv
.glsl
lygia
/color
/space
/rgb2oklab
.glsl
Use:
colorDistance(<float3|float4> rgbA, <float3|float4> rgbA)
#ifndef COLORDISTANCE_FNC
#define COLORDISTANCE_FNC colorDistanceLABCIE94
#endif
#ifndef FNC_PERCEPTUALDISTANCE
#define FNC_PERCEPTUALDISTANCE
float colorDistanceLABCIE94(float3 rgb1, float3 rgb2) {
float3 lab1 = rgb2lab(rgb1);
float3 lab2 = rgb2lab(rgb2);
float3 delta = lab1 - lab2;
float c1 = sqrt(lab1.y * lab1.y + lab1.z * lab1.z);
float c2 = sqrt(lab2.y * lab2.y + lab2.z * lab2.z);
float delta_c = c1 - c2;
float delta_h = delta.x * delta.x + delta.z * delta.z - delta_c * delta_c;
delta_h = mix( 0., sqrt(delta_h), step(0.,delta_h));
float sc = 1. +.045 * c1;
float sh = 1. + .015 * c1;
float delta_ckcsc = delta_c / sc;
float delta_hkhsh = delta_h / sh;
float delta_e = delta.x * delta.x + delta_ckcsc * delta_ckcsc + delta_hkhsh * delta_hkhsh;
return mix( 0., sqrt(delta_e), step(0.,delta_e));
}
float colorDistanceLAB(float3 rgb1, float3 rgb2) { return distance(rgb2lab(rgb1), rgb2lab(rgb2)); }
float colorDistanceYCbCr(float3 rgb1, float3 rgb2) { return distance(rgb2YCbCr(rgb1).yz, rgb2YCbCr(rgb2).yz); }
float colorDistanceYPbPr(float3 rgb1, float3 rgb2) { return distance(rgb2YPbPr(rgb1).yz, rgb2YPbPr(rgb2).yz); }
float colorDistanceYUV(float3 rgb1, float3 rgb2) { return distance(rgb2yuv(rgb1), rgb2yuv(rgb2)); }
float colorDistanceOKLAB(float3 rgb1, float3 rgb2) { return distance(rgb2oklab(rgb1), rgb2oklab(rgb2)); }
float colorDistance(float3 rgb1, float3 rgb2) { return COLORDISTANCE_FNC(rgb1, rgb2); }
float colorDistance(float4 rgb1, float4 rgb2) { return COLORDISTANCE_FNC(rgb1.rgb, rgb2.rgb); }
#endif
Dependencies:
lygia
/color
/space
/rgb2lab
.glsl
lygia
/color
/space
/rgb2YCbCr
.glsl
lygia
/color
/space
/rgb2YPbPr
.glsl
lygia
/color
/space
/rgb2yuv
.glsl
lygia
/color
/space
/rgb2oklab
.glsl
Use:
colorDistance(<vec3|vec4> rgbA, <vec3|vec4> rgbA)
fn colorDistanceLABCIE94(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
let lab1 = rgb2lab(rgb1);
let lab2 = rgb2lab(rgb2);
let delta = lab1 - lab2;
let c1 = sqrt(lab1.y * lab1.y + lab1.z * lab1.z);
let c2 = sqrt(lab2.y * lab2.y + lab2.z * lab2.z);
let delta_c = c1 - c2;
var delta_h = delta.x * delta.x + delta.z * delta.z - delta_c * delta_c;
delta_h = mix(0., sqrt(delta_h), step(0., delta_h));
let sc = 1. + .045 * c1;
let sh = 1. + .015 * c1;
let delta_ckcsc = delta_c / sc;
let delta_hkhsh = delta_h / sh;
let delta_e = delta.x * delta.x + delta_ckcsc * delta_ckcsc + delta_hkhsh * delta_hkhsh;
return mix(0., sqrt(delta_e), step(0., delta_e));
}
fn colorDistanceLAB(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
return distance(rgb2lab(rgb1), rgb2lab(rgb2));
}
fn colorDistanceYCbCr(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
return distance(rgb2YCbCr(rgb1).yz, rgb2YCbCr(rgb2).yz);
}
fn colorDistanceYPbPr(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
return distance(rgb2YPbPr(rgb1).yz, rgb2YPbPr(rgb2).yz);
}
fn colorDistanceYUV(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
return distance(rgb2yuv(rgb1), rgb2yuv(rgb2));
}
fn colorDistanceOKLAB(rgb1 : vec3<f32>, rgb2 : vec3<f32>) -> f32 {
return distance(rgb2oklab(rgb1), rgb2oklab(rgb2));
}
LYGIA is dual-licensed under the Prosperity License and the Patron License for sponsors and contributors.
Sponsors and contributors are automatically added to the Patron License and they can ignore the any non-commercial rule of the Prosperity Licensed software (please take a look to the exception).
It's also possible to get a permanent comercial license hook to a single and specific version of LYGIA.
Sign up for the news letter bellow, joing the LYGIA's channel on Discord or follow the Github repository