{
  "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": [
              0
            ]
          },
          {
            "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",
        "description": "Adjusts image brightness and contrast using a real-time GPU fragment shader."
      }
    ]
  },
  "extra": {}
}