diff --git a/README.md b/README.md index c0ea671..3409411 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ A set of ComfyUI nodes to dynamically create QR image layers for generative QR art without the hassle of leaving the webui. +Everything in this pack is for the purpose of creating patterns. If you would like to evaluate rendered patterns for scannability, check out the companion project [Comfy QR Validation Nodes](https://gitlab.com/sofuego-comfy-nodes/comfy-qr-validation-nodes). Any workflow in the example that ends with "validated" assume the installation of the validation pack as well. + This repository is managed publicly on [Gitlab](https://gitlab.com/sofuego-comfy-nodes/comfy-qr), but also mirrored on [Github](https://github.com/coreyryanhanson/comfy-qr). Please submit any [issues](https://gitlab.com/sofuego-comfy-nodes/comfy-qr/-/issues) or [pull requests](https://gitlab.com/sofuego-comfy-nodes/comfy-qr/-/merge_requests) to the gitlab repo. -![QR code with repo link](img/badgers.png) +![QR code with repo link](img/badgers_levels_adjusted.png) ## Getting started @@ -71,6 +73,37 @@ A QR code fixed to specific output dimensions through image resampling. * `IMAGE` - The QR code * `QR_VERSION` - An integer of the QR version that was selected based on the text length and error correction level. +### QR Code (Split) + +A version of the `QR Code` node that also outputs split layers for the function patterns and a mask for the function patterns. + +#### Inputs + +* `protocol` - If enabled this will prefix the textbox input with a preset to represent the internet protocol. This is included both for convenience and as a workaround for the textbox clipping strings with this character combination. + * `Http` - Adds "http://" before the text. + * `Https` - Adds "https://" before the text. + * `None` - Uses only the contents of the `text` box. +* `text` - What text to build your QR code with. If `protocol` is specified, this textbox will be combined it with the selected option. +* `module_size` - The pixel width of the smallest unit of a QR code. +* `max_image_size` - The maximum size of the resulting QR code. If the combination of `text`, `module_size`, and `error_correction` create dimensions that exceed this, an error will halt the pipeline. +* `fill_hexcolor` - A string of characters representing the hex value of the QR units. Can be 3 or 6 hexadecimal characters with an optional # before. +* `back_hexcolor` - A string of characters representing the hex value of the space around the QR units. Can be 3 or 6 hexadecimal characters with an optional # before. +* `error_correction` - The level of error correction to apply. + * `Low` - 7% error correction. + * `Medium` - 15% error correction. + * `Quartile` - 25% error correction. + * `High` - 30% error correction. +* `border` - The border size (In multiples of `module` widths) + +#### Outputs + +* `QR_FLATTENED` - The QR code +* `MODULE_LAYER` - The QR code with the `back_hexcolor` filling in the function patterns (to remove their influence from the early diffusion steps). +* `FINDER_LAYER` - The isolated finder patterns over the `back_hexcolor`. +* `FINDER_MASK` - A mask that isolates the locations of the 3 finder patterns. +* `QR_VERSION` - An integer of the QR version that was selected based on the text length and error correction level. +* `IMAGE_SIZE` - An integer based on the pixel width of the resulting QR code. + ## Future updates -If the solution is clean enough, I plan on implementing a node that will automatically generate a mask to extract the 3 QR markers (based on `module_size`, `border`, and `QR_VERSION`) for more advanced workflows. \ No newline at end of file +If the solution is clean enough and if it can definitively improve scanability, there may be additional plans for the seperation of alignment patterns (based on `module_size`, `border`, and `QR_VERSION`) for more advanced workflows. diff --git a/examples/module-driven-control-net.json b/examples/module-driven-control-net.json index d050439..d2de4d4 100644 --- a/examples/module-driven-control-net.json +++ b/examples/module-driven-control-net.json @@ -127,10 +127,10 @@ 678, 604 ], - "size": [ - 315, - 106 - ], + "size": { + "0": 315, + "1": 106 + }, "flags": {}, "order": 5, "mode": 0, @@ -312,7 +312,7 @@ "Node name for S&R": "KSampler" }, "widgets_values": [ - 679629273700059, + 483918444996335, "randomize", 20, 8, @@ -321,6 +321,45 @@ 1 ] }, + { + "id": 8, + "type": "CLIPTextEncode", + "pos": [ + 656, + 351 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 3 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 23 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "worst quality" + ] + }, { "id": 14, "type": "comfy-qr-by-module-size", @@ -371,55 +410,16 @@ 16, 512, "#000000", - "#999999", + "#FFFFFF", "Medium", 1 ] }, - { - "id": 8, - "type": "CLIPTextEncode", - "pos": [ - 656, - 351 - ], - "size": { - "0": 400, - "1": 200 - }, - "flags": {}, - "order": 4, - "mode": 0, - "inputs": [ - { - "name": "clip", - "type": "CLIP", - "link": 3 - } - ], - "outputs": [ - { - "name": "CONDITIONING", - "type": "CONDITIONING", - "links": [ - 23 - ], - "shape": 3, - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "CLIPTextEncode" - }, - "widgets_values": [ - "worst quality" - ] - }, { "id": 17, "type": "ControlNetApplyAdvanced", "pos": [ - 808, + 804, 796 ], "size": { @@ -475,7 +475,7 @@ "Node name for S&R": "ControlNetApplyAdvanced" }, "widgets_values": [ - 2.49999999999999, + 1.6, 0, 1 ] diff --git a/examples/noisy-latent-split-controlnet-validated.json b/examples/noisy-latent-split-controlnet-validated.json new file mode 100644 index 0000000..2dde4cf --- /dev/null +++ b/examples/noisy-latent-split-controlnet-validated.json @@ -0,0 +1,2863 @@ +{ + "last_node_id": 69, + "last_link_id": 158, + "nodes": [ + { + "id": 13, + "type": "VAEDecode", + "pos": [ + 1272, + 671 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 63 + }, + { + "name": "vae", + "type": "VAE", + "link": 11 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 25, + 28 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 21, + "type": "ImagePadForOutpaint", + "pos": [ + 1227, + 790 + ], + "size": { + "0": 315, + "1": 174 + }, + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 25 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 26 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "ImagePadForOutpaint" + }, + "widgets_values": [ + 40, + 40, + 40, + 40, + 0 + ] + }, + { + "id": 19, + "type": "comfy-qr-read", + "pos": [ + 1243, + 1046 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 36, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 26 + } + ], + "outputs": [ + { + "name": "EXTRACTED_TEXT", + "type": "STRING", + "links": [ + 27 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "comfy-qr-read" + }, + "widgets_values": [ + "pyzbar" + ] + }, + { + "id": 47, + "type": "MaskToImage", + "pos": [ + -242, + 776 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 104 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 49, + "type": "MaskComposite", + "pos": [ + 25, + 841 + ], + "size": { + "0": 315, + "1": 126 + }, + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "MASK", + "link": 107 + }, + { + "name": "source", + "type": "MASK", + "link": 106 + }, + { + "name": "x", + "type": "INT", + "link": 117, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 121, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 124 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "MaskComposite" + }, + "widgets_values": [ + 48, + 48, + "add" + ] + }, + { + "id": 44, + "type": "ImageCompositeMasked", + "pos": [ + 29, + 663 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 146 + }, + { + "name": "source", + "type": "IMAGE", + "link": 127 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 115, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 120, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 123, + 132 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Finder Layer Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 8, + "type": "CLIPTextEncode", + "pos": [ + 372, + 47 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 3 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 23, + 34, + 88 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Negative Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "worst quality" + ] + }, + { + "id": 7, + "type": "CLIPTextEncode", + "pos": [ + 376, + -201 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 2 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 17, + 87 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Positive Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Hot lava" + ] + }, + { + "id": 39, + "type": "comfy-qr-by-module-split", + "pos": [ + -422, + 353 + ], + "size": [ + 400, + 344 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 155, + "widget": { + "name": "text", + "config": [ + "STRING", + { + "multiline": true + } + ] + } + }, + { + "name": "protocol", + "type": "Http,Https,None", + "link": 156, + "widget": { + "name": "protocol", + "config": [ + [ + "Http", + "Https", + "None" + ], + { + "default": "Https" + } + ] + } + } + ], + "outputs": [ + { + "name": "QR_FLATTENED", + "type": "IMAGE", + "links": [ + 102 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MODULE_LAYER", + "type": "IMAGE", + "links": [ + 126 + ], + "shape": 3, + "slot_index": 1 + }, + { + "name": "FINDER_LAYER", + "type": "IMAGE", + "links": [ + 127 + ], + "shape": 3, + "slot_index": 2 + }, + { + "name": "FINDER_MASK", + "type": "MASK", + "links": [ + 104, + 106 + ], + "shape": 3, + "slot_index": 3 + }, + { + "name": "QR_VERSION", + "type": "INT", + "links": null, + "shape": 3 + }, + { + "name": "IMAGE_SIZE", + "type": "INT", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "comfy-qr-by-module-split" + }, + "widgets_values": [ + "Https", + "gitlab.com/sofuego-comfy-nodes/comfy-qr", + 16, + 768, + "#000000", + "#FFFFFF", + "High", + 1 + ] + }, + { + "id": 54, + "type": "PrimitiveNode", + "pos": [ + -594, + 733 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 114, + 115, + 116, + 117 + ], + "slot_index": 0, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "X Offset", + "properties": {}, + "widgets_values": [ + 48, + "fixed" + ] + }, + { + "id": 55, + "type": "PrimitiveNode", + "pos": [ + -592, + 863 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 118, + 119, + 120, + 121 + ], + "slot_index": 0, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Y Offset", + "properties": {}, + "widgets_values": [ + 48, + "fixed" + ] + }, + { + "id": 29, + "type": "LatentCompositeMasked", + "pos": [ + 1234, + 432 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "LATENT", + "link": 57 + }, + { + "name": "source", + "type": "LATENT", + "link": 65 + }, + { + "name": "mask", + "type": "MASK", + "link": 124 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 64 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LatentCompositeMasked" + }, + "widgets_values": [ + 0, + 0 + ] + }, + { + "id": 18, + "type": "ControlNetLoader", + "pos": [ + 27, + 217 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 19, + 35, + 92 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ControlNetLoader" + }, + "widgets_values": [ + "control_v1p_sd15_qrcode_monster_v2.safetensors" + ] + }, + { + "id": 20, + "type": "comfy-qr-validate", + "pos": [ + 1581, + 685 + ], + "size": [ + 400, + 200 + ], + "flags": {}, + "order": 37, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 28 + }, + { + "name": "extracted_text", + "type": "STRING", + "link": 27 + }, + { + "name": "protocol", + "type": "Http,Https,None", + "link": 157, + "widget": { + "name": "protocol", + "config": [ + [ + "Http", + "Https", + "None" + ], + { + "default": "Https" + } + ] + } + }, + { + "name": "text", + "type": "STRING", + "link": 158, + "widget": { + "name": "text", + "config": [ + "STRING", + { + "multiline": true + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 130 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "VALIDATION_CODE", + "type": "INT", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "comfy-qr-validate" + }, + "widgets_values": [ + "Https", + "gitlab.com/sofuego-comfy-nodes/comfy-qr", + "False" + ] + }, + { + "id": 23, + "type": "ControlNetApplyAdvanced", + "pos": [ + 480, + 809 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 135 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 34 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 35 + }, + { + "name": "image", + "type": "IMAGE", + "link": 123 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 136 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 48 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (FG)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 3, + 0, + 1 + ] + }, + { + "id": 57, + "type": "CLIPTextEncode", + "pos": [ + 413, + 1033 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 134 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 135 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Finder Layer Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Yellow with black markings" + ] + }, + { + "id": 36, + "type": "VAEEncode", + "pos": [ + 522, + 689 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 132 + }, + { + "name": "vae", + "type": "VAE", + "link": 78 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 80 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "VAE Encode (FG)", + "properties": { + "Node name for S&R": "VAEEncode" + } + }, + { + "id": 63, + "type": "VAEEncode", + "pos": [ + 519, + 550 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 140 + }, + { + "name": "vae", + "type": "VAE", + "link": 141 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 139 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "VAE Encode (BG)", + "properties": { + "Node name for S&R": "VAEEncode" + } + }, + { + "id": 52, + "type": "PrimitiveNode", + "pos": [ + -591, + 991 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 3, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 110, + 112 + ], + "slot_index": 0, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Width", + "properties": {}, + "widgets_values": [ + 768, + "fixed" + ] + }, + { + "id": 53, + "type": "PrimitiveNode", + "pos": [ + -593, + 1130 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 4, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 111, + 113, + 144, + 145 + ], + "slot_index": 0, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Height", + "properties": {}, + "widgets_values": [ + 768, + "fixed" + ] + }, + { + "id": 64, + "type": "SolidMask", + "pos": [ + -344, + 1263 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 144, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 145, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 142 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (White)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 1, + 768, + 768 + ] + }, + { + "id": 40, + "type": "SolidMask", + "pos": [ + -347, + 949 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 110, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 111, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 100 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (Grey)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 0.5, + 768, + 768 + ] + }, + { + "id": 42, + "type": "ImageCompositeMasked", + "pos": [ + 30, + 322 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 153 + }, + { + "name": "source", + "type": "IMAGE", + "link": 102 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 116, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 118, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 125 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "QR Flattened Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 43, + "type": "ImageCompositeMasked", + "pos": [ + 42, + 491 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 154 + }, + { + "name": "source", + "type": "IMAGE", + "link": 126 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 114, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 119, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 122, + 140 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Module Layer Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 65, + "type": "MaskToImage", + "pos": [ + 32, + 1267 + ], + "size": { + "0": 195.12049865722656, + "1": 26 + }, + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 142 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 146 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (White)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 50, + "type": "SolidMask", + "pos": [ + -345, + 1106 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 112, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 113, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 107, + 151 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (Black)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 0, + 768, + 768 + ] + }, + { + "id": 67, + "type": "MaskToImage", + "pos": [ + 36, + 1144 + ], + "size": { + "0": 195.12049865722656, + "1": 26 + }, + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 151 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (Black)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 24, + "type": "KSamplerAdvanced", + "pos": [ + 878, + -37 + ], + "size": { + "0": 315, + "1": 546 + }, + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 40 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 89 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 38 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 139 + }, + { + "name": "end_at_step", + "type": "INT", + "link": 45, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 82, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 57 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (BG)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "enable", + 1004190433642169, + "randomize", + 25, + 8, + "euler_ancestral", + "normal", + 0, + 13, + "enable" + ] + }, + { + "id": 30, + "type": "KSamplerAdvanced", + "pos": [ + 1634, + 25 + ], + "size": { + "0": 315, + "1": 542 + }, + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 62 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 90 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 91 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 64 + }, + { + "name": "start_at_step", + "type": "INT", + "link": 58, + "widget": { + "name": "start_at_step", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 84, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 63 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (Combined)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "disable", + 399768739536783, + "randomize", + 25, + 8, + "euler_ancestral", + "normal", + 13, + 10000, + "disable" + ] + }, + { + "id": 37, + "type": "PrimitiveNode", + "pos": [ + 991, + -189 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 5, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 82, + 83, + 84 + ], + "slot_index": 0, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "title": "Steps", + "properties": {}, + "widgets_values": [ + 25, + "fixed" + ] + }, + { + "id": 17, + "type": "ControlNetApplyAdvanced", + "pos": [ + 471, + 294 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 17 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 23 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 19 + }, + { + "name": "image", + "type": "IMAGE", + "link": 122 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 89 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 38 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (BG)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 1.4000000000000001, + 0, + 1 + ] + }, + { + "id": 27, + "type": "KSamplerAdvanced", + "pos": [ + 872, + 571 + ], + "size": { + "0": 315, + "1": 546 + }, + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 46 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 136 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 48 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 80 + }, + { + "name": "end_at_step", + "type": "INT", + "link": 44, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 83, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 65 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (FG)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "enable", + 604210257117158, + "randomize", + 25, + 8, + "euler", + "normal", + 2, + 13, + "enable" + ] + }, + { + "id": 12, + "type": "SaveImage", + "pos": [ + 2032, + 646 + ], + "size": { + "0": 315, + "1": 270 + }, + "flags": {}, + "order": 38, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 130 + } + ], + "properties": {}, + "widgets_values": [ + "ComfyUI" + ] + }, + { + "id": 28, + "type": "PrimitiveNode", + "pos": [ + 1235, + -191 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 6, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 44, + 45, + 58 + ], + "slot_index": 0, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + } + ], + "title": "Seperation Step", + "properties": {}, + "widgets_values": [ + 13, + "fixed" + ] + }, + { + "id": 38, + "type": "ControlNetApplyAdvanced", + "pos": [ + 1235, + 204 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 87 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 88 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 92 + }, + { + "name": "image", + "type": "IMAGE", + "link": 125 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 90 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 91 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (Combined)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 1.5, + 0, + 1 + ] + }, + { + "id": 6, + "type": "CheckpointLoaderSimple", + "pos": [ + 24, + 53 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 7, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 40, + 46, + 62 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 2, + 3, + 134 + ], + "shape": 3, + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 11, + 78, + 141 + ], + "shape": 3, + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "1.5/v1-5-pruned-emaonly.safetensors" + ] + }, + { + "id": 41, + "type": "MaskToImage", + "pos": [ + -247, + 864 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 100 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 153, + 154 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (Grey)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 68, + "type": "PrimitiveNode", + "pos": [ + -422, + 208 + ], + "size": { + "0": 210, + "1": 76 + }, + "flags": {}, + "order": 8, + "mode": 0, + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 155, + 158 + ], + "slot_index": 0, + "widget": { + "name": "text", + "config": [ + "STRING", + { + "multiline": true + } + ] + } + } + ], + "title": "URL", + "properties": {}, + "widgets_values": [ + "gitlab.com/sofuego-comfy-nodes/comfy-qr" + ] + }, + { + "id": 69, + "type": "PrimitiveNode", + "pos": [ + -422, + 70 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 9, + "mode": 0, + "outputs": [ + { + "name": "COMBO", + "type": "Http,Https,None", + "links": [ + 156, + 157 + ], + "slot_index": 0, + "widget": { + "name": "protocol", + "config": [ + [ + "Http", + "Https", + "None" + ], + { + "default": "Https" + } + ] + } + } + ], + "title": "Protocol", + "properties": {}, + "widgets_values": [ + "Https", + "fixed" + ] + } + ], + "links": [ + [ + 2, + 6, + 1, + 7, + 0, + "CLIP" + ], + [ + 3, + 6, + 1, + 8, + 0, + "CLIP" + ], + [ + 11, + 6, + 2, + 13, + 1, + "VAE" + ], + [ + 17, + 7, + 0, + 17, + 0, + "CONDITIONING" + ], + [ + 19, + 18, + 0, + 17, + 2, + "CONTROL_NET" + ], + [ + 23, + 8, + 0, + 17, + 1, + "CONDITIONING" + ], + [ + 25, + 13, + 0, + 21, + 0, + "IMAGE" + ], + [ + 26, + 21, + 0, + 19, + 0, + "IMAGE" + ], + [ + 27, + 19, + 0, + 20, + 1, + "STRING" + ], + [ + 28, + 13, + 0, + 20, + 0, + "IMAGE" + ], + [ + 34, + 8, + 0, + 23, + 1, + "CONDITIONING" + ], + [ + 35, + 18, + 0, + 23, + 2, + "CONTROL_NET" + ], + [ + 38, + 17, + 1, + 24, + 2, + "CONDITIONING" + ], + [ + 40, + 6, + 0, + 24, + 0, + "MODEL" + ], + [ + 44, + 28, + 0, + 27, + 4, + "INT" + ], + [ + 45, + 28, + 0, + 24, + 4, + "INT" + ], + [ + 46, + 6, + 0, + 27, + 0, + "MODEL" + ], + [ + 48, + 23, + 1, + 27, + 2, + "CONDITIONING" + ], + [ + 57, + 24, + 0, + 29, + 0, + "LATENT" + ], + [ + 58, + 28, + 0, + 30, + 4, + "INT" + ], + [ + 62, + 6, + 0, + 30, + 0, + "MODEL" + ], + [ + 63, + 30, + 0, + 13, + 0, + "LATENT" + ], + [ + 64, + 29, + 0, + 30, + 3, + "LATENT" + ], + [ + 65, + 27, + 0, + 29, + 1, + "LATENT" + ], + [ + 78, + 6, + 2, + 36, + 1, + "VAE" + ], + [ + 80, + 36, + 0, + 27, + 3, + "LATENT" + ], + [ + 82, + 37, + 0, + 24, + 5, + "INT" + ], + [ + 83, + 37, + 0, + 27, + 5, + "INT" + ], + [ + 84, + 37, + 0, + 30, + 5, + "INT" + ], + [ + 87, + 7, + 0, + 38, + 0, + "CONDITIONING" + ], + [ + 88, + 8, + 0, + 38, + 1, + "CONDITIONING" + ], + [ + 89, + 17, + 0, + 24, + 1, + "CONDITIONING" + ], + [ + 90, + 38, + 0, + 30, + 1, + "CONDITIONING" + ], + [ + 91, + 38, + 1, + 30, + 2, + "CONDITIONING" + ], + [ + 92, + 18, + 0, + 38, + 2, + "CONTROL_NET" + ], + [ + 100, + 40, + 0, + 41, + 0, + "MASK" + ], + [ + 102, + 39, + 0, + 42, + 1, + "IMAGE" + ], + [ + 104, + 39, + 3, + 47, + 0, + "MASK" + ], + [ + 106, + 39, + 3, + 49, + 1, + "MASK" + ], + [ + 107, + 50, + 0, + 49, + 0, + "MASK" + ], + [ + 110, + 52, + 0, + 40, + 0, + "INT" + ], + [ + 111, + 53, + 0, + 40, + 1, + "INT" + ], + [ + 112, + 52, + 0, + 50, + 0, + "INT" + ], + [ + 113, + 53, + 0, + 50, + 1, + "INT" + ], + [ + 114, + 54, + 0, + 43, + 3, + "INT" + ], + [ + 115, + 54, + 0, + 44, + 3, + "INT" + ], + [ + 116, + 54, + 0, + 42, + 3, + "INT" + ], + [ + 117, + 54, + 0, + 49, + 2, + "INT" + ], + [ + 118, + 55, + 0, + 42, + 4, + "INT" + ], + [ + 119, + 55, + 0, + 43, + 4, + "INT" + ], + [ + 120, + 55, + 0, + 44, + 4, + "INT" + ], + [ + 121, + 55, + 0, + 49, + 3, + "INT" + ], + [ + 122, + 43, + 0, + 17, + 3, + "IMAGE" + ], + [ + 123, + 44, + 0, + 23, + 3, + "IMAGE" + ], + [ + 124, + 49, + 0, + 29, + 2, + "MASK" + ], + [ + 125, + 42, + 0, + 38, + 3, + "IMAGE" + ], + [ + 126, + 39, + 1, + 43, + 1, + "IMAGE" + ], + [ + 127, + 39, + 2, + 44, + 1, + "IMAGE" + ], + [ + 130, + 20, + 0, + 12, + 0, + "IMAGE" + ], + [ + 132, + 44, + 0, + 36, + 0, + "IMAGE" + ], + [ + 134, + 6, + 1, + 57, + 0, + "CLIP" + ], + [ + 135, + 57, + 0, + 23, + 0, + "CONDITIONING" + ], + [ + 136, + 23, + 0, + 27, + 1, + "CONDITIONING" + ], + [ + 139, + 63, + 0, + 24, + 3, + "LATENT" + ], + [ + 140, + 43, + 0, + 63, + 0, + "IMAGE" + ], + [ + 141, + 6, + 2, + 63, + 1, + "VAE" + ], + [ + 142, + 64, + 0, + 65, + 0, + "MASK" + ], + [ + 144, + 53, + 0, + 64, + 0, + "INT" + ], + [ + 145, + 53, + 0, + 64, + 1, + "INT" + ], + [ + 146, + 65, + 0, + 44, + 0, + "IMAGE" + ], + [ + 151, + 50, + 0, + 67, + 0, + "MASK" + ], + [ + 153, + 41, + 0, + 42, + 0, + "IMAGE" + ], + [ + 154, + 41, + 0, + 43, + 0, + "IMAGE" + ], + [ + 155, + 68, + 0, + 39, + 0, + "STRING" + ], + [ + 156, + 69, + 0, + 39, + 1, + "Http,Https,None" + ], + [ + 157, + 69, + 0, + 20, + 2, + "Http,Https,None" + ], + [ + 158, + 68, + 0, + 20, + 3, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": {}, + "version": 0.4 +} diff --git a/examples/noisy-latent-split-controlnet.json b/examples/noisy-latent-split-controlnet.json new file mode 100644 index 0000000..071f4c2 --- /dev/null +++ b/examples/noisy-latent-split-controlnet.json @@ -0,0 +1,2640 @@ +{ + "last_node_id": 69, + "last_link_id": 160, + "nodes": [ + { + "id": 47, + "type": "MaskToImage", + "pos": [ + -242, + 776 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 104 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 49, + "type": "MaskComposite", + "pos": [ + 25, + 841 + ], + "size": { + "0": 315, + "1": 126 + }, + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "MASK", + "link": 107 + }, + { + "name": "source", + "type": "MASK", + "link": 106 + }, + { + "name": "x", + "type": "INT", + "link": 117, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 121, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 124 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "MaskComposite" + }, + "widgets_values": [ + 48, + 48, + "add" + ] + }, + { + "id": 44, + "type": "ImageCompositeMasked", + "pos": [ + 29, + 663 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 146 + }, + { + "name": "source", + "type": "IMAGE", + "link": 127 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 115, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 120, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 123, + 132 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Finder Layer Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 8, + "type": "CLIPTextEncode", + "pos": [ + 372, + 47 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 3 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 23, + 34, + 88 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Negative Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "worst quality" + ] + }, + { + "id": 7, + "type": "CLIPTextEncode", + "pos": [ + 376, + -201 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 2 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 17, + 87 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Positive Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Hot lava" + ] + }, + { + "id": 39, + "type": "comfy-qr-by-module-split", + "pos": [ + -422, + 353 + ], + "size": [ + 400, + 344 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 155, + "widget": { + "name": "text", + "config": [ + "STRING", + { + "multiline": true + } + ] + } + }, + { + "name": "protocol", + "type": "Http,Https,None", + "link": 156, + "widget": { + "name": "protocol", + "config": [ + [ + "Http", + "Https", + "None" + ], + { + "default": "Https" + } + ] + } + } + ], + "outputs": [ + { + "name": "QR_FLATTENED", + "type": "IMAGE", + "links": [ + 102 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MODULE_LAYER", + "type": "IMAGE", + "links": [ + 126 + ], + "shape": 3, + "slot_index": 1 + }, + { + "name": "FINDER_LAYER", + "type": "IMAGE", + "links": [ + 127 + ], + "shape": 3, + "slot_index": 2 + }, + { + "name": "FINDER_MASK", + "type": "MASK", + "links": [ + 104, + 106 + ], + "shape": 3, + "slot_index": 3 + }, + { + "name": "QR_VERSION", + "type": "INT", + "links": null, + "shape": 3 + }, + { + "name": "IMAGE_SIZE", + "type": "INT", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "comfy-qr-by-module-split" + }, + "widgets_values": [ + "Https", + "gitlab.com/sofuego-comfy-nodes/comfy-qr", + 16, + 768, + "#000000", + "#FFFFFF", + "High", + 1 + ] + }, + { + "id": 54, + "type": "PrimitiveNode", + "pos": [ + -594, + 733 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 114, + 115, + 116, + 117 + ], + "slot_index": 0, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "X Offset", + "properties": {}, + "widgets_values": [ + 48, + "fixed" + ] + }, + { + "id": 55, + "type": "PrimitiveNode", + "pos": [ + -592, + 863 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 118, + 119, + 120, + 121 + ], + "slot_index": 0, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Y Offset", + "properties": {}, + "widgets_values": [ + 48, + "fixed" + ] + }, + { + "id": 29, + "type": "LatentCompositeMasked", + "pos": [ + 1234, + 432 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "LATENT", + "link": 57 + }, + { + "name": "source", + "type": "LATENT", + "link": 65 + }, + { + "name": "mask", + "type": "MASK", + "link": 124 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 64 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LatentCompositeMasked" + }, + "widgets_values": [ + 0, + 0 + ] + }, + { + "id": 18, + "type": "ControlNetLoader", + "pos": [ + 27, + 217 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 19, + 35, + 92 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ControlNetLoader" + }, + "widgets_values": [ + "control_v1p_sd15_qrcode_monster_v2.safetensors" + ] + }, + { + "id": 23, + "type": "ControlNetApplyAdvanced", + "pos": [ + 480, + 809 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 28, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 135 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 34 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 35 + }, + { + "name": "image", + "type": "IMAGE", + "link": 123 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 136 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 48 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (FG)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 3, + 0, + 1 + ] + }, + { + "id": 57, + "type": "CLIPTextEncode", + "pos": [ + 413, + 1033 + ], + "size": { + "0": 400, + "1": 200 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 134 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 135 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Finder Layer Prompt", + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Yellow with black markings" + ] + }, + { + "id": 36, + "type": "VAEEncode", + "pos": [ + 522, + 689 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 132 + }, + { + "name": "vae", + "type": "VAE", + "link": 78 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 80 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "VAE Encode (FG)", + "properties": { + "Node name for S&R": "VAEEncode" + } + }, + { + "id": 63, + "type": "VAEEncode", + "pos": [ + 519, + 550 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 27, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 140 + }, + { + "name": "vae", + "type": "VAE", + "link": 141 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 139 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "VAE Encode (BG)", + "properties": { + "Node name for S&R": "VAEEncode" + } + }, + { + "id": 52, + "type": "PrimitiveNode", + "pos": [ + -591, + 991 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 3, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 110, + 112 + ], + "slot_index": 0, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Width", + "properties": {}, + "widgets_values": [ + 768, + "fixed" + ] + }, + { + "id": 53, + "type": "PrimitiveNode", + "pos": [ + -593, + 1130 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 4, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 111, + 113, + 144, + 145 + ], + "slot_index": 0, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "title": "Height", + "properties": {}, + "widgets_values": [ + 768, + "fixed" + ] + }, + { + "id": 64, + "type": "SolidMask", + "pos": [ + -344, + 1263 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 144, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 145, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 142 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (White)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 1, + 768, + 768 + ] + }, + { + "id": 40, + "type": "SolidMask", + "pos": [ + -347, + 949 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 110, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 111, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 100 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (Grey)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 0.5, + 768, + 768 + ] + }, + { + "id": 42, + "type": "ImageCompositeMasked", + "pos": [ + 30, + 322 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 153 + }, + { + "name": "source", + "type": "IMAGE", + "link": 102 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 116, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 118, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 125 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "QR Flattened Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 43, + "type": "ImageCompositeMasked", + "pos": [ + 42, + 491 + ], + "size": { + "0": 315, + "1": 122 + }, + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "name": "destination", + "type": "IMAGE", + "link": 154 + }, + { + "name": "source", + "type": "IMAGE", + "link": 126 + }, + { + "name": "mask", + "type": "MASK", + "link": null + }, + { + "name": "x", + "type": "INT", + "link": 114, + "widget": { + "name": "x", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "y", + "type": "INT", + "link": 119, + "widget": { + "name": "y", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 122, + 140 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Module Layer Composite", + "properties": { + "Node name for S&R": "ImageCompositeMasked" + }, + "widgets_values": [ + 48, + 48 + ] + }, + { + "id": 65, + "type": "MaskToImage", + "pos": [ + 32, + 1267 + ], + "size": { + "0": 195.12049865722656, + "1": 26 + }, + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 142 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 146 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (White)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 50, + "type": "SolidMask", + "pos": [ + -345, + 1106 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "link": 112, + "widget": { + "name": "width", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + }, + { + "name": "height", + "type": "INT", + "link": 113, + "widget": { + "name": "height", + "config": [ + "INT", + { + "default": 512, + "min": 1, + "max": 8192, + "step": 1 + } + ] + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 107, + 151 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "SolidMask (Black)", + "properties": { + "Node name for S&R": "SolidMask" + }, + "widgets_values": [ + 0, + 768, + 768 + ] + }, + { + "id": 67, + "type": "MaskToImage", + "pos": [ + 36, + 1144 + ], + "size": { + "0": 195.12049865722656, + "1": 26 + }, + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 151 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (Black)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 24, + "type": "KSamplerAdvanced", + "pos": [ + 878, + -37 + ], + "size": { + "0": 315, + "1": 546 + }, + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 40 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 89 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 38 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 139 + }, + { + "name": "end_at_step", + "type": "INT", + "link": 45, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 82, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 57 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (BG)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "enable", + 414560518288903, + "randomize", + 25, + 8, + "euler_ancestral", + "normal", + 0, + 13, + "enable" + ] + }, + { + "id": 30, + "type": "KSamplerAdvanced", + "pos": [ + 1634, + 25 + ], + "size": { + "0": 315, + "1": 542 + }, + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 62 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 90 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 91 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 64 + }, + { + "name": "start_at_step", + "type": "INT", + "link": 58, + "widget": { + "name": "start_at_step", + "config": [ + "INT", + { + "default": 0, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 84, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 63 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (Combined)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "disable", + 447592191701148, + "randomize", + 25, + 8, + "euler_ancestral", + "normal", + 13, + 10000, + "disable" + ] + }, + { + "id": 37, + "type": "PrimitiveNode", + "pos": [ + 991, + -189 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 5, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 82, + 83, + 84 + ], + "slot_index": 0, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "title": "Steps", + "properties": {}, + "widgets_values": [ + 25, + "fixed" + ] + }, + { + "id": 17, + "type": "ControlNetApplyAdvanced", + "pos": [ + 471, + 294 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 26, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 17 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 23 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 19 + }, + { + "name": "image", + "type": "IMAGE", + "link": 122 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 89 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 38 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (BG)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 1.4000000000000001, + 0, + 1 + ] + }, + { + "id": 27, + "type": "KSamplerAdvanced", + "pos": [ + 872, + 571 + ], + "size": { + "0": 315, + "1": 546 + }, + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 46 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 136 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 48 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 80 + }, + { + "name": "end_at_step", + "type": "INT", + "link": 44, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + }, + { + "name": "steps", + "type": "INT", + "link": 83, + "widget": { + "name": "steps", + "config": [ + "INT", + { + "default": 20, + "min": 1, + "max": 10000 + } + ] + } + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 65 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "KSampler (FG)", + "properties": { + "Node name for S&R": "KSamplerAdvanced" + }, + "widgets_values": [ + "enable", + 502985537802905, + "randomize", + 25, + 8, + "euler", + "normal", + 2, + 13, + "enable" + ] + }, + { + "id": 28, + "type": "PrimitiveNode", + "pos": [ + 1235, + -191 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 6, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 44, + 45, + 58 + ], + "slot_index": 0, + "widget": { + "name": "end_at_step", + "config": [ + "INT", + { + "default": 10000, + "min": 0, + "max": 10000 + } + ] + } + } + ], + "title": "Seperation Step", + "properties": {}, + "widgets_values": [ + 13, + "fixed" + ] + }, + { + "id": 38, + "type": "ControlNetApplyAdvanced", + "pos": [ + 1235, + 204 + ], + "size": { + "0": 315, + "1": 166 + }, + "flags": {}, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 87 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 88 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 92 + }, + { + "name": "image", + "type": "IMAGE", + "link": 125 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 90 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 91 + ], + "shape": 3, + "slot_index": 1 + } + ], + "title": "ControlNet (Combined)", + "properties": { + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 1.5, + 0, + 1 + ] + }, + { + "id": 6, + "type": "CheckpointLoaderSimple", + "pos": [ + 24, + 53 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 7, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 40, + 46, + 62 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 2, + 3, + 134 + ], + "shape": 3, + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 11, + 78, + 141 + ], + "shape": 3, + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "1.5/v1-5-pruned-emaonly.safetensors" + ] + }, + { + "id": 41, + "type": "MaskToImage", + "pos": [ + -247, + 864 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 100 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 153, + 154 + ], + "shape": 3, + "slot_index": 0 + } + ], + "title": "Solid (Grey)", + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 68, + "type": "PrimitiveNode", + "pos": [ + -422, + 208 + ], + "size": { + "0": 210, + "1": 76 + }, + "flags": {}, + "order": 8, + "mode": 0, + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 155 + ], + "slot_index": 0, + "widget": { + "name": "text", + "config": [ + "STRING", + { + "multiline": true + } + ] + } + } + ], + "title": "URL", + "properties": {}, + "widgets_values": [ + "gitlab.com/sofuego-comfy-nodes/comfy-qr" + ] + }, + { + "id": 69, + "type": "PrimitiveNode", + "pos": [ + -422, + 70 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 9, + "mode": 0, + "outputs": [ + { + "name": "COMBO", + "type": "Http,Https,None", + "links": [ + 156 + ], + "slot_index": 0, + "widget": { + "name": "protocol", + "config": [ + [ + "Http", + "Https", + "None" + ], + { + "default": "Https" + } + ] + } + } + ], + "title": "Protocol", + "properties": {}, + "widgets_values": [ + "Https", + "fixed" + ] + }, + { + "id": 13, + "type": "VAEDecode", + "pos": [ + 1272, + 671 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 34, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 63 + }, + { + "name": "vae", + "type": "VAE", + "link": 11 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 159 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 12, + "type": "SaveImage", + "pos": [ + 1537, + 672 + ], + "size": { + "0": 315, + "1": 270 + }, + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 159 + } + ], + "properties": {}, + "widgets_values": [ + "ComfyUI" + ] + } + ], + "links": [ + [ + 2, + 6, + 1, + 7, + 0, + "CLIP" + ], + [ + 3, + 6, + 1, + 8, + 0, + "CLIP" + ], + [ + 11, + 6, + 2, + 13, + 1, + "VAE" + ], + [ + 17, + 7, + 0, + 17, + 0, + "CONDITIONING" + ], + [ + 19, + 18, + 0, + 17, + 2, + "CONTROL_NET" + ], + [ + 23, + 8, + 0, + 17, + 1, + "CONDITIONING" + ], + [ + 34, + 8, + 0, + 23, + 1, + "CONDITIONING" + ], + [ + 35, + 18, + 0, + 23, + 2, + "CONTROL_NET" + ], + [ + 38, + 17, + 1, + 24, + 2, + "CONDITIONING" + ], + [ + 40, + 6, + 0, + 24, + 0, + "MODEL" + ], + [ + 44, + 28, + 0, + 27, + 4, + "INT" + ], + [ + 45, + 28, + 0, + 24, + 4, + "INT" + ], + [ + 46, + 6, + 0, + 27, + 0, + "MODEL" + ], + [ + 48, + 23, + 1, + 27, + 2, + "CONDITIONING" + ], + [ + 57, + 24, + 0, + 29, + 0, + "LATENT" + ], + [ + 58, + 28, + 0, + 30, + 4, + "INT" + ], + [ + 62, + 6, + 0, + 30, + 0, + "MODEL" + ], + [ + 63, + 30, + 0, + 13, + 0, + "LATENT" + ], + [ + 64, + 29, + 0, + 30, + 3, + "LATENT" + ], + [ + 65, + 27, + 0, + 29, + 1, + "LATENT" + ], + [ + 78, + 6, + 2, + 36, + 1, + "VAE" + ], + [ + 80, + 36, + 0, + 27, + 3, + "LATENT" + ], + [ + 82, + 37, + 0, + 24, + 5, + "INT" + ], + [ + 83, + 37, + 0, + 27, + 5, + "INT" + ], + [ + 84, + 37, + 0, + 30, + 5, + "INT" + ], + [ + 87, + 7, + 0, + 38, + 0, + "CONDITIONING" + ], + [ + 88, + 8, + 0, + 38, + 1, + "CONDITIONING" + ], + [ + 89, + 17, + 0, + 24, + 1, + "CONDITIONING" + ], + [ + 90, + 38, + 0, + 30, + 1, + "CONDITIONING" + ], + [ + 91, + 38, + 1, + 30, + 2, + "CONDITIONING" + ], + [ + 92, + 18, + 0, + 38, + 2, + "CONTROL_NET" + ], + [ + 100, + 40, + 0, + 41, + 0, + "MASK" + ], + [ + 102, + 39, + 0, + 42, + 1, + "IMAGE" + ], + [ + 104, + 39, + 3, + 47, + 0, + "MASK" + ], + [ + 106, + 39, + 3, + 49, + 1, + "MASK" + ], + [ + 107, + 50, + 0, + 49, + 0, + "MASK" + ], + [ + 110, + 52, + 0, + 40, + 0, + "INT" + ], + [ + 111, + 53, + 0, + 40, + 1, + "INT" + ], + [ + 112, + 52, + 0, + 50, + 0, + "INT" + ], + [ + 113, + 53, + 0, + 50, + 1, + "INT" + ], + [ + 114, + 54, + 0, + 43, + 3, + "INT" + ], + [ + 115, + 54, + 0, + 44, + 3, + "INT" + ], + [ + 116, + 54, + 0, + 42, + 3, + "INT" + ], + [ + 117, + 54, + 0, + 49, + 2, + "INT" + ], + [ + 118, + 55, + 0, + 42, + 4, + "INT" + ], + [ + 119, + 55, + 0, + 43, + 4, + "INT" + ], + [ + 120, + 55, + 0, + 44, + 4, + "INT" + ], + [ + 121, + 55, + 0, + 49, + 3, + "INT" + ], + [ + 122, + 43, + 0, + 17, + 3, + "IMAGE" + ], + [ + 123, + 44, + 0, + 23, + 3, + "IMAGE" + ], + [ + 124, + 49, + 0, + 29, + 2, + "MASK" + ], + [ + 125, + 42, + 0, + 38, + 3, + "IMAGE" + ], + [ + 126, + 39, + 1, + 43, + 1, + "IMAGE" + ], + [ + 127, + 39, + 2, + 44, + 1, + "IMAGE" + ], + [ + 132, + 44, + 0, + 36, + 0, + "IMAGE" + ], + [ + 134, + 6, + 1, + 57, + 0, + "CLIP" + ], + [ + 135, + 57, + 0, + 23, + 0, + "CONDITIONING" + ], + [ + 136, + 23, + 0, + 27, + 1, + "CONDITIONING" + ], + [ + 139, + 63, + 0, + 24, + 3, + "LATENT" + ], + [ + 140, + 43, + 0, + 63, + 0, + "IMAGE" + ], + [ + 141, + 6, + 2, + 63, + 1, + "VAE" + ], + [ + 142, + 64, + 0, + 65, + 0, + "MASK" + ], + [ + 144, + 53, + 0, + 64, + 0, + "INT" + ], + [ + 145, + 53, + 0, + 64, + 1, + "INT" + ], + [ + 146, + 65, + 0, + 44, + 0, + "IMAGE" + ], + [ + 151, + 50, + 0, + 67, + 0, + "MASK" + ], + [ + 153, + 41, + 0, + 42, + 0, + "IMAGE" + ], + [ + 154, + 41, + 0, + 43, + 0, + "IMAGE" + ], + [ + 155, + 68, + 0, + 39, + 0, + "STRING" + ], + [ + 156, + 69, + 0, + 39, + 1, + "Http,Https,None" + ], + [ + 159, + 13, + 0, + 12, + 0, + "IMAGE" + ] + ], + "groups": [], + "config": {}, + "extra": {}, + "version": 0.4 +} diff --git a/img/badgers_levels_adjusted.png b/img/badgers_levels_adjusted.png new file mode 100644 index 0000000..0db4458 Binary files /dev/null and b/img/badgers_levels_adjusted.png differ diff --git a/qr_nodes.py b/qr_nodes.py index 3fd8b12..db1441d 100644 --- a/qr_nodes.py +++ b/qr_nodes.py @@ -7,6 +7,8 @@ import torch class QRBase: def __init__(self): self.text = "" + self.fill = None + self.back = None FUNCTION = "generate_qr" CATEGORY = "Comfy-QR" @@ -25,10 +27,10 @@ class QRBase: return torch.from_numpy(out_image).unsqueeze(0) def _make_qr(self, qr, fill_hexcolor, back_hexcolor): - fill_color = self._parse_hexcolor_string(fill_hexcolor, "fill_hexcolor") - back_color = self._parse_hexcolor_string(back_hexcolor, "back_hexcolor") + self.fill = self._parse_hexcolor_string(fill_hexcolor, "fill_hexcolor") + self.back = self._parse_hexcolor_string(back_hexcolor, "back_hexcolor") qr.make(fit=True) - return qr.make_image(fill_color=fill_color, back_color=back_color) + return qr.make_image(fill_color=self.fill, back_color=self.back) def _parse_hexcolor_string(self, s, parameter): if s.startswith("#"): @@ -171,13 +173,94 @@ class QRByModuleSize(QRBase): return (self._img_to_tensor(img), qr.version, img.pixel_size) +class QRByModuleSizeSplitFunctionPatterns(QRBase): + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "protocol": (["Http", "Https", "None"], {"default": "Https"}), + "text": ("STRING", {"multiline": True}), + "module_size": ("INT", {"default": 16, "min": 1, "max": 64, "step": 1}), + "max_image_size": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}), + "fill_hexcolor": ("STRING", {"multiline": False, "default": "#000000"}), + "back_hexcolor": ("STRING", {"multiline": False, "default": "#FFFFFF"}), + "error_correction": (["Low", "Medium", "Quartile", "High"], {"default": "High"}), + "border": ("INT", {"default": 1, "min": 0, "max": 100, "step": 1}), + }, + } + + RETURN_TYPES = ("IMAGE", "IMAGE", "IMAGE", "MASK", "INT", "INT") + RETURN_NAMES = ("QR_FLATTENED", "MODULE_LAYER", "FINDER_LAYER", "FINDER_MASK", "QR_VERSION", "IMAGE_SIZE") + + def _generate_finder_pattern_ranges(self, module_size, border_size): + outer = module_size * border_size + inner = 7 * module_size + outer + return [ + (outer, inner, outer, inner), + (outer, inner, -inner, -outer), + (-inner, -outer, outer, inner) + ] + + def _generate_finder_pattern_mask(self, pixel_size, module_size, border_size): + mask = np.zeros((pixel_size, pixel_size), dtype=bool) + for x_min, x_max, y_min, y_max in self._generate_finder_pattern_ranges(module_size, border_size): + mask[y_min:y_max, x_min:x_max] = True + return mask + + def _apply_fill_to_mask(self, img, mask): + array = np.array(img).copy() + indices = np.nonzero(mask) + array[indices[0], indices[1], :] = self.back + return Image.fromarray(array) + + def _mask_to_tensor(self, mask): + out_image = mask.astype(np.float32) + return torch.from_numpy(out_image) + + def generate_qr( + self, + protocol, + text, + module_size, + max_image_size, + fill_hexcolor, + back_hexcolor, + error_correction, + border + ): + self.update_text(protocol, text) + error_level = self._get_error_correction_constant(error_correction) + qr = qrcode.QRCode( + error_correction=error_level, + box_size=module_size, + border=border) + qr.add_data(self.text) + img = self._make_qr(qr, fill_hexcolor, back_hexcolor) + pixel_size = img.pixel_size + self._validate_qr_size(pixel_size, max_image_size) + mask = self._generate_finder_pattern_mask(pixel_size, module_size, border) + module_image = self._apply_fill_to_mask(img, mask) + function_image = self._apply_fill_to_mask(img, ~mask) + return ( + self._img_to_tensor(img), + self._img_to_tensor(module_image), + self._img_to_tensor(function_image), + self._mask_to_tensor(mask), + qr.version, + pixel_size, + ) + + NODE_CLASS_MAPPINGS = { "comfy-qr-by-module-size": QRByModuleSize, "comfy-qr-by-image-size": QRByImageSize, + "comfy-qr-by-module-split": QRByModuleSizeSplitFunctionPatterns, } NODE_DISPLAY_NAME_MAPPINGS = { "comfy-qr-by-module-size": "QR Code", "comfy-qr-by-image-size": "QR Code (Conformed to Image Size)", + "comfy-qr-by-module-split": "QR Code (Split)", }