Nodes/Jovi_GLSL/COLOR CONVERSION (JOV_GL)
ComfyUI Node

COLOR CONVERSION (JOV_GL)

Convert an image from one color space (RGB, HSV, LAB, XYZ) to another.

By Amorano·Created 2 years ago·Updated 12 months ago· 20
COLOR CONVERSION (JOV_GL)
  • image
  • RGBA
  • RGB
  • MASK
operatorRGB2HSV
FRAGMENT// name: COLOR CONVERSION // desc: Convert an image from one color space (RGB, HSV, LAB, XYZ) to another. // category: COLOR #ifndef LIB_CONVERT #define LIB_CONVERT //------------------------------------------------------------------------------ // COLOR //------------------------------------------------------------------------------ #ifndef LIB_CONST #define LIB_CONST //------------------------------------------------------------------------------ // CONSTANT //------------------------------------------------------------------------------ #define M_EPSILON 1.0e-10 // zero value for float comparisons #define M_DEG2RAD 0.017453292519943 // Degree to radian conversion factor #define M_RAD2DEG 57.29577951308232 // Radian to degree conversion factor #define M_TAU 6.283185307179586 // TAU (2 * π) #define M_TAU_INV 0.159154943091895 // TAU Inverse (1 / TAU) #define M_PI 3.141592653589793 // π #define M_PI_INV 0.318309886183790 // π Inverse (1 / π) #define M_PI_2 1.570796326794896 // π divided by 2 (π / 2) #define M_PI_4 0.785398163397448 // π divided by 4 (π / 4) #define M_3PI_4 2.356194490192345 // 3 * π divided by 4 (3π / 4) #define M_PHI 1.618033988749895 // Golden ratio (φ) #define M_PHI_INV 0.618033988749895 // Inverse of golden ratio (1 / φ) #define M_PHI_SQ 2.618033988749895 // Square of the golden ratio (φ^2) #define M_PHI_SQRT5 0.723606797749979 // φ / √5 (useful for fibonacci spherical distribution) #define M_GOLD_ANG 2.399963229728653 // Golden angle in radians #define M_E 2.718281828459045 // Euler's number (base of natural logarithm) #define M_LOG2E 1.442695040888963 // Log base 2 of e #define M_LOG10E 0.434294481903252 // Log base 10 of e #define M_LN2 0.693147180559945 // Natural log of 2 #define M_LN10 2.302585092994046 // Natural log of 10 #define M_SQRT2 1.414213562373095 // Square root of 2 #define M_SQRT3 1.732050807568877 // Square root of 3 #define M_SQRT2_INV 0.707106781186547 // 1 divided by square root of 2 (1 / sqrt(2)) #define M_SQRT3_INV 0.577350269189626 // 1 divided by square root of 3 (1 / sqrt(3)) #define M_SQRT5 2.236067977499790 // Square root of 5 //------------------------------------------------------------------------------ // GENERAL //------------------------------------------------------------------------------ // useful for triangle interpolation vec3 barycentricCoords(vec2 p, vec2 a, vec2 b, vec2 c) { vec2 v0 = b - a; vec2 v1 = c - a; vec2 v2 = p - a; float d00 = dot(v0, v0); float d01 = dot(v0, v1); float d11 = dot(v1, v1); float d20 = dot(v2, v0); float d21 = dot(v2, v1); float denom = d00 * d11 - d01 * d01; vec3 result; result.y = (d11 * d20 - d01 * d21) / denom; result.z = (d00 * d21 - d01 * d20) / denom; result.x = 1.0 - result.y - result.z; return result; } #endif #define M_SRGB_ALPHA 0.055 #define M_SRGB_THRESH 0.04045 // LAB constants #define M_LAB_E 0.008856 // LAB epsilon #define M_LAB_K 903.3 // LAB kappa #define M_LAB_16_116 0.137931 // 16/116 // Additional illuminants #define M_D50 vec3(96.422, 100.0, 82.521) // D50 reference white #define M_D65 vec3(95.047, 100.0, 108.883) // D65 reference white #define M_D75 vec3(94.972, 100.0, 122.638) // D75 reference white // ============================================================================= // PROTOTYPES // ============================================================================= vec3 convert_rgb2hsv(vec3 rgb); vec3 convert_rgb2lab(vec3 rgb); vec3 convert_rgb2xyz(vec3 rgb); vec3 convert_hsv2rgb(vec3 hsv); vec3 convert_hsv2lab(vec3 hsv); vec3 convert_hsv2xyz(vec3 hsv); vec3 convert_lab2rgb(vec3 lab); vec3 convert_lab2hsv(vec3 lab); vec3 convert_lab2xyz(vec3 lab); vec3 convert_xyz2rgb(vec3 xyz); vec3 convert_xyz2hsv(vec3 xyz); vec3 convert_xyz2lab(vec3 xyz); vec3 convert_rgb2oklab(vec3 rgb); vec3 convert_oklab2rgb(vec3 lab); //------------------------------------------------------------------------------ // RGB //------------------------------------------------------------------------------ vec3 convert_rgb2hsv(vec3 rgb) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g)); vec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r)); float d = q.x - min(q.w, q.y); return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + M_EPSILON)), d / (q.x + M_EPSILON), q.x); } vec3 convert_rgb2lab(vec3 rgb) { vec3 xyz = convert_rgb2xyz(rgb); return convert_xyz2lab(xyz); } vec3 convert_rgb2xyz(vec3 rgb) { vec3 tmp; tmp.x = (rgb.r > 0.04045) ? pow((rgb.r + 0.055) / 1.055, 2.4) : rgb.r / 12.92; tmp.y = (rgb.g > 0.04045) ? pow((rgb.g + 0.055) / 1.055, 2.4) : rgb.g / 12.92; tmp.z = (rgb.b > 0.04045) ? pow((rgb.b + 0.055) / 1.055, 2.4) : rgb.b / 12.92; return 100.0 * tmp * mat3( 0.4124, 0.3576, 0.1805, 0.2126, 0.7152, 0.0722, 0.0193, 0.1192, 0.9505 ); } //------------------------------------------------------------------------------ // HSV //------------------------------------------------------------------------------ vec3 convert_hsv2rgb(vec3 hsv) { hsv = vec3(hsv.x, clamp(hsv.yz, 0.0, 1.0)); vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(hsv.xxx + K.xyz) * 6.0 - K.www); return hsv.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), hsv.y); } vec3 convert_hsv2lab(vec3 hsv) { float H = hsv.x * 360.0; float S = hsv.y; float V = hsv.z; // Convert to LAB float L = V * 100.0; float C = S * L; float h = H * M_PI / 180.0; float a = C * cos(h); float b = C * sin(h); // Normalize LAB return vec3(L / 100.0, (a + 128.0) / 255.0, (b + 128.0) / 255.0); } vec3 convert_hsv2xyz(vec3 hsv) { vec3 rgb = convert_hsv2rgb(hsv); return convert_rgb2xyz(rgb); } //------------------------------------------------------------------------------ // LAB //------------------------------------------------------------------------------ vec3 convert_lab2rgb(vec3 lab) { vec3 xyz = convert_lab2xyz(lab); return convert_xyz2rgb(xyz); } vec3 convert_lab2hsv(vec3 lab) { vec3 rgb = convert_lab2rgb(lab); return convert_rgb2hsv(rgb); } vec3 convert_lab2xyz(vec3 lab) { float fy = (lab.x + 16.0) / 116.0; float fx = lab.y / 500.0 + fy; float fz = fy - lab.z / 200.0; vec3 f = vec3(fx, fy, fz); vec3 thresh = step(vec3(0.206897), f); vec3 xyz = mix( (f - vec3(16.0/116.0)) / 7.787, f * f * f, thresh ); return xyz * M_D65; } //------------------------------------------------------------------------------ // XYZ //------------------------------------------------------------------------------ vec3 convert_xyz2rgb(vec3 xyz) { vec3 v = xyz / M_D65; vec3 thresh = step(0.0031308, v); return mix( 12.92 * v, 1.055 * pow(v, vec3(1.0/2.4)) - 0.055, thresh ); } vec3 convert_xyz2hsv(vec3 xyz) { vec3 rgb = convert_xyz2rgb(xyz); return convert_rgb2hsv(rgb); } vec3 convert_xyz2lab(vec3 xyz) { vec3 n = xyz / M_D65; vec3 thresh = step(vec3(0.008856), n); vec3 v = mix( 7.787 * n + vec3(16.0/116.0), pow(n, vec3(1.0/3.0)), thresh ); return vec3( 116.0 * v.y - 16.0, 500.0 * (v.x - v.y), 200.0 * (v.y - v.z) ); } //------------------------------------------------------------------------------ // OKLAB //------------------------------------------------------------------------------ // RGB to Oklab (perceptually uniform color space) vec3 convert_rgb2oklab(vec3 rgb) { vec3 lms = rgb * mat3( 0.4122214708, 0.5363325363, 0.0514459929, 0.2119034982, 0.6806995451, 0.1073969566, 0.0883024619, 0.2817188376, 0.6299787005 ); lms = pow(lms, vec3(1.0/3.0)); return lms * mat3( 0.2104542553, 0.7936177850, -0.0040720468, 1.9779984951, -2.4285922050, 0.4505937099, 0.0259040371, 0.7827717662, -0.8086757660 ); } // Oklab to RGB vec3 convert_oklab2rgb(vec3 lab) { vec3 lms = lab * mat3( 1.0000000000, 0.3963377774, 0.2158037573, 1.0000000000, -0.1055613458, -0.0638541728, 1.0000000000, -0.0894841775, -1.2914855480 ); lms = lms * lms * lms; return lms * mat3( 4.0767416621, -3.3077115913, 0.2309699292, -1.2684380046, 2.6097574011, -0.3413193965, -0.0041960863, -0.7034186147, 1.7076147010 ); } #endif uniform sampler2D image; // | Image to convert uniform int operator; // EnumGLSLColorConvert | conversion operation to perform. // ============================================================================= // SELECTOR // ============================================================================= vec3 convertColor(vec3 color, int operator) { // RGB if (operator == 0) { return convert_rgb2hsv(color); } else if (operator == 1) { return convert_rgb2lab(color); } else if (operator == 2) { return convert_rgb2xyz(color); // HSV } else if (operator == 10) { return convert_hsv2rgb(color); } else if (operator == 11) { return convert_hsv2lab(color); } else if (operator == 12) { return convert_hsv2xyz(color); // LAB } else if (operator == 20) { return convert_lab2rgb(color); } else if (operator == 21) { return convert_lab2hsv(color); } else if (operator == 22) { return convert_lab2xyz(color); // XYZ } else if (operator == 30) { return convert_xyz2rgb(color); } else if (operator == 31) { return convert_xyz2hsv(color); } else if (operator == 32) { return convert_xyz2lab(color); } return color; } void mainImage(out vec4 fragColor, vec2 fragCoord) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); vec3 rgb = convertColor(color.rgb, operator); fragColor = vec4(rgb, color.a); }
CategoryJOV_GL 🌈/COLOR

