工作流 /
节点基础 /
色彩调整蓝图展示

色彩调整蓝图展示
Color Adjustment Blueprints Showcase
内置蓝图颜色分级子图的并排演示。
节点基础
33 个节点 1 个输入 9 次使用 ComfyUI ≥ 0.19.0 ComfyUI 217 KB
节点构成
PreviewImage
× 13
MarkdownNote
× 9
bde8681c-adbd-4b44-a31c-2a4acb8cf45a
× 1
e864f288-0bda-497b-a111-800d4c0cd171
× 1
b5143322-553a-4d96-9539-76b3707ef275
× 1
1d319b86-6e4f-43d0-83e1-99dc988e1db3
× 1
bf0f7afe-2f48-42b1-9e47-57e362efc6dd
× 1
b7c3a768-1a1c-4a3d-bddf-043f4a8ffb20
× 1
1cccc258-98ed-4c17-8a0b-392e48a99dfa
× 1
LoadImage
× 1
8e3709c0-2209-4184-8a96-264ee9f1eed2
× 1
ed876eb4-358d-4e40-af28-de21afc3af7f
× 1
45b59a1a-ac53-4f90-8ebd-9f3ab79f21e3
× 1
官方标注的模型
None
工作流 JSON
和上面「下载工作流 JSON」是同一份文件。
1{
2 "id": "7875aac3-f583-4351-a4b0-c283491c6d4f",
3 "revision": 0,
4 "last_node_id": 204,
5 "last_link_id": 142,
6 "nodes": [
7 {
8 "id": 147,
9 "type": "bde8681c-adbd-4b44-a31c-2a4acb8cf45a",
10 "pos": [
11 -120,
12 2270
13 ],
14 "size": [
15 330,
16 500
17 ],
18 "flags": [],
19 "order": 13,
20 "mode": 0,
21 "inputs": [
22 {
23 "label": "image",
24 "name": "images.image0",
25 "type": "IMAGE",
26 "link": 122
27 }
28 ],
29 "outputs": [
30 {
31 "label": "IMAGE",
32 "name": "IMAGE0",
33 "type": "IMAGE",
34 "links": [
35 131
36 ]
37 }
38 ],
39 "properties": {
40 "proxyWidgets": [
41 [
42 "34",
43 "value"
44 ],
45 [
46 "35",
47 "value"
48 ],
49 [
50 "33",
51 "value"
52 ],
53 [
54 "146",
55 "choice"
56 ],
57 [
58 "32",
59 "color"
60 ],
61 [
62 "145",
63 "$$canvas-image-preview"
64 ]
65 ],
66 "cnr_id": "comfy-core",
67 "ver": "0.22.0",
68 "enableTabs": false,
69 "tabWidth": 65,
70 "tabXOffset": 10,
71 "hasSecondTab": false,
72 "secondTabText": "Send Back",
73 "secondTabOffset": 80,
74 "secondTabWidth": 65
75 },
76 "widgets_values": []
77 },
78 {
79 "id": 148,
80 "type": "e864f288-0bda-497b-a111-800d4c0cd171",
81 "pos": [
82 -120,
83 3480
84 ],
85 "size": [
86 250,
87 500
88 ],
89 "flags": [],
90 "order": 14,
91 "mode": 0,
92 "inputs": [
93 {
94 "label": "image",
95 "name": "images.image0",
96 "type": "IMAGE",
97 "link": 123
98 }
99 ],
100 "outputs": [
101 {
102 "label": "IMAGE",
103 "name": "IMAGE0",
104 "type": "IMAGE",
105 "links": [
106 132
107 ]
108 }
109 ],
110 "properties": {
111 "proxyWidgets": [
112 [
113 "17",
114 "value"
115 ],
116 [
117 "18",
118 "value"
119 ],
120 [
121 "19",
122 "value"
123 ],
124 [
125 "20",
126 "value"
127 ],
128 [
129 "21",
130 "choice"
131 ],
132 [
133 "15",
134 "$$canvas-image-preview"
135 ]
136 ],
137 "cnr_id": "comfy-core",
138 "ver": "0.22.0",
139 "enableTabs": false,
140 "tabWidth": 65,
141 "tabXOffset": 10,
142 "hasSecondTab": false,
143 "secondTabText": "Send Back",
144 "secondTabOffset": 80,
145 "secondTabWidth": 65
146 },
147 "widgets_values": []
148 },
149 {
150 "id": 160,
151 "type": "b5143322-553a-4d96-9539-76b3707ef275",
152 "pos": [
153 -120,
154 2910
155 ],
156 "size": [
157 270,
158 420
159 ],
160 "flags": [],
161 "order": 17,
162 "mode": 0,
163 "inputs": [
164 {
165 "label": "image",
166 "name": "images.image0",
167 "type": "IMAGE",
168 "link": 126
169 }
170 ],
171 "outputs": [
172 {
173 "label": "IMAGE",
174 "name": "IMAGE0",
175 "type": "IMAGE",
176 "links": [
177 135
178 ]
179 }
180 ],
181 "properties": {
182 "proxyWidgets": [
183 [
184 "159",
185 "choice"
186 ],
187 [
188 "158",
189 "value"
190 ],
191 [
192 "16",
193 "$$canvas-image-preview"
194 ]
195 ],
196 "cnr_id": "comfy-core",
197 "ver": "0.22.0",
198 "enableTabs": false,
199 "tabWidth": 65,
200 "tabXOffset": 10,
201 "hasSecondTab": false,
202 "secondTabText": "Send Back",
203 "secondTabOffset": 80,
204 "secondTabWidth": 65
205 },
206 "widgets_values": []
207 },
208 {
209 "id": 171,
210 "type": "1d319b86-6e4f-43d0-83e1-99dc988e1db3",
211 "pos": [
212 -120,
213 4130
214 ],
215 "size": [
216 270,
217 470
218 ],
219 "flags": [],
220 "order": 18,
221 "mode": 0,
222 "inputs": [
223 {
224 "label": "image",
225 "name": "images.image0",
226 "type": "IMAGE",
227 "link": 127
228 }
229 ],
230 "outputs": [
231 {
232 "label": "IMAGE",
233 "name": "IMAGE0",
234 "type": "IMAGE",
235 "links": [
236 136
237 ]
238 }
239 ],
240 "properties": {
241 "proxyWidgets": [
242 [
243 "170",
244 "value"
245 ],
246 [
247 "169",
248 "value"
249 ],
250 [
251 "168",
252 "value"
253 ],
254 [
255 "167",
256 "value"
257 ],
258 [
259 "166",
260 "$$canvas-image-preview"
261 ]
262 ],
263 "cnr_id": "comfy-core",
264 "ver": "0.22.0",
265 "enableTabs": false,
266 "tabWidth": 65,
267 "tabXOffset": 10,
268 "hasSecondTab": false,
269 "secondTabText": "Send Back",
270 "secondTabOffset": 80,
271 "secondTabWidth": 65
272 },
273 "widgets_values": []
274 },
275 {
276 "id": 179,
277 "type": "bf0f7afe-2f48-42b1-9e47-57e362efc6dd",
278 "pos": [
279 -120,
280 1610
281 ],
282 "size": [
283 330,
284 540
285 ],
286 "flags": [],
287 "order": 16,
288 "mode": 0,
289 "inputs": [
290 {
291 "label": "image",
292 "name": "images.image0",
293 "type": "IMAGE",
294 "link": 125
295 }
296 ],
297 "outputs": [
298 {
299 "label": "IMAGE",
300 "name": "IMAGE0",
301 "type": "IMAGE",
302 "links": [
303 134
304 ]
305 }
306 ],
307 "properties": {
308 "proxyWidgets": [
309 [
310 "172",
311 "choice"
312 ],
313 [
314 "174",
315 "value"
316 ],
317 [
318 "175",
319 "value"
320 ],
321 [
322 "176",
323 "value"
324 ],
325 [
326 "173",
327 "value"
328 ],
329 [
330 "177",
331 "value"
332 ],
333 [
334 "178",
335 "$$canvas-image-preview"
336 ]
337 ],
338 "cnr_id": "comfy-core",
339 "ver": "0.22.0",
340 "enableTabs": false,
341 "tabWidth": 65,
342 "tabXOffset": 10,
343 "hasSecondTab": false,
344 "secondTabText": "Send Back",
345 "secondTabOffset": 80,
346 "secondTabWidth": 65
347 },
348 "widgets_values": []
349 },
350 {
351 "id": 165,
352 "type": "b7c3a768-1a1c-4a3d-bddf-043f4a8ffb20",
353 "pos": [
354 -120,
355 4770
356 ],
357 "size": [
358 300,
359 540
360 ],
361 "flags": [],
362 "order": 19,
363 "mode": 0,
364 "inputs": [
365 {
366 "label": "image",
367 "name": "images.image0",
368 "type": "IMAGE",
369 "link": 128
370 }
371 ],
372 "outputs": [
373 {
374 "label": "IMAGE",
375 "name": "IMAGE0",
376 "type": "IMAGE",
377 "links": [
378 137
379 ]
380 }
381 ],
382 "properties": {
383 "proxyWidgets": [
384 [
385 "2",
386 "choice"
387 ],
388 [
389 "164",
390 "value"
391 ],
392 [
393 "163",
394 "value"
395 ],
396 [
397 "162",
398 "value"
399 ],
400 [
401 "161",
402 "value"
403 ],
404 [
405 "3",
406 "choice"
407 ],
408 [
409 "1",
410 "$$canvas-image-preview"
411 ]
412 ],
413 "cnr_id": "comfy-core",
414 "ver": "0.22.0",
415 "enableTabs": false,
416 "tabWidth": 65,
417 "tabXOffset": 10,
418 "hasSecondTab": false,
419 "secondTabText": "Send Back",
420 "secondTabOffset": 80,
421 "secondTabWidth": 65
422 },
423 "widgets_values": []
424 },
425 {
426 "id": 29,
427 "type": "1cccc258-98ed-4c17-8a0b-392e48a99dfa",
428 "pos": [
429 -170,
430 -430
431 ],
432 "size": [
433 230,
434 410
435 ],
436 "flags": [],
437 "order": 11,
438 "mode": 0,
439 "inputs": [
440 {
441 "label": "image",
442 "name": "images.image0",
443 "type": "IMAGE",
444 "link": 120
445 }
446 ],
447 "outputs": [
448 {
449 "label": "R",
450 "name": "IMAGE0",
451 "type": "IMAGE",
452 "links": [
453 138
454 ]
455 },
456 {
457 "label": "G",
458 "name": "IMAGE1",
459 "type": "IMAGE",
460 "links": [
461 139
462 ]
463 },
464 {
465 "label": "B",
466 "name": "IMAGE2",
467 "type": "IMAGE",
468 "links": [
469 142
470 ]
471 },
472 {
473 "label": "A",
474 "name": "IMAGE3",
475 "type": "IMAGE",
476 "links": [
477 141
478 ]
479 }
480 ],
481 "properties": {
482 "proxyWidgets": [
483 [
484 "23",
485 "$$canvas-image-preview"
486 ]
487 ],
488 "cnr_id": "comfy-core",
489 "ver": "0.22.0",
490 "enableTabs": false,
491 "tabWidth": 65,
492 "tabXOffset": 10,
493 "hasSecondTab": false,
494 "secondTabText": "Send Back",
495 "secondTabOffset": 80,
496 "secondTabWidth": 65
497 },
498 "widgets_values": []
499 },
500 {
501 "id": 180,
502 "type": "LoadImage",
503 "pos": [
504 -1170,
505 2270
506 ],
507 "size": [
508 290,
509 370
510 ],
511 "flags": [],
512 "order": 0,
513 "mode": 0,
514 "inputs": [],
515 "outputs": [
516 {
517 "name": "IMAGE",
518 "type": "IMAGE",
519 "links": [
520 119,
521 120,
522 121,
523 122,
524 123,
525 124,
526 125,
527 126,
528 127,
529 128
530 ]
531 },
532 {
533 "name": "MASK",
534 "type": "MASK",
535 "links": null
536 }
537 ],
538 "properties": {
539 "Node name for S&R": "LoadImage",
540 "cnr_id": "comfy-core",
541 "ver": "0.22.0",
542 "enableTabs": false,
543 "tabWidth": 65,
544 "tabXOffset": 10,
545 "hasSecondTab": false,
546 "secondTabText": "Send Back",
547 "secondTabOffset": 80,
548 "secondTabWidth": 65
549 },
550 "widgets_values": [
551 "example.png",
552 "image"
553 ]
554 },
555 {
556 "id": 182,
557 "type": "PreviewImage",
558 "pos": [
559 320,
560 950
561 ],
562 "size": [
563 380,
564 460
565 ],
566 "flags": [],
567 "order": 25,
568 "mode": 0,
569 "inputs": [
570 {
571 "name": "images",
572 "type": "IMAGE",
573 "link": 130
574 }
575 ],
576 "outputs": [],
577 "properties": {
578 "Node name for S&R": "PreviewImage",
579 "cnr_id": "comfy-core",
580 "ver": "0.22.0",
581 "enableTabs": false,
582 "tabWidth": 65,
583 "tabXOffset": 10,
584 "hasSecondTab": false,
585 "secondTabText": "Send Back",
586 "secondTabOffset": 80,
587 "secondTabWidth": 65
588 },
589 "widgets_values": []
590 },
591 {
592 "id": 183,
593 "type": "PreviewImage",
594 "pos": [
595 320,
596 2280
597 ],
598 "size": [
599 380,
600 490
601 ],
602 "flags": [],
603 "order": 26,
604 "mode": 0,
605 "inputs": [
606 {
607 "name": "images",
608 "type": "IMAGE",
609 "link": 131
610 }
611 ],
612 "outputs": [],
613 "properties": {
614 "Node name for S&R": "PreviewImage",
615 "cnr_id": "comfy-core",
616 "ver": "0.22.0",
617 "enableTabs": false,
618 "tabWidth": 65,
619 "tabXOffset": 10,
620 "hasSecondTab": false,
621 "secondTabText": "Send Back",
622 "secondTabOffset": 80,
623 "secondTabWidth": 65
624 },
625 "widgets_values": []
626 },
627 {
628 "id": 184,
629 "type": "PreviewImage",
630 "pos": [
631 320,
632 3480
633 ],
634 "size": [
635 380,
636 500
637 ],
638 "flags": [],
639 "order": 27,
640 "mode": 0,
641 "inputs": [
642 {
643 "name": "images",
644 "type": "IMAGE",
645 "link": 132
646 }
647 ],
648 "outputs": [],
649 "properties": {
650 "Node name for S&R": "PreviewImage",
651 "cnr_id": "comfy-core",
652 "ver": "0.22.0",
653 "enableTabs": false,
654 "tabWidth": 65,
655 "tabXOffset": 10,
656 "hasSecondTab": false,
657 "secondTabText": "Send Back",
658 "secondTabOffset": 80,
659 "secondTabWidth": 65
660 },
661 "widgets_values": []
662 },
663 {
664 "id": 187,
665 "type": "PreviewImage",
666 "pos": [
667 320,
668 1610
669 ],
670 "size": [
671 380,
672 540
673 ],
674 "flags": [],
675 "order": 29,
676 "mode": 0,
677 "inputs": [
678 {
679 "name": "images",
680 "type": "IMAGE",
681 "link": 134
682 }
683 ],
684 "outputs": [],
685 "properties": {
686 "Node name for S&R": "PreviewImage",
687 "cnr_id": "comfy-core",
688 "ver": "0.22.0",
689 "enableTabs": false,
690 "tabWidth": 65,
691 "tabXOffset": 10,
692 "hasSecondTab": false,
693 "secondTabText": "Send Back",
694 "secondTabOffset": 80,
695 "secondTabWidth": 65
696 },
697 "widgets_values": []
698 },
699 {
700 "id": 188,
701 "type": "PreviewImage",
702 "pos": [
703 320,
704 2910
705 ],
706 "size": [
707 380,
708 420
709 ],
710 "flags": [],
711 "order": 30,
712 "mode": 0,
713 "inputs": [
714 {
715 "name": "images",
716 "type": "IMAGE",
717 "link": 135
718 }
719 ],
720 "outputs": [],
721 "properties": {
722 "Node name for S&R": "PreviewImage",
723 "cnr_id": "comfy-core",
724 "ver": "0.22.0",
725 "enableTabs": false,
726 "tabWidth": 65,
727 "tabXOffset": 10,
728 "hasSecondTab": false,
729 "secondTabText": "Send Back",
730 "secondTabOffset": 80,
731 "secondTabWidth": 65
732 },
733 "widgets_values": []
734 },
735 {
736 "id": 189,
737 "type": "PreviewImage",
738 "pos": [
739 320,
740 4140
741 ],
742 "size": [
743 380,
744 480
745 ],
746 "flags": [],
747 "order": 31,
748 "mode": 0,
749 "inputs": [
750 {
751 "name": "images",
752 "type": "IMAGE",
753 "link": 136
754 }
755 ],
756 "outputs": [],
757 "properties": {
758 "Node name for S&R": "PreviewImage",
759 "cnr_id": "comfy-core",
760 "ver": "0.22.0",
761 "enableTabs": false,
762 "tabWidth": 65,
763 "tabXOffset": 10,
764 "hasSecondTab": false,
765 "secondTabText": "Send Back",
766 "secondTabOffset": 80,
767 "secondTabWidth": 65
768 },
769 "widgets_values": []
770 },
771 {
772 "id": 190,
773 "type": "PreviewImage",
774 "pos": [
775 320,
776 4770
777 ],
778 "size": [
779 380,
780 500
781 ],
782 "flags": [],
783 "order": 32,
784 "mode": 0,
785 "inputs": [
786 {
787 "name": "images",
788 "type": "IMAGE",
789 "link": 137
790 }
791 ],
792 "outputs": [],
793 "properties": {
794 "Node name for S&R": "PreviewImage",
795 "cnr_id": "comfy-core",
796 "ver": "0.22.0",
797 "enableTabs": false,
798 "tabWidth": 65,
799 "tabXOffset": 10,
800 "hasSecondTab": false,
801 "secondTabText": "Send Back",
802 "secondTabOffset": 80,
803 "secondTabWidth": 65
804 },
805 "widgets_values": []
806 },
807 {
808 "id": 193,
809 "type": "PreviewImage",
810 "pos": [
811 980,
812 -430
813 ],
814 "size": [
815 230,
816 410
817 ],
818 "flags": [],
819 "order": 24,
820 "mode": 0,
821 "inputs": [
822 {
823 "name": "images",
824 "type": "IMAGE",
825 "link": 141
826 }
827 ],
828 "outputs": [],
829 "properties": {
830 "Node name for S&R": "PreviewImage",
831 "cnr_id": "comfy-core",
832 "ver": "0.22.0",
833 "enableTabs": false,
834 "tabWidth": 65,
835 "tabXOffset": 10,
836 "hasSecondTab": false,
837 "secondTabText": "Send Back",
838 "secondTabOffset": 80,
839 "secondTabWidth": 65
840 },
841 "widgets_values": []
842 },
843 {
844 "id": 194,
845 "type": "PreviewImage",
846 "pos": [
847 690,
848 -430
849 ],
850 "size": [
851 230,
852 410
853 ],
854 "flags": [],
855 "order": 23,
856 "mode": 0,
857 "inputs": [
858 {
859 "name": "images",
860 "type": "IMAGE",
861 "link": 142
862 }
863 ],
864 "outputs": [],
865 "properties": {
866 "Node name for S&R": "PreviewImage",
867 "cnr_id": "comfy-core",
868 "ver": "0.22.0",
869 "enableTabs": false,
870 "tabWidth": 65,
871 "tabXOffset": 10,
872 "hasSecondTab": false,
873 "secondTabText": "Send Back",
874 "secondTabOffset": 80,
875 "secondTabWidth": 65
876 },
877 "widgets_values": []
878 },
879 {
880 "id": 191,
881 "type": "PreviewImage",
882 "pos": [
883 120,
884 -430
885 ],
886 "size": [
887 230,
888 410
889 ],
890 "flags": [],
891 "order": 21,
892 "mode": 0,
893 "inputs": [
894 {
895 "name": "images",
896 "type": "IMAGE",
897 "link": 138
898 }
899 ],
900 "outputs": [],
901 "properties": {
902 "Node name for S&R": "PreviewImage",
903 "cnr_id": "comfy-core",
904 "ver": "0.22.0",
905 "enableTabs": false,
906 "tabWidth": 65,
907 "tabXOffset": 10,
908 "hasSecondTab": false,
909 "secondTabText": "Send Back",
910 "secondTabOffset": 80,
911 "secondTabWidth": 65
912 },
913 "widgets_values": []
914 },
915 {
916 "id": 192,
917 "type": "PreviewImage",
918 "pos": [
919 410,
920 -430
921 ],
922 "size": [
923 230,
924 410
925 ],
926 "flags": [],
927 "order": 22,
928 "mode": 0,
929 "inputs": [
930 {
931 "name": "images",
932 "type": "IMAGE",
933 "link": 139
934 }
935 ],
936 "outputs": [],
937 "properties": {
938 "Node name for S&R": "PreviewImage",
939 "cnr_id": "comfy-core",
940 "ver": "0.22.0",
941 "enableTabs": false,
942 "tabWidth": 65,
943 "tabXOffset": 10,
944 "hasSecondTab": false,
945 "secondTabText": "Send Back",
946 "secondTabOffset": 80,
947 "secondTabWidth": 65
948 },
949 "widgets_values": []
950 },
951 {
952 "id": 10,
953 "type": "8e3709c0-2209-4184-8a96-264ee9f1eed2",
954 "pos": [
955 1510,
956 190
957 ],
958 "size": [
959 270,
960 1470
961 ],
962 "flags": [],
963 "order": 10,
964 "mode": 0,
965 "inputs": [
966 {
967 "label": "image",
968 "name": "images.image0",
969 "type": "IMAGE",
970 "link": 119
971 }
972 ],
973 "outputs": [
974 {
975 "label": "IMAGE",
976 "name": "IMAGE0",
977 "type": "IMAGE",
978 "links": [
979 129
980 ]
981 }
982 ],
983 "properties": {
984 "proxyWidgets": [
985 [
986 "4",
987 "curve"
988 ],
989 [
990 "5",
991 "curve"
992 ],
993 [
994 "6",
995 "curve"
996 ],
997 [
998 "7",
999 "curve"
1000 ],
1001 [
1002 "8",
1003 "$$canvas-image-preview"
1004 ]
1005 ],
1006 "cnr_id": "comfy-core",
1007 "ver": "0.22.0",
1008 "enableTabs": false,
1009 "tabWidth": 65,
1010 "tabXOffset": 10,
1011 "hasSecondTab": false,
1012 "secondTabText": "Send Back",
1013 "secondTabOffset": 80,
1014 "secondTabWidth": 65
1015 },
1016 "widgets_values": []
1017 },
1018 {
1019 "id": 181,
1020 "type": "PreviewImage",
1021 "pos": [
1022 1870,
1023 190
1024 ],
1025 "size": [
1026 570,
1027 640
1028 ],
1029 "flags": [],
1030 "order": 20,
1031 "mode": 0,
1032 "inputs": [
1033 {
1034 "name": "images",
1035 "type": "IMAGE",
1036 "link": 129
1037 }
1038 ],
1039 "outputs": [],
1040 "properties": {
1041 "Node name for S&R": "PreviewImage",
1042 "cnr_id": "comfy-core",
1043 "ver": "0.22.0",
1044 "enableTabs": false,
1045 "tabWidth": 65,
1046 "tabXOffset": 10,
1047 "hasSecondTab": false,
1048 "secondTabText": "Send Back",
1049 "secondTabOffset": 80,
1050 "secondTabWidth": 65
1051 },
1052 "widgets_values": []
1053 },
1054 {
1055 "id": 157,
1056 "type": "ed876eb4-358d-4e40-af28-de21afc3af7f",
1057 "pos": [
1058 -130,
1059 130
1060 ],
1061 "size": [
1062 400,
1063 660
1064 ],
1065 "flags": [],
1066 "order": 15,
1067 "mode": 0,
1068 "inputs": [
1069 {
1070 "label": "image",
1071 "name": "images.image0",
1072 "type": "IMAGE",
1073 "link": 124
1074 }
1075 ],
1076 "outputs": [
1077 {
1078 "label": "IMAGE",
1079 "name": "IMAGE0",
1080 "type": "IMAGE",
1081 "links": [
1082 133
1083 ]
1084 }
1085 ],
1086 "properties": {
1087 "proxyWidgets": [
1088 [
1089 "149",
1090 "value"
1091 ],
1092 [
1093 "150",
1094 "value"
1095 ],
1096 [
1097 "151",
1098 "value"
1099 ],
1100 [
1101 "152",
1102 "value"
1103 ],
1104 [
1105 "153",
1106 "value"
1107 ],
1108 [
1109 "154",
1110 "value"
1111 ],
1112 [
1113 "155",
1114 "value"
1115 ],
1116 [
1117 "11",
1118 "value"
1119 ],
1120 [
1121 "12",
1122 "value"
1123 ],
1124 [
1125 "13",
1126 "value"
1127 ],
1128 [
1129 "156",
1130 "$$canvas-image-preview"
1131 ]
1132 ],
1133 "cnr_id": "comfy-core",
1134 "ver": "0.22.0",
1135 "enableTabs": false,
1136 "tabWidth": 65,
1137 "tabXOffset": 10,
1138 "hasSecondTab": false,
1139 "secondTabText": "Send Back",
1140 "secondTabOffset": 80,
1141 "secondTabWidth": 65
1142 },
1143 "widgets_values": []
1144 },
1145 {
1146 "id": 186,
1147 "type": "PreviewImage",
1148 "pos": [
1149 320,
1150 130
1151 ],
1152 "size": [
1153 380,
1154 650
1155 ],
1156 "flags": [],
1157 "order": 28,
1158 "mode": 0,
1159 "inputs": [
1160 {
1161 "name": "images",
1162 "type": "IMAGE",
1163 "link": 133
1164 }
1165 ],
1166 "outputs": [],
1167 "properties": {
1168 "Node name for S&R": "PreviewImage",
1169 "cnr_id": "comfy-core",
1170 "ver": "0.22.0",
1171 "enableTabs": false,
1172 "tabWidth": 65,
1173 "tabXOffset": 10,
1174 "hasSecondTab": false,
1175 "secondTabText": "Send Back",
1176 "secondTabOffset": 80,
1177 "secondTabWidth": 65
1178 },
1179 "widgets_values": []
1180 },
1181 {
1182 "id": 196,
1183 "type": "MarkdownNote",
1184 "pos": [
1185 730,
1186 140
1187 ],
1188 "size": [
1189 430,
1190 640
1191 ],
1192 "flags": [],
1193 "order": 1,
1194 "mode": 0,
1195 "inputs": [],
1196 "outputs": [],
1197 "title": "Color Balance",
1198 "properties": [],
1199 "widgets_values": [
1200 "## Color Balance\n\n**Purpose**: Adjust RGB color balance separately in **shadows, midtones, and highlights**.\n\n**Highlights**: Real-time GPU fragment shader; independent sliders for precise color grading.\n\n**Use when**: Fixing color casts, matching tone across the image, or cinematic split-toning without crushing contrast."
1201 ],
1202 "color": "#222",
1203 "bgcolor": "#000"
1204 },
1205 {
1206 "id": 197,
1207 "type": "MarkdownNote",
1208 "pos": [
1209 730,
1210 960
1211 ],
1212 "size": [
1213 410,
1214 470
1215 ],
1216 "flags": [],
1217 "order": 2,
1218 "mode": 0,
1219 "inputs": [],
1220 "outputs": [],
1221 "title": "Brightness and Contrast",
1222 "properties": [],
1223 "widgets_values": [
1224 "## Brightness and Contrast\n\n**Purpose**: Change overall image **brightness** and **contrast**.\n\n**Highlights**: GPU shader; simple controls with fast preview for exposure tweaks.\n\n**Use when**: Brightening underexposed shots, taming highlights, or boosting/separating subject from background."
1225 ],
1226 "color": "#222",
1227 "bgcolor": "#000"
1228 },
1229 {
1230 "id": 198,
1231 "type": "MarkdownNote",
1232 "pos": [
1233 730,
1234 1630
1235 ],
1236 "size": [
1237 410,
1238 470
1239 ],
1240 "flags": [],
1241 "order": 3,
1242 "mode": 0,
1243 "inputs": [],
1244 "outputs": [],
1245 "title": "Image Levels",
1246 "properties": [],
1247 "widgets_values": [
1248 "## Image Levels\n\n**Purpose**: Set **black point, white point, and gamma** to control tonal distribution.\n\n**Highlights**: Familiar Levels-style workflow; GPU shader with live preview.\n\n**Use when**: Expanding dynamic range, fixing flat or crushed blacks, before other color passes."
1249 ],
1250 "color": "#222",
1251 "bgcolor": "#000"
1252 },
1253 {
1254 "id": 199,
1255 "type": "MarkdownNote",
1256 "pos": [
1257 730,
1258 2290
1259 ],
1260 "size": [
1261 410,
1262 470
1263 ],
1264 "flags": [],
1265 "order": 4,
1266 "mode": 0,
1267 "inputs": [],
1268 "outputs": [],
1269 "title": "Glow",
1270 "properties": [],
1271 "widgets_values": [
1272 "## Glow\n\n**Purpose**: Add **bloom / glow** around bright areas of the image.\n\n**Highlights**: GPU shader; adjustable strength, radius, blend mode, and tint color.\n\n**Use when**: Dreamy, neon, or cinematic halation around lights and specular highlights."
1273 ],
1274 "color": "#222",
1275 "bgcolor": "#000"
1276 },
1277 {
1278 "id": 200,
1279 "type": "MarkdownNote",
1280 "pos": [
1281 730,
1282 2920
1283 ],
1284 "size": [
1285 410,
1286 420
1287 ],
1288 "flags": [],
1289 "order": 5,
1290 "mode": 0,
1291 "inputs": [],
1292 "outputs": [],
1293 "title": "Chromatic Aberration",
1294 "properties": [],
1295 "widgets_values": [
1296 "## Chromatic Aberration\n\n**Purpose**: Simulate lens **color fringing** (e.g. red/cyan edges).\n\n**Highlights**: GPU real-time; adjustable strength and direction for strong stylization.\n\n**Use when**: Vintage, film, or lo-fi lens character; subtle edge accent effects."
1297 ],
1298 "color": "#222",
1299 "bgcolor": "#000"
1300 },
1301 {
1302 "id": 201,
1303 "type": "MarkdownNote",
1304 "pos": [
1305 730,
1306 3510
1307 ],
1308 "size": [
1309 410,
1310 420
1311 ],
1312 "flags": [],
1313 "order": 6,
1314 "mode": 0,
1315 "inputs": [],
1316 "outputs": [],
1317 "title": "Film Grain",
1318 "properties": [],
1319 "widgets_values": [
1320 "## Film Grain\n\n**Purpose**: Overlay procedural **film grain** texture.\n\n**Highlights**: GPU shader; control grain size, amount, and related parameters.\n\n**Use when**: Reducing overly clean digital look; adding cinematic texture and depth."
1321 ],
1322 "color": "#222",
1323 "bgcolor": "#000"
1324 },
1325 {
1326 "id": 202,
1327 "type": "MarkdownNote",
1328 "pos": [
1329 730,
1330 4140
1331 ],
1332 "size": [
1333 410,
1334 420
1335 ],
1336 "flags": [],
1337 "order": 7,
1338 "mode": 0,
1339 "inputs": [],
1340 "outputs": [],
1341 "title": "Color Adjustment",
1342 "properties": [],
1343 "widgets_values": [
1344 "## Color Adjustment\n\n**Purpose**: Tune global **saturation, temperature, tint, and vibrance**.\n\n**Highlights**: GPU real-time; broad global grade that complements zone-based Color Balance.\n\n**Use when**: Quick warm/cool shifts or overall saturation changes for mood."
1345 ],
1346 "color": "#222",
1347 "bgcolor": "#000"
1348 },
1349 {
1350 "id": 203,
1351 "type": "MarkdownNote",
1352 "pos": [
1353 730,
1354 4830
1355 ],
1356 "size": [
1357 410,
1358 420
1359 ],
1360 "flags": [],
1361 "order": 8,
1362 "mode": 0,
1363 "inputs": [],
1364 "outputs": [],
1365 "title": "Hue and Saturation",
1366 "properties": [],
1367 "widgets_values": [
1368 "## Hue and Saturation\n\n**Purpose**: Shift **hue**, **saturation**, and **lightness**.\n\n**Highlights**: GPU shader; channel or global modes depending on subgraph controls.\n\n**Use when**: Creative recoloring, desaturation, or pushing a specific color palette."
1369 ],
1370 "color": "#222",
1371 "bgcolor": "#000"
1372 },
1373 {
1374 "id": 204,
1375 "type": "MarkdownNote",
1376 "pos": [
1377 -1710,
1378 2260
1379 ],
1380 "size": [
1381 480,
1382 650
1383 ],
1384 "flags": [],
1385 "order": 9,
1386 "mode": 0,
1387 "inputs": [],
1388 "outputs": [],
1389 "title": "About this workflow",
1390 "properties": [],
1391 "widgets_values": [
1392 "## Built-in Color Adjustment Blueprints Demo\n\nThis workflow demonstrates built-in image color and tone **subgraphs** from ComfyUI **blueprints**. **Load Image** on the left feeds every branch; **Preview Image** on the right shows each result side by side.\n\n### Tips\n- Drag any subgraph from the Comfy Subgraph in the Node library into your own graphs, or keep this layout for comparison.\n- All color subgraphs use **GPU fragment shaders** for low-latency preview and export.\n\n### Strongly recommended\nEnable **[Nodes 2.0](https://docs.comfy.org/interface/nodes-2)** in ComfyUI settings for proxied subgraph widgets, canvas previews, and a smoother editing experience."
1393 ],
1394 "color": "#222",
1395 "bgcolor": "#000"
1396 },
1397 {
1398 "id": 144,
1399 "type": "45b59a1a-ac53-4f90-8ebd-9f3ab79f21e3",
1400 "pos": [
1401 -120,
1402 950
1403 ],
1404 "size": [
1405 320,
1406 460
1407 ],
1408 "flags": [],
1409 "order": 12,
1410 "mode": 0,
1411 "inputs": [
1412 {
1413 "label": "image",
1414 "name": "images.image0",
1415 "type": "IMAGE",
1416 "link": 121
1417 }
1418 ],
1419 "outputs": [
1420 {
1421 "label": "IMAGE",
1422 "name": "IMAGE0",
1423 "type": "IMAGE",
1424 "links": [
1425 130
1426 ]
1427 }
1428 ],
1429 "properties": {
1430 "proxyWidgets": [
1431 [
1432 "30",
1433 "value"
1434 ],
1435 [
1436 "31",
1437 "value"
1438 ],
1439 [
1440 "143",
1441 "$$canvas-image-preview"
1442 ]
1443 ],
1444 "cnr_id": "comfy-core",
1445 "ver": "0.22.0",
1446 "enableTabs": false,
1447 "tabWidth": 65,
1448 "tabXOffset": 10,
1449 "hasSecondTab": false,
1450 "secondTabText": "Send Back",
1451 "secondTabOffset": 80,
1452 "secondTabWidth": 65
1453 },
1454 "widgets_values": []
1455 }
1456 ],
1457 "links": [
1458 [
1459 119,
1460 180,
1461 0,
1462 10,
1463 0,
1464 "IMAGE"
1465 ],
1466 [
1467 120,
1468 180,
1469 0,
1470 29,
1471 0,
1472 "IMAGE"
1473 ],
1474 [
1475 121,
1476 180,
1477 0,
1478 144,
1479 0,
1480 "IMAGE"
1481 ],
1482 [
1483 122,
1484 180,
1485 0,
1486 147,
1487 0,
1488 "IMAGE"
1489 ],
1490 [
1491 123,
1492 180,
1493 0,
1494 148,
1495 0,
1496 "IMAGE"
1497 ],
1498 [
1499 124,
1500 180,
1501 0,
1502 157,
1503 0,
1504 "IMAGE"
1505 ],
1506 [
1507 125,
1508 180,
1509 0,
1510 179,
1511 0,
1512 "IMAGE"
1513 ],
1514 [
1515 126,
1516 180,
1517 0,
1518 160,
1519 0,
1520 "IMAGE"
1521 ],
1522 [
1523 127,
1524 180,
1525 0,
1526 171,
1527 0,
1528 "IMAGE"
1529 ],
1530 [
1531 128,
1532 180,
1533 0,
1534 165,
1535 0,
1536 "IMAGE"
1537 ],
1538 [
1539 129,
1540 10,
1541 0,
1542 181,
1543 0,
1544 "IMAGE"
1545 ],
1546 [
1547 130,
1548 144,
1549 0,
1550 182,
1551 0,
1552 "IMAGE"
1553 ],
1554 [
1555 131,
1556 147,
1557 0,
1558 183,
1559 0,
1560 "IMAGE"
1561 ],
1562 [
1563 132,
1564 148,
1565 0,
1566 184,
1567 0,
1568 "IMAGE"
1569 ],
1570 [
1571 133,
1572 157,
1573 0,
1574 186,
1575 0,
1576 "IMAGE"
1577 ],
1578 [
1579 134,
1580 179,
1581 0,
1582 187,
1583 0,
1584 "IMAGE"
1585 ],
1586 [
1587 135,
1588 160,
1589 0,
1590 188,
1591 0,
1592 "IMAGE"
1593 ],
1594 [
1595 136,
1596 171,
1597 0,
1598 189,
1599 0,
1600 "IMAGE"
1601 ],
1602 [
1603 137,
1604 165,
1605 0,
1606 190,
1607 0,
1608 "IMAGE"
1609 ],
1610 [
1611 138,
1612 29,
1613 0,
1614 191,
1615 0,
1616 "IMAGE"
1617 ],
1618 [
1619 139,
1620 29,
1621 1,
1622 192,
1623 0,
1624 "IMAGE"
1625 ],
1626 [
1627 141,
1628 29,
1629 3,
1630 193,
1631 0,
1632 "IMAGE"
1633 ],
1634 [
1635 142,
1636 29,
1637 2,
1638 194,
1639 0,
1640 "IMAGE"
1641 ]
1642 ],
1643 "groups": [
1644 {
1645 "id": 1,
1646 "title": "Image Channels",
1647 "bounding": [
1648 -180,
1649 -500,
1650 1393,
1651 490
1652 ],
1653 "color": "#3f789e",
1654 "flags": []
1655 },
1656 {
1657 "id": 2,
1658 "title": "Color Balance",
1659 "bounding": [
1660 -180,
1661 30,
1662 1390,
1663 820
1664 ],
1665 "color": "#3f789e",
1666 "flags": []
1667 },
1668 {
1669 "id": 3,
1670 "title": "Brightness and Contrast",
1671 "bounding": [
1672 -180,
1673 880,
1674 1390,
1675 620
1676 ],
1677 "color": "#3f789e",
1678 "flags": []
1679 },
1680 {
1681 "id": 4,
1682 "title": "Image Levels",
1683 "bounding": [
1684 -180,
1685 1540,
1686 1390,
1687 630
1688 ],
1689 "color": "#3f789e",
1690 "flags": []
1691 },
1692 {
1693 "id": 5,
1694 "title": "Glow",
1695 "bounding": [
1696 -180,
1697 2200,
1698 1390,
1699 600
1700 ],
1701 "color": "#3f789e",
1702 "flags": []
1703 },
1704 {
1705 "id": 6,
1706 "title": "Chromatic Aberration",
1707 "bounding": [
1708 -180,
1709 2840,
1710 1390,
1711 530
1712 ],
1713 "color": "#3f789e",
1714 "flags": []
1715 },
1716 {
1717 "id": 7,
1718 "title": "Film Grain",
1719 "bounding": [
1720 -180,
1721 3410,
1722 1390,
1723 620
1724 ],
1725 "color": "#3f789e",
1726 "flags": []
1727 },
1728 {
1729 "id": 8,
1730 "title": "Color Adjustment",
1731 "bounding": [
1732 -180,
1733 4060,
1734 1390,
1735 600
1736 ],
1737 "color": "#3f789e",
1738 "flags": []
1739 },
1740 {
1741 "id": 9,
1742 "title": "Hue and Saturation",
1743 "bounding": [
1744 -180,
1745 4700,
1746 1390,
1747 650
1748 ],
1749 "color": "#3f789e",
1750 "flags": []
1751 }
1752 ],
1753 "definitions": {
1754 "subgraphs": [
1755 {
1756 "id": "8e3709c0-2209-4184-8a96-264ee9f1eed2",
1757 "version": 1,
1758 "state": {
1759 "lastGroupId": 9,
1760 "lastNodeId": 204,
1761 "lastLinkId": 142,
1762 "lastRerouteId": 0
1763 },
1764 "revision": 0,
1765 "config": [],
1766 "name": "Color Curves",
1767 "description": "Fine-tunes tone and color with per-channel curve adjustments using a real-time GPU fragment shader.",
1768 "inputNode": {
1769 "id": -10,
1770 "bounding": [
1771 2660,
1772 -4500,
1773 120,
1774 60
1775 ]
1776 },
1777 "outputNode": {
1778 "id": -20,
1779 "bounding": [
1780 4270,
1781 -4500,
1782 120,
1783 60
1784 ]
1785 },
1786 "inputs": [
1787 {
1788 "id": "abc345b7-f55e-4f32-a11d-3aa4c2b0936b",
1789 "name": "images.image0",
1790 "type": "IMAGE",
1791 "linkIds": [
1792 29,
1793 34
1794 ],
1795 "localized_name": "images.image0",
1796 "label": "image",
1797 "pos": [
1798 2760,
1799 -4480
1800 ]
1801 }
1802 ],
1803 "outputs": [
1804 {
1805 "id": "eb0ec079-46da-4408-8263-9ef85569d33d",
1806 "name": "IMAGE0",
1807 "type": "IMAGE",
1808 "linkIds": [
1809 28
1810 ],
1811 "localized_name": "IMAGE0",
1812 "label": "IMAGE",
1813 "pos": [
1814 4290,
1815 -4480
1816 ]
1817 }
1818 ],
1819 "widgets": [],
1820 "nodes": [
1821 {
1822 "id": 4,
1823 "type": "CurveEditor",
1824 "pos": [
1825 3060,
1826 -4500
1827 ],
1828 "size": [
1829 270,
1830 200
1831 ],
1832 "flags": [],
1833 "order": 0,
1834 "mode": 0,
1835 "inputs": [
1836 {
1837 "label": "histogram",
1838 "localized_name": "histogram",
1839 "name": "histogram",
1840 "shape": 7,
1841 "type": "HISTOGRAM",
1842 "link": 35
1843 },
1844 {
1845 "label": "curve",
1846 "localized_name": "curve",
1847 "name": "curve",
1848 "type": "CURVE",
1849 "widget": {
1850 "name": "curve"
1851 },
1852 "link": null
1853 }
1854 ],
1855 "outputs": [
1856 {
1857 "localized_name": "curve",
1858 "name": "curve",
1859 "type": "CURVE",
1860 "links": [
1861 30
1862 ]
1863 }
1864 ],
1865 "title": "RGB Master",
1866 "properties": {
1867 "Node name for S&R": "CurveEditor",
1868 "cnr_id": "comfy-core",
1869 "ver": "0.22.0",
1870 "enableTabs": false,
1871 "tabWidth": 65,
1872 "tabXOffset": 10,
1873 "hasSecondTab": false,
1874 "secondTabText": "Send Back",
1875 "secondTabOffset": 80,
1876 "secondTabWidth": 65
1877 },
1878 "widgets_values": [
1879 {
1880 "points": [
1881 [
1882 0,
1883 0
1884 ],
1885 [
1886 0.3890328631875253,
1887 0.5266163706133749
1888 ],
1889 [
1890 0.7358435323017858,
1891 0.4499509575506062
1892 ],
1893 [
1894 1,
1895 1
1896 ]
1897 ],
1898 "interpolation": "monotone_cubic"
1899 }
1900 ]
1901 },
1902 {
1903 "id": 5,
1904 "type": "CurveEditor",
1905 "pos": [
1906 3060,
1907 -4250
1908 ],
1909 "size": [
1910 270,
1911 200
1912 ],
1913 "flags": [],
1914 "order": 1,
1915 "mode": 0,
1916 "inputs": [
1917 {
1918 "label": "histogram",
1919 "localized_name": "histogram",
1920 "name": "histogram",
1921 "shape": 7,
1922 "type": "HISTOGRAM",
1923 "link": 36
1924 },
1925 {
1926 "label": "curve",
1927 "localized_name": "curve",
1928 "name": "curve",
1929 "type": "CURVE",
1930 "widget": {
1931 "name": "curve"
1932 },
1933 "link": null
1934 }
1935 ],
1936 "outputs": [
1937 {
1938 "localized_name": "curve",
1939 "name": "curve",
1940 "type": "CURVE",
1941 "links": [
1942 31
1943 ]
1944 }
1945 ],
1946 "title": "Red",
1947 "properties": {
1948 "Node name for S&R": "CurveEditor",
1949 "cnr_id": "comfy-core",
1950 "ver": "0.22.0",
1951 "enableTabs": false,
1952 "tabWidth": 65,
1953 "tabXOffset": 10,
1954 "hasSecondTab": false,
1955 "secondTabText": "Send Back",
1956 "secondTabOffset": 80,
1957 "secondTabWidth": 65
1958 },
1959 "widgets_values": [
1960 {
1961 "points": [
1962 [
1963 0,
1964 0
1965 ],
1966 [
1967 0.5142255201011272,
1968 0.5774399905293097
1969 ],
1970 [
1971 0.6955375075900738,
1972 0.4189873777462001
1973 ],
1974 [
1975 1,
1976 1
1977 ]
1978 ],
1979 "interpolation": "monotone_cubic"
1980 }
1981 ]
1982 },
1983 {
1984 "id": 6,
1985 "type": "CurveEditor",
1986 "pos": [
1987 3060,
1988 -4000
1989 ],
1990 "size": [
1991 270,
1992 200
1993 ],
1994 "flags": [],
1995 "order": 2,
1996 "mode": 0,
1997 "inputs": [
1998 {
1999 "label": "histogram",
2000 "localized_name": "histogram",
2001 "name": "histogram",
2002 "shape": 7,
2003 "type": "HISTOGRAM",
2004 "link": 37
2005 },
2006 {
2007 "label": "curve",
2008 "localized_name": "curve",
2009 "name": "curve",
2010 "type": "CURVE",
2011 "widget": {
2012 "name": "curve"
2013 },
2014 "link": null
2015 }
2016 ],
2017 "outputs": [
2018 {
2019 "localized_name": "curve",
2020 "name": "curve",
2021 "type": "CURVE",
2022 "links": [
2023 32
2024 ]
2025 }
2026 ],
2027 "title": "Green",
2028 "properties": {
2029 "Node name for S&R": "CurveEditor",
2030 "cnr_id": "comfy-core",
2031 "ver": "0.22.0",
2032 "enableTabs": false,
2033 "tabWidth": 65,
2034 "tabXOffset": 10,
2035 "hasSecondTab": false,
2036 "secondTabText": "Send Back",
2037 "secondTabOffset": 80,
2038 "secondTabWidth": 65
2039 },
2040 "widgets_values": [
2041 {
2042 "points": [
2043 [
2044 0,
2045 0
2046 ],
2047 [
2048 0.4243823305151788,
2049 0.6834676161170985
2050 ],
2051 [
2052 0.648385876985464,
2053 0.6135687127234282
2054 ],
2055 [
2056 0.7751285241199568,
2057 0.5661072416153683
2058 ],
2059 [
2060 1,
2061 1
2062 ]
2063 ],
2064 "interpolation": "monotone_cubic"
2065 }
2066 ]
2067 },
2068 {
2069 "id": 7,
2070 "type": "CurveEditor",
2071 "pos": [
2072 3060,
2073 -3750
2074 ],
2075 "size": [
2076 270,
2077 200
2078 ],
2079 "flags": [],
2080 "order": 3,
2081 "mode": 0,
2082 "inputs": [
2083 {
2084 "label": "histogram",
2085 "localized_name": "histogram",
2086 "name": "histogram",
2087 "shape": 7,
2088 "type": "HISTOGRAM",
2089 "link": 38
2090 },
2091 {
2092 "label": "curve",
2093 "localized_name": "curve",
2094 "name": "curve",
2095 "type": "CURVE",
2096 "widget": {
2097 "name": "curve"
2098 },
2099 "link": null
2100 }
2101 ],
2102 "outputs": [
2103 {
2104 "localized_name": "curve",
2105 "name": "curve",
2106 "type": "CURVE",
2107 "links": [
2108 33
2109 ]
2110 }
2111 ],
2112 "title": "Blue",
2113 "properties": {
2114 "Node name for S&R": "CurveEditor",
2115 "cnr_id": "comfy-core",
2116 "ver": "0.22.0",
2117 "enableTabs": false,
2118 "tabWidth": 65,
2119 "tabXOffset": 10,
2120 "hasSecondTab": false,
2121 "secondTabText": "Send Back",
2122 "secondTabOffset": 80,
2123 "secondTabWidth": 65
2124 },
2125 "widgets_values": [
2126 {
2127 "points": [
2128 [
2129 0,
2130 0
2131 ],
2132 [
2133 1,
2134 1
2135 ]
2136 ],
2137 "interpolation": "monotone_cubic"
2138 }
2139 ]
2140 },
2141 {
2142 "id": 8,
2143 "type": "GLSLShader",
2144 "pos": [
2145 3590,
2146 -4500
2147 ],
2148 "size": [
2149 420,
2150 280
2151 ],
2152 "flags": [],
2153 "order": 4,
2154 "mode": 0,
2155 "inputs": [
2156 {
2157 "label": "image0",
2158 "localized_name": "images.image0",
2159 "name": "images.image0",
2160 "type": "IMAGE",
2161 "link": 29
2162 },
2163 {
2164 "label": "image1",
2165 "localized_name": "images.image1",
2166 "name": "images.image1",
2167 "shape": 7,
2168 "type": "IMAGE",
2169 "link": null
2170 },
2171 {
2172 "label": "u_float0",
2173 "localized_name": "floats.u_float0",
2174 "name": "floats.u_float0",
2175 "shape": 7,
2176 "type": "FLOAT",
2177 "link": null
2178 },
2179 {
2180 "label": "u_int0",
2181 "localized_name": "ints.u_int0",
2182 "name": "ints.u_int0",
2183 "shape": 7,
2184 "type": "INT",
2185 "link": null
2186 },
2187 {
2188 "label": "u_bool0",
2189 "localized_name": "bools.u_bool0",
2190 "name": "bools.u_bool0",
2191 "shape": 7,
2192 "type": "BOOLEAN",
2193 "link": null
2194 },
2195 {
2196 "label": "u_curve0",
2197 "localized_name": "curves.u_curve0",
2198 "name": "curves.u_curve0",
2199 "shape": 7,
2200 "type": "CURVE",
2201 "link": 30
2202 },
2203 {
2204 "label": "u_curve1",
2205 "localized_name": "curves.u_curve1",
2206 "name": "curves.u_curve1",
2207 "shape": 7,
2208 "type": "CURVE",
2209 "link": 31
2210 },
2211 {
2212 "label": "u_curve2",
2213 "localized_name": "curves.u_curve2",
2214 "name": "curves.u_curve2",
2215 "shape": 7,
2216 "type": "CURVE",
2217 "link": 32
2218 },
2219 {
2220 "label": "u_curve3",
2221 "localized_name": "curves.u_curve3",
2222 "name": "curves.u_curve3",
2223 "shape": 7,
2224 "type": "CURVE",
2225 "link": 33
2226 }
2227 ],
2228 "outputs": [
2229 {
2230 "localized_name": "IMAGE0",
2231 "name": "IMAGE0",
2232 "type": "IMAGE",
2233 "links": [
2234 28
2235 ]
2236 },
2237 {
2238 "localized_name": "IMAGE1",
2239 "name": "IMAGE1",
2240 "type": "IMAGE",
2241 "links": null
2242 },
2243 {
2244 "localized_name": "IMAGE2",
2245 "name": "IMAGE2",
2246 "type": "IMAGE",
2247 "links": null
2248 },
2249 {
2250 "localized_name": "IMAGE3",
2251 "name": "IMAGE3",
2252 "type": "IMAGE",
2253 "links": null
2254 }
2255 ],
2256 "properties": {
2257 "Node name for S&R": "GLSLShader",
2258 "cnr_id": "comfy-core",
2259 "ver": "0.22.0",
2260 "enableTabs": false,
2261 "tabWidth": 65,
2262 "tabXOffset": 10,
2263 "hasSecondTab": false,
2264 "secondTabText": "Send Back",
2265 "secondTabOffset": 80,
2266 "secondTabWidth": 65
2267 },
2268 "widgets_values": [
2269 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform sampler2D u_curve0; // RGB master curve (256x1 LUT)\nuniform sampler2D u_curve1; // Red channel curve\nuniform sampler2D u_curve2; // Green channel curve\nuniform sampler2D u_curve3; // Blue channel curve\n\nin vec2 v_texCoord;\nlayout(location = 0) out vec4 fragColor0;\n\n// GIMP-compatible curve lookup with manual linear interpolation.\n// Matches gimp_curve_map_value_inline() from gimpcurve-map.c:\n// index = value * (n_samples - 1)\n// f = fract(index)\n// result = (1-f) * samples[floor] + f * samples[ceil]\n//\n// Uses texelFetch (NEAREST) to avoid GPU half-texel offset issues\n// that occur with texture() + GL_LINEAR on small 256x1 LUTs.\nfloat applyCurve(sampler2D curve, float value) {\n value = clamp(value, 0.0, 1.0);\n\n float pos = value * 255.0;\n int lo = int(floor(pos));\n int hi = min(lo + 1, 255);\n float f = pos - float(lo);\n\n float a = texelFetch(curve, ivec2(lo, 0), 0).r;\n float b = texelFetch(curve, ivec2(hi, 0), 0).r;\n\n return a + f * (b - a);\n}\n\nvoid main() {\n vec4 color = texture(u_image0, v_texCoord);\n\n // GIMP order: per-channel curves first, then RGB master curve.\n // See gimp_curve_map_pixels() default case in gimpcurve-map.c:\n // dest = colors_curve( channel_curve( src ) )\n float tmp_r = applyCurve(u_curve1, color.r);\n float tmp_g = applyCurve(u_curve2, color.g);\n float tmp_b = applyCurve(u_curve3, color.b);\n color.r = applyCurve(u_curve0, tmp_r);\n color.g = applyCurve(u_curve0, tmp_g);\n color.b = applyCurve(u_curve0, tmp_b);\n\n fragColor0 = vec4(color.rgb, color.a);\n}\n",
2270 "from_input"
2271 ]
2272 },
2273 {
2274 "id": 9,
2275 "type": "ImageHistogram",
2276 "pos": [
2277 2800,
2278 -4300
2279 ],
2280 "size": [
2281 210,
2282 150
2283 ],
2284 "flags": [],
2285 "order": 5,
2286 "mode": 0,
2287 "inputs": [
2288 {
2289 "label": "image",
2290 "localized_name": "image",
2291 "name": "image",
2292 "type": "IMAGE",
2293 "link": 34
2294 }
2295 ],
2296 "outputs": [
2297 {
2298 "localized_name": "rgb",
2299 "name": "rgb",
2300 "type": "HISTOGRAM",
2301 "links": [
2302 35
2303 ]
2304 },
2305 {
2306 "localized_name": "luminance",
2307 "name": "luminance",
2308 "type": "HISTOGRAM",
2309 "links": []
2310 },
2311 {
2312 "localized_name": "red",
2313 "name": "red",
2314 "type": "HISTOGRAM",
2315 "links": [
2316 36
2317 ]
2318 },
2319 {
2320 "localized_name": "green",
2321 "name": "green",
2322 "type": "HISTOGRAM",
2323 "links": [
2324 37
2325 ]
2326 },
2327 {
2328 "localized_name": "blue",
2329 "name": "blue",
2330 "type": "HISTOGRAM",
2331 "links": [
2332 38
2333 ]
2334 }
2335 ],
2336 "properties": {
2337 "Node name for S&R": "ImageHistogram",
2338 "cnr_id": "comfy-core",
2339 "ver": "0.22.0",
2340 "enableTabs": false,
2341 "tabWidth": 65,
2342 "tabXOffset": 10,
2343 "hasSecondTab": false,
2344 "secondTabText": "Send Back",
2345 "secondTabOffset": 80,
2346 "secondTabWidth": 65
2347 },
2348 "widgets_values": []
2349 }
2350 ],
2351 "groups": [],
2352 "links": [
2353 {
2354 "id": 29,
2355 "origin_id": -10,
2356 "origin_slot": 0,
2357 "target_id": 8,
2358 "target_slot": 0,
2359 "type": "IMAGE"
2360 },
2361 {
2362 "id": 28,
2363 "origin_id": 8,
2364 "origin_slot": 0,
2365 "target_id": -20,
2366 "target_slot": 0,
2367 "type": "IMAGE"
2368 },
2369 {
2370 "id": 30,
2371 "origin_id": 4,
2372 "origin_slot": 0,
2373 "target_id": 8,
2374 "target_slot": 5,
2375 "type": "CURVE"
2376 },
2377 {
2378 "id": 31,
2379 "origin_id": 5,
2380 "origin_slot": 0,
2381 "target_id": 8,
2382 "target_slot": 6,
2383 "type": "CURVE"
2384 },
2385 {
2386 "id": 32,
2387 "origin_id": 6,
2388 "origin_slot": 0,
2389 "target_id": 8,
2390 "target_slot": 7,
2391 "type": "CURVE"
2392 },
2393 {
2394 "id": 33,
2395 "origin_id": 7,
2396 "origin_slot": 0,
2397 "target_id": 8,
2398 "target_slot": 8,
2399 "type": "CURVE"
2400 },
2401 {
2402 "id": 34,
2403 "origin_id": -10,
2404 "origin_slot": 0,
2405 "target_id": 9,
2406 "target_slot": 0,
2407 "type": "IMAGE"
2408 },
2409 {
2410 "id": 35,
2411 "origin_id": 9,
2412 "origin_slot": 0,
2413 "target_id": 4,
2414 "target_slot": 0,
2415 "type": "HISTOGRAM"
2416 },
2417 {
2418 "id": 36,
2419 "origin_id": 9,
2420 "origin_slot": 2,
2421 "target_id": 5,
2422 "target_slot": 0,
2423 "type": "HISTOGRAM"
2424 },
2425 {
2426 "id": 37,
2427 "origin_id": 9,
2428 "origin_slot": 3,
2429 "target_id": 6,
2430 "target_slot": 0,
2431 "type": "HISTOGRAM"
2432 },
2433 {
2434 "id": 38,
2435 "origin_id": 9,
2436 "origin_slot": 4,
2437 "target_id": 7,
2438 "target_slot": 0,
2439 "type": "HISTOGRAM"
2440 }
2441 ],
2442 "extra": {
2443 "workflowRendererVersion": "LG"
2444 }
2445 },
2446 {
2447 "id": "1cccc258-98ed-4c17-8a0b-392e48a99dfa",
2448 "version": 1,
2449 "state": {
2450 "lastGroupId": 9,
2451 "lastNodeId": 204,
2452 "lastLinkId": 142,
2453 "lastRerouteId": 0
2454 },
2455 "revision": 0,
2456 "config": [],
2457 "name": "Image Channels",
2458 "description": "Manipulates individual RGBA channels for masking, compositing, and channel effects.",
2459 "inputNode": {
2460 "id": -10,
2461 "bounding": [
2462 1820,
2463 -185,
2464 120,
2465 60
2466 ]
2467 },
2468 "outputNode": {
2469 "id": -20,
2470 "bounding": [
2471 2460,
2472 -215,
2473 120,
2474 120
2475 ]
2476 },
2477 "inputs": [
2478 {
2479 "id": "3522932b-2d86-4a1f-a02a-cb29f3a9d7fe",
2480 "name": "images.image0",
2481 "type": "IMAGE",
2482 "linkIds": [
2483 39
2484 ],
2485 "localized_name": "images.image0",
2486 "label": "image",
2487 "pos": [
2488 1920,
2489 -165
2490 ]
2491 }
2492 ],
2493 "outputs": [
2494 {
2495 "id": "605cb9c3-b065-4d9b-81d2-3ec331889b2b",
2496 "name": "IMAGE0",
2497 "type": "IMAGE",
2498 "linkIds": [
2499 26
2500 ],
2501 "localized_name": "IMAGE0",
2502 "label": "R",
2503 "pos": [
2504 2480,
2505 -195
2506 ]
2507 },
2508 {
2509 "id": "fb44a77e-0522-43e9-9527-82e7465b3596",
2510 "name": "IMAGE1",
2511 "type": "IMAGE",
2512 "linkIds": [
2513 27
2514 ],
2515 "localized_name": "IMAGE1",
2516 "label": "G",
2517 "pos": [
2518 2480,
2519 -175
2520 ]
2521 },
2522 {
2523 "id": "81460ee6-0131-402a-874f-6bf3001fc4ff",
2524 "name": "IMAGE2",
2525 "type": "IMAGE",
2526 "linkIds": [
2527 28
2528 ],
2529 "localized_name": "IMAGE2",
2530 "label": "B",
2531 "pos": [
2532 2480,
2533 -155
2534 ]
2535 },
2536 {
2537 "id": "ae690246-80d4-4951-b1d9-9306d8a77417",
2538 "name": "IMAGE3",
2539 "type": "IMAGE",
2540 "linkIds": [
2541 29
2542 ],
2543 "localized_name": "IMAGE3",
2544 "label": "A",
2545 "pos": [
2546 2480,
2547 -135
2548 ]
2549 }
2550 ],
2551 "widgets": [],
2552 "nodes": [
2553 {
2554 "id": 23,
2555 "type": "GLSLShader",
2556 "pos": [
2557 2000,
2558 -330
2559 ],
2560 "size": [
2561 400,
2562 220
2563 ],
2564 "flags": [],
2565 "order": 0,
2566 "mode": 0,
2567 "inputs": [
2568 {
2569 "label": "image",
2570 "localized_name": "images.image0",
2571 "name": "images.image0",
2572 "type": "IMAGE",
2573 "link": 39
2574 },
2575 {
2576 "label": "image1",
2577 "localized_name": "images.image1",
2578 "name": "images.image1",
2579 "shape": 7,
2580 "type": "IMAGE",
2581 "link": null
2582 },
2583 {
2584 "label": "u_float0",
2585 "localized_name": "floats.u_float0",
2586 "name": "floats.u_float0",
2587 "shape": 7,
2588 "type": "FLOAT",
2589 "link": null
2590 },
2591 {
2592 "label": "u_int0",
2593 "localized_name": "ints.u_int0",
2594 "name": "ints.u_int0",
2595 "shape": 7,
2596 "type": "INT",
2597 "link": null
2598 },
2599 {
2600 "label": "u_bool0",
2601 "localized_name": "bools.u_bool0",
2602 "name": "bools.u_bool0",
2603 "shape": 7,
2604 "type": "BOOLEAN",
2605 "link": null
2606 },
2607 {
2608 "label": "u_curve0",
2609 "localized_name": "curves.u_curve0",
2610 "name": "curves.u_curve0",
2611 "shape": 7,
2612 "type": "CURVE",
2613 "link": null
2614 }
2615 ],
2616 "outputs": [
2617 {
2618 "label": "R",
2619 "localized_name": "IMAGE0",
2620 "name": "IMAGE0",
2621 "type": "IMAGE",
2622 "links": [
2623 26
2624 ]
2625 },
2626 {
2627 "label": "G",
2628 "localized_name": "IMAGE1",
2629 "name": "IMAGE1",
2630 "type": "IMAGE",
2631 "links": [
2632 27
2633 ]
2634 },
2635 {
2636 "label": "B",
2637 "localized_name": "IMAGE2",
2638 "name": "IMAGE2",
2639 "type": "IMAGE",
2640 "links": [
2641 28
2642 ]
2643 },
2644 {
2645 "label": "A",
2646 "localized_name": "IMAGE3",
2647 "name": "IMAGE3",
2648 "type": "IMAGE",
2649 "links": [
2650 29
2651 ]
2652 }
2653 ],
2654 "properties": {
2655 "Node name for S&R": "GLSLShader",
2656 "cnr_id": "comfy-core",
2657 "ver": "0.22.0",
2658 "enableTabs": false,
2659 "tabWidth": 65,
2660 "tabXOffset": 10,
2661 "hasSecondTab": false,
2662 "secondTabText": "Send Back",
2663 "secondTabOffset": 80,
2664 "secondTabWidth": 65
2665 },
2666 "widgets_values": [
2667 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\n\nin vec2 v_texCoord;\nlayout(location = 0) out vec4 fragColor0;\nlayout(location = 1) out vec4 fragColor1;\nlayout(location = 2) out vec4 fragColor2;\nlayout(location = 3) out vec4 fragColor3;\n\nvoid main() {\n vec4 color = texture(u_image0, v_texCoord);\n // Output each channel as grayscale to separate render targets\n fragColor0 = vec4(vec3(color.r), 1.0); // Red channel\n fragColor1 = vec4(vec3(color.g), 1.0); // Green channel\n fragColor2 = vec4(vec3(color.b), 1.0); // Blue channel\n fragColor3 = vec4(vec3(color.a), 1.0); // Alpha channel\n}\n",
2668 "from_input"
2669 ]
2670 }
2671 ],
2672 "groups": [],
2673 "links": [
2674 {
2675 "id": 39,
2676 "origin_id": -10,
2677 "origin_slot": 0,
2678 "target_id": 23,
2679 "target_slot": 0,
2680 "type": "IMAGE"
2681 },
2682 {
2683 "id": 26,
2684 "origin_id": 23,
2685 "origin_slot": 0,
2686 "target_id": -20,
2687 "target_slot": 0,
2688 "type": "IMAGE"
2689 },
2690 {
2691 "id": 27,
2692 "origin_id": 23,
2693 "origin_slot": 1,
2694 "target_id": -20,
2695 "target_slot": 1,
2696 "type": "IMAGE"
2697 },
2698 {
2699 "id": 28,
2700 "origin_id": 23,
2701 "origin_slot": 2,
2702 "target_id": -20,
2703 "target_slot": 2,
2704 "type": "IMAGE"
2705 },
2706 {
2707 "id": 29,
2708 "origin_id": 23,
2709 "origin_slot": 3,
2710 "target_id": -20,
2711 "target_slot": 3,
2712 "type": "IMAGE"
2713 }
2714 ],
2715 "extra": {
2716 "workflowRendererVersion": "LG"
2717 }
2718 },
2719 {
2720 "id": "45b59a1a-ac53-4f90-8ebd-9f3ab79f21e3",
2721 "version": 1,
2722 "state": {
2723 "lastGroupId": 9,
2724 "lastNodeId": 204,
2725 "lastLinkId": 142,
2726 "lastRerouteId": 0
2727 },
2728 "revision": 0,
2729 "config": [],
2730 "name": "Brightness and Contrast",
2731 "description": "Adjusts image brightness and contrast using a real-time GPU fragment shader.",
2732 "inputNode": {
2733 "id": -10,
2734 "bounding": [
2735 360,
2736 -176,
2737 120,
2738 60
2739 ]
2740 },
2741 "outputNode": {
2742 "id": -20,
2743 "bounding": [
2744 1410,
2745 -176,
2746 120,
2747 60
2748 ]
2749 },
2750 "inputs": [
2751 {
2752 "id": "a5aae7ea-b511-4045-b5da-94101e269cd7",
2753 "name": "images.image0",
2754 "type": "IMAGE",
2755 "linkIds": [
2756 117
2757 ],
2758 "localized_name": "images.image0",
2759 "label": "image",
2760 "pos": [
2761 460,
2762 -156
2763 ]
2764 }
2765 ],
2766 "outputs": [
2767 {
2768 "id": "30b72604-69b3-4944-b253-a9099bbd73a9",
2769 "name": "IMAGE0",
2770 "type": "IMAGE",
2771 "linkIds": [
2772 118
2773 ],
2774 "localized_name": "IMAGE0",
2775 "label": "IMAGE",
2776 "pos": [
2777 1430,
2778 -156
2779 ]
2780 }
2781 ],
2782 "widgets": [],
2783 "nodes": [
2784 {
2785 "id": 30,
2786 "type": "PrimitiveFloat",
2787 "pos": [
2788 540,
2789 -280
2790 ],
2791 "size": [
2792 270,
2793 60
2794 ],
2795 "flags": [],
2796 "order": 0,
2797 "mode": 0,
2798 "inputs": [
2799 {
2800 "label": "brightness",
2801 "localized_name": "value",
2802 "name": "value",
2803 "type": "FLOAT",
2804 "widget": {
2805 "name": "value"
2806 },
2807 "link": null
2808 }
2809 ],
2810 "outputs": [
2811 {
2812 "localized_name": "FLOAT",
2813 "name": "FLOAT",
2814 "type": "FLOAT",
2815 "links": [
2816 115
2817 ]
2818 }
2819 ],
2820 "properties": {
2821 "Node name for S&R": "PrimitiveFloat",
2822 "cnr_id": "comfy-core",
2823 "ver": "0.22.0",
2824 "enableTabs": false,
2825 "tabWidth": 65,
2826 "tabXOffset": 10,
2827 "hasSecondTab": false,
2828 "secondTabText": "Send Back",
2829 "secondTabOffset": 80,
2830 "secondTabWidth": 65,
2831 "min": 0,
2832 "max": 100,
2833 "precision": 1,
2834 "step": 1,
2835 "display": "gradientslider",
2836 "gradient_stops": [
2837 {
2838 "offset": 0,
2839 "color": [
2840 0,
2841 0,
2842 0
2843 ]
2844 },
2845 {
2846 "offset": 1,
2847 "color": [
2848 255,
2849 255,
2850 255
2851 ]
2852 }
2853 ]
2854 },
2855 "widgets_values": [
2856 13
2857 ]
2858 },
2859 {
2860 "id": 31,
2861 "type": "PrimitiveFloat",
2862 "pos": [
2863 540,
2864 -170
2865 ],
2866 "size": [
2867 270,
2868 60
2869 ],
2870 "flags": [],
2871 "order": 1,
2872 "mode": 0,
2873 "inputs": [
2874 {
2875 "label": "contrast",
2876 "localized_name": "value",
2877 "name": "value",
2878 "type": "FLOAT",
2879 "widget": {
2880 "name": "value"
2881 },
2882 "link": null
2883 }
2884 ],
2885 "outputs": [
2886 {
2887 "localized_name": "FLOAT",
2888 "name": "FLOAT",
2889 "type": "FLOAT",
2890 "links": [
2891 116
2892 ]
2893 }
2894 ],
2895 "properties": {
2896 "Node name for S&R": "PrimitiveFloat",
2897 "cnr_id": "comfy-core",
2898 "ver": "0.22.0",
2899 "enableTabs": false,
2900 "tabWidth": 65,
2901 "tabXOffset": 10,
2902 "hasSecondTab": false,
2903 "secondTabText": "Send Back",
2904 "secondTabOffset": 80,
2905 "secondTabWidth": 65,
2906 "min": 0,
2907 "max": 100,
2908 "precision": 1,
2909 "step": 1,
2910 "display": "gradientslider",
2911 "gradient_stops": [
2912 {
2913 "offset": 0,
2914 "color": [
2915 136,
2916 136,
2917 136
2918 ]
2919 },
2920 {
2921 "offset": 0.4,
2922 "color": [
2923 68,
2924 68,
2925 68
2926 ]
2927 },
2928 {
2929 "offset": 0.6,
2930 "color": [
2931 187,
2932 187,
2933 187
2934 ]
2935 },
2936 {
2937 "offset": 0.8,
2938 "color": [
2939 0,
2940 0,
2941 0
2942 ]
2943 },
2944 {
2945 "offset": 1,
2946 "color": [
2947 255,
2948 255,
2949 255
2950 ]
2951 }
2952 ]
2953 },
2954 "widgets_values": [
2955 51
2956 ]
2957 },
2958 {
2959 "id": 143,
2960 "type": "GLSLShader",
2961 "pos": [
2962 840,
2963 -280
2964 ],
2965 "size": [
2966 400,
2967 260
2968 ],
2969 "flags": [],
2970 "order": 2,
2971 "mode": 0,
2972 "inputs": [
2973 {
2974 "label": "image0",
2975 "localized_name": "images.image0",
2976 "name": "images.image0",
2977 "type": "IMAGE",
2978 "link": 117
2979 },
2980 {
2981 "label": "image1",
2982 "localized_name": "images.image1",
2983 "name": "images.image1",
2984 "shape": 7,
2985 "type": "IMAGE",
2986 "link": null
2987 },
2988 {
2989 "label": "u_float0",
2990 "localized_name": "floats.u_float0",
2991 "name": "floats.u_float0",
2992 "shape": 7,
2993 "type": "FLOAT",
2994 "link": 115
2995 },
2996 {
2997 "label": "u_float1",
2998 "localized_name": "floats.u_float1",
2999 "name": "floats.u_float1",
3000 "shape": 7,
3001 "type": "FLOAT",
3002 "link": 116
3003 },
3004 {
3005 "label": "u_float2",
3006 "localized_name": "floats.u_float2",
3007 "name": "floats.u_float2",
3008 "shape": 7,
3009 "type": "FLOAT",
3010 "link": null
3011 },
3012 {
3013 "label": "u_int0",
3014 "localized_name": "ints.u_int0",
3015 "name": "ints.u_int0",
3016 "shape": 7,
3017 "type": "INT",
3018 "link": null
3019 },
3020 {
3021 "label": "u_bool0",
3022 "localized_name": "bools.u_bool0",
3023 "name": "bools.u_bool0",
3024 "shape": 7,
3025 "type": "BOOLEAN",
3026 "link": null
3027 },
3028 {
3029 "label": "u_curve0",
3030 "localized_name": "curves.u_curve0",
3031 "name": "curves.u_curve0",
3032 "shape": 7,
3033 "type": "CURVE",
3034 "link": null
3035 }
3036 ],
3037 "outputs": [
3038 {
3039 "localized_name": "IMAGE0",
3040 "name": "IMAGE0",
3041 "type": "IMAGE",
3042 "links": [
3043 118
3044 ]
3045 },
3046 {
3047 "localized_name": "IMAGE1",
3048 "name": "IMAGE1",
3049 "type": "IMAGE",
3050 "links": null
3051 },
3052 {
3053 "localized_name": "IMAGE2",
3054 "name": "IMAGE2",
3055 "type": "IMAGE",
3056 "links": null
3057 },
3058 {
3059 "localized_name": "IMAGE3",
3060 "name": "IMAGE3",
3061 "type": "IMAGE",
3062 "links": null
3063 }
3064 ],
3065 "properties": {
3066 "Node name for S&R": "GLSLShader",
3067 "cnr_id": "comfy-core",
3068 "ver": "0.22.0",
3069 "enableTabs": false,
3070 "tabWidth": 65,
3071 "tabXOffset": 10,
3072 "hasSecondTab": false,
3073 "secondTabText": "Send Back",
3074 "secondTabOffset": 80,
3075 "secondTabWidth": 65
3076 },
3077 "widgets_values": [
3078 "#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",
3079 "from_input"
3080 ]
3081 }
3082 ],
3083 "groups": [],
3084 "links": [
3085 {
3086 "id": 115,
3087 "origin_id": 30,
3088 "origin_slot": 0,
3089 "target_id": 143,
3090 "target_slot": 2,
3091 "type": "FLOAT"
3092 },
3093 {
3094 "id": 116,
3095 "origin_id": 31,
3096 "origin_slot": 0,
3097 "target_id": 143,
3098 "target_slot": 3,
3099 "type": "FLOAT"
3100 },
3101 {
3102 "id": 117,
3103 "origin_id": -10,
3104 "origin_slot": 0,
3105 "target_id": 143,
3106 "target_slot": 0,
3107 "type": "IMAGE"
3108 },
3109 {
3110 "id": 118,
3111 "origin_id": 143,
3112 "origin_slot": 0,
3113 "target_id": -20,
3114 "target_slot": 0,
3115 "type": "IMAGE"
3116 }
3117 ],
3118 "extra": {
3119 "workflowRendererVersion": "LG"
3120 }
3121 },
3122 {
3123 "id": "bde8681c-adbd-4b44-a31c-2a4acb8cf45a",
3124 "version": 1,
3125 "state": {
3126 "lastGroupId": 9,
3127 "lastNodeId": 204,
3128 "lastLinkId": 142,
3129 "lastRerouteId": 0
3130 },
3131 "revision": 0,
3132 "config": [],
3133 "name": "Glow",
3134 "description": "Adds a glow/bloom effect around bright image areas via GPU fragment shader.",
3135 "inputNode": {
3136 "id": -10,
3137 "bounding": [
3138 2110,
3139 -165,
3140 120,
3141 60
3142 ]
3143 },
3144 "outputNode": {
3145 "id": -20,
3146 "bounding": [
3147 3170,
3148 -165,
3149 120,
3150 60
3151 ]
3152 },
3153 "inputs": [
3154 {
3155 "id": "ffc7cf94-be90-4d56-a3b8-d0514d61c015",
3156 "name": "images.image0",
3157 "type": "IMAGE",
3158 "linkIds": [
3159 45
3160 ],
3161 "localized_name": "images.image0",
3162 "label": "image",
3163 "pos": [
3164 2210,
3165 -145
3166 ]
3167 }
3168 ],
3169 "outputs": [
3170 {
3171 "id": "04986101-50be-4762-8957-8e2a5e460bbb",
3172 "name": "IMAGE0",
3173 "type": "IMAGE",
3174 "linkIds": [
3175 53
3176 ],
3177 "localized_name": "IMAGE0",
3178 "label": "IMAGE",
3179 "pos": [
3180 3190,
3181 -145
3182 ]
3183 }
3184 ],
3185 "widgets": [],
3186 "nodes": [
3187 {
3188 "id": 145,
3189 "type": "GLSLShader",
3190 "pos": [
3191 2590,
3192 -520
3193 ],
3194 "size": [
3195 520,
3196 320
3197 ],
3198 "flags": [],
3199 "order": 5,
3200 "mode": 0,
3201 "inputs": [
3202 {
3203 "label": "image0",
3204 "localized_name": "images.image0",
3205 "name": "images.image0",
3206 "type": "IMAGE",
3207 "link": 45
3208 },
3209 {
3210 "label": "image1",
3211 "localized_name": "images.image1",
3212 "name": "images.image1",
3213 "shape": 7,
3214 "type": "IMAGE",
3215 "link": null
3216 },
3217 {
3218 "label": "u_float0",
3219 "localized_name": "floats.u_float0",
3220 "name": "floats.u_float0",
3221 "shape": 7,
3222 "type": "FLOAT",
3223 "link": 51
3224 },
3225 {
3226 "label": "u_float1",
3227 "localized_name": "floats.u_float1",
3228 "name": "floats.u_float1",
3229 "shape": 7,
3230 "type": "FLOAT",
3231 "link": 50
3232 },
3233 {
3234 "label": "u_float2",
3235 "localized_name": "floats.u_float2",
3236 "name": "floats.u_float2",
3237 "shape": 7,
3238 "type": "FLOAT",
3239 "link": 52
3240 },
3241 {
3242 "label": "u_float3",
3243 "localized_name": "floats.u_float3",
3244 "name": "floats.u_float3",
3245 "shape": 7,
3246 "type": "FLOAT",
3247 "link": null
3248 },
3249 {
3250 "label": "u_int0",
3251 "localized_name": "ints.u_int0",
3252 "name": "ints.u_int0",
3253 "shape": 7,
3254 "type": "INT",
3255 "link": 46
3256 },
3257 {
3258 "label": "u_int1",
3259 "localized_name": "ints.u_int1",
3260 "name": "ints.u_int1",
3261 "shape": 7,
3262 "type": "INT",
3263 "link": 47
3264 },
3265 {
3266 "label": "u_int2",
3267 "localized_name": "ints.u_int2",
3268 "name": "ints.u_int2",
3269 "shape": 7,
3270 "type": "INT",
3271 "link": null
3272 },
3273 {
3274 "label": "u_bool0",
3275 "localized_name": "bools.u_bool0",
3276 "name": "bools.u_bool0",
3277 "shape": 7,
3278 "type": "BOOLEAN",
3279 "link": null
3280 },
3281 {
3282 "label": "u_curve0",
3283 "localized_name": "curves.u_curve0",
3284 "name": "curves.u_curve0",
3285 "shape": 7,
3286 "type": "CURVE",
3287 "link": null
3288 }
3289 ],
3290 "outputs": [
3291 {
3292 "localized_name": "IMAGE0",
3293 "name": "IMAGE0",
3294 "type": "IMAGE",
3295 "links": [
3296 53
3297 ]
3298 },
3299 {
3300 "localized_name": "IMAGE1",
3301 "name": "IMAGE1",
3302 "type": "IMAGE",
3303 "links": null
3304 },
3305 {
3306 "localized_name": "IMAGE2",
3307 "name": "IMAGE2",
3308 "type": "IMAGE",
3309 "links": null
3310 },
3311 {
3312 "localized_name": "IMAGE3",
3313 "name": "IMAGE3",
3314 "type": "IMAGE",
3315 "links": null
3316 }
3317 ],
3318 "properties": {
3319 "Node name for S&R": "GLSLShader",
3320 "cnr_id": "comfy-core",
3321 "ver": "0.22.0",
3322 "enableTabs": false,
3323 "tabWidth": 65,
3324 "tabXOffset": 10,
3325 "hasSecondTab": false,
3326 "secondTabText": "Send Back",
3327 "secondTabOffset": 80,
3328 "secondTabWidth": 65
3329 },
3330 "widgets_values": [
3331 "#version 300 es\nprecision mediump float;\n\nuniform sampler2D u_image0;\nuniform int u_int0; // Blend mode\nuniform int u_int1; // Color tint\nuniform float u_float0; // Intensity\nuniform float u_float1; // Radius\nuniform float u_float2; // Threshold\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nconst int BLEND_ADD = 0;\nconst int BLEND_SCREEN = 1;\nconst int BLEND_SOFT = 2;\nconst int BLEND_OVERLAY = 3;\nconst int BLEND_LIGHTEN = 4;\n\nconst float GOLDEN_ANGLE = 2.39996323;\nconst int MAX_SAMPLES = 48;\nconst vec3 LUMA = vec3(0.299, 0.587, 0.114);\n\nfloat hash(vec2 p) {\n p = fract(p * vec2(123.34, 456.21));\n p += dot(p, p + 45.32);\n return fract(p.x * p.y);\n}\n\nvec3 hexToRgb(int h) {\n return vec3(\n float((h >> 16) & 255),\n float((h >> 8) & 255),\n float(h & 255)\n ) * (1.0 / 255.0);\n}\n\nvec3 blend(vec3 base, vec3 glow, int mode) {\n if (mode == BLEND_SCREEN) {\n return 1.0 - (1.0 - base) * (1.0 - glow);\n }\n if (mode == BLEND_SOFT) {\n return mix(\n base - (1.0 - 2.0 * glow) * base * (1.0 - base),\n base + (2.0 * glow - 1.0) * (sqrt(base) - base),\n step(0.5, glow)\n );\n }\n if (mode == BLEND_OVERLAY) {\n return mix(\n 2.0 * base * glow,\n 1.0 - 2.0 * (1.0 - base) * (1.0 - glow),\n step(0.5, base)\n );\n }\n if (mode == BLEND_LIGHTEN) {\n return max(base, glow);\n }\n return base + glow;\n}\n\nvoid main() {\n vec4 original = texture(u_image0, v_texCoord);\n \n float intensity = u_float0 * 0.05;\n float radius = u_float1 * u_float1 * 0.012;\n \n if (intensity < 0.001 || radius < 0.1) {\n fragColor = original;\n return;\n }\n \n float threshold = 1.0 - u_float2 * 0.01;\n float t0 = threshold - 0.15;\n float t1 = threshold + 0.15;\n \n vec2 texelSize = 1.0 / vec2(textureSize(u_image0, 0));\n float radius2 = radius * radius;\n \n float sampleScale = clamp(radius * 0.75, 0.35, 1.0);\n int samples = int(float(MAX_SAMPLES) * sampleScale);\n \n float noise = hash(gl_FragCoord.xy);\n float angleOffset = noise * GOLDEN_ANGLE;\n float radiusJitter = 0.85 + noise * 0.3;\n \n float ca = cos(GOLDEN_ANGLE);\n float sa = sin(GOLDEN_ANGLE);\n vec2 dir = vec2(cos(angleOffset), sin(angleOffset));\n \n vec3 glow = vec3(0.0);\n float totalWeight = 0.0;\n \n // Center tap\n float centerMask = smoothstep(t0, t1, dot(original.rgb, LUMA));\n glow += original.rgb * centerMask * 2.0;\n totalWeight += 2.0;\n \n for (int i = 1; i < MAX_SAMPLES; i++) {\n if (i >= samples) break;\n \n float fi = float(i);\n float dist = sqrt(fi / float(samples)) * radius * radiusJitter;\n \n vec2 offset = dir * dist * texelSize;\n vec3 c = texture(u_image0, v_texCoord + offset).rgb;\n float mask = smoothstep(t0, t1, dot(c, LUMA));\n \n float w = 1.0 - (dist * dist) / (radius2 * 1.5);\n w = max(w, 0.0);\n w *= w;\n \n glow += c * mask * w;\n totalWeight += w;\n \n dir = vec2(\n dir.x * ca - dir.y * sa,\n dir.x * sa + dir.y * ca\n );\n }\n \n glow *= intensity / max(totalWeight, 0.001);\n \n if (u_int1 > 0) {\n glow *= hexToRgb(u_int1);\n }\n \n vec3 result = blend(original.rgb, glow, u_int0);\n result += (noise - 0.5) * (1.0 / 255.0);\n \n fragColor = vec4(clamp(result, 0.0, 1.0), original.a);\n}",
3332 "from_input"
3333 ]
3334 },
3335 {
3336 "id": 34,
3337 "type": "PrimitiveFloat",
3338 "pos": [
3339 2290,
3340 -510
3341 ],
3342 "size": [
3343 270,
3344 60
3345 ],
3346 "flags": [],
3347 "order": 0,
3348 "mode": 0,
3349 "inputs": [
3350 {
3351 "label": "intensity",
3352 "localized_name": "value",
3353 "name": "value",
3354 "type": "FLOAT",
3355 "widget": {
3356 "name": "value"
3357 },
3358 "link": null
3359 }
3360 ],
3361 "outputs": [
3362 {
3363 "localized_name": "FLOAT",
3364 "name": "FLOAT",
3365 "type": "FLOAT",
3366 "links": [
3367 51
3368 ]
3369 }
3370 ],
3371 "properties": {
3372 "Node name for S&R": "PrimitiveFloat",
3373 "cnr_id": "comfy-core",
3374 "ver": "0.22.0",
3375 "enableTabs": false,
3376 "tabWidth": 65,
3377 "tabXOffset": 10,
3378 "hasSecondTab": false,
3379 "secondTabText": "Send Back",
3380 "secondTabOffset": 80,
3381 "secondTabWidth": 65,
3382 "min": 0,
3383 "max": 100,
3384 "precision": 1,
3385 "step": 1
3386 },
3387 "widgets_values": [
3388 2
3389 ]
3390 },
3391 {
3392 "id": 35,
3393 "type": "PrimitiveFloat",
3394 "pos": [
3395 2290,
3396 -410
3397 ],
3398 "size": [
3399 270,
3400 60
3401 ],
3402 "flags": [],
3403 "order": 1,
3404 "mode": 0,
3405 "inputs": [
3406 {
3407 "label": "radius",
3408 "localized_name": "value",
3409 "name": "value",
3410 "type": "FLOAT",
3411 "widget": {
3412 "name": "value"
3413 },
3414 "link": null
3415 }
3416 ],
3417 "outputs": [
3418 {
3419 "localized_name": "FLOAT",
3420 "name": "FLOAT",
3421 "type": "FLOAT",
3422 "links": [
3423 50
3424 ]
3425 }
3426 ],
3427 "properties": {
3428 "Node name for S&R": "PrimitiveFloat",
3429 "cnr_id": "comfy-core",
3430 "ver": "0.22.0",
3431 "enableTabs": false,
3432 "tabWidth": 65,
3433 "tabXOffset": 10,
3434 "hasSecondTab": false,
3435 "secondTabText": "Send Back",
3436 "secondTabOffset": 80,
3437 "secondTabWidth": 65,
3438 "min": 0,
3439 "max": 100,
3440 "precision": 1,
3441 "step": 1
3442 },
3443 "widgets_values": [
3444 29
3445 ]
3446 },
3447 {
3448 "id": 33,
3449 "type": "PrimitiveFloat",
3450 "pos": [
3451 2290,
3452 -310
3453 ],
3454 "size": [
3455 270,
3456 60
3457 ],
3458 "flags": [],
3459 "order": 2,
3460 "mode": 0,
3461 "inputs": [
3462 {
3463 "label": "threshold",
3464 "localized_name": "value",
3465 "name": "value",
3466 "type": "FLOAT",
3467 "widget": {
3468 "name": "value"
3469 },
3470 "link": null
3471 }
3472 ],
3473 "outputs": [
3474 {
3475 "localized_name": "FLOAT",
3476 "name": "FLOAT",
3477 "type": "FLOAT",
3478 "links": [
3479 52
3480 ]
3481 }
3482 ],
3483 "properties": {
3484 "Node name for S&R": "PrimitiveFloat",
3485 "cnr_id": "comfy-core",
3486 "ver": "0.22.0",
3487 "enableTabs": false,
3488 "tabWidth": 65,
3489 "tabXOffset": 10,
3490 "hasSecondTab": false,
3491 "secondTabText": "Send Back",
3492 "secondTabOffset": 80,
3493 "secondTabWidth": 65,
3494 "min": 0,
3495 "max": 100,
3496 "precision": 1,
3497 "step": 1
3498 },
3499 "widgets_values": [
3500 100
3501 ]
3502 },
3503 {
3504 "id": 32,
3505 "type": "ColorToRGBInt",
3506 "pos": [
3507 2290,
3508 -210
3509 ],
3510 "size": [
3511 270,
3512 60
3513 ],
3514 "flags": [],
3515 "order": 3,
3516 "mode": 0,
3517 "inputs": [
3518 {
3519 "label": "color_tint",
3520 "localized_name": "color",
3521 "name": "color",
3522 "type": "COLOR",
3523 "widget": {
3524 "name": "color"
3525 },
3526 "link": null
3527 }
3528 ],
3529 "outputs": [
3530 {
3531 "localized_name": "rgb_int",
3532 "name": "rgb_int",
3533 "type": "INT",
3534 "links": [
3535 47
3536 ]
3537 }
3538 ],
3539 "properties": {
3540 "Node name for S&R": "ColorToRGBInt",
3541 "cnr_id": "comfy-core",
3542 "ver": "0.22.0",
3543 "enableTabs": false,
3544 "tabWidth": 65,
3545 "tabXOffset": 10,
3546 "hasSecondTab": false,
3547 "secondTabText": "Send Back",
3548 "secondTabOffset": 80,
3549 "secondTabWidth": 65
3550 },
3551 "widgets_values": [
3552 "#0a9299"
3553 ]
3554 },
3555 {
3556 "id": 146,
3557 "type": "CustomCombo",
3558 "pos": [
3559 2290,
3560 -110
3561 ],
3562 "size": [
3563 270,
3564 230
3565 ],
3566 "flags": [],
3567 "order": 4,
3568 "mode": 0,
3569 "inputs": [
3570 {
3571 "label": "blend_mode",
3572 "localized_name": "choice",
3573 "name": "choice",
3574 "type": "COMBO",
3575 "widget": {
3576 "name": "choice"
3577 },
3578 "link": null
3579 }
3580 ],
3581 "outputs": [
3582 {
3583 "localized_name": "STRING",
3584 "name": "STRING",
3585 "type": "STRING",
3586 "links": null
3587 },
3588 {
3589 "localized_name": "INDEX",
3590 "name": "INDEX",
3591 "type": "INT",
3592 "links": [
3593 46
3594 ]
3595 }
3596 ],
3597 "properties": {
3598 "Node name for S&R": "CustomCombo",
3599 "cnr_id": "comfy-core",
3600 "ver": "0.22.0",
3601 "enableTabs": false,
3602 "tabWidth": 65,
3603 "tabXOffset": 10,
3604 "hasSecondTab": false,
3605 "secondTabText": "Send Back",
3606 "secondTabOffset": 80,
3607 "secondTabWidth": 65
3608 },
3609 "widgets_values": [
3610 "screen",
3611 1,
3612 "add",
3613 "screen",
3614 "soft",
3615 "overlay",
3616 "lighten",
3617 ""
3618 ]
3619 }
3620 ],
3621 "groups": [],
3622 "links": [
3623 {
3624 "id": 51,
3625 "origin_id": 34,
3626 "origin_slot": 0,
3627 "target_id": 145,
3628 "target_slot": 2,
3629 "type": "FLOAT"
3630 },
3631 {
3632 "id": 50,
3633 "origin_id": 35,
3634 "origin_slot": 0,
3635 "target_id": 145,
3636 "target_slot": 3,
3637 "type": "FLOAT"
3638 },
3639 {
3640 "id": 52,
3641 "origin_id": 33,
3642 "origin_slot": 0,
3643 "target_id": 145,
3644 "target_slot": 4,
3645 "type": "FLOAT"
3646 },
3647 {
3648 "id": 46,
3649 "origin_id": 146,
3650 "origin_slot": 1,
3651 "target_id": 145,
3652 "target_slot": 6,
3653 "type": "INT"
3654 },
3655 {
3656 "id": 47,
3657 "origin_id": 32,
3658 "origin_slot": 0,
3659 "target_id": 145,
3660 "target_slot": 7,
3661 "type": "INT"
3662 },
3663 {
3664 "id": 45,
3665 "origin_id": -10,
3666 "origin_slot": 0,
3667 "target_id": 145,
3668 "target_slot": 0,
3669 "type": "IMAGE"
3670 },
3671 {
3672 "id": 53,
3673 "origin_id": 145,
3674 "origin_slot": 0,
3675 "target_id": -20,
3676 "target_slot": 0,
3677 "type": "IMAGE"
3678 }
3679 ],
3680 "extra": {
3681 "workflowRendererVersion": "LG"
3682 }
3683 },
3684 {
3685 "id": "e864f288-0bda-497b-a111-800d4c0cd171",
3686 "version": 1,
3687 "state": {
3688 "lastGroupId": 9,
3689 "lastNodeId": 204,
3690 "lastLinkId": 142,
3691 "lastRerouteId": 0
3692 },
3693 "revision": 0,
3694 "config": [],
3695 "name": "Film Grain",
3696 "description": "Adds procedural film grain texture for a cinematic look via GPU fragment shader.",
3697 "inputNode": {
3698 "id": -10,
3699 "bounding": [
3700 4096.671470760602,
3701 -948.2184031393472,
3702 120,
3703 60
3704 ]
3705 },
3706 "outputNode": {
3707 "id": -20,
3708 "bounding": [
3709 4900,
3710 -948.2184031393472,
3711 120,
3712 60
3713 ]
3714 },
3715 "inputs": [
3716 {
3717 "id": "062968ea-da25-47e7-a180-d913c267f148",
3718 "name": "images.image0",
3719 "type": "IMAGE",
3720 "linkIds": [
3721 22
3722 ],
3723 "localized_name": "images.image0",
3724 "label": "image",
3725 "pos": [
3726 4196.671470760602,
3727 -928.2184031393472
3728 ]
3729 }
3730 ],
3731 "outputs": [
3732 {
3733 "id": "43247d06-a39f-4733-9828-c39400fe02a4",
3734 "name": "IMAGE0",
3735 "type": "IMAGE",
3736 "linkIds": [
3737 23
3738 ],
3739 "localized_name": "IMAGE0",
3740 "label": "IMAGE",
3741 "pos": [
3742 4920,
3743 -928.2184031393472
3744 ]
3745 }
3746 ],
3747 "widgets": [],
3748 "nodes": [
3749 {
3750 "id": 15,
3751 "type": "GLSLShader",
3752 "pos": [
3753 4510,
3754 -1180
3755 ],
3756 "size": [
3757 330,
3758 320
3759 ],
3760 "flags": [],
3761 "order": 5,
3762 "mode": 0,
3763 "inputs": [
3764 {
3765 "label": "image0",
3766 "localized_name": "images.image0",
3767 "name": "images.image0",
3768 "type": "IMAGE",
3769 "link": 22
3770 },
3771 {
3772 "label": "image1",
3773 "localized_name": "images.image1",
3774 "name": "images.image1",
3775 "shape": 7,
3776 "type": "IMAGE",
3777 "link": null
3778 },
3779 {
3780 "label": "u_float0",
3781 "localized_name": "floats.u_float0",
3782 "name": "floats.u_float0",
3783 "shape": 7,
3784 "type": "FLOAT",
3785 "link": 26
3786 },
3787 {
3788 "label": "u_float1",
3789 "localized_name": "floats.u_float1",
3790 "name": "floats.u_float1",
3791 "shape": 7,
3792 "type": "FLOAT",
3793 "link": 27
3794 },
3795 {
3796 "label": "u_float2",
3797 "localized_name": "floats.u_float2",
3798 "name": "floats.u_float2",
3799 "shape": 7,
3800 "type": "FLOAT",
3801 "link": 28
3802 },
3803 {
3804 "label": "u_float3",
3805 "localized_name": "floats.u_float3",
3806 "name": "floats.u_float3",
3807 "shape": 7,
3808 "type": "FLOAT",
3809 "link": 29
3810 },
3811 {
3812 "label": "u_float4",
3813 "localized_name": "floats.u_float4",
3814 "name": "floats.u_float4",
3815 "shape": 7,
3816 "type": "FLOAT",
3817 "link": null
3818 },
3819 {
3820 "label": "u_int0",
3821 "localized_name": "ints.u_int0",
3822 "name": "ints.u_int0",
3823 "shape": 7,
3824 "type": "INT",
3825 "link": 30
3826 },
3827 {
3828 "label": "u_int1",
3829 "localized_name": "ints.u_int1",
3830 "name": "ints.u_int1",
3831 "shape": 7,
3832 "type": "INT",
3833 "link": null
3834 },
3835 {
3836 "label": "u_bool0",
3837 "localized_name": "bools.u_bool0",
3838 "name": "bools.u_bool0",
3839 "shape": 7,
3840 "type": "BOOLEAN",
3841 "link": null
3842 },
3843 {
3844 "label": "u_curve0",
3845 "localized_name": "curves.u_curve0",
3846 "name": "curves.u_curve0",
3847 "shape": 7,
3848 "type": "CURVE",
3849 "link": null
3850 }
3851 ],
3852 "outputs": [
3853 {
3854 "localized_name": "IMAGE0",
3855 "name": "IMAGE0",
3856 "type": "IMAGE",
3857 "links": [
3858 23
3859 ]
3860 },
3861 {
3862 "localized_name": "IMAGE1",
3863 "name": "IMAGE1",
3864 "type": "IMAGE",
3865 "links": null
3866 },
3867 {
3868 "localized_name": "IMAGE2",
3869 "name": "IMAGE2",
3870 "type": "IMAGE",
3871 "links": null
3872 },
3873 {
3874 "localized_name": "IMAGE3",
3875 "name": "IMAGE3",
3876 "type": "IMAGE",
3877 "links": null
3878 }
3879 ],
3880 "properties": {
3881 "Node name for S&R": "GLSLShader",
3882 "cnr_id": "comfy-core",
3883 "ver": "0.22.0",
3884 "enableTabs": false,
3885 "tabWidth": 65,
3886 "tabXOffset": 10,
3887 "hasSecondTab": false,
3888 "secondTabText": "Send Back",
3889 "secondTabOffset": 80,
3890 "secondTabWidth": 65
3891 },
3892 "widgets_values": [
3893 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform vec2 u_resolution;\nuniform float u_float0; // grain amount [0.0 – 1.0] typical: 0.2–0.8\nuniform float u_float1; // grain size [0.3 – 3.0] lower = finer grain\nuniform float u_float2; // color amount [0.0 – 1.0] 0 = monochrome, 1 = RGB grain\nuniform float u_float3; // luminance bias [0.0 – 1.0] 0 = uniform, 1 = shadows only\nuniform int u_int0; // noise mode [0 or 1] 0 = smooth, 1 = grainy\n\nin vec2 v_texCoord;\nlayout(location = 0) out vec4 fragColor0;\n\n// High-quality integer hash (pcg-like)\nuint pcg(uint v) {\n uint state = v * 747796405u + 2891336453u;\n uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;\n return (word >> 22u) ^ word;\n}\n\n// 2D -> 1D hash input\nuint hash2d(uvec2 p) {\n return pcg(p.x + pcg(p.y));\n}\n\n// Hash to float [0, 1]\nfloat hashf(uvec2 p) {\n return float(hash2d(p)) / float(0xffffffffu);\n}\n\n// Hash to float with offset (for RGB channels)\nfloat hashf(uvec2 p, uint offset) {\n return float(pcg(hash2d(p) + offset)) / float(0xffffffffu);\n}\n\n// Convert uniform [0,1] to roughly Gaussian distribution\n// Using simple approximation: average of multiple samples\nfloat toGaussian(uvec2 p) {\n float sum = hashf(p, 0u) + hashf(p, 1u) + hashf(p, 2u) + hashf(p, 3u);\n return (sum - 2.0) * 0.7; // Centered, scaled\n}\n\nfloat toGaussian(uvec2 p, uint offset) {\n float sum = hashf(p, offset) + hashf(p, offset + 1u) \n + hashf(p, offset + 2u) + hashf(p, offset + 3u);\n return (sum - 2.0) * 0.7;\n}\n\n// Smooth noise with better interpolation\nfloat smoothNoise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n \n // Quintic interpolation (less banding than cubic)\n f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);\n \n uvec2 ui = uvec2(i);\n float a = toGaussian(ui);\n float b = toGaussian(ui + uvec2(1u, 0u));\n float c = toGaussian(ui + uvec2(0u, 1u));\n float d = toGaussian(ui + uvec2(1u, 1u));\n \n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\nfloat smoothNoise(vec2 p, uint offset) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n \n f = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);\n \n uvec2 ui = uvec2(i);\n float a = toGaussian(ui, offset);\n float b = toGaussian(ui + uvec2(1u, 0u), offset);\n float c = toGaussian(ui + uvec2(0u, 1u), offset);\n float d = toGaussian(ui + uvec2(1u, 1u), offset);\n \n return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);\n}\n\nvoid main() {\n vec4 color = texture(u_image0, v_texCoord);\n \n // Luminance (Rec.709)\n float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));\n \n // Grain UV (resolution-independent)\n vec2 grainUV = v_texCoord * u_resolution / max(u_float1, 0.01);\n uvec2 grainPixel = uvec2(grainUV);\n \n float g;\n vec3 grainRGB;\n \n if (u_int0 == 1) {\n // Grainy mode: pure hash noise (no interpolation = no banding)\n g = toGaussian(grainPixel);\n grainRGB = vec3(\n toGaussian(grainPixel, 100u),\n toGaussian(grainPixel, 200u),\n toGaussian(grainPixel, 300u)\n );\n } else {\n // Smooth mode: interpolated with quintic curve\n g = smoothNoise(grainUV);\n grainRGB = vec3(\n smoothNoise(grainUV, 100u),\n smoothNoise(grainUV, 200u),\n smoothNoise(grainUV, 300u)\n );\n }\n \n // Luminance weighting (less grain in highlights)\n float lumWeight = mix(1.0, 1.0 - luma, clamp(u_float3, 0.0, 1.0));\n \n // Strength\n float strength = u_float0 * 0.15;\n \n // Color vs monochrome grain\n vec3 grainColor = mix(vec3(g), grainRGB, clamp(u_float2, 0.0, 1.0));\n \n color.rgb += grainColor * strength * lumWeight;\n fragColor0 = vec4(clamp(color.rgb, 0.0, 1.0), color.a);\n}\n",
3894 "from_input"
3895 ]
3896 },
3897 {
3898 "id": 21,
3899 "type": "CustomCombo",
3900 "pos": [
3901 4280,
3902 -780
3903 ],
3904 "size": [
3905 210,
3906 160
3907 ],
3908 "flags": [],
3909 "order": 0,
3910 "mode": 0,
3911 "inputs": [
3912 {
3913 "label": "grain_mode",
3914 "localized_name": "choice",
3915 "name": "choice",
3916 "type": "COMBO",
3917 "widget": {
3918 "name": "choice"
3919 },
3920 "link": null
3921 }
3922 ],
3923 "outputs": [
3924 {
3925 "localized_name": "STRING",
3926 "name": "STRING",
3927 "type": "STRING",
3928 "links": null
3929 },
3930 {
3931 "localized_name": "INDEX",
3932 "name": "INDEX",
3933 "type": "INT",
3934 "links": [
3935 30
3936 ]
3937 }
3938 ],
3939 "properties": {
3940 "Node name for S&R": "CustomCombo",
3941 "cnr_id": "comfy-core",
3942 "ver": "0.22.0",
3943 "enableTabs": false,
3944 "tabWidth": 65,
3945 "tabXOffset": 10,
3946 "hasSecondTab": false,
3947 "secondTabText": "Send Back",
3948 "secondTabOffset": 80,
3949 "secondTabWidth": 65
3950 },
3951 "widgets_values": [
3952 "Smooth",
3953 0,
3954 "Smooth",
3955 "Grainy",
3956 ""
3957 ]
3958 },
3959 {
3960 "id": 17,
3961 "type": "PrimitiveFloat",
3962 "pos": [
3963 4280,
3964 -1180
3965 ],
3966 "size": [
3967 210,
3968 60
3969 ],
3970 "flags": [],
3971 "order": 1,
3972 "mode": 0,
3973 "inputs": [
3974 {
3975 "label": "grain_amount",
3976 "localized_name": "value",
3977 "name": "value",
3978 "type": "FLOAT",
3979 "widget": {
3980 "name": "value"
3981 },
3982 "link": null
3983 }
3984 ],
3985 "outputs": [
3986 {
3987 "localized_name": "FLOAT",
3988 "name": "FLOAT",
3989 "type": "FLOAT",
3990 "links": [
3991 26
3992 ]
3993 }
3994 ],
3995 "title": "Grain amount",
3996 "properties": {
3997 "Node name for S&R": "PrimitiveFloat",
3998 "cnr_id": "comfy-core",
3999 "ver": "0.22.0",
4000 "enableTabs": false,
4001 "tabWidth": 65,
4002 "tabXOffset": 10,
4003 "hasSecondTab": false,
4004 "secondTabText": "Send Back",
4005 "secondTabOffset": 80,
4006 "secondTabWidth": 65,
4007 "min": 0,
4008 "max": 1,
4009 "step": 0.05,
4010 "precision": 2
4011 },
4012 "widgets_values": [
4013 0.75
4014 ]
4015 },
4016 {
4017 "id": 18,
4018 "type": "PrimitiveFloat",
4019 "pos": [
4020 4280,
4021 -1080
4022 ],
4023 "size": [
4024 210,
4025 60
4026 ],
4027 "flags": [],
4028 "order": 2,
4029 "mode": 0,
4030 "inputs": [
4031 {
4032 "label": "grain_size",
4033 "localized_name": "value",
4034 "name": "value",
4035 "type": "FLOAT",
4036 "widget": {
4037 "name": "value"
4038 },
4039 "link": null
4040 }
4041 ],
4042 "outputs": [
4043 {
4044 "localized_name": "FLOAT",
4045 "name": "FLOAT",
4046 "type": "FLOAT",
4047 "links": [
4048 27
4049 ]
4050 }
4051 ],
4052 "title": "Grain size",
4053 "properties": {
4054 "Node name for S&R": "PrimitiveFloat",
4055 "cnr_id": "comfy-core",
4056 "ver": "0.22.0",
4057 "enableTabs": false,
4058 "tabWidth": 65,
4059 "tabXOffset": 10,
4060 "hasSecondTab": false,
4061 "secondTabText": "Send Back",
4062 "secondTabOffset": 80,
4063 "secondTabWidth": 65,
4064 "min": 0.05,
4065 "max": 3,
4066 "precision": 2,
4067 "step": 0.05
4068 },
4069 "widgets_values": [
4070 0.45
4071 ]
4072 },
4073 {
4074 "id": 19,
4075 "type": "PrimitiveFloat",
4076 "pos": [
4077 4280,
4078 -980
4079 ],
4080 "size": [
4081 210,
4082 60
4083 ],
4084 "flags": [],
4085 "order": 3,
4086 "mode": 0,
4087 "inputs": [
4088 {
4089 "label": "color_amount",
4090 "localized_name": "value",
4091 "name": "value",
4092 "type": "FLOAT",
4093 "widget": {
4094 "name": "value"
4095 },
4096 "link": null
4097 }
4098 ],
4099 "outputs": [
4100 {
4101 "localized_name": "FLOAT",
4102 "name": "FLOAT",
4103 "type": "FLOAT",
4104 "links": [
4105 28
4106 ]
4107 }
4108 ],
4109 "title": "Color amount",
4110 "properties": {
4111 "Node name for S&R": "PrimitiveFloat",
4112 "cnr_id": "comfy-core",
4113 "ver": "0.22.0",
4114 "enableTabs": false,
4115 "tabWidth": 65,
4116 "tabXOffset": 10,
4117 "hasSecondTab": false,
4118 "secondTabText": "Send Back",
4119 "secondTabOffset": 80,
4120 "secondTabWidth": 65,
4121 "min": 0,
4122 "max": 1,
4123 "precision": 2,
4124 "step": 0.05
4125 },
4126 "widgets_values": [
4127 0.35
4128 ]
4129 },
4130 {
4131 "id": 20,
4132 "type": "PrimitiveFloat",
4133 "pos": [
4134 4280,
4135 -880
4136 ],
4137 "size": [
4138 210,
4139 60
4140 ],
4141 "flags": [],
4142 "order": 4,
4143 "mode": 0,
4144 "inputs": [
4145 {
4146 "label": "shadow_focus",
4147 "localized_name": "value",
4148 "name": "value",
4149 "type": "FLOAT",
4150 "widget": {
4151 "name": "value"
4152 },
4153 "link": null
4154 }
4155 ],
4156 "outputs": [
4157 {
4158 "localized_name": "FLOAT",
4159 "name": "FLOAT",
4160 "type": "FLOAT",
4161 "links": [
4162 29
4163 ]
4164 }
4165 ],
4166 "title": "Luminance bias",
4167 "properties": {
4168 "Node name for S&R": "PrimitiveFloat",
4169 "cnr_id": "comfy-core",
4170 "ver": "0.22.0",
4171 "enableTabs": false,
4172 "tabWidth": 65,
4173 "tabXOffset": 10,
4174 "hasSecondTab": false,
4175 "secondTabText": "Send Back",
4176 "secondTabOffset": 80,
4177 "secondTabWidth": 65,
4178 "min": 0,
4179 "max": 1,
4180 "precision": 2,
4181 "step": 0.05
4182 },
4183 "widgets_values": [
4184 0.15
4185 ]
4186 }
4187 ],
4188 "groups": [],
4189 "links": [
4190 {
4191 "id": 26,
4192 "origin_id": 17,
4193 "origin_slot": 0,
4194 "target_id": 15,
4195 "target_slot": 2,
4196 "type": "FLOAT"
4197 },
4198 {
4199 "id": 27,
4200 "origin_id": 18,
4201 "origin_slot": 0,
4202 "target_id": 15,
4203 "target_slot": 3,
4204 "type": "FLOAT"
4205 },
4206 {
4207 "id": 28,
4208 "origin_id": 19,
4209 "origin_slot": 0,
4210 "target_id": 15,
4211 "target_slot": 4,
4212 "type": "FLOAT"
4213 },
4214 {
4215 "id": 29,
4216 "origin_id": 20,
4217 "origin_slot": 0,
4218 "target_id": 15,
4219 "target_slot": 5,
4220 "type": "FLOAT"
4221 },
4222 {
4223 "id": 30,
4224 "origin_id": 21,
4225 "origin_slot": 1,
4226 "target_id": 15,
4227 "target_slot": 7,
4228 "type": "INT"
4229 },
4230 {
4231 "id": 22,
4232 "origin_id": -10,
4233 "origin_slot": 0,
4234 "target_id": 15,
4235 "target_slot": 0,
4236 "type": "IMAGE"
4237 },
4238 {
4239 "id": 23,
4240 "origin_id": 15,
4241 "origin_slot": 0,
4242 "target_id": -20,
4243 "target_slot": 0,
4244 "type": "IMAGE"
4245 }
4246 ],
4247 "extra": {
4248 "workflowRendererVersion": "LG"
4249 }
4250 },
4251 {
4252 "id": "ed876eb4-358d-4e40-af28-de21afc3af7f",
4253 "version": 1,
4254 "state": {
4255 "lastGroupId": 9,
4256 "lastNodeId": 204,
4257 "lastLinkId": 142,
4258 "lastRerouteId": 0
4259 },
4260 "revision": 0,
4261 "config": [],
4262 "name": "Color Balance",
4263 "description": "Balances colors across shadows, midtones, and highlights using a real-time GPU fragment shader.",
4264 "inputNode": {
4265 "id": -10,
4266 "bounding": [
4267 2660,
4268 -4500,
4269 120,
4270 60
4271 ]
4272 },
4273 "outputNode": {
4274 "id": -20,
4275 "bounding": [
4276 4270,
4277 -4500,
4278 120,
4279 60
4280 ]
4281 },
4282 "inputs": [
4283 {
4284 "id": "d24c0b6d-00bd-4e95-be80-8114e8376ec0",
4285 "name": "images.image0",
4286 "type": "IMAGE",
4287 "linkIds": [
4288 29
4289 ],
4290 "localized_name": "images.image0",
4291 "label": "image",
4292 "pos": [
4293 2760,
4294 -4480
4295 ]
4296 }
4297 ],
4298 "outputs": [
4299 {
4300 "id": "92723f62-996e-496d-ad4f-81a38be4ad64",
4301 "name": "IMAGE0",
4302 "type": "IMAGE",
4303 "linkIds": [
4304 28
4305 ],
4306 "localized_name": "IMAGE0",
4307 "label": "IMAGE",
4308 "pos": [
4309 4290,
4310 -4480
4311 ]
4312 }
4313 ],
4314 "widgets": [],
4315 "nodes": [
4316 {
4317 "id": 149,
4318 "type": "PrimitiveFloat",
4319 "pos": [
4320 3060,
4321 -4500
4322 ],
4323 "size": [
4324 270,
4325 60
4326 ],
4327 "flags": [],
4328 "order": 0,
4329 "mode": 0,
4330 "inputs": [
4331 {
4332 "label": "shadows red",
4333 "localized_name": "value",
4334 "name": "value",
4335 "type": "FLOAT",
4336 "widget": {
4337 "name": "value"
4338 },
4339 "link": null
4340 }
4341 ],
4342 "outputs": [
4343 {
4344 "localized_name": "FLOAT",
4345 "name": "FLOAT",
4346 "type": "FLOAT",
4347 "links": [
4348 30
4349 ]
4350 }
4351 ],
4352 "title": "Shadows Red",
4353 "properties": {
4354 "Node name for S&R": "PrimitiveFloat",
4355 "cnr_id": "comfy-core",
4356 "ver": "0.22.0",
4357 "enableTabs": false,
4358 "tabWidth": 65,
4359 "tabXOffset": 10,
4360 "hasSecondTab": false,
4361 "secondTabText": "Send Back",
4362 "secondTabOffset": 80,
4363 "secondTabWidth": 65,
4364 "max": 100,
4365 "min": -100,
4366 "step": 1,
4367 "display": "gradientslider",
4368 "gradient_stops": [
4369 {
4370 "offset": 0,
4371 "color": [
4372 0,
4373 255,
4374 255
4375 ]
4376 },
4377 {
4378 "offset": 0.5,
4379 "color": [
4380 128,
4381 128,
4382 128
4383 ]
4384 },
4385 {
4386 "offset": 1,
4387 "color": [
4388 255,
4389 0,
4390 0
4391 ]
4392 }
4393 ]
4394 },
4395 "widgets_values": [
4396 -100
4397 ]
4398 },
4399 {
4400 "id": 150,
4401 "type": "PrimitiveFloat",
4402 "pos": [
4403 3060,
4404 -4390
4405 ],
4406 "size": [
4407 270,
4408 60
4409 ],
4410 "flags": [],
4411 "order": 1,
4412 "mode": 0,
4413 "inputs": [
4414 {
4415 "label": "shadows green",
4416 "localized_name": "value",
4417 "name": "value",
4418 "type": "FLOAT",
4419 "widget": {
4420 "name": "value"
4421 },
4422 "link": null
4423 }
4424 ],
4425 "outputs": [
4426 {
4427 "localized_name": "FLOAT",
4428 "name": "FLOAT",
4429 "type": "FLOAT",
4430 "links": [
4431 31
4432 ]
4433 }
4434 ],
4435 "title": "Shadows Green",
4436 "properties": {
4437 "Node name for S&R": "PrimitiveFloat",
4438 "cnr_id": "comfy-core",
4439 "ver": "0.22.0",
4440 "enableTabs": false,
4441 "tabWidth": 65,
4442 "tabXOffset": 10,
4443 "hasSecondTab": false,
4444 "secondTabText": "Send Back",
4445 "secondTabOffset": 80,
4446 "secondTabWidth": 65,
4447 "max": 100,
4448 "min": -100,
4449 "step": 1,
4450 "display": "gradientslider",
4451 "gradient_stops": [
4452 {
4453 "offset": 0,
4454 "color": [
4455 255,
4456 0,
4457 255
4458 ]
4459 },
4460 {
4461 "offset": 0.5,
4462 "color": [
4463 128,
4464 128,
4465 128
4466 ]
4467 },
4468 {
4469 "offset": 1,
4470 "color": [
4471 0,
4472 255,
4473 0
4474 ]
4475 }
4476 ]
4477 },
4478 "widgets_values": [
4479 47
4480 ]
4481 },
4482 {
4483 "id": 151,
4484 "type": "PrimitiveFloat",
4485 "pos": [
4486 3060,
4487 -4280
4488 ],
4489 "size": [
4490 270,
4491 60
4492 ],
4493 "flags": [],
4494 "order": 2,
4495 "mode": 0,
4496 "inputs": [
4497 {
4498 "label": "shadows blue",
4499 "localized_name": "value",
4500 "name": "value",
4501 "type": "FLOAT",
4502 "widget": {
4503 "name": "value"
4504 },
4505 "link": null
4506 }
4507 ],
4508 "outputs": [
4509 {
4510 "localized_name": "FLOAT",
4511 "name": "FLOAT",
4512 "type": "FLOAT",
4513 "links": [
4514 32
4515 ]
4516 }
4517 ],
4518 "title": "Shadows Blue",
4519 "properties": {
4520 "Node name for S&R": "PrimitiveFloat",
4521 "cnr_id": "comfy-core",
4522 "ver": "0.22.0",
4523 "enableTabs": false,
4524 "tabWidth": 65,
4525 "tabXOffset": 10,
4526 "hasSecondTab": false,
4527 "secondTabText": "Send Back",
4528 "secondTabOffset": 80,
4529 "secondTabWidth": 65,
4530 "max": 100,
4531 "min": -100,
4532 "step": 1,
4533 "display": "gradientslider",
4534 "gradient_stops": [
4535 {
4536 "offset": 0,
4537 "color": [
4538 255,
4539 255,
4540 0
4541 ]
4542 },
4543 {
4544 "offset": 0.5,
4545 "color": [
4546 128,
4547 128,
4548 128
4549 ]
4550 },
4551 {
4552 "offset": 1,
4553 "color": [
4554 0,
4555 0,
4556 255
4557 ]
4558 }
4559 ]
4560 },
4561 "widgets_values": [
4562 6
4563 ]
4564 },
4565 {
4566 "id": 152,
4567 "type": "PrimitiveFloat",
4568 "pos": [
4569 3060,
4570 -4170
4571 ],
4572 "size": [
4573 270,
4574 60
4575 ],
4576 "flags": [],
4577 "order": 3,
4578 "mode": 0,
4579 "inputs": [
4580 {
4581 "label": "midtones red",
4582 "localized_name": "value",
4583 "name": "value",
4584 "type": "FLOAT",
4585 "widget": {
4586 "name": "value"
4587 },
4588 "link": null
4589 }
4590 ],
4591 "outputs": [
4592 {
4593 "localized_name": "FLOAT",
4594 "name": "FLOAT",
4595 "type": "FLOAT",
4596 "links": [
4597 33
4598 ]
4599 }
4600 ],
4601 "title": "Midtones Red",
4602 "properties": {
4603 "Node name for S&R": "PrimitiveFloat",
4604 "cnr_id": "comfy-core",
4605 "ver": "0.22.0",
4606 "enableTabs": false,
4607 "tabWidth": 65,
4608 "tabXOffset": 10,
4609 "hasSecondTab": false,
4610 "secondTabText": "Send Back",
4611 "secondTabOffset": 80,
4612 "secondTabWidth": 65,
4613 "max": 100,
4614 "min": -100,
4615 "step": 1,
4616 "display": "gradientslider",
4617 "gradient_stops": [
4618 {
4619 "offset": 0,
4620 "color": [
4621 0,
4622 255,
4623 255
4624 ]
4625 },
4626 {
4627 "offset": 0.5,
4628 "color": [
4629 128,
4630 128,
4631 128
4632 ]
4633 },
4634 {
4635 "offset": 1,
4636 "color": [
4637 255,
4638 0,
4639 0
4640 ]
4641 }
4642 ]
4643 },
4644 "widgets_values": [
4645 -6
4646 ]
4647 },
4648 {
4649 "id": 153,
4650 "type": "PrimitiveFloat",
4651 "pos": [
4652 3060,
4653 -4060
4654 ],
4655 "size": [
4656 270,
4657 60
4658 ],
4659 "flags": [],
4660 "order": 4,
4661 "mode": 0,
4662 "inputs": [
4663 {
4664 "label": "midtones green",
4665 "localized_name": "value",
4666 "name": "value",
4667 "type": "FLOAT",
4668 "widget": {
4669 "name": "value"
4670 },
4671 "link": null
4672 }
4673 ],
4674 "outputs": [
4675 {
4676 "localized_name": "FLOAT",
4677 "name": "FLOAT",
4678 "type": "FLOAT",
4679 "links": [
4680 34
4681 ]
4682 }
4683 ],
4684 "title": "Midtones Green",
4685 "properties": {
4686 "Node name for S&R": "PrimitiveFloat",
4687 "cnr_id": "comfy-core",
4688 "ver": "0.22.0",
4689 "enableTabs": false,
4690 "tabWidth": 65,
4691 "tabXOffset": 10,
4692 "hasSecondTab": false,
4693 "secondTabText": "Send Back",
4694 "secondTabOffset": 80,
4695 "secondTabWidth": 65,
4696 "max": 100,
4697 "min": -100,
4698 "step": 1,
4699 "display": "gradientslider",
4700 "gradient_stops": [
4701 {
4702 "offset": 0,
4703 "color": [
4704 255,
4705 0,
4706 255
4707 ]
4708 },
4709 {
4710 "offset": 0.5,
4711 "color": [
4712 128,
4713 128,
4714 128
4715 ]
4716 },
4717 {
4718 "offset": 1,
4719 "color": [
4720 0,
4721 255,
4722 0
4723 ]
4724 }
4725 ]
4726 },
4727 "widgets_values": [
4728 7
4729 ]
4730 },
4731 {
4732 "id": 154,
4733 "type": "PrimitiveFloat",
4734 "pos": [
4735 3060,
4736 -3950
4737 ],
4738 "size": [
4739 270,
4740 60
4741 ],
4742 "flags": [],
4743 "order": 5,
4744 "mode": 0,
4745 "inputs": [
4746 {
4747 "label": "midtones blue",
4748 "localized_name": "value",
4749 "name": "value",
4750 "type": "FLOAT",
4751 "widget": {
4752 "name": "value"
4753 },
4754 "link": null
4755 }
4756 ],
4757 "outputs": [
4758 {
4759 "localized_name": "FLOAT",
4760 "name": "FLOAT",
4761 "type": "FLOAT",
4762 "links": [
4763 35
4764 ]
4765 }
4766 ],
4767 "title": "Midtones Blue",
4768 "properties": {
4769 "Node name for S&R": "PrimitiveFloat",
4770 "cnr_id": "comfy-core",
4771 "ver": "0.22.0",
4772 "enableTabs": false,
4773 "tabWidth": 65,
4774 "tabXOffset": 10,
4775 "hasSecondTab": false,
4776 "secondTabText": "Send Back",
4777 "secondTabOffset": 80,
4778 "secondTabWidth": 65,
4779 "max": 100,
4780 "min": -100,
4781 "step": 1,
4782 "display": "gradientslider",
4783 "gradient_stops": [
4784 {
4785 "offset": 0,
4786 "color": [
4787 255,
4788 255,
4789 0
4790 ]
4791 },
4792 {
4793 "offset": 0.5,
4794 "color": [
4795 128,
4796 128,
4797 128
4798 ]
4799 },
4800 {
4801 "offset": 1,
4802 "color": [
4803 0,
4804 0,
4805 255
4806 ]
4807 }
4808 ]
4809 },
4810 "widgets_values": [
4811 0
4812 ]
4813 },
4814 {
4815 "id": 155,
4816 "type": "PrimitiveFloat",
4817 "pos": [
4818 3060,
4819 -3840
4820 ],
4821 "size": [
4822 270,
4823 60
4824 ],
4825 "flags": [],
4826 "order": 6,
4827 "mode": 0,
4828 "inputs": [
4829 {
4830 "label": "highlights red",
4831 "localized_name": "value",
4832 "name": "value",
4833 "type": "FLOAT",
4834 "widget": {
4835 "name": "value"
4836 },
4837 "link": null
4838 }
4839 ],
4840 "outputs": [
4841 {
4842 "localized_name": "FLOAT",
4843 "name": "FLOAT",
4844 "type": "FLOAT",
4845 "links": [
4846 36
4847 ]
4848 }
4849 ],
4850 "title": "Highlights Red",
4851 "properties": {
4852 "Node name for S&R": "PrimitiveFloat",
4853 "cnr_id": "comfy-core",
4854 "ver": "0.22.0",
4855 "enableTabs": false,
4856 "tabWidth": 65,
4857 "tabXOffset": 10,
4858 "hasSecondTab": false,
4859 "secondTabText": "Send Back",
4860 "secondTabOffset": 80,
4861 "secondTabWidth": 65,
4862 "max": 100,
4863 "min": -100,
4864 "step": 1,
4865 "display": "gradientslider",
4866 "gradient_stops": [
4867 {
4868 "offset": 0,
4869 "color": [
4870 0,
4871 255,
4872 255
4873 ]
4874 },
4875 {
4876 "offset": 0.5,
4877 "color": [
4878 128,
4879 128,
4880 128
4881 ]
4882 },
4883 {
4884 "offset": 1,
4885 "color": [
4886 255,
4887 0,
4888 0
4889 ]
4890 }
4891 ]
4892 },
4893 "widgets_values": [
4894 0
4895 ]
4896 },
4897 {
4898 "id": 11,
4899 "type": "PrimitiveFloat",
4900 "pos": [
4901 3060,
4902 -3730
4903 ],
4904 "size": [
4905 270,
4906 60
4907 ],
4908 "flags": [],
4909 "order": 7,
4910 "mode": 0,
4911 "inputs": [
4912 {
4913 "label": "highlights green",
4914 "localized_name": "value",
4915 "name": "value",
4916 "type": "FLOAT",
4917 "widget": {
4918 "name": "value"
4919 },
4920 "link": null
4921 }
4922 ],
4923 "outputs": [
4924 {
4925 "localized_name": "FLOAT",
4926 "name": "FLOAT",
4927 "type": "FLOAT",
4928 "links": [
4929 37
4930 ]
4931 }
4932 ],
4933 "title": "Highlights Green",
4934 "properties": {
4935 "Node name for S&R": "PrimitiveFloat",
4936 "cnr_id": "comfy-core",
4937 "ver": "0.22.0",
4938 "enableTabs": false,
4939 "tabWidth": 65,
4940 "tabXOffset": 10,
4941 "hasSecondTab": false,
4942 "secondTabText": "Send Back",
4943 "secondTabOffset": 80,
4944 "secondTabWidth": 65,
4945 "max": 100,
4946 "min": -100,
4947 "step": 1,
4948 "display": "gradientslider",
4949 "gradient_stops": [
4950 {
4951 "offset": 0,
4952 "color": [
4953 255,
4954 0,
4955 255
4956 ]
4957 },
4958 {
4959 "offset": 0.5,
4960 "color": [
4961 128,
4962 128,
4963 128
4964 ]
4965 },
4966 {
4967 "offset": 1,
4968 "color": [
4969 0,
4970 255,
4971 0
4972 ]
4973 }
4974 ]
4975 },
4976 "widgets_values": [
4977 0
4978 ]
4979 },
4980 {
4981 "id": 12,
4982 "type": "PrimitiveFloat",
4983 "pos": [
4984 3060,
4985 -3620
4986 ],
4987 "size": [
4988 270,
4989 60
4990 ],
4991 "flags": [],
4992 "order": 8,
4993 "mode": 0,
4994 "inputs": [
4995 {
4996 "label": "highlights blue",
4997 "localized_name": "value",
4998 "name": "value",
4999 "type": "FLOAT",
5000 "widget": {
5001 "name": "value"
5002 },
5003 "link": null
5004 }
5005 ],
5006 "outputs": [
5007 {
5008 "localized_name": "FLOAT",
5009 "name": "FLOAT",
5010 "type": "FLOAT",
5011 "links": [
5012 38
5013 ]
5014 }
5015 ],
5016 "title": "Highlights Blue",
5017 "properties": {
5018 "Node name for S&R": "PrimitiveFloat",
5019 "cnr_id": "comfy-core",
5020 "ver": "0.22.0",
5021 "enableTabs": false,
5022 "tabWidth": 65,
5023 "tabXOffset": 10,
5024 "hasSecondTab": false,
5025 "secondTabText": "Send Back",
5026 "secondTabOffset": 80,
5027 "secondTabWidth": 65,
5028 "max": 100,
5029 "min": -100,
5030 "step": 1,
5031 "display": "gradientslider",
5032 "gradient_stops": [
5033 {
5034 "offset": 0,
5035 "color": [
5036 255,
5037 255,
5038 0
5039 ]
5040 },
5041 {
5042 "offset": 0.5,
5043 "color": [
5044 128,
5045 128,
5046 128
5047 ]
5048 },
5049 {
5050 "offset": 1,
5051 "color": [
5052 0,
5053 0,
5054 255
5055 ]
5056 }
5057 ]
5058 },
5059 "widgets_values": [
5060 58
5061 ]
5062 },
5063 {
5064 "id": 13,
5065 "type": "PrimitiveBoolean",
5066 "pos": [
5067 3060,
5068 -3510
5069 ],
5070 "size": [
5071 270,
5072 60
5073 ],
5074 "flags": [],
5075 "order": 9,
5076 "mode": 0,
5077 "inputs": [
5078 {
5079 "label": "preserve luminosity",
5080 "localized_name": "value",
5081 "name": "value",
5082 "type": "BOOLEAN",
5083 "widget": {
5084 "name": "value"
5085 },
5086 "link": null
5087 }
5088 ],
5089 "outputs": [
5090 {
5091 "localized_name": "BOOLEAN",
5092 "name": "BOOLEAN",
5093 "type": "BOOLEAN",
5094 "links": [
5095 39
5096 ]
5097 }
5098 ],
5099 "title": "Preserve Luminosity",
5100 "properties": {
5101 "Node name for S&R": "PrimitiveBoolean",
5102 "cnr_id": "comfy-core",
5103 "ver": "0.22.0",
5104 "enableTabs": false,
5105 "tabWidth": 65,
5106 "tabXOffset": 10,
5107 "hasSecondTab": false,
5108 "secondTabText": "Send Back",
5109 "secondTabOffset": 80,
5110 "secondTabWidth": 65
5111 },
5112 "widgets_values": [
5113 true
5114 ]
5115 },
5116 {
5117 "id": 156,
5118 "type": "GLSLShader",
5119 "pos": [
5120 3590,
5121 -4500
5122 ],
5123 "size": [
5124 420,
5125 420
5126 ],
5127 "flags": [],
5128 "order": 10,
5129 "mode": 0,
5130 "inputs": [
5131 {
5132 "label": "image0",
5133 "localized_name": "images.image0",
5134 "name": "images.image0",
5135 "type": "IMAGE",
5136 "link": 29
5137 },
5138 {
5139 "label": "image1",
5140 "localized_name": "images.image1",
5141 "name": "images.image1",
5142 "shape": 7,
5143 "type": "IMAGE",
5144 "link": null
5145 },
5146 {
5147 "label": "u_float0",
5148 "localized_name": "floats.u_float0",
5149 "name": "floats.u_float0",
5150 "shape": 7,
5151 "type": "FLOAT",
5152 "link": 30
5153 },
5154 {
5155 "label": "u_float1",
5156 "localized_name": "floats.u_float1",
5157 "name": "floats.u_float1",
5158 "shape": 7,
5159 "type": "FLOAT",
5160 "link": 31
5161 },
5162 {
5163 "label": "u_float2",
5164 "localized_name": "floats.u_float2",
5165 "name": "floats.u_float2",
5166 "shape": 7,
5167 "type": "FLOAT",
5168 "link": 32
5169 },
5170 {
5171 "label": "u_float3",
5172 "localized_name": "floats.u_float3",
5173 "name": "floats.u_float3",
5174 "shape": 7,
5175 "type": "FLOAT",
5176 "link": 33
5177 },
5178 {
5179 "label": "u_float4",
5180 "localized_name": "floats.u_float4",
5181 "name": "floats.u_float4",
5182 "shape": 7,
5183 "type": "FLOAT",
5184 "link": 34
5185 },
5186 {
5187 "label": "u_float5",
5188 "localized_name": "floats.u_float5",
5189 "name": "floats.u_float5",
5190 "shape": 7,
5191 "type": "FLOAT",
5192 "link": 35
5193 },
5194 {
5195 "label": "u_float6",
5196 "localized_name": "floats.u_float6",
5197 "name": "floats.u_float6",
5198 "shape": 7,
5199 "type": "FLOAT",
5200 "link": 36
5201 },
5202 {
5203 "label": "u_float7",
5204 "localized_name": "floats.u_float7",
5205 "name": "floats.u_float7",
5206 "shape": 7,
5207 "type": "FLOAT",
5208 "link": 37
5209 },
5210 {
5211 "label": "u_float8",
5212 "localized_name": "floats.u_float8",
5213 "name": "floats.u_float8",
5214 "shape": 7,
5215 "type": "FLOAT",
5216 "link": 38
5217 },
5218 {
5219 "label": "u_float9",
5220 "localized_name": "floats.u_float9",
5221 "name": "floats.u_float9",
5222 "shape": 7,
5223 "type": "FLOAT",
5224 "link": null
5225 },
5226 {
5227 "label": "u_int0",
5228 "localized_name": "ints.u_int0",
5229 "name": "ints.u_int0",
5230 "shape": 7,
5231 "type": "INT",
5232 "link": null
5233 },
5234 {
5235 "label": "u_bool0",
5236 "localized_name": "bools.u_bool0",
5237 "name": "bools.u_bool0",
5238 "shape": 7,
5239 "type": "BOOLEAN",
5240 "link": 39
5241 },
5242 {
5243 "label": "u_bool1",
5244 "localized_name": "bools.u_bool1",
5245 "name": "bools.u_bool1",
5246 "shape": 7,
5247 "type": "BOOLEAN",
5248 "link": null
5249 },
5250 {
5251 "label": "u_curve0",
5252 "localized_name": "curves.u_curve0",
5253 "name": "curves.u_curve0",
5254 "shape": 7,
5255 "type": "CURVE",
5256 "link": null
5257 }
5258 ],
5259 "outputs": [
5260 {
5261 "localized_name": "IMAGE0",
5262 "name": "IMAGE0",
5263 "type": "IMAGE",
5264 "links": [
5265 28
5266 ]
5267 },
5268 {
5269 "localized_name": "IMAGE1",
5270 "name": "IMAGE1",
5271 "type": "IMAGE",
5272 "links": null
5273 },
5274 {
5275 "localized_name": "IMAGE2",
5276 "name": "IMAGE2",
5277 "type": "IMAGE",
5278 "links": null
5279 },
5280 {
5281 "localized_name": "IMAGE3",
5282 "name": "IMAGE3",
5283 "type": "IMAGE",
5284 "links": null
5285 }
5286 ],
5287 "properties": {
5288 "Node name for S&R": "GLSLShader",
5289 "cnr_id": "comfy-core",
5290 "ver": "0.22.0",
5291 "enableTabs": false,
5292 "tabWidth": 65,
5293 "tabXOffset": 10,
5294 "hasSecondTab": false,
5295 "secondTabText": "Send Back",
5296 "secondTabOffset": 80,
5297 "secondTabWidth": 65
5298 },
5299 "widgets_values": [
5300 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform float u_float0; // shadows red (-100 to 100)\nuniform float u_float1; // shadows green (-100 to 100)\nuniform float u_float2; // shadows blue (-100 to 100)\nuniform float u_float3; // midtones red (-100 to 100)\nuniform float u_float4; // midtones green (-100 to 100)\nuniform float u_float5; // midtones blue (-100 to 100)\nuniform float u_float6; // highlights red (-100 to 100)\nuniform float u_float7; // highlights green (-100 to 100)\nuniform float u_float8; // highlights blue (-100 to 100)\nuniform bool u_bool0; // preserve luminosity\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nvec3 rgb2hsl(vec3 c) {\n float maxC = max(c.r, max(c.g, c.b));\n float minC = min(c.r, min(c.g, c.b));\n float l = (maxC + minC) * 0.5;\n if (maxC == minC) return vec3(0.0, 0.0, l);\n float d = maxC - minC;\n float s = l > 0.5 ? d / (2.0 - maxC - minC) : d / (maxC + minC);\n float h;\n if (maxC == c.r) {\n h = (c.g - c.b) / d + (c.g < c.b ? 6.0 : 0.0);\n } else if (maxC == c.g) {\n h = (c.b - c.r) / d + 2.0;\n } else {\n h = (c.r - c.g) / d + 4.0;\n }\n h /= 6.0;\n return vec3(h, s, l);\n}\n\nfloat hue2rgb(float p, float q, float t) {\n if (t < 0.0) t += 1.0;\n if (t > 1.0) t -= 1.0;\n if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;\n if (t < 1.0 / 2.0) return q;\n if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;\n return p;\n}\n\nvec3 hsl2rgb(vec3 hsl) {\n float h = hsl.x, s = hsl.y, l = hsl.z;\n if (s == 0.0) return vec3(l);\n float q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;\n float p = 2.0 * l - q;\n return vec3(\n hue2rgb(p, q, h + 1.0 / 3.0),\n hue2rgb(p, q, h),\n hue2rgb(p, q, h - 1.0 / 3.0)\n );\n}\n\nvoid main() {\n vec4 tex = texture(u_image0, v_texCoord);\n vec3 color = tex.rgb;\n\n // Build shadows/midtones/highlights vectors (scale -100..100 to -1..1)\n vec3 shadows = vec3(u_float0, u_float1, u_float2) * 0.01;\n vec3 midtones = vec3(u_float3, u_float4, u_float5) * 0.01;\n vec3 highlights = vec3(u_float6, u_float7, u_float8) * 0.01;\n\n // GIMP: HSL lightness for weight calculation\n float maxC = max(color.r, max(color.g, color.b));\n float minC = min(color.r, min(color.g, color.b));\n float lightness = (maxC + minC) * 0.5;\n\n // GIMP weight curves: linear ramps with constants a=0.25, b=0.333, scale=0.7\n const float a = 0.25;\n const float b = 0.333;\n const float scale = 0.7;\n\n float sw = clamp((lightness - b) / -a + 0.5, 0.0, 1.0) * scale;\n float mw = clamp((lightness - b) / a + 0.5, 0.0, 1.0) *\n clamp((lightness + b - 1.0) / -a + 0.5, 0.0, 1.0) * scale;\n float hw = clamp((lightness + b - 1.0) / a + 0.5, 0.0, 1.0) * scale;\n\n color += sw * shadows + mw * midtones + hw * highlights;\n\n if (u_bool0) {\n vec3 hsl = rgb2hsl(clamp(color, 0.0, 1.0));\n hsl.z = lightness;\n color = hsl2rgb(hsl);\n }\n\n fragColor = vec4(clamp(color, 0.0, 1.0), tex.a);\n}",
5301 "from_input"
5302 ]
5303 }
5304 ],
5305 "groups": [],
5306 "links": [
5307 {
5308 "id": 29,
5309 "origin_id": -10,
5310 "origin_slot": 0,
5311 "target_id": 156,
5312 "target_slot": 0,
5313 "type": "IMAGE"
5314 },
5315 {
5316 "id": 28,
5317 "origin_id": 156,
5318 "origin_slot": 0,
5319 "target_id": -20,
5320 "target_slot": 0,
5321 "type": "IMAGE"
5322 },
5323 {
5324 "id": 30,
5325 "origin_id": 149,
5326 "origin_slot": 0,
5327 "target_id": 156,
5328 "target_slot": 2,
5329 "type": "FLOAT"
5330 },
5331 {
5332 "id": 31,
5333 "origin_id": 150,
5334 "origin_slot": 0,
5335 "target_id": 156,
5336 "target_slot": 3,
5337 "type": "FLOAT"
5338 },
5339 {
5340 "id": 32,
5341 "origin_id": 151,
5342 "origin_slot": 0,
5343 "target_id": 156,
5344 "target_slot": 4,
5345 "type": "FLOAT"
5346 },
5347 {
5348 "id": 33,
5349 "origin_id": 152,
5350 "origin_slot": 0,
5351 "target_id": 156,
5352 "target_slot": 5,
5353 "type": "FLOAT"
5354 },
5355 {
5356 "id": 34,
5357 "origin_id": 153,
5358 "origin_slot": 0,
5359 "target_id": 156,
5360 "target_slot": 6,
5361 "type": "FLOAT"
5362 },
5363 {
5364 "id": 35,
5365 "origin_id": 154,
5366 "origin_slot": 0,
5367 "target_id": 156,
5368 "target_slot": 7,
5369 "type": "FLOAT"
5370 },
5371 {
5372 "id": 36,
5373 "origin_id": 155,
5374 "origin_slot": 0,
5375 "target_id": 156,
5376 "target_slot": 8,
5377 "type": "FLOAT"
5378 },
5379 {
5380 "id": 37,
5381 "origin_id": 11,
5382 "origin_slot": 0,
5383 "target_id": 156,
5384 "target_slot": 9,
5385 "type": "FLOAT"
5386 },
5387 {
5388 "id": 38,
5389 "origin_id": 12,
5390 "origin_slot": 0,
5391 "target_id": 156,
5392 "target_slot": 10,
5393 "type": "FLOAT"
5394 },
5395 {
5396 "id": 39,
5397 "origin_id": 13,
5398 "origin_slot": 0,
5399 "target_id": 156,
5400 "target_slot": 13,
5401 "type": "BOOLEAN"
5402 }
5403 ],
5404 "extra": {
5405 "workflowRendererVersion": "LG"
5406 }
5407 },
5408 {
5409 "id": "b5143322-553a-4d96-9539-76b3707ef275",
5410 "version": 1,
5411 "state": {
5412 "lastGroupId": 9,
5413 "lastNodeId": 204,
5414 "lastLinkId": 142,
5415 "lastRerouteId": 0
5416 },
5417 "revision": 0,
5418 "config": [],
5419 "name": "Chromatic Aberration",
5420 "description": "Adds lens-style chromatic aberration (color fringing) using a real-time GPU fragment shader.",
5421 "inputNode": {
5422 "id": -10,
5423 "bounding": [
5424 3270,
5425 -2050,
5426 120,
5427 60
5428 ]
5429 },
5430 "outputNode": {
5431 "id": -20,
5432 "bounding": [
5433 4260,
5434 -2050,
5435 120,
5436 60
5437 ]
5438 },
5439 "inputs": [
5440 {
5441 "id": "3b33ac46-93a6-4b1c-896a-ed6fbd24e59c",
5442 "name": "images.image0",
5443 "type": "IMAGE",
5444 "linkIds": [
5445 20
5446 ],
5447 "localized_name": "images.image0",
5448 "label": "image",
5449 "pos": [
5450 3370,
5451 -2030
5452 ]
5453 }
5454 ],
5455 "outputs": [
5456 {
5457 "id": "abe7cd79-a87b-4bd0-8923-d79a57d81a6e",
5458 "name": "IMAGE0",
5459 "type": "IMAGE",
5460 "linkIds": [
5461 23
5462 ],
5463 "localized_name": "IMAGE0",
5464 "label": "IMAGE",
5465 "pos": [
5466 4280,
5467 -2030
5468 ]
5469 }
5470 ],
5471 "widgets": [],
5472 "nodes": [
5473 {
5474 "id": 16,
5475 "type": "GLSLShader",
5476 "pos": [
5477 3810,
5478 -2320
5479 ],
5480 "size": [
5481 390,
5482 260
5483 ],
5484 "flags": [],
5485 "order": 2,
5486 "mode": 0,
5487 "inputs": [
5488 {
5489 "label": "image0",
5490 "localized_name": "images.image0",
5491 "name": "images.image0",
5492 "type": "IMAGE",
5493 "link": 20
5494 },
5495 {
5496 "label": "image1",
5497 "localized_name": "images.image1",
5498 "name": "images.image1",
5499 "shape": 7,
5500 "type": "IMAGE",
5501 "link": null
5502 },
5503 {
5504 "label": "u_float0",
5505 "localized_name": "floats.u_float0",
5506 "name": "floats.u_float0",
5507 "shape": 7,
5508 "type": "FLOAT",
5509 "link": 22
5510 },
5511 {
5512 "label": "u_float1",
5513 "localized_name": "floats.u_float1",
5514 "name": "floats.u_float1",
5515 "shape": 7,
5516 "type": "FLOAT",
5517 "link": null
5518 },
5519 {
5520 "label": "u_int0",
5521 "localized_name": "ints.u_int0",
5522 "name": "ints.u_int0",
5523 "shape": 7,
5524 "type": "INT",
5525 "link": 21
5526 },
5527 {
5528 "label": "u_int1",
5529 "localized_name": "ints.u_int1",
5530 "name": "ints.u_int1",
5531 "shape": 7,
5532 "type": "INT",
5533 "link": null
5534 },
5535 {
5536 "label": "u_bool0",
5537 "localized_name": "bools.u_bool0",
5538 "name": "bools.u_bool0",
5539 "shape": 7,
5540 "type": "BOOLEAN",
5541 "link": null
5542 },
5543 {
5544 "label": "u_curve0",
5545 "localized_name": "curves.u_curve0",
5546 "name": "curves.u_curve0",
5547 "shape": 7,
5548 "type": "CURVE",
5549 "link": null
5550 }
5551 ],
5552 "outputs": [
5553 {
5554 "localized_name": "IMAGE0",
5555 "name": "IMAGE0",
5556 "type": "IMAGE",
5557 "links": [
5558 23
5559 ]
5560 },
5561 {
5562 "localized_name": "IMAGE1",
5563 "name": "IMAGE1",
5564 "type": "IMAGE",
5565 "links": null
5566 },
5567 {
5568 "localized_name": "IMAGE2",
5569 "name": "IMAGE2",
5570 "type": "IMAGE",
5571 "links": null
5572 },
5573 {
5574 "localized_name": "IMAGE3",
5575 "name": "IMAGE3",
5576 "type": "IMAGE",
5577 "links": null
5578 }
5579 ],
5580 "properties": {
5581 "Node name for S&R": "GLSLShader",
5582 "cnr_id": "comfy-core",
5583 "ver": "0.22.0",
5584 "enableTabs": false,
5585 "tabWidth": 65,
5586 "tabXOffset": 10,
5587 "hasSecondTab": false,
5588 "secondTabText": "Send Back",
5589 "secondTabOffset": 80,
5590 "secondTabWidth": 65
5591 },
5592 "widgets_values": [
5593 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform vec2 u_resolution;\nuniform int u_int0; // Mode\nuniform float u_float0; // Amount (0 to 100)\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nconst int MODE_LINEAR = 0;\nconst int MODE_RADIAL = 1;\nconst int MODE_BARREL = 2;\nconst int MODE_SWIRL = 3;\nconst int MODE_DIAGONAL = 4;\n\nconst float AMOUNT_SCALE = 0.0005;\nconst float RADIAL_MULT = 4.0;\nconst float BARREL_MULT = 8.0;\nconst float INV_SQRT2 = 0.70710678118;\n\nvoid main() {\n vec2 uv = v_texCoord;\n vec4 original = texture(u_image0, uv);\n\n float amount = u_float0 * AMOUNT_SCALE;\n\n if (amount < 0.000001) {\n fragColor = original;\n return;\n }\n\n // Aspect-corrected coordinates for circular effects\n float aspect = u_resolution.x / u_resolution.y;\n vec2 centered = uv - 0.5;\n vec2 corrected = vec2(centered.x * aspect, centered.y);\n float r = length(corrected);\n vec2 dir = r > 0.0001 ? corrected / r : vec2(0.0);\n vec2 offset = vec2(0.0);\n\n if (u_int0 == MODE_LINEAR) {\n // Horizontal shift (no aspect correction needed)\n offset = vec2(amount, 0.0);\n }\n else if (u_int0 == MODE_RADIAL) {\n // Outward from center, stronger at edges\n offset = dir * r * amount * RADIAL_MULT;\n offset.x /= aspect; // Convert back to UV space\n }\n else if (u_int0 == MODE_BARREL) {\n // Lens distortion simulation (r² falloff)\n offset = dir * r * r * amount * BARREL_MULT;\n offset.x /= aspect; // Convert back to UV space\n }\n else if (u_int0 == MODE_SWIRL) {\n // Perpendicular to radial (rotational aberration)\n vec2 perp = vec2(-dir.y, dir.x);\n offset = perp * r * amount * RADIAL_MULT;\n offset.x /= aspect; // Convert back to UV space\n }\n else if (u_int0 == MODE_DIAGONAL) {\n // 45° offset (no aspect correction needed)\n offset = vec2(amount, amount) * INV_SQRT2;\n }\n \n float red = texture(u_image0, uv + offset).r;\n float green = original.g;\n float blue = texture(u_image0, uv - offset).b;\n \n fragColor = vec4(red, green, blue, original.a);\n}",
5594 "from_input"
5595 ]
5596 },
5597 {
5598 "id": 158,
5599 "type": "PrimitiveFloat",
5600 "pos": [
5601 3810,
5602 -2430
5603 ],
5604 "size": [
5605 270,
5606 60
5607 ],
5608 "flags": [],
5609 "order": 0,
5610 "mode": 0,
5611 "inputs": [
5612 {
5613 "label": "amount",
5614 "localized_name": "value",
5615 "name": "value",
5616 "type": "FLOAT",
5617 "widget": {
5618 "name": "value"
5619 },
5620 "link": null
5621 }
5622 ],
5623 "outputs": [
5624 {
5625 "localized_name": "FLOAT",
5626 "name": "FLOAT",
5627 "type": "FLOAT",
5628 "links": [
5629 22
5630 ]
5631 }
5632 ],
5633 "properties": {
5634 "Node name for S&R": "PrimitiveFloat",
5635 "cnr_id": "comfy-core",
5636 "ver": "0.22.0",
5637 "enableTabs": false,
5638 "tabWidth": 65,
5639 "tabXOffset": 10,
5640 "hasSecondTab": false,
5641 "secondTabText": "Send Back",
5642 "secondTabOffset": 80,
5643 "secondTabWidth": 65,
5644 "min": 0,
5645 "max": 100,
5646 "step": 1
5647 },
5648 "widgets_values": [
5649 31
5650 ]
5651 },
5652 {
5653 "id": 159,
5654 "type": "CustomCombo",
5655 "pos": [
5656 3520,
5657 -2320
5658 ],
5659 "size": [
5660 270,
5661 230
5662 ],
5663 "flags": [],
5664 "order": 1,
5665 "mode": 0,
5666 "inputs": [
5667 {
5668 "label": "mode",
5669 "localized_name": "choice",
5670 "name": "choice",
5671 "type": "COMBO",
5672 "widget": {
5673 "name": "choice"
5674 },
5675 "link": null
5676 }
5677 ],
5678 "outputs": [
5679 {
5680 "localized_name": "STRING",
5681 "name": "STRING",
5682 "type": "STRING",
5683 "links": null
5684 },
5685 {
5686 "localized_name": "INDEX",
5687 "name": "INDEX",
5688 "type": "INT",
5689 "links": [
5690 21
5691 ]
5692 }
5693 ],
5694 "properties": {
5695 "Node name for S&R": "CustomCombo",
5696 "cnr_id": "comfy-core",
5697 "ver": "0.22.0",
5698 "enableTabs": false,
5699 "tabWidth": 65,
5700 "tabXOffset": 10,
5701 "hasSecondTab": false,
5702 "secondTabText": "Send Back",
5703 "secondTabOffset": 80,
5704 "secondTabWidth": 65
5705 },
5706 "widgets_values": [
5707 "Linear",
5708 0,
5709 "Linear",
5710 "Radial",
5711 "Barrel",
5712 "Swirl",
5713 "Diagonal",
5714 ""
5715 ]
5716 }
5717 ],
5718 "groups": [],
5719 "links": [
5720 {
5721 "id": 22,
5722 "origin_id": 158,
5723 "origin_slot": 0,
5724 "target_id": 16,
5725 "target_slot": 2,
5726 "type": "FLOAT"
5727 },
5728 {
5729 "id": 21,
5730 "origin_id": 159,
5731 "origin_slot": 1,
5732 "target_id": 16,
5733 "target_slot": 4,
5734 "type": "INT"
5735 },
5736 {
5737 "id": 20,
5738 "origin_id": -10,
5739 "origin_slot": 0,
5740 "target_id": 16,
5741 "target_slot": 0,
5742 "type": "IMAGE"
5743 },
5744 {
5745 "id": 23,
5746 "origin_id": 16,
5747 "origin_slot": 0,
5748 "target_id": -20,
5749 "target_slot": 0,
5750 "type": "IMAGE"
5751 }
5752 ],
5753 "extra": {
5754 "workflowRendererVersion": "LG"
5755 }
5756 },
5757 {
5758 "id": "b7c3a768-1a1c-4a3d-bddf-043f4a8ffb20",
5759 "version": 1,
5760 "state": {
5761 "lastGroupId": 9,
5762 "lastNodeId": 204,
5763 "lastLinkId": 142,
5764 "lastRerouteId": 0
5765 },
5766 "revision": 0,
5767 "config": [],
5768 "name": "Hue and Saturation",
5769 "description": "Adjusts hue, saturation, and lightness of an image using a real-time GPU fragment shader.",
5770 "inputNode": {
5771 "id": -10,
5772 "bounding": [
5773 360,
5774 -176,
5775 120,
5776 60
5777 ]
5778 },
5779 "outputNode": {
5780 "id": -20,
5781 "bounding": [
5782 1410,
5783 -176,
5784 120,
5785 60
5786 ]
5787 },
5788 "inputs": [
5789 {
5790 "id": "a5aae7ea-b511-4045-b5da-94101e269cd7",
5791 "name": "images.image0",
5792 "type": "IMAGE",
5793 "linkIds": [
5794 10
5795 ],
5796 "localized_name": "images.image0",
5797 "label": "image",
5798 "pos": [
5799 460,
5800 -156
5801 ]
5802 }
5803 ],
5804 "outputs": [
5805 {
5806 "id": "30b72604-69b3-4944-b253-a9099bbd73a9",
5807 "name": "IMAGE0",
5808 "type": "IMAGE",
5809 "linkIds": [
5810 8
5811 ],
5812 "localized_name": "IMAGE0",
5813 "label": "IMAGE",
5814 "pos": [
5815 1430,
5816 -156
5817 ]
5818 }
5819 ],
5820 "widgets": [],
5821 "nodes": [
5822 {
5823 "id": 3,
5824 "type": "CustomCombo",
5825 "pos": [
5826 540,
5827 -240
5828 ],
5829 "size": [
5830 270,
5831 150
5832 ],
5833 "flags": [],
5834 "order": 0,
5835 "mode": 0,
5836 "inputs": [
5837 {
5838 "label": "color_space",
5839 "localized_name": "choice",
5840 "name": "choice",
5841 "type": "COMBO",
5842 "widget": {
5843 "name": "choice"
5844 },
5845 "link": null
5846 }
5847 ],
5848 "outputs": [
5849 {
5850 "localized_name": "STRING",
5851 "name": "STRING",
5852 "type": "STRING",
5853 "links": null
5854 },
5855 {
5856 "localized_name": "INDEX",
5857 "name": "INDEX",
5858 "type": "INT",
5859 "links": [
5860 2
5861 ]
5862 }
5863 ],
5864 "properties": {
5865 "Node name for S&R": "CustomCombo",
5866 "cnr_id": "comfy-core",
5867 "ver": "0.22.0",
5868 "enableTabs": false,
5869 "tabWidth": 65,
5870 "tabXOffset": 10,
5871 "hasSecondTab": false,
5872 "secondTabText": "Send Back",
5873 "secondTabOffset": 80,
5874 "secondTabWidth": 65
5875 },
5876 "widgets_values": [
5877 "HSL",
5878 0,
5879 "HSL",
5880 "HSB/HSV",
5881 ""
5882 ]
5883 },
5884 {
5885 "id": 2,
5886 "type": "CustomCombo",
5887 "pos": [
5888 540,
5889 -580
5890 ],
5891 "size": [
5892 270,
5893 300
5894 ],
5895 "flags": [],
5896 "order": 1,
5897 "mode": 0,
5898 "inputs": [
5899 {
5900 "label": "mode",
5901 "localized_name": "choice",
5902 "name": "choice",
5903 "type": "COMBO",
5904 "widget": {
5905 "name": "choice"
5906 },
5907 "link": null
5908 }
5909 ],
5910 "outputs": [
5911 {
5912 "localized_name": "STRING",
5913 "name": "STRING",
5914 "type": "STRING",
5915 "links": null
5916 },
5917 {
5918 "localized_name": "INDEX",
5919 "name": "INDEX",
5920 "type": "INT",
5921 "links": [
5922 1
5923 ]
5924 }
5925 ],
5926 "properties": {
5927 "Node name for S&R": "CustomCombo",
5928 "cnr_id": "comfy-core",
5929 "ver": "0.22.0",
5930 "enableTabs": false,
5931 "tabWidth": 65,
5932 "tabXOffset": 10,
5933 "hasSecondTab": false,
5934 "secondTabText": "Send Back",
5935 "secondTabOffset": 80,
5936 "secondTabWidth": 65
5937 },
5938 "widgets_values": [
5939 "Master",
5940 0,
5941 "Master",
5942 "Reds",
5943 "Yellows",
5944 "Greens",
5945 "Cyans",
5946 "Blues",
5947 "Magentas",
5948 "Colorize",
5949 ""
5950 ]
5951 },
5952 {
5953 "id": 161,
5954 "type": "PrimitiveFloat",
5955 "pos": [
5956 540,
5957 260
5958 ],
5959 "size": [
5960 270,
5961 60
5962 ],
5963 "flags": [],
5964 "order": 2,
5965 "mode": 0,
5966 "inputs": [
5967 {
5968 "label": "overlap",
5969 "localized_name": "value",
5970 "name": "value",
5971 "type": "FLOAT",
5972 "widget": {
5973 "name": "value"
5974 },
5975 "link": null
5976 }
5977 ],
5978 "outputs": [
5979 {
5980 "localized_name": "FLOAT",
5981 "name": "FLOAT",
5982 "type": "FLOAT",
5983 "links": [
5984 6
5985 ]
5986 }
5987 ],
5988 "properties": {
5989 "Node name for S&R": "PrimitiveFloat",
5990 "cnr_id": "comfy-core",
5991 "ver": "0.22.0",
5992 "enableTabs": false,
5993 "tabWidth": 65,
5994 "tabXOffset": 10,
5995 "hasSecondTab": false,
5996 "secondTabText": "Send Back",
5997 "secondTabOffset": 80,
5998 "secondTabWidth": 65,
5999 "min": 0,
6000 "max": 100,
6001 "precision": 1,
6002 "step": 1
6003 },
6004 "widgets_values": [
6005 50
6006 ]
6007 },
6008 {
6009 "id": 162,
6010 "type": "PrimitiveFloat",
6011 "pos": [
6012 540,
6013 160
6014 ],
6015 "size": [
6016 270,
6017 60
6018 ],
6019 "flags": [],
6020 "order": 3,
6021 "mode": 0,
6022 "inputs": [
6023 {
6024 "label": "brightness",
6025 "localized_name": "value",
6026 "name": "value",
6027 "type": "FLOAT",
6028 "widget": {
6029 "name": "value"
6030 },
6031 "link": null
6032 }
6033 ],
6034 "outputs": [
6035 {
6036 "localized_name": "FLOAT",
6037 "name": "FLOAT",
6038 "type": "FLOAT",
6039 "links": [
6040 5
6041 ]
6042 }
6043 ],
6044 "properties": {
6045 "Node name for S&R": "PrimitiveFloat",
6046 "cnr_id": "comfy-core",
6047 "ver": "0.22.0",
6048 "enableTabs": false,
6049 "tabWidth": 65,
6050 "tabXOffset": 10,
6051 "hasSecondTab": false,
6052 "secondTabText": "Send Back",
6053 "secondTabOffset": 80,
6054 "secondTabWidth": 65,
6055 "min": -100,
6056 "max": 100,
6057 "precision": 1,
6058 "step": 1,
6059 "display": "gradientslider",
6060 "gradient_stops": [
6061 {
6062 "offset": 0,
6063 "color": [
6064 0,
6065 0,
6066 0
6067 ]
6068 },
6069 {
6070 "offset": 1,
6071 "color": [
6072 255,
6073 255,
6074 255
6075 ]
6076 }
6077 ]
6078 },
6079 "widgets_values": [
6080 0
6081 ]
6082 },
6083 {
6084 "id": 163,
6085 "type": "PrimitiveFloat",
6086 "pos": [
6087 540,
6088 60
6089 ],
6090 "size": [
6091 270,
6092 60
6093 ],
6094 "flags": [],
6095 "order": 4,
6096 "mode": 0,
6097 "inputs": [
6098 {
6099 "label": "saturation",
6100 "localized_name": "value",
6101 "name": "value",
6102 "type": "FLOAT",
6103 "widget": {
6104 "name": "value"
6105 },
6106 "link": null
6107 }
6108 ],
6109 "outputs": [
6110 {
6111 "localized_name": "FLOAT",
6112 "name": "FLOAT",
6113 "type": "FLOAT",
6114 "links": [
6115 4
6116 ]
6117 }
6118 ],
6119 "properties": {
6120 "Node name for S&R": "PrimitiveFloat",
6121 "cnr_id": "comfy-core",
6122 "ver": "0.22.0",
6123 "enableTabs": false,
6124 "tabWidth": 65,
6125 "tabXOffset": 10,
6126 "hasSecondTab": false,
6127 "secondTabText": "Send Back",
6128 "secondTabOffset": 80,
6129 "secondTabWidth": 65,
6130 "min": -100,
6131 "max": 100,
6132 "precision": 1,
6133 "step": 1,
6134 "display": "gradientslider",
6135 "gradient_stops": [
6136 {
6137 "offset": 0,
6138 "color": [
6139 128,
6140 128,
6141 128
6142 ]
6143 },
6144 {
6145 "offset": 1,
6146 "color": [
6147 255,
6148 0,
6149 0
6150 ]
6151 }
6152 ]
6153 },
6154 "widgets_values": [
6155 0
6156 ]
6157 },
6158 {
6159 "id": 164,
6160 "type": "PrimitiveFloat",
6161 "pos": [
6162 540,
6163 -40
6164 ],
6165 "size": [
6166 270,
6167 60
6168 ],
6169 "flags": [],
6170 "order": 5,
6171 "mode": 0,
6172 "inputs": [
6173 {
6174 "label": "hue",
6175 "localized_name": "value",
6176 "name": "value",
6177 "type": "FLOAT",
6178 "widget": {
6179 "name": "value"
6180 },
6181 "link": null
6182 }
6183 ],
6184 "outputs": [
6185 {
6186 "localized_name": "FLOAT",
6187 "name": "FLOAT",
6188 "type": "FLOAT",
6189 "links": [
6190 3
6191 ]
6192 }
6193 ],
6194 "properties": {
6195 "Node name for S&R": "PrimitiveFloat",
6196 "cnr_id": "comfy-core",
6197 "ver": "0.22.0",
6198 "enableTabs": false,
6199 "tabWidth": 65,
6200 "tabXOffset": 10,
6201 "hasSecondTab": false,
6202 "secondTabText": "Send Back",
6203 "secondTabOffset": 80,
6204 "secondTabWidth": 65,
6205 "min": -180,
6206 "max": 180,
6207 "precision": 1,
6208 "step": 1,
6209 "display": "gradientslider",
6210 "gradient_stops": [
6211 {
6212 "offset": 0,
6213 "color": [
6214 255,
6215 0,
6216 0
6217 ]
6218 },
6219 {
6220 "offset": 0.16666666666666666,
6221 "color": [
6222 255,
6223 255,
6224 0
6225 ]
6226 },
6227 {
6228 "offset": 0.3333333333333333,
6229 "color": [
6230 0,
6231 255,
6232 0
6233 ]
6234 },
6235 {
6236 "offset": 0.5,
6237 "color": [
6238 0,
6239 255,
6240 255
6241 ]
6242 },
6243 {
6244 "offset": 0.6666666666666666,
6245 "color": [
6246 0,
6247 0,
6248 255
6249 ]
6250 },
6251 {
6252 "offset": 0.8333333333333334,
6253 "color": [
6254 255,
6255 0,
6256 255
6257 ]
6258 },
6259 {
6260 "offset": 1,
6261 "color": [
6262 255,
6263 0,
6264 0
6265 ]
6266 }
6267 ]
6268 },
6269 "widgets_values": [
6270 3.9
6271 ]
6272 },
6273 {
6274 "id": 1,
6275 "type": "GLSLShader",
6276 "pos": [
6277 880,
6278 -300
6279 ],
6280 "size": [
6281 470,
6282 340
6283 ],
6284 "flags": [],
6285 "order": 6,
6286 "mode": 0,
6287 "inputs": [
6288 {
6289 "label": "image0",
6290 "localized_name": "images.image0",
6291 "name": "images.image0",
6292 "type": "IMAGE",
6293 "link": 10
6294 },
6295 {
6296 "label": "image1",
6297 "localized_name": "images.image1",
6298 "name": "images.image1",
6299 "shape": 7,
6300 "type": "IMAGE",
6301 "link": null
6302 },
6303 {
6304 "label": "u_float0",
6305 "localized_name": "floats.u_float0",
6306 "name": "floats.u_float0",
6307 "shape": 7,
6308 "type": "FLOAT",
6309 "link": 3
6310 },
6311 {
6312 "label": "u_float1",
6313 "localized_name": "floats.u_float1",
6314 "name": "floats.u_float1",
6315 "shape": 7,
6316 "type": "FLOAT",
6317 "link": 4
6318 },
6319 {
6320 "label": "u_float2",
6321 "localized_name": "floats.u_float2",
6322 "name": "floats.u_float2",
6323 "shape": 7,
6324 "type": "FLOAT",
6325 "link": 5
6326 },
6327 {
6328 "label": "u_float3",
6329 "localized_name": "floats.u_float3",
6330 "name": "floats.u_float3",
6331 "shape": 7,
6332 "type": "FLOAT",
6333 "link": 6
6334 },
6335 {
6336 "label": "u_float4",
6337 "localized_name": "floats.u_float4",
6338 "name": "floats.u_float4",
6339 "shape": 7,
6340 "type": "FLOAT",
6341 "link": null
6342 },
6343 {
6344 "label": "u_int0",
6345 "localized_name": "ints.u_int0",
6346 "name": "ints.u_int0",
6347 "shape": 7,
6348 "type": "INT",
6349 "link": 1
6350 },
6351 {
6352 "label": "u_int1",
6353 "localized_name": "ints.u_int1",
6354 "name": "ints.u_int1",
6355 "shape": 7,
6356 "type": "INT",
6357 "link": 2
6358 },
6359 {
6360 "label": "u_int2",
6361 "localized_name": "ints.u_int2",
6362 "name": "ints.u_int2",
6363 "shape": 7,
6364 "type": "INT",
6365 "link": null
6366 },
6367 {
6368 "label": "u_bool0",
6369 "localized_name": "bools.u_bool0",
6370 "name": "bools.u_bool0",
6371 "shape": 7,
6372 "type": "BOOLEAN",
6373 "link": null
6374 },
6375 {
6376 "label": "u_curve0",
6377 "localized_name": "curves.u_curve0",
6378 "name": "curves.u_curve0",
6379 "shape": 7,
6380 "type": "CURVE",
6381 "link": null
6382 }
6383 ],
6384 "outputs": [
6385 {
6386 "localized_name": "IMAGE0",
6387 "name": "IMAGE0",
6388 "type": "IMAGE",
6389 "links": [
6390 8
6391 ]
6392 },
6393 {
6394 "localized_name": "IMAGE1",
6395 "name": "IMAGE1",
6396 "type": "IMAGE",
6397 "links": null
6398 },
6399 {
6400 "localized_name": "IMAGE2",
6401 "name": "IMAGE2",
6402 "type": "IMAGE",
6403 "links": null
6404 },
6405 {
6406 "localized_name": "IMAGE3",
6407 "name": "IMAGE3",
6408 "type": "IMAGE",
6409 "links": null
6410 }
6411 ],
6412 "properties": {
6413 "Node name for S&R": "GLSLShader",
6414 "cnr_id": "comfy-core",
6415 "ver": "0.22.0",
6416 "enableTabs": false,
6417 "tabWidth": 65,
6418 "tabXOffset": 10,
6419 "hasSecondTab": false,
6420 "secondTabText": "Send Back",
6421 "secondTabOffset": 80,
6422 "secondTabWidth": 65
6423 },
6424 "widgets_values": [
6425 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform int u_int0; // Mode: 0=Master, 1=Reds, 2=Yellows, 3=Greens, 4=Cyans, 5=Blues, 6=Magentas, 7=Colorize\nuniform int u_int1; // Color Space: 0=HSL, 1=HSB/HSV\nuniform float u_float0; // Hue (-180 to 180)\nuniform float u_float1; // Saturation (-100 to 100)\nuniform float u_float2; // Lightness/Brightness (-100 to 100)\nuniform float u_float3; // Overlap (0 to 100) - feathering between adjacent color ranges\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\n// Color range modes\nconst int MODE_MASTER = 0;\nconst int MODE_RED = 1;\nconst int MODE_YELLOW = 2;\nconst int MODE_GREEN = 3;\nconst int MODE_CYAN = 4;\nconst int MODE_BLUE = 5;\nconst int MODE_MAGENTA = 6;\nconst int MODE_COLORIZE = 7;\n\n// Color space modes\nconst int COLORSPACE_HSL = 0;\nconst int COLORSPACE_HSB = 1;\n\nconst float EPSILON = 0.0001;\n\n//=============================================================================\n// RGB <-> HSL Conversions\n//=============================================================================\n\nvec3 rgb2hsl(vec3 c) {\n float maxC = max(max(c.r, c.g), c.b);\n float minC = min(min(c.r, c.g), c.b);\n float delta = maxC - minC;\n\n float h = 0.0;\n float s = 0.0;\n float l = (maxC + minC) * 0.5;\n\n if (delta > EPSILON) {\n s = l < 0.5\n ? delta / (maxC + minC)\n : delta / (2.0 - maxC - minC);\n\n if (maxC == c.r) {\n h = (c.g - c.b) / delta + (c.g < c.b ? 6.0 : 0.0);\n } else if (maxC == c.g) {\n h = (c.b - c.r) / delta + 2.0;\n } else {\n h = (c.r - c.g) / delta + 4.0;\n }\n h /= 6.0;\n }\n\n return vec3(h, s, l);\n}\n\nfloat hue2rgb(float p, float q, float t) {\n t = fract(t);\n if (t < 1.0/6.0) return p + (q - p) * 6.0 * t;\n if (t < 0.5) return q;\n if (t < 2.0/3.0) return p + (q - p) * (2.0/3.0 - t) * 6.0;\n return p;\n}\n\nvec3 hsl2rgb(vec3 hsl) {\n if (hsl.y < EPSILON) return vec3(hsl.z);\n\n float q = hsl.z < 0.5\n ? hsl.z * (1.0 + hsl.y)\n : hsl.z + hsl.y - hsl.z * hsl.y;\n float p = 2.0 * hsl.z - q;\n\n return vec3(\n hue2rgb(p, q, hsl.x + 1.0/3.0),\n hue2rgb(p, q, hsl.x),\n hue2rgb(p, q, hsl.x - 1.0/3.0)\n );\n}\n\nvec3 rgb2hsb(vec3 c) {\n float maxC = max(max(c.r, c.g), c.b);\n float minC = min(min(c.r, c.g), c.b);\n float delta = maxC - minC;\n\n float h = 0.0;\n float s = (maxC > EPSILON) ? delta / maxC : 0.0;\n float b = maxC;\n\n if (delta > EPSILON) {\n if (maxC == c.r) {\n h = (c.g - c.b) / delta + (c.g < c.b ? 6.0 : 0.0);\n } else if (maxC == c.g) {\n h = (c.b - c.r) / delta + 2.0;\n } else {\n h = (c.r - c.g) / delta + 4.0;\n }\n h /= 6.0;\n }\n\n return vec3(h, s, b);\n}\n\nvec3 hsb2rgb(vec3 hsb) {\n vec3 rgb = clamp(abs(mod(hsb.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);\n return hsb.z * mix(vec3(1.0), rgb, hsb.y);\n}\n\n//=============================================================================\n// Color Range Weight Calculation\n//=============================================================================\n\nfloat hueDistance(float a, float b) {\n float d = abs(a - b);\n return min(d, 1.0 - d);\n}\n\nfloat getHueWeight(float hue, float center, float overlap) {\n float baseWidth = 1.0 / 6.0;\n float feather = baseWidth * overlap;\n\n float d = hueDistance(hue, center);\n\n float inner = baseWidth * 0.5;\n float outer = inner + feather;\n\n return 1.0 - smoothstep(inner, outer, d);\n}\n\nfloat getModeWeight(float hue, int mode, float overlap) {\n if (mode == MODE_MASTER || mode == MODE_COLORIZE) return 1.0;\n\n if (mode == MODE_RED) {\n return max(\n getHueWeight(hue, 0.0, overlap),\n getHueWeight(hue, 1.0, overlap)\n );\n }\n\n float center = float(mode - 1) / 6.0;\n return getHueWeight(hue, center, overlap);\n}\n\n//=============================================================================\n// Adjustment Functions\n//=============================================================================\n\nfloat adjustLightness(float l, float amount) {\n return amount > 0.0\n ? l + (1.0 - l) * amount\n : l + l * amount;\n}\n\nfloat adjustBrightness(float b, float amount) {\n return clamp(b + amount, 0.0, 1.0);\n}\n\nfloat adjustSaturation(float s, float amount) {\n return amount > 0.0\n ? s + (1.0 - s) * amount\n : s + s * amount;\n}\n\nvec3 colorize(vec3 rgb, float hue, float sat, float light) {\n float lum = dot(rgb, vec3(0.299, 0.587, 0.114));\n float l = adjustLightness(lum, light);\n\n vec3 hsl = vec3(fract(hue), clamp(sat, 0.0, 1.0), clamp(l, 0.0, 1.0));\n return hsl2rgb(hsl);\n}\n\n//=============================================================================\n// Main\n//=============================================================================\n\nvoid main() {\n vec4 original = texture(u_image0, v_texCoord);\n\n float hueShift = u_float0 / 360.0; // -180..180 -> -0.5..0.5\n float satAmount = u_float1 / 100.0; // -100..100 -> -1..1\n float lightAmount= u_float2 / 100.0; // -100..100 -> -1..1\n float overlap = u_float3 / 100.0; // 0..100 -> 0..1\n\n vec3 result;\n\n if (u_int0 == MODE_COLORIZE) {\n result = colorize(original.rgb, hueShift, satAmount, lightAmount);\n fragColor = vec4(result, original.a);\n return;\n }\n\n vec3 hsx = (u_int1 == COLORSPACE_HSL)\n ? rgb2hsl(original.rgb)\n : rgb2hsb(original.rgb);\n\n float weight = getModeWeight(hsx.x, u_int0, overlap);\n\n if (u_int0 != MODE_MASTER && hsx.y < EPSILON) {\n weight = 0.0;\n }\n\n if (weight > EPSILON) {\n float h = fract(hsx.x + hueShift * weight);\n float s = clamp(adjustSaturation(hsx.y, satAmount * weight), 0.0, 1.0);\n float v = (u_int1 == COLORSPACE_HSL)\n ? clamp(adjustLightness(hsx.z, lightAmount * weight), 0.0, 1.0)\n : clamp(adjustBrightness(hsx.z, lightAmount * weight), 0.0, 1.0);\n\n vec3 adjusted = vec3(h, s, v);\n result = (u_int1 == COLORSPACE_HSL)\n ? hsl2rgb(adjusted)\n : hsb2rgb(adjusted);\n } else {\n result = original.rgb;\n }\n\n fragColor = vec4(result, original.a);\n}\n",
6426 "from_input"
6427 ]
6428 }
6429 ],
6430 "groups": [],
6431 "links": [
6432 {
6433 "id": 3,
6434 "origin_id": 164,
6435 "origin_slot": 0,
6436 "target_id": 1,
6437 "target_slot": 2,
6438 "type": "FLOAT"
6439 },
6440 {
6441 "id": 4,
6442 "origin_id": 163,
6443 "origin_slot": 0,
6444 "target_id": 1,
6445 "target_slot": 3,
6446 "type": "FLOAT"
6447 },
6448 {
6449 "id": 5,
6450 "origin_id": 162,
6451 "origin_slot": 0,
6452 "target_id": 1,
6453 "target_slot": 4,
6454 "type": "FLOAT"
6455 },
6456 {
6457 "id": 6,
6458 "origin_id": 161,
6459 "origin_slot": 0,
6460 "target_id": 1,
6461 "target_slot": 5,
6462 "type": "FLOAT"
6463 },
6464 {
6465 "id": 1,
6466 "origin_id": 2,
6467 "origin_slot": 1,
6468 "target_id": 1,
6469 "target_slot": 7,
6470 "type": "INT"
6471 },
6472 {
6473 "id": 2,
6474 "origin_id": 3,
6475 "origin_slot": 1,
6476 "target_id": 1,
6477 "target_slot": 8,
6478 "type": "INT"
6479 },
6480 {
6481 "id": 10,
6482 "origin_id": -10,
6483 "origin_slot": 0,
6484 "target_id": 1,
6485 "target_slot": 0,
6486 "type": "IMAGE"
6487 },
6488 {
6489 "id": 8,
6490 "origin_id": 1,
6491 "origin_slot": 0,
6492 "target_id": -20,
6493 "target_slot": 0,
6494 "type": "IMAGE"
6495 }
6496 ],
6497 "extra": {
6498 "workflowRendererVersion": "LG"
6499 }
6500 },
6501 {
6502 "id": "1d319b86-6e4f-43d0-83e1-99dc988e1db3",
6503 "version": 1,
6504 "state": {
6505 "lastGroupId": 9,
6506 "lastNodeId": 204,
6507 "lastLinkId": 142,
6508 "lastRerouteId": 0
6509 },
6510 "revision": 0,
6511 "config": [],
6512 "name": "Color Adjustment",
6513 "description": "Adjusts saturation, temperature, tint, and vibrance using a real-time GPU fragment shader.",
6514 "inputNode": {
6515 "id": -10,
6516 "bounding": [
6517 3110,
6518 -3560,
6519 120,
6520 60
6521 ]
6522 },
6523 "outputNode": {
6524 "id": -20,
6525 "bounding": [
6526 4070,
6527 -3560,
6528 120,
6529 60
6530 ]
6531 },
6532 "inputs": [
6533 {
6534 "id": "0431d493-5f28-4430-bd00-84733997fc08",
6535 "name": "images.image0",
6536 "type": "IMAGE",
6537 "linkIds": [
6538 29
6539 ],
6540 "localized_name": "images.image0",
6541 "label": "image",
6542 "pos": [
6543 3210,
6544 -3540
6545 ]
6546 }
6547 ],
6548 "outputs": [
6549 {
6550 "id": "bee8ea06-a114-4612-8937-939f2c927bdb",
6551 "name": "IMAGE0",
6552 "type": "IMAGE",
6553 "linkIds": [
6554 28
6555 ],
6556 "localized_name": "IMAGE0",
6557 "label": "IMAGE",
6558 "pos": [
6559 4090,
6560 -3540
6561 ]
6562 }
6563 ],
6564 "widgets": [],
6565 "nodes": [
6566 {
6567 "id": 166,
6568 "type": "GLSLShader",
6569 "pos": [
6570 3590,
6571 -3940
6572 ],
6573 "size": [
6574 420,
6575 300
6576 ],
6577 "flags": [],
6578 "order": 4,
6579 "mode": 0,
6580 "inputs": [
6581 {
6582 "label": "image0",
6583 "localized_name": "images.image0",
6584 "name": "images.image0",
6585 "type": "IMAGE",
6586 "link": 29
6587 },
6588 {
6589 "label": "image1",
6590 "localized_name": "images.image1",
6591 "name": "images.image1",
6592 "shape": 7,
6593 "type": "IMAGE",
6594 "link": null
6595 },
6596 {
6597 "label": "u_float0",
6598 "localized_name": "floats.u_float0",
6599 "name": "floats.u_float0",
6600 "shape": 7,
6601 "type": "FLOAT",
6602 "link": 34
6603 },
6604 {
6605 "label": "u_float1",
6606 "localized_name": "floats.u_float1",
6607 "name": "floats.u_float1",
6608 "shape": 7,
6609 "type": "FLOAT",
6610 "link": 30
6611 },
6612 {
6613 "label": "u_float2",
6614 "localized_name": "floats.u_float2",
6615 "name": "floats.u_float2",
6616 "shape": 7,
6617 "type": "FLOAT",
6618 "link": 31
6619 },
6620 {
6621 "label": "u_float3",
6622 "localized_name": "floats.u_float3",
6623 "name": "floats.u_float3",
6624 "shape": 7,
6625 "type": "FLOAT",
6626 "link": 33
6627 },
6628 {
6629 "label": "u_float4",
6630 "localized_name": "floats.u_float4",
6631 "name": "floats.u_float4",
6632 "shape": 7,
6633 "type": "FLOAT",
6634 "link": null
6635 },
6636 {
6637 "label": "u_int0",
6638 "localized_name": "ints.u_int0",
6639 "name": "ints.u_int0",
6640 "shape": 7,
6641 "type": "INT",
6642 "link": null
6643 },
6644 {
6645 "label": "u_bool0",
6646 "localized_name": "bools.u_bool0",
6647 "name": "bools.u_bool0",
6648 "shape": 7,
6649 "type": "BOOLEAN",
6650 "link": null
6651 },
6652 {
6653 "label": "u_curve0",
6654 "localized_name": "curves.u_curve0",
6655 "name": "curves.u_curve0",
6656 "shape": 7,
6657 "type": "CURVE",
6658 "link": null
6659 }
6660 ],
6661 "outputs": [
6662 {
6663 "localized_name": "IMAGE0",
6664 "name": "IMAGE0",
6665 "type": "IMAGE",
6666 "links": [
6667 28
6668 ]
6669 },
6670 {
6671 "localized_name": "IMAGE1",
6672 "name": "IMAGE1",
6673 "type": "IMAGE",
6674 "links": null
6675 },
6676 {
6677 "localized_name": "IMAGE2",
6678 "name": "IMAGE2",
6679 "type": "IMAGE",
6680 "links": null
6681 },
6682 {
6683 "localized_name": "IMAGE3",
6684 "name": "IMAGE3",
6685 "type": "IMAGE",
6686 "links": null
6687 }
6688 ],
6689 "properties": {
6690 "Node name for S&R": "GLSLShader",
6691 "cnr_id": "comfy-core",
6692 "ver": "0.22.0",
6693 "enableTabs": false,
6694 "tabWidth": 65,
6695 "tabXOffset": 10,
6696 "hasSecondTab": false,
6697 "secondTabText": "Send Back",
6698 "secondTabOffset": 80,
6699 "secondTabWidth": 65
6700 },
6701 "widgets_values": [
6702 "#version 300 es\nprecision highp float;\n\nuniform sampler2D u_image0;\nuniform float u_float0; // temperature (-100 to 100)\nuniform float u_float1; // tint (-100 to 100)\nuniform float u_float2; // vibrance (-100 to 100)\nuniform float u_float3; // saturation (-100 to 100)\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nconst float INPUT_SCALE = 0.01;\nconst float TEMP_TINT_PRIMARY = 0.3;\nconst float TEMP_TINT_SECONDARY = 0.15;\nconst float VIBRANCE_BOOST = 2.0;\nconst float SATURATION_BOOST = 2.0;\nconst float SKIN_PROTECTION = 0.5;\nconst float EPSILON = 0.001;\nconst vec3 LUMA_WEIGHTS = vec3(0.299, 0.587, 0.114);\n\nvoid main() {\n vec4 tex = texture(u_image0, v_texCoord);\n vec3 color = tex.rgb;\n \n // Scale inputs: -100/100 → -1/1\n float temperature = u_float0 * INPUT_SCALE;\n float tint = u_float1 * INPUT_SCALE;\n float vibrance = u_float2 * INPUT_SCALE;\n float saturation = u_float3 * INPUT_SCALE;\n \n // Temperature (warm/cool): positive = warm, negative = cool\n color.r += temperature * TEMP_TINT_PRIMARY;\n color.b -= temperature * TEMP_TINT_PRIMARY;\n \n // Tint (green/magenta): positive = green, negative = magenta\n color.g += tint * TEMP_TINT_PRIMARY;\n color.r -= tint * TEMP_TINT_SECONDARY;\n color.b -= tint * TEMP_TINT_SECONDARY;\n \n // Single clamp after temperature/tint\n color = clamp(color, 0.0, 1.0);\n \n // Vibrance with skin protection\n if (vibrance != 0.0) {\n float maxC = max(color.r, max(color.g, color.b));\n float minC = min(color.r, min(color.g, color.b));\n float sat = maxC - minC;\n float gray = dot(color, LUMA_WEIGHTS);\n \n if (vibrance < 0.0) {\n // Desaturate: -100 → gray\n color = mix(vec3(gray), color, 1.0 + vibrance);\n } else {\n // Boost less saturated colors more\n float vibranceAmt = vibrance * (1.0 - sat);\n \n // Branchless skin tone protection\n float isWarmTone = step(color.b, color.g) * step(color.g, color.r);\n float warmth = (color.r - color.b) / max(maxC, EPSILON);\n float skinTone = isWarmTone * warmth * sat * (1.0 - sat);\n vibranceAmt *= (1.0 - skinTone * SKIN_PROTECTION);\n \n color = mix(vec3(gray), color, 1.0 + vibranceAmt * VIBRANCE_BOOST);\n }\n }\n \n // Saturation\n if (saturation != 0.0) {\n float gray = dot(color, LUMA_WEIGHTS);\n float satMix = saturation < 0.0\n ? 1.0 + saturation // -100 → gray\n : 1.0 + saturation * SATURATION_BOOST; // +100 → 3x boost\n color = mix(vec3(gray), color, satMix);\n }\n \n fragColor = vec4(clamp(color, 0.0, 1.0), tex.a);\n}",
6703 "from_input"
6704 ]
6705 },
6706 {
6707 "id": 167,
6708 "type": "PrimitiveFloat",
6709 "pos": [
6710 3290,
6711 -3610
6712 ],
6713 "size": [
6714 270,
6715 60
6716 ],
6717 "flags": [],
6718 "order": 0,
6719 "mode": 0,
6720 "inputs": [
6721 {
6722 "label": "vibrance",
6723 "localized_name": "value",
6724 "name": "value",
6725 "type": "FLOAT",
6726 "widget": {
6727 "name": "value"
6728 },
6729 "link": null
6730 }
6731 ],
6732 "outputs": [
6733 {
6734 "localized_name": "FLOAT",
6735 "name": "FLOAT",
6736 "type": "FLOAT",
6737 "links": [
6738 26,
6739 31
6740 ]
6741 }
6742 ],
6743 "title": "Vibrance",
6744 "properties": {
6745 "Node name for S&R": "PrimitiveFloat",
6746 "cnr_id": "comfy-core",
6747 "ver": "0.22.0",
6748 "enableTabs": false,
6749 "tabWidth": 65,
6750 "tabXOffset": 10,
6751 "hasSecondTab": false,
6752 "secondTabText": "Send Back",
6753 "secondTabOffset": 80,
6754 "secondTabWidth": 65,
6755 "max": 100,
6756 "min": -100,
6757 "step": 1,
6758 "display": "gradientslider",
6759 "gradient_stops": [
6760 {
6761 "offset": 0,
6762 "color": [
6763 128,
6764 128,
6765 128
6766 ]
6767 },
6768 {
6769 "offset": 1,
6770 "color": [
6771 255,
6772 0,
6773 0
6774 ]
6775 }
6776 ]
6777 },
6778 "widgets_values": [
6779 0
6780 ]
6781 },
6782 {
6783 "id": 168,
6784 "type": "PrimitiveFloat",
6785 "pos": [
6786 3290,
6787 -3720
6788 ],
6789 "size": [
6790 270,
6791 60
6792 ],
6793 "flags": [],
6794 "order": 1,
6795 "mode": 0,
6796 "inputs": [
6797 {
6798 "label": "saturation",
6799 "localized_name": "value",
6800 "name": "value",
6801 "type": "FLOAT",
6802 "widget": {
6803 "name": "value"
6804 },
6805 "link": null
6806 }
6807 ],
6808 "outputs": [
6809 {
6810 "localized_name": "FLOAT",
6811 "name": "FLOAT",
6812 "type": "FLOAT",
6813 "links": [
6814 33
6815 ]
6816 }
6817 ],
6818 "title": "Saturation",
6819 "properties": {
6820 "Node name for S&R": "PrimitiveFloat",
6821 "cnr_id": "comfy-core",
6822 "ver": "0.22.0",
6823 "enableTabs": false,
6824 "tabWidth": 65,
6825 "tabXOffset": 10,
6826 "hasSecondTab": false,
6827 "secondTabText": "Send Back",
6828 "secondTabOffset": 80,
6829 "secondTabWidth": 65,
6830 "max": 100,
6831 "min": -100,
6832 "step": 1,
6833 "display": "gradientslider",
6834 "gradient_stops": [
6835 {
6836 "offset": 0,
6837 "color": [
6838 128,
6839 128,
6840 128
6841 ]
6842 },
6843 {
6844 "offset": 1,
6845 "color": [
6846 255,
6847 0,
6848 0
6849 ]
6850 }
6851 ]
6852 },
6853 "widgets_values": [
6854 0
6855 ]
6856 },
6857 {
6858 "id": 169,
6859 "type": "PrimitiveFloat",
6860 "pos": [
6861 3290,
6862 -3830
6863 ],
6864 "size": [
6865 270,
6866 60
6867 ],
6868 "flags": [],
6869 "order": 2,
6870 "mode": 0,
6871 "inputs": [
6872 {
6873 "label": "tint",
6874 "localized_name": "value",
6875 "name": "value",
6876 "type": "FLOAT",
6877 "widget": {
6878 "name": "value"
6879 },
6880 "link": null
6881 }
6882 ],
6883 "outputs": [
6884 {
6885 "localized_name": "FLOAT",
6886 "name": "FLOAT",
6887 "type": "FLOAT",
6888 "links": [
6889 30
6890 ]
6891 }
6892 ],
6893 "title": "Tint",
6894 "properties": {
6895 "Node name for S&R": "PrimitiveFloat",
6896 "cnr_id": "comfy-core",
6897 "ver": "0.22.0",
6898 "enableTabs": false,
6899 "tabWidth": 65,
6900 "tabXOffset": 10,
6901 "hasSecondTab": false,
6902 "secondTabText": "Send Back",
6903 "secondTabOffset": 80,
6904 "secondTabWidth": 65,
6905 "max": 100,
6906 "min": -100,
6907 "step": 1,
6908 "display": "gradientslider",
6909 "gradient_stops": [
6910 {
6911 "offset": 0,
6912 "color": [
6913 0,
6914 255,
6915 0
6916 ]
6917 },
6918 {
6919 "offset": 0.5,
6920 "color": [
6921 255,
6922 255,
6923 255
6924 ]
6925 },
6926 {
6927 "offset": 1,
6928 "color": [
6929 255,
6930 0,
6931 255
6932 ]
6933 }
6934 ]
6935 },
6936 "widgets_values": [
6937 0
6938 ]
6939 },
6940 {
6941 "id": 170,
6942 "type": "PrimitiveFloat",
6943 "pos": [
6944 3290,
6945 -3940
6946 ],
6947 "size": [
6948 270,
6949 60
6950 ],
6951 "flags": [],
6952 "order": 3,
6953 "mode": 0,
6954 "inputs": [
6955 {
6956 "label": "temperature",
6957 "localized_name": "value",
6958 "name": "value",
6959 "type": "FLOAT",
6960 "widget": {
6961 "name": "value"
6962 },
6963 "link": null
6964 }
6965 ],
6966 "outputs": [
6967 {
6968 "localized_name": "FLOAT",
6969 "name": "FLOAT",
6970 "type": "FLOAT",
6971 "links": [
6972 34
6973 ]
6974 }
6975 ],
6976 "title": "Temperature",
6977 "properties": {
6978 "Node name for S&R": "PrimitiveFloat",
6979 "cnr_id": "comfy-core",
6980 "ver": "0.22.0",
6981 "enableTabs": false,
6982 "tabWidth": 65,
6983 "tabXOffset": 10,
6984 "hasSecondTab": false,
6985 "secondTabText": "Send Back",
6986 "secondTabOffset": 80,
6987 "secondTabWidth": 65,
6988 "max": 100,
6989 "min": -100,
6990 "step": 1,
6991 "display": "gradientslider",
6992 "gradient_stops": [
6993 {
6994 "offset": 0,
6995 "color": [
6996 68,
6997 136,
6998 255
6999 ]
7000 },
7001 {
7002 "offset": 0.5,
7003 "color": [
7004 255,
7005 255,
7006 255
7007 ]
7008 },
7009 {
7010 "offset": 1,
7011 "color": [
7012 255,
7013 136,
7014 0
7015 ]
7016 }
7017 ]
7018 },
7019 "widgets_values": [
7020 0
7021 ]
7022 }
7023 ],
7024 "groups": [],
7025 "links": [
7026 {
7027 "id": 34,
7028 "origin_id": 170,
7029 "origin_slot": 0,
7030 "target_id": 166,
7031 "target_slot": 2,
7032 "type": "FLOAT"
7033 },
7034 {
7035 "id": 30,
7036 "origin_id": 169,
7037 "origin_slot": 0,
7038 "target_id": 166,
7039 "target_slot": 3,
7040 "type": "FLOAT"
7041 },
7042 {
7043 "id": 31,
7044 "origin_id": 167,
7045 "origin_slot": 0,
7046 "target_id": 166,
7047 "target_slot": 4,
7048 "type": "FLOAT"
7049 },
7050 {
7051 "id": 33,
7052 "origin_id": 168,
7053 "origin_slot": 0,
7054 "target_id": 166,
7055 "target_slot": 5,
7056 "type": "FLOAT"
7057 },
7058 {
7059 "id": 29,
7060 "origin_id": -10,
7061 "origin_slot": 0,
7062 "target_id": 166,
7063 "target_slot": 0,
7064 "type": "IMAGE"
7065 },
7066 {
7067 "id": 28,
7068 "origin_id": 166,
7069 "origin_slot": 0,
7070 "target_id": -20,
7071 "target_slot": 0,
7072 "type": "IMAGE"
7073 }
7074 ],
7075 "extra": {
7076 "workflowRendererVersion": "LG"
7077 }
7078 },
7079 {
7080 "id": "bf0f7afe-2f48-42b1-9e47-57e362efc6dd",
7081 "version": 1,
7082 "state": {
7083 "lastGroupId": 9,
7084 "lastNodeId": 204,
7085 "lastLinkId": 142,
7086 "lastRerouteId": 0
7087 },
7088 "revision": 0,
7089 "config": [],
7090 "name": "Image Levels",
7091 "description": "Adjusts black point, white point, and gamma for tonal range control via GPU shader.",
7092 "inputNode": {
7093 "id": -10,
7094 "bounding": [
7095 3840,
7096 -3430,
7097 120,
7098 60
7099 ]
7100 },
7101 "outputNode": {
7102 "id": -20,
7103 "bounding": [
7104 4950,
7105 -3430,
7106 120,
7107 60
7108 ]
7109 },
7110 "inputs": [
7111 {
7112 "id": "b53e5012-fa47-400f-a324-28c74854ccae",
7113 "name": "images.image0",
7114 "type": "IMAGE",
7115 "linkIds": [
7116 1
7117 ],
7118 "localized_name": "images.image0",
7119 "label": "image",
7120 "pos": [
7121 3940,
7122 -3410
7123 ]
7124 }
7125 ],
7126 "outputs": [
7127 {
7128 "id": "de7f2ffa-155f-41fd-b054-aa4d91ef49ca",
7129 "name": "IMAGE0",
7130 "type": "IMAGE",
7131 "linkIds": [
7132 8
7133 ],
7134 "localized_name": "IMAGE0",
7135 "label": "IMAGE",
7136 "pos": [
7137 4970,
7138 -3410
7139 ]
7140 }
7141 ],
7142 "widgets": [],
7143 "nodes": [
7144 {
7145 "id": 172,
7146 "type": "CustomCombo",
7147 "pos": [
7148 4020,
7149 -3350
7150 ],
7151 "size": [
7152 270,
7153 200
7154 ],
7155 "flags": [],
7156 "order": 0,
7157 "mode": 0,
7158 "inputs": [
7159 {
7160 "label": "channel",
7161 "localized_name": "choice",
7162 "name": "choice",
7163 "type": "COMBO",
7164 "widget": {
7165 "name": "choice"
7166 },
7167 "link": null
7168 }
7169 ],
7170 "outputs": [
7171 {
7172 "localized_name": "STRING",
7173 "name": "STRING",
7174 "type": "STRING",
7175 "links": null
7176 },
7177 {
7178 "localized_name": "INDEX",
7179 "name": "INDEX",
7180 "type": "INT",
7181 "links": [
7182 3
7183 ]
7184 }
7185 ],
7186 "title": "Channel",
7187 "properties": {
7188 "Node name for S&R": "CustomCombo",
7189 "cnr_id": "comfy-core",
7190 "ver": "0.22.0",
7191 "enableTabs": false,
7192 "tabWidth": 65,
7193 "tabXOffset": 10,
7194 "hasSecondTab": false,
7195 "secondTabText": "Send Back",
7196 "secondTabOffset": 80,
7197 "secondTabWidth": 65
7198 },
7199 "widgets_values": [
7200 "RGB",
7201 0,
7202 "RGB",
7203 "R",
7204 "G",
7205 "B",
7206 ""
7207 ]
7208 },
7209 {
7210 "id": 173,
7211 "type": "PrimitiveFloat",
7212 "pos": [
7213 4020,
7214 -3550
7215 ],
7216 "size": [
7217 270,
7218 60
7219 ],
7220 "flags": [],
7221 "order": 1,
7222 "mode": 0,
7223 "inputs": [
7224 {
7225 "label": "output_black",
7226 "localized_name": "value",
7227 "name": "value",
7228 "type": "FLOAT",
7229 "widget": {
7230 "name": "value"
7231 },
7232 "link": null
7233 }
7234 ],
7235 "outputs": [
7236 {
7237 "localized_name": "FLOAT",
7238 "name": "FLOAT",
7239 "type": "FLOAT",
7240 "links": [
7241 6
7242 ]
7243 }
7244 ],
7245 "title": "Output Black",
7246 "properties": {
7247 "Node name for S&R": "PrimitiveFloat",
7248 "cnr_id": "comfy-core",
7249 "ver": "0.22.0",
7250 "enableTabs": false,
7251 "tabWidth": 65,
7252 "tabXOffset": 10,
7253 "hasSecondTab": false,
7254 "secondTabText": "Send Back",
7255 "secondTabOffset": 80,
7256 "secondTabWidth": 65,
7257 "max": 255,
7258 "min": 0,
7259 "step": 1,
7260 "display": "gradientslider",
7261 "gradient_stops": [
7262 {
7263 "offset": 0,
7264 "color": [
7265 0,
7266 0,
7267 0
7268 ]
7269 },
7270 {
7271 "offset": 1,
7272 "color": [
7273 255,
7274 255,
7275 255
7276 ]
7277 }
7278 ]
7279 },
7280 "widgets_values": [
7281 36
7282 ]
7283 },
7284 {
7285 "id": 174,
7286 "type": "PrimitiveFloat",
7287 "pos": [
7288 4020,
7289 -3850
7290 ],
7291 "size": [
7292 270,
7293 60
7294 ],
7295 "flags": [],
7296 "order": 2,
7297 "mode": 0,
7298 "inputs": [
7299 {
7300 "label": "input_black",
7301 "localized_name": "value",
7302 "name": "value",
7303 "type": "FLOAT",
7304 "widget": {
7305 "name": "value"
7306 },
7307 "link": null
7308 }
7309 ],
7310 "outputs": [
7311 {
7312 "localized_name": "FLOAT",
7313 "name": "FLOAT",
7314 "type": "FLOAT",
7315 "links": [
7316 2
7317 ]
7318 }
7319 ],
7320 "title": "Input Black",
7321 "properties": {
7322 "Node name for S&R": "PrimitiveFloat",
7323 "cnr_id": "comfy-core",
7324 "ver": "0.22.0",
7325 "enableTabs": false,
7326 "tabWidth": 65,
7327 "tabXOffset": 10,
7328 "hasSecondTab": false,
7329 "secondTabText": "Send Back",
7330 "secondTabOffset": 80,
7331 "secondTabWidth": 65,
7332 "min": 0,
7333 "max": 255,
7334 "step": 1,
7335 "display": "gradientslider",
7336 "gradient_stops": [
7337 {
7338 "offset": 0,
7339 "color": [
7340 0,
7341 0,
7342 0
7343 ]
7344 },
7345 {
7346 "offset": 1,
7347 "color": [
7348 255,
7349 255,
7350 255
7351 ]
7352 }
7353 ]
7354 },
7355 "widgets_values": [
7356 85
7357 ]
7358 },
7359 {
7360 "id": 175,
7361 "type": "PrimitiveFloat",
7362 "pos": [
7363 4020,
7364 -3750
7365 ],
7366 "size": [
7367 270,
7368 60
7369 ],
7370 "flags": [],
7371 "order": 3,
7372 "mode": 0,
7373 "inputs": [
7374 {
7375 "label": "input_white",
7376 "localized_name": "value",
7377 "name": "value",
7378 "type": "FLOAT",
7379 "widget": {
7380 "name": "value"
7381 },
7382 "link": null
7383 }
7384 ],
7385 "outputs": [
7386 {
7387 "localized_name": "FLOAT",
7388 "name": "FLOAT",
7389 "type": "FLOAT",
7390 "links": [
7391 4
7392 ]
7393 }
7394 ],
7395 "title": "Input White",
7396 "properties": {
7397 "Node name for S&R": "PrimitiveFloat",
7398 "cnr_id": "comfy-core",
7399 "ver": "0.22.0",
7400 "enableTabs": false,
7401 "tabWidth": 65,
7402 "tabXOffset": 10,
7403 "hasSecondTab": false,
7404 "secondTabText": "Send Back",
7405 "secondTabOffset": 80,
7406 "secondTabWidth": 65,
7407 "max": 255,
7408 "min": 0,
7409 "step": 1,
7410 "display": "gradientslider",
7411 "gradient_stops": [
7412 {
7413 "offset": 0,
7414 "color": [
7415 0,
7416 0,
7417 0
7418 ]
7419 },
7420 {
7421 "offset": 1,
7422 "color": [
7423 255,
7424 255,
7425 255
7426 ]
7427 }
7428 ]
7429 },
7430 "widgets_values": [
7431 255
7432 ]
7433 },
7434 {
7435 "id": 176,
7436 "type": "PrimitiveFloat",
7437 "pos": [
7438 4020,
7439 -3650
7440 ],
7441 "size": [
7442 270,
7443 60
7444 ],
7445 "flags": [],
7446 "order": 4,
7447 "mode": 0,
7448 "inputs": [
7449 {
7450 "label": "gamma",
7451 "localized_name": "value",
7452 "name": "value",
7453 "type": "FLOAT",
7454 "widget": {
7455 "name": "value"
7456 },
7457 "link": null
7458 }
7459 ],
7460 "outputs": [
7461 {
7462 "localized_name": "FLOAT",
7463 "name": "FLOAT",
7464 "type": "FLOAT",
7465 "links": [
7466 5
7467 ]
7468 }
7469 ],
7470 "title": "Gamma",
7471 "properties": {
7472 "Node name for S&R": "PrimitiveFloat",
7473 "cnr_id": "comfy-core",
7474 "ver": "0.22.0",
7475 "enableTabs": false,
7476 "tabWidth": 65,
7477 "tabXOffset": 10,
7478 "hasSecondTab": false,
7479 "secondTabText": "Send Back",
7480 "secondTabOffset": 80,
7481 "secondTabWidth": 65,
7482 "max": 10,
7483 "min": 0,
7484 "step": 0.01,
7485 "precision": 2,
7486 "display": "gradientslider",
7487 "gradient_stops": [
7488 {
7489 "offset": 0,
7490 "color": [
7491 0,
7492 0,
7493 0
7494 ]
7495 },
7496 {
7497 "offset": 0.5,
7498 "color": [
7499 128,
7500 128,
7501 128
7502 ]
7503 },
7504 {
7505 "offset": 1,
7506 "color": [
7507 255,
7508 255,
7509 255
7510 ]
7511 }
7512 ]
7513 },
7514 "widgets_values": [
7515 4.33
7516 ]
7517 },
7518 {
7519 "id": 177,
7520 "type": "PrimitiveFloat",
7521 "pos": [
7522 4020,
7523 -3450
7524 ],
7525 "size": [
7526 270,
7527 60
7528 ],
7529 "flags": [],
7530 "order": 5,
7531 "mode": 0,
7532 "inputs": [
7533 {
7534 "label": "output_white",
7535 "localized_name": "value",
7536 "name": "value",
7537 "type": "FLOAT",
7538 "widget": {
7539 "name": "value"
7540 },
7541 "link": null
7542 }
7543 ],
7544 "outputs": [
7545 {
7546 "localized_name": "FLOAT",
7547 "name": "FLOAT",
7548 "type": "FLOAT",
7549 "links": [
7550 7
7551 ]
7552 }
7553 ],
7554 "title": "Output White",
7555 "properties": {
7556 "Node name for S&R": "PrimitiveFloat",
7557 "cnr_id": "comfy-core",
7558 "ver": "0.22.0",
7559 "enableTabs": false,
7560 "tabWidth": 65,
7561 "tabXOffset": 10,
7562 "hasSecondTab": false,
7563 "secondTabText": "Send Back",
7564 "secondTabOffset": 80,
7565 "secondTabWidth": 65,
7566 "max": 255,
7567 "min": 0,
7568 "step": 1,
7569 "display": "gradientslider",
7570 "gradient_stops": [
7571 {
7572 "offset": 0,
7573 "color": [
7574 0,
7575 0,
7576 0
7577 ]
7578 },
7579 {
7580 "offset": 1,
7581 "color": [
7582 255,
7583 255,
7584 255
7585 ]
7586 }
7587 ]
7588 },
7589 "widgets_values": [
7590 201
7591 ]
7592 },
7593 {
7594 "id": 178,
7595 "type": "GLSLShader",
7596 "pos": [
7597 4310,
7598 -3850
7599 ],
7600 "size": [
7601 580,
7602 340
7603 ],
7604 "flags": [],
7605 "order": 6,
7606 "mode": 0,
7607 "inputs": [
7608 {
7609 "label": "image0",
7610 "localized_name": "images.image0",
7611 "name": "images.image0",
7612 "type": "IMAGE",
7613 "link": 1
7614 },
7615 {
7616 "label": "image1",
7617 "localized_name": "images.image1",
7618 "name": "images.image1",
7619 "shape": 7,
7620 "type": "IMAGE",
7621 "link": null
7622 },
7623 {
7624 "label": "u_float0",
7625 "localized_name": "floats.u_float0",
7626 "name": "floats.u_float0",
7627 "shape": 7,
7628 "type": "FLOAT",
7629 "link": 2
7630 },
7631 {
7632 "label": "u_float1",
7633 "localized_name": "floats.u_float1",
7634 "name": "floats.u_float1",
7635 "shape": 7,
7636 "type": "FLOAT",
7637 "link": 4
7638 },
7639 {
7640 "label": "u_float2",
7641 "localized_name": "floats.u_float2",
7642 "name": "floats.u_float2",
7643 "shape": 7,
7644 "type": "FLOAT",
7645 "link": 5
7646 },
7647 {
7648 "label": "u_float3",
7649 "localized_name": "floats.u_float3",
7650 "name": "floats.u_float3",
7651 "shape": 7,
7652 "type": "FLOAT",
7653 "link": 6
7654 },
7655 {
7656 "label": "u_float4",
7657 "localized_name": "floats.u_float4",
7658 "name": "floats.u_float4",
7659 "shape": 7,
7660 "type": "FLOAT",
7661 "link": 7
7662 },
7663 {
7664 "label": "u_float5",
7665 "localized_name": "floats.u_float5",
7666 "name": "floats.u_float5",
7667 "shape": 7,
7668 "type": "FLOAT",
7669 "link": null
7670 },
7671 {
7672 "label": "u_int0",
7673 "localized_name": "ints.u_int0",
7674 "name": "ints.u_int0",
7675 "shape": 7,
7676 "type": "INT",
7677 "link": 3
7678 },
7679 {
7680 "label": "u_int1",
7681 "localized_name": "ints.u_int1",
7682 "name": "ints.u_int1",
7683 "shape": 7,
7684 "type": "INT",
7685 "link": null
7686 },
7687 {
7688 "label": "u_bool0",
7689 "localized_name": "bools.u_bool0",
7690 "name": "bools.u_bool0",
7691 "shape": 7,
7692 "type": "BOOLEAN",
7693 "link": null
7694 },
7695 {
7696 "label": "u_curve0",
7697 "localized_name": "curves.u_curve0",
7698 "name": "curves.u_curve0",
7699 "shape": 7,
7700 "type": "CURVE",
7701 "link": null
7702 }
7703 ],
7704 "outputs": [
7705 {
7706 "localized_name": "IMAGE0",
7707 "name": "IMAGE0",
7708 "type": "IMAGE",
7709 "links": [
7710 8
7711 ]
7712 },
7713 {
7714 "localized_name": "IMAGE1",
7715 "name": "IMAGE1",
7716 "type": "IMAGE",
7717 "links": null
7718 },
7719 {
7720 "localized_name": "IMAGE2",
7721 "name": "IMAGE2",
7722 "type": "IMAGE",
7723 "links": null
7724 },
7725 {
7726 "localized_name": "IMAGE3",
7727 "name": "IMAGE3",
7728 "type": "IMAGE",
7729 "links": null
7730 }
7731 ],
7732 "properties": {
7733 "Node name for S&R": "GLSLShader",
7734 "cnr_id": "comfy-core",
7735 "ver": "0.22.0",
7736 "enableTabs": false,
7737 "tabWidth": 65,
7738 "tabXOffset": 10,
7739 "hasSecondTab": false,
7740 "secondTabText": "Send Back",
7741 "secondTabOffset": 80,
7742 "secondTabWidth": 65
7743 },
7744 "widgets_values": [
7745 "#version 300 es\nprecision highp float;\n\n// Levels Adjustment\n// u_int0: channel (0=RGB, 1=R, 2=G, 3=B) default: 0\n// u_float0: input black (0-255) default: 0\n// u_float1: input white (0-255) default: 255\n// u_float2: gamma (0.01-9.99) default: 1.0\n// u_float3: output black (0-255) default: 0\n// u_float4: output white (0-255) default: 255\n\nuniform sampler2D u_image0;\nuniform int u_int0;\nuniform float u_float0;\nuniform float u_float1;\nuniform float u_float2;\nuniform float u_float3;\nuniform float u_float4;\n\nin vec2 v_texCoord;\nout vec4 fragColor;\n\nvec3 applyLevels(vec3 color, float inBlack, float inWhite, float gamma, float outBlack, float outWhite) {\n float inRange = max(inWhite - inBlack, 0.0001);\n vec3 result = clamp((color - inBlack) / inRange, 0.0, 1.0);\n result = pow(result, vec3(1.0 / gamma));\n result = mix(vec3(outBlack), vec3(outWhite), result);\n return result;\n}\n\nfloat applySingleChannel(float value, float inBlack, float inWhite, float gamma, float outBlack, float outWhite) {\n float inRange = max(inWhite - inBlack, 0.0001);\n float result = clamp((value - inBlack) / inRange, 0.0, 1.0);\n result = pow(result, 1.0 / gamma);\n result = mix(outBlack, outWhite, result);\n return result;\n}\n\nvoid main() {\n vec4 texColor = texture(u_image0, v_texCoord);\n vec3 color = texColor.rgb;\n \n float inBlack = u_float0 / 255.0;\n float inWhite = u_float1 / 255.0;\n float gamma = u_float2;\n float outBlack = u_float3 / 255.0;\n float outWhite = u_float4 / 255.0;\n \n vec3 result;\n \n if (u_int0 == 0) {\n result = applyLevels(color, inBlack, inWhite, gamma, outBlack, outWhite);\n }\n else if (u_int0 == 1) {\n result = color;\n result.r = applySingleChannel(color.r, inBlack, inWhite, gamma, outBlack, outWhite);\n }\n else if (u_int0 == 2) {\n result = color;\n result.g = applySingleChannel(color.g, inBlack, inWhite, gamma, outBlack, outWhite);\n }\n else if (u_int0 == 3) {\n result = color;\n result.b = applySingleChannel(color.b, inBlack, inWhite, gamma, outBlack, outWhite);\n }\n else {\n result = color;\n }\n \n fragColor = vec4(result, texColor.a);\n}",
7746 "from_input"
7747 ]
7748 }
7749 ],
7750 "groups": [],
7751 "links": [
7752 {
7753 "id": 2,
7754 "origin_id": 174,
7755 "origin_slot": 0,
7756 "target_id": 178,
7757 "target_slot": 2,
7758 "type": "FLOAT"
7759 },
7760 {
7761 "id": 4,
7762 "origin_id": 175,
7763 "origin_slot": 0,
7764 "target_id": 178,
7765 "target_slot": 3,
7766 "type": "FLOAT"
7767 },
7768 {
7769 "id": 5,
7770 "origin_id": 176,
7771 "origin_slot": 0,
7772 "target_id": 178,
7773 "target_slot": 4,
7774 "type": "FLOAT"
7775 },
7776 {
7777 "id": 6,
7778 "origin_id": 173,
7779 "origin_slot": 0,
7780 "target_id": 178,
7781 "target_slot": 5,
7782 "type": "FLOAT"
7783 },
7784 {
7785 "id": 7,
7786 "origin_id": 177,
7787 "origin_slot": 0,
7788 "target_id": 178,
7789 "target_slot": 6,
7790 "type": "FLOAT"
7791 },
7792 {
7793 "id": 3,
7794 "origin_id": 172,
7795 "origin_slot": 1,
7796 "target_id": 178,
7797 "target_slot": 8,
7798 "type": "INT"
7799 },
7800 {
7801 "id": 1,
7802 "origin_id": -10,
7803 "origin_slot": 0,
7804 "target_id": 178,
7805 "target_slot": 0,
7806 "type": "IMAGE"
7807 },
7808 {
7809 "id": 8,
7810 "origin_id": 178,
7811 "origin_slot": 0,
7812 "target_id": -20,
7813 "target_slot": 0,
7814 "type": "IMAGE"
7815 }
7816 ],
7817 "extra": {
7818 "workflowRendererVersion": "LG"
7819 }
7820 }
7821 ]
7822 },
7823 "config": [],
7824 "extra": {
7825 "ds": {
7826 "scale": 0.13310000000000147,
7827 "offset": [
7828 7040.666964526875,
7829 1586.6273200719797
7830 ]
7831 },
7832 "frontendVersion": "1.43.18",
7833 "VHS_latentpreview": false,
7834 "VHS_latentpreviewrate": 0,
7835 "VHS_MetadataImage": true,
7836 "VHS_KeepIntermediate": true
7837 },
7838 "version": 0.4
7839}