ComfyUI/blueprints/Unsharp Mask.json
Terry Jia 50076f3439
format blueprint (#13315)
Co-authored-by: guill <jacob.e.segal@gmail.com>
2026-04-06 23:33:55 -04:00

442 lines
12 KiB
JSON

{
"revision": 0,
"last_node_id": 30,
"last_link_id": 0,
"nodes": [
{
"id": 30,
"type": "d99ba3f5-8a56-4365-8e45-3f3ea7c572a1",
"pos": [
4420,
-370
],
"size": [
210,
106
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"label": "image0",
"localized_name": "images.image0",
"name": "images.image0",
"type": "IMAGE",
"link": null
}
],
"outputs": [
{
"localized_name": "IMAGE0",
"name": "IMAGE0",
"type": "IMAGE",
"links": []
}
],
"title": "Unsharp Mask",
"properties": {
"proxyWidgets": [
[
"27",
"value"
],
[
"28",
"value"
],
[
"29",
"value"
]
]
},
"widgets_values": []
}
],
"links": [],
"version": 0.4,
"definitions": {
"subgraphs": [
{
"id": "d99ba3f5-8a56-4365-8e45-3f3ea7c572a1",
"version": 1,
"state": {
"lastGroupId": 0,
"lastNodeId": 29,
"lastLinkId": 43,
"lastRerouteId": 0
},
"revision": 0,
"config": {},
"name": "Unsharp Mask",
"inputNode": {
"id": -10,
"bounding": [
3920,
-405,
120,
60
]
},
"outputNode": {
"id": -20,
"bounding": [
4930,
-405,
120,
60
]
},
"inputs": [
{
"id": "75354555-d2f3-46b9-a3dd-b076dcfca561",
"name": "images.image0",
"type": "IMAGE",
"linkIds": [
39
],
"localized_name": "images.image0",
"label": "image0",
"pos": [
4020,
-385
]
}
],
"outputs": [
{
"id": "04368b94-2a96-46ff-8c07-d0ce3235b40d",
"name": "IMAGE0",
"type": "IMAGE",
"linkIds": [
40
],
"localized_name": "IMAGE0",
"pos": [
4950,
-385
]
}
],
"widgets": [],
"nodes": [
{
"id": 27,
"type": "PrimitiveFloat",
"pos": [
4100,
-540
],
"size": [
270,
58
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [
{
"label": "amount",
"localized_name": "value",
"name": "value",
"type": "FLOAT",
"widget": {
"name": "value"
},
"link": null
}
],
"outputs": [
{
"localized_name": "FLOAT",
"name": "FLOAT",
"type": "FLOAT",
"links": [
41
]
}
],
"properties": {
"Node name for S&R": "PrimitiveFloat",
"min": 0,
"max": 3,
"precision": 2,
"step": 0.05
},
"widgets_values": [
1
]
},
{
"id": 28,
"type": "PrimitiveFloat",
"pos": [
4100,
-430
],
"size": [
270,
58
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"label": "radius",
"localized_name": "value",
"name": "value",
"type": "FLOAT",
"widget": {
"name": "value"
},
"link": null
}
],
"outputs": [
{
"localized_name": "FLOAT",
"name": "FLOAT",
"type": "FLOAT",
"links": [
42
]
}
],
"properties": {
"Node name for S&R": "PrimitiveFloat",
"min": 0,
"max": 10,
"precision": 1,
"step": 0.5
},
"widgets_values": [
3
]
},
{
"id": 29,
"type": "PrimitiveFloat",
"pos": [
4100,
-320
],
"size": [
270,
58
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"label": "threshold",
"localized_name": "value",
"name": "value",
"type": "FLOAT",
"widget": {
"name": "value"
},
"link": null
}
],
"outputs": [
{
"localized_name": "FLOAT",
"name": "FLOAT",
"type": "FLOAT",
"links": [
43
]
}
],
"properties": {
"Node name for S&R": "PrimitiveFloat",
"min": 0,
"max": 1,
"precision": 2,
"step": 0.05
},
"widgets_values": [
0
]
},
{
"id": 26,
"type": "GLSLShader",
"pos": [
4470,
-580
],
"size": [
400,
232
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"label": "image0",
"localized_name": "images.image0",
"name": "images.image0",
"type": "IMAGE",
"link": 39
},
{
"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": 41
},
{
"label": "u_float1",
"localized_name": "floats.u_float1",
"name": "floats.u_float1",
"shape": 7,
"type": "FLOAT",
"link": 42
},
{
"label": "u_float2",
"localized_name": "floats.u_float2",
"name": "floats.u_float2",
"shape": 7,
"type": "FLOAT",
"link": 43
},
{
"label": "u_float3",
"localized_name": "floats.u_float3",
"name": "floats.u_float3",
"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": [
40
]
},
{
"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 vec2 u_resolution;\nuniform float u_float0; // amount [0.0 - 3.0] typical: 0.5-1.5\nuniform float u_float1; // radius [0.5 - 10.0] blur radius in pixels\nuniform float u_float2; // threshold [0.0 - 0.1] min difference to sharpen\n\nin vec2 v_texCoord;\nlayout(location = 0) out vec4 fragColor0;\n\nfloat gaussian(float x, float sigma) {\n return exp(-(x * x) / (2.0 * sigma * sigma));\n}\n\nfloat getLuminance(vec3 color) {\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec2 texel = 1.0 / u_resolution;\n float radius = max(u_float1, 0.5);\n float amount = u_float0;\n float threshold = u_float2;\n\n vec4 original = texture(u_image0, v_texCoord);\n\n // Gaussian blur for the \"unsharp\" mask\n int samples = int(ceil(radius));\n float sigma = radius / 2.0;\n\n vec4 blurred = vec4(0.0);\n float totalWeight = 0.0;\n\n for (int x = -samples; x <= samples; x++) {\n for (int y = -samples; y <= samples; y++) {\n vec2 offset = vec2(float(x), float(y)) * texel;\n vec4 sample_color = texture(u_image0, v_texCoord + offset);\n\n float dist = length(vec2(float(x), float(y)));\n float weight = gaussian(dist, sigma);\n blurred += sample_color * weight;\n totalWeight += weight;\n }\n }\n blurred /= totalWeight;\n\n // Unsharp mask = original - blurred\n vec3 mask = original.rgb - blurred.rgb;\n\n // Luminance-based threshold with smooth falloff\n float lumaDelta = abs(getLuminance(original.rgb) - getLuminance(blurred.rgb));\n float thresholdScale = smoothstep(0.0, threshold, lumaDelta);\n mask *= thresholdScale;\n\n // Sharpen: original + mask * amount\n vec3 sharpened = original.rgb + mask * amount;\n\n fragColor0 = vec4(clamp(sharpened, 0.0, 1.0), original.a);\n}\n",
"from_input"
]
}
],
"groups": [],
"links": [
{
"id": 41,
"origin_id": 27,
"origin_slot": 0,
"target_id": 26,
"target_slot": 2,
"type": "FLOAT"
},
{
"id": 42,
"origin_id": 28,
"origin_slot": 0,
"target_id": 26,
"target_slot": 3,
"type": "FLOAT"
},
{
"id": 43,
"origin_id": 29,
"origin_slot": 0,
"target_id": 26,
"target_slot": 4,
"type": "FLOAT"
},
{
"id": 39,
"origin_id": -10,
"origin_slot": 0,
"target_id": 26,
"target_slot": 0,
"type": "IMAGE"
},
{
"id": 40,
"origin_id": 26,
"origin_slot": 0,
"target_id": -20,
"target_slot": 0,
"type": "IMAGE"
}
],
"extra": {
"workflowRendererVersion": "LG"
},
"category": "Image Tools/Sharpen"
}
]
}
}