Nodes/Jovi_GLSL/MIN MAX (JOV_GL)
ComfyUI Node

MIN MAX (JOV_GL)

A per-pixel channel-spread map, not a global analyzer

By Amorano·Created 2 years ago·Updated about a year ago· 20
MIN MAX (JOV_GL)
  • image
  • RGBA
  • RGB
  • MASK
FRAGMENT// name: MIN MAX // desc: Gets the minimum and maximum of an image // category: FILTER uniform sampler2D image; // | RGB(A) image void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); fragColor = vec4( min(min(color.r, color.g), color.b), max(max(color.r, color.g), color.b), 0.0, 1.0 ); }

The name makes this node sound like an analyzer - "get me the darkest and brightest pixel in my image" - and the first time you run it you'll probably stare at the output wondering what you're looking at. Here's what it actually does: for every pixel it writes the minimum of that pixel's RGB channels to the red channel and the maximum to the green channel, zeros the blue, and sets alpha to 1. It is a per-pixel map of "how much do this pixel's channels spread apart," not a global extrema report. Understand that and the node stops being confusing and becomes a decent little diagnostic.

How it works

The shader is three lines of math: sample the image, then vec4(min(r,g,b), max(r,g,b), 0, 1). There's no reduction pass, no whole-image scan - just per-pixel min and max. What that means in practice:

  • A neutral gray pixel (r ≈ g ≈ b) outputs red = green = that gray, blue = 0, which renders as a warm yellow-orange.
  • A saturated pixel (one channel much higher than the others) outputs a small min and a big max - red low, green high - which renders green.
  • A pure red pixel (1, 0, 0) becomes min 0 / max 1 → green.

So the output is a heat-map-ish readout of channel spread: colorful pixels light up in green, neutral pixels sit in the yellow-orange band. It's genuinely niche, but it has its moments - checking whether a mask or texture actually has channel variation, or debugging why a downstream color op is misbehaving.

The input

  • image - RGB, RGBA, or MASK. That's the only input; the node has zero parameters.

Outputs are the pack's standard RGBA, RGB, and MASK. The MASK output here is just the per-pixel min/max logic as a single channel, which is why you won't find many workflows wiring it anywhere serious - but it's there if you want it.

Install

One-time pack install. Via ComfyUI Manager, search Jovi_GLSL; or:

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

Restart ComfyUI. Standard pack deps (PyOpenGL, glfw, opencv-contrib-python, cozy_comfyui from git), needs an OpenGL context. No models, no keys. Under JOVI_GLSL 🌈 → FILTER.

Where people get tripped up

The one-true-trap: expecting global extrema. If you want "the brightest single pixel in this entire image," that's a reduction over the whole frame, and this node doesn't do that - GLSL per-pixel shaders fundamentally can't without extra passes. This node answers "within each pixel, how do this pixel's channels compare," and once you read the output as that, it stops being confusing. It's a diagnostic and a curiosity, not an image-analysis tool - and that's fine.

CategoryJOV_GL 🌈/FILTER

Inputs (2)

NameTypeDefaultDescription
imageoptIMAGERGB(A) image
FRAGMENToptSTRING// name: MIN MAX // desc: Gets the minimum and maximum of an image // category: FILTER uniform sampler2D image; // | RGB(A) image void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; vec4 color = texture(image, uv); fragColor = vec4( min(min(color.r, color.g), color.b), max(max(color.r, color.g), color.b), 0.0, 1.0 ); }

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.