Nodes/Jovi_GLSL/COLOR CONVERSION (JOV_GL)
ComfyUI Node

COLOR CONVERSION (JOV_GL)

Convert RGB to LAB, HSV, XYZ — all on the GPU, no Python math in sight

By Amorano·Created 2 years ago·Updated about a year 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); }

Most of the time you don't think about what color space your image is in - you think "looks good" and move on. Then you hit the workflow where you need to shift hue without wrecking luminance, or match a look by working in perceptual space, and you discover that ComfyUI's built-in options for color math are surprisingly thin. This node fixes that. It converts an image between RGB, HSV, LAB, and XYZ, all inside a fragment shader, and it's the kind of tool you don't reach for often but are very glad exists when you do.

How it works

Pick an operator and the node runs the corresponding conversion function from the pack's GLSL color library across every pixel in one GPU pass. The twelve options cover every direction between the four spaces: RGB↔HSV, RGB↔LAB, RGB↔XYZ, HSV↔LAB, HSV↔XYZ, LAB↔XYZ. Under the hood it's the standard formulas - Rec. 709 luma math, D65 white point for the XYZ↔LAB path, the usual HSV cylinder model - written out in shader code rather than Python.

Two practical notes on what the numbers mean here. First, the shader doesn't clamp anything - it writes the raw conversion result straight to the output. HSV stays comfortably in 0–1, but a LAB conversion returns conventional values (L around 0–100, a and b around −128..127), and on extreme inputs even those can overflow. So a LAB output from this node is real LAB, not a normalized approximation - which is great if you want to do math in perceptual space, but it means the values aren't displayable as an image until you rescale. And no, it won't match a color-grading app byte-for-byte; each library has its own rounding and white-point quirks.

The inputs

  • image - the image to convert. RGB, RGBA, or MASK all work.
  • operator - the dropdown, defaulting to RGB2HSV, with the other eleven conversions listed. This is the entire control surface; there are no numeric parameters, which is refreshing after the last color node you tuned by hand.

Outputs are the pack's usual three: RGBA, RGB (alpha dropped), and MASK. The MASK output is where this gets quietly useful - convert to a luminance-ish space and grab the mask, and you've got a quick tonal selection without touching any other node.

Install

One install for the whole pack. Via ComfyUI Manager, search Jovi_GLSL; or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/Amorano/Jovi_GLSL.git
cd Jovi_GLSL
pip install -r requirements.txt

Then restart ComfyUI. Dependencies are the pack's standard set - PyOpenGL, glfw, opencv-contrib-python, numpy>=1.25, and cozy_comfyui from git - so it needs a real OpenGL context at runtime. No model files, no keys. Nodes live under JOVI_GLSL 🌈 → COLOR.

Where people trip up

The big one is assuming the outputs are display-ready images. Converting to HSV and back for hue work is perfect - the round-trip is lossless enough for grading. But a raw LAB or XYZ output is floating-point data outside the 0–1 range; feed it straight into a node that expects a normal image and you'll get a blown-out or clamped-looking preview. Rescale before treating it as a picture, or just keep the conversion inside a round-trip where the values never need to be seen.

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.