{ "revision": 0, "last_node_id": 140, "last_link_id": 0, "nodes": [ { "id": 140, "type": "916dff42-6166-4d45-b028-04eaf69fbb35", "pos": [ 500, 1440 ], "size": [ 250, 178 ], "flags": {}, "order": 2, "mode": 0, "inputs": [ { "label": "image", "localized_name": "images.image0", "name": "images.image0", "type": "IMAGE", "link": null } ], "outputs": [ { "label": "IMAGE", "localized_name": "IMAGE0", "name": "IMAGE0", "type": "IMAGE", "links": [] } ], "properties": { "proxyWidgets": [ [ "4", "value" ], [ "5", "value" ] ] }, "widgets_values": [], "title": "Brightness and Contrast" } ], "links": [], "version": 0.4, "definitions": { "subgraphs": [ { "id": "916dff42-6166-4d45-b028-04eaf69fbb35", "version": 1, "state": { "lastGroupId": 0, "lastNodeId": 143, "lastLinkId": 118, "lastRerouteId": 0 }, "revision": 0, "config": {}, "name": "Brightness and Contrast", "inputNode": { "id": -10, "bounding": [ 360, -176, 120, 60 ] }, "outputNode": { "id": -20, "bounding": [ 1410, -176, 120, 60 ] }, "inputs": [ { "id": "a5aae7ea-b511-4045-b5da-94101e269cd7", "name": "images.image0", "type": "IMAGE", "linkIds": [ 117 ], "localized_name": "images.image0", "label": "image", "pos": [ 460, -156 ] } ], "outputs": [ { "id": "30b72604-69b3-4944-b253-a9099bbd73a9", "name": "IMAGE0", "type": "IMAGE", "linkIds": [ 118 ], "localized_name": "IMAGE0", "label": "IMAGE", "pos": [ 1430, -156 ] } ], "widgets": [], "nodes": [ { "id": 4, "type": "PrimitiveFloat", "pos": [ 540, -280 ], "size": [ 270, 58 ], "flags": {}, "order": 0, "mode": 0, "inputs": [ { "label": "brightness", "localized_name": "value", "name": "value", "type": "FLOAT", "widget": { "name": "value" }, "link": null } ], "outputs": [ { "localized_name": "FLOAT", "name": "FLOAT", "type": "FLOAT", "links": [ 115 ] } ], "properties": { "Node name for S&R": "PrimitiveFloat", "min": 0, "max": 100, "precision": 1, "step": 1, "display": "gradientslider", "gradient_stops": [ { "offset": 0, "color": [ 0, 0, 0 ] }, { "offset": 1, "color": [ 255, 255, 255 ] } ] }, "widgets_values": [ 50 ] }, { "id": 5, "type": "PrimitiveFloat", "pos": [ 540, -170 ], "size": [ 270, 58 ], "flags": {}, "order": 1, "mode": 0, "inputs": [ { "label": "contrast", "localized_name": "value", "name": "value", "type": "FLOAT", "widget": { "name": "value" }, "link": null } ], "outputs": [ { "localized_name": "FLOAT", "name": "FLOAT", "type": "FLOAT", "links": [ 116 ] } ], "properties": { "Node name for S&R": "PrimitiveFloat", "min": 0, "max": 100, "precision": 1, "step": 1, "display": "gradientslider", "gradient_stops": [ { "offset": 0, "color": [ 136, 136, 136 ] }, { "offset": 0.4, "color": [ 68, 68, 68 ] }, { "offset": 0.6, "color": [ 187, 187, 187 ] }, { "offset": 0.8, "color": [ 0, 0, 0 ] }, { "offset": 1, "color": [ 255, 255, 255 ] } ] }, "widgets_values": [ 0 ] }, { "id": 143, "type": "GLSLShader", "pos": [ 840, -280 ], "size": [ 400, 212 ], "flags": {}, "order": 2, "mode": 0, "inputs": [ { "label": "image0", "localized_name": "images.image0", "name": "images.image0", "type": "IMAGE", "link": 117 }, { "label": "image1", "localized_name": "images.image1", "name": "images.image1", "shape": 7, "type": "IMAGE", "link": null }, { "label": "u_float0", "localized_name": "floats.u_float0", "name": "floats.u_float0", "shape": 7, "type": "FLOAT", "link": 115 }, { "label": "u_float1", "localized_name": "floats.u_float1", "name": "floats.u_float1", "shape": 7, "type": "FLOAT", "link": 116 }, { "label": "u_float2", "localized_name": "floats.u_float2", "name": "floats.u_float2", "shape": 7, "type": "FLOAT", "link": null }, { "label": "u_int0", "localized_name": "ints.u_int0", "name": "ints.u_int0", "shape": 7, "type": "INT", "link": null }, { "localized_name": "fragment_shader", "name": "fragment_shader", "type": "STRING", "widget": { "name": "fragment_shader" }, "link": null }, { "localized_name": "size_mode", "name": "size_mode", "type": "COMFY_DYNAMICCOMBO_V3", "widget": { "name": "size_mode" }, "link": null } ], "outputs": [ { "localized_name": "IMAGE0", "name": "IMAGE0", "type": "IMAGE", "links": [ 118 ] }, { "localized_name": "IMAGE1", "name": "IMAGE1", "type": "IMAGE", "links": null }, { "localized_name": "IMAGE2", "name": "IMAGE2", "type": "IMAGE", "links": null }, { "localized_name": "IMAGE3", "name": "IMAGE3", "type": "IMAGE", "links": null } ], "properties": { "Node name for S&R": "GLSLShader" }, "widgets_values": [ "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform float u_float0; // Brightness slider -100..100\nuniform float u_float1; // Contrast slider -100..100\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nconst float MID_GRAY = 0.18; // 18% reflectance\n\n// sRGB gamma 2.2 approximation\nvec3 srgbToLinear(vec3 c) {\n return pow(max(c, 0.0), vec3(2.2));\n}\n\nvec3 linearToSrgb(vec3 c) {\n return pow(max(c, 0.0), vec3(1.0/2.2));\n}\n\nfloat mapBrightness(float b) {\n return clamp(b / 100.0, -1.0, 1.0);\n}\n\nfloat mapContrast(float c) {\n return clamp(c / 100.0 + 1.0, 0.0, 2.0);\n}\n\nvoid main() {\n vec4 orig = texture(u_image0, v_texCoord);\n\n float brightness = mapBrightness(u_float0);\n float contrast = mapContrast(u_float1);\n\n vec3 lin = srgbToLinear(orig.rgb);\n\n lin = (lin - MID_GRAY) * contrast + brightness + MID_GRAY;\n\n // Convert back to sRGB\n vec3 result = linearToSrgb(clamp(lin, 0.0, 1.0));\n\n fragColor = vec4(result, orig.a);\n}\n", "from_input" ] } ], "groups": [], "links": [ { "id": 115, "origin_id": 4, "origin_slot": 0, "target_id": 143, "target_slot": 2, "type": "FLOAT" }, { "id": 116, "origin_id": 5, "origin_slot": 0, "target_id": 143, "target_slot": 3, "type": "FLOAT" }, { "id": 117, "origin_id": -10, "origin_slot": 0, "target_id": 143, "target_slot": 0, "type": "IMAGE" }, { "id": 118, "origin_id": 143, "origin_slot": 0, "target_id": -20, "target_slot": 0, "type": "IMAGE" } ], "extra": { "workflowRendererVersion": "LG" }, "category": "Image Tools/Color adjust" } ] }, "extra": {} }