Inputs (3)

NameTypeDefaultDescription
imageoptIMAGEImage to convert
operatoroptCOMBORGB2HSVconversion operation to perform.
FRAGMENToptSTRING// name: COLOR CONVERSION // desc: Convert an image from one color space (RGB, HSV, LAB, XYZ) to another. // category: COLOR #ifndef LIB_CONVERT #define LIB_CONVERT //------------------------------------------------------------------------------ // COLOR //------------------------------------------------------------------------------ #ifndef LIB_CONST #define LIB_CONST //------------------------------------------------------------------------------ // CONSTANT //------------------------------------------------------------------------------ #define M_EPSILON 1.0e-10 // zero value for float comparisons #define M_DEG2RAD 0.017453292519943 // Degree to radian conversion factor #define M_RAD2DEG 57.29577951308232 // Radian to degree conversion factor #define M_TAU 6.283185307179586 // TAU (2 * π) #define M_TAU_INV 0.159154943091895 // TAU Inverse (1 / TAU) #define M_PI 3.141592653589793 // π #define M_PI_INV 0.318309886183790 // π Inverse (1 / π) #define M_PI_2 1.570796326794896 // π divided by 2 (π / 2) #define M_PI_4 0.785398163397448 // π divided by 4 (π / 4) #define M_3PI_4 2.356194490192345 // 3 * π divided by 4 (3π / 4) #define M_PHI 1.618033988749895 // Golden ratio (φ) #define M_PHI_INV 0.618033988749895 // Inverse of golden ratio (1 / φ) #define M_PHI_SQ 2.618033988749895 // Square of the golden ratio (φ^2) #define M_PHI_SQRT5 0.723606797749979 // φ / √5 (useful for fibonacci spherical distribution) #define M_GOLD_ANG 2.399963229728653 // Golden angle in radians #define M_E 2.718281828459045 // Euler's number (base of natural logarithm) #define M_LOG2E 1.442695040888963 // Log base 2 of e #define M_LOG10E 0.434294481903252 // Log base 10 of e #define M_LN2 0.693147180559945 // Natural log of 2 #define M_LN10 2.302585092994046 // Natural log of 10 #define M_SQRT2 1.414213562373095 // Square root of 2 #define M_SQRT3 1.732050807568877 // Square root of 3 #define M_SQRT2_INV 0.707106781186547 // 1 divided by square root of 2 (1 / sqrt(2)) #define M_SQRT3_INV 0.577350269189626 // 1 divided by square root of 3 (1 / sqrt(3)) #define M_SQRT5 2.236067977499790 // Square root of 5 //------------------------------------------------------------------------------ // GENERAL //------------------------------------------------------------------------------ // useful for triangle interpolation vec3 barycentricCoords(vec2 p, vec2 a, vec2 b, vec2 c) { vec2 v0 = b - a; vec2 v1 = c - a; vec2 v2 = p - a; float d00 = dot(v0, v0); float d01 = dot(v0, v1); float d11 = dot(v1, v1); float d20 = dot(v2, v0); float d21 = dot(v2, v1); float denom = d00 * d11 - d01 * d01; vec3 result; result.y = (d11 * d20 - d01 * d21) / denom; result.z = (d00 * d21 - d01 * d20) / denom; result.x = 1.0 - result.y - result.z; return result; } #endif #define M_SRGB_ALPHA 0.055 #define M_SRGB_THRESH 0.04045 // LAB constants #define M_LAB_E 0.008856 // LAB epsilon #define M_LAB_K 903.3 // LAB kappa #define M_LAB_16_116 0.137931 // 16/116 // Additional illuminants #define M_D50 vec3(96.422, 100.0, 82.521) // D50 reference white #define M_D65 vec3(95.047, 100.0, 108.883) // D65 reference white #define M_D75 vec3(94.972, 100.0, 122.638) // D75 reference white // ============================================================================= // PROTOTYPES // ============================================================================= vec3 convert_rgb2hsv(vec3 rgb); vec3 convert_rgb2lab(vec3 rgb); vec3 convert_rgb2xyz(vec3 rgb); vec3 convert_hsv2rgb(vec3 hsv); vec3 convert_hsv2lab(vec3 hsv); vec3 convert_hsv2xyz(vec3 hsv); vec3 convert_lab2rgb(vec3 lab); vec3 convert_lab2hsv(vec3 lab); vec3 convert_lab2xyz(vec3 lab); vec3 convert_xyz2rgb(vec3 xyz); vec3 convert_xyz2hsv(vec3 xyz); vec3 convert_xyz2lab(vec3 xyz); vec3 convert_rgb2oklab(vec3 rgb); vec3 convert_oklab2rgb(vec3 lab); //------------------------------------------------------------------------------ // RGB //------------------------------------------------------------------------------ vec3 convert_rgb2hsv(vec3 rgb) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g)); vec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r)); float d = q.x - min(q.w, q.y); return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + M_EPSILON)), d / (q.x + M_EPSILON), q.x); } vec3 convert_rgb2lab(vec3 rgb) { vec3 xyz = convert_rgb2xyz(rgb); return convert_xyz2lab(xyz); } vec3 convert_rgb2xyz(vec3 rgb) { vec3 tmp; tmp.x = (rgb.r > 0.04045) ? pow((rgb.r + 0.055) / 1.055, 2.4) : rgb.r / 12.92; tmp.y = (rgb.g > 0.04045) ? pow((rgb.g + 0.055) / 1.055, 2.4) : rgb.g / 12.92; tmp.z = (rgb.b > 0.04045) ? pow((rgb.b + 0.055) / 1.055, 2.4) : rgb.b / 12.92; return 100.0 * tmp * mat3( 0.4124, 0.3576, 0.1805, 0.2126, 0.7152, 0.0722, 0.0193, 0.1192, 0.9505 ); } //------------------------------------------------------------------------------ // HSV //------------------------------------------------------------------------------ vec3 convert_hsv2rgb(vec3 hsv) { hsv = vec3(hsv.x, clamp(hsv.yz, 0.0, 1.0)); vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(hsv.xxx + K.xyz) * 6.0 - K.www); return hsv.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), hsv.y); } vec3 convert_hsv2lab(vec3 hsv) { float H = hsv.x * 360.0; float S = hsv.y; float V = hsv.z; // Convert to LAB float L = V * 100.0; float C = S * L; float h = H * M_PI / 180.0; float a = C * cos(h); float b = C * sin(h); // Normalize LAB return vec3(L / 100.0, (a + 128.0) / 255.0, (b + 128.0) / 255.0); } vec3 convert_hsv2xyz(vec3 hsv) { vec3 rgb = convert_hsv2rgb(hsv); return convert_rgb2xyz(rgb); } //------------------------------------------------------------------------------ // LAB //------------------------------------------------------------------------------ vec3 convert_lab2rgb(vec3 lab) { vec3 xyz = convert_lab2xyz(lab); return convert_xyz2rgb(xyz); } vec3 convert_lab2hsv(vec3 lab) { vec3 rgb = convert_lab2rgb(lab); return convert_rgb2hsv(rgb); } vec3 convert_lab2xyz(vec3 lab) { float fy = (lab.x + 16.0) / 116.0; float fx = lab.y / 500.0 + fy; float fz = fy - lab.z / 200.0; vec3 f = vec3(fx, fy, fz); vec3 thresh = step(vec3(0.206897), f); vec3 xyz = mix( (f - vec3(16.0/116.0)) / 7.787, f * f * f, thresh ); return xyz * M_D65; } //------------------------------------------------------------------------------ // XYZ //------------------------------------------------------------------------------ vec3 convert_xyz2rgb(vec3 xyz) { vec3 v = xyz / M_D65; vec3 thresh = step(0.0031308, v); return mix( 12.92 * v, 1.055 * pow(v, vec3(1.0/2.4)) - 0.055, thresh ); } vec3 convert_xyz2hsv(vec3 xyz) { vec3 rgb = convert_xyz2rgb(xyz); return convert_rgb2hsv(rgb); } vec3 convert_xyz2lab(vec3 xyz) { vec3 n = xyz / M_D65; vec3 thresh = step(vec3(0.008856), n); vec3 v = mix( 7.787 * n + vec3(16.0/116.0), pow(n, vec3(1.0/3.0)), thresh ); return vec3( 116.0 * v.y - 16.0, 500.0 * (v.x - v.y), 200.0 * (v.y - v.z) ); } //------------------------------------------------------------------------------ // OKLAB //------------------------------------------------------------------------------ // RGB to Oklab (perceptually uniform color space) vec3 convert_rgb2oklab(vec3 rgb) { vec3 lms = rgb * mat3( 0.4122214708, 0.5363325363, 0.0514459929, 0.2119034982, 0.6806995451, 0.1073969566, 0.0883024619, 0.2817188376, 0.6299787005 ); lms = pow(lms, vec3(1.0/3.0)); return lms * mat3( 0.2104542553, 0.7936177850, -0.0040720468, 1.9779984951, -2.4285922050, 0.4505937099, 0.0259040371, 0.7827717662, -0.8086757660 ); } // Oklab to RGB vec3 convert_oklab2rgb(vec3 lab) { vec3 lms = lab * mat3( 1.0000000000, 0.3963377774, 0.2158037573, 1.0000000000, -0.1055613458, -0.0638541728, 1.0000000000, -0.0894841775, -1.2914855480 ); lms = lms * lms * lms; return lms * mat3( 4.0767416621, -3.3077115913, 0.2309699292, -1.2684380046, 2.6097574011, -0.3413193965, -0.0041960863, -0.7034186147, 1.7076147010 ); } #endif uniform sampler2D image; // | Image to convert uniform int operator; // EnumGLSLColorConvert | conversion operation to perform. // ============================================================================= // SELECTOR // ============================================================================= vec3 convertColor(vec3 color, int operator) { // RGB if (operator == 0) { return convert_rgb2hsv(color); } else if (operator == 1) { return convert_rgb2lab(color); } else if (operator == 2) { return convert_rgb2xyz(color); // HSV } else if (operator == 10) { return convert_hsv2rgb(color); } else if (operator == 11) { return convert_hsv2lab(color); } else if (operator == 12) { return convert_hsv2xyz(color); // LAB } else if (operator == 20) { return convert_lab2rgb(color); } else if (operator == 21) { return convert_lab2hsv(color); } else if (operator == 22) { return convert_lab2xyz(color); // XYZ } else if (operator == 30) { return convert_xyz2rgb(color); } else if (operator == 31) { return convert_xyz2hsv(color); } else if (operator == 32) { return convert_xyz2lab(color); } return color; } void mainImage(out vec4 fragColor, vec2 fragCoord) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); vec3 rgb = convertColor(color.rgb, operator); fragColor = vec4(rgb, color.a); }

Outputs (3)

NameTypeDescription
RGBAIMAGEFull channel [RGBA] image. If there is an alpha, the image will be masked out with it when using this output.
RGBIMAGEThree channel [RGB] image. There will be no alpha.
MASKMASKSingle channel mask output.