├── .github └── workflows │ └── publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── pyproject.toml ├── resharpen.py └── samples ├── -0.5.jpg ├── 0.0.jpg └── 0.5.jpg /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to Comfy registry 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "pyproject.toml" 9 | 10 | jobs: 11 | publish-node: 12 | name: Publish Custom Node to registry 13 | runs-on: ubuntu-latest 14 | # Skip forked repository 15 | if: github.event.repository.fork == false 16 | steps: 17 | - name: Check out code 18 | uses: actions/checkout@v4 19 | - name: Publish Custom Node 20 | uses: Comfy-Org/publish-node-action@main 21 | with: 22 | personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Haoming 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ComfyUI ReSharpen 2 | This is an Extension for [ComfyUI](https://github.com/comfyanonymous/ComfyUI), which allows you to increase or decrease the amount of details generated during the Stable Diffusion pipeline. 3 | 4 | > **ie.** This is not just a postprocessing filter 5 | 6 | ## How to Use 7 | - Attach the **ReSharpen** node between `Empty Latent` and your `Sampler` node of choice 8 | - Adjust the **details** slider: 9 | - **Positive** values cause the images to be noisy 10 | - **Negative** values cause the images to be blurry 11 | 12 | > Values too large or small may cause the result to become distorted! 13 | 14 | ### Important: 15 | - `Ancestral` samplers *(**eg.** `Euler a`)* do **not** work. 16 | - The effect is "global," meaning if you want to disable it during other parts of the workflow *(**eg.** during `Hires. Fix`)*, you need to add another **ReSharpen** node and set the `details` to `0` again. 17 | 18 | ## Examples 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
Sharpness-0.50.00.5
Result
38 | 39 |
40 | 41 | - [How does it work?](https://github.com/Haoming02/sd-webui-resharpen/blob/main/README.md#how-does-it-work) 42 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | from .resharpen import ReSharpen, disable_resharpen 2 | from functools import wraps 3 | from typing import Callable 4 | import execution 5 | 6 | NODE_CLASS_MAPPINGS = {"Resharpen": ReSharpen} 7 | NODE_DISPLAY_NAME_MAPPINGS = {"Resharpen": "ReSharpen"} 8 | 9 | 10 | def find_node(prompt: dict) -> bool: 11 | """Find any ReSharpen Node""" 12 | 13 | return any(v.get("class_type") == "Resharpen" for v in prompt.values()) 14 | 15 | 16 | original_validate: Callable = execution.validate_prompt 17 | 18 | 19 | @wraps(original_validate) 20 | def hijack_validate(prompt: dict) -> Callable: 21 | 22 | if not find_node(prompt): 23 | disable_resharpen() 24 | 25 | return original_validate(prompt) 26 | 27 | 28 | execution.validate_prompt = hijack_validate 29 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "comfyui-resharpen" 3 | description = "Manipulate the details of generations" 4 | version = "1.1.1" 5 | license = { text = "MIT License" } 6 | dependencies = [] 7 | 8 | [project.urls] 9 | Repository = "https://github.com/Haoming02/comfyui-resharpen" 10 | 11 | [tool.comfy] 12 | PublisherId = "haoming02" 13 | DisplayName = "ReSharpen" 14 | Icon = "" 15 | -------------------------------------------------------------------------------- /resharpen.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | from typing import Callable 3 | import latent_preview 4 | import torch 5 | 6 | 7 | ORIGINAL_PREP: Callable = latent_preview.prepare_callback 8 | 9 | RESHARPEN_STRENGTH: float = 0.0 10 | LATENT_CACHE: torch.Tensor = None 11 | 12 | 13 | def disable_resharpen(): 14 | """Reset the ReSharpen Strength""" 15 | global RESHARPEN_STRENGTH 16 | RESHARPEN_STRENGTH = 0.0 17 | 18 | 19 | def hijack(PREP) -> Callable: 20 | 21 | @wraps(PREP) 22 | def prep_callback(*args, **kwargs): 23 | global LATENT_CACHE 24 | LATENT_CACHE = None 25 | 26 | original_callback: Callable = PREP(*args, **kwargs) 27 | if not RESHARPEN_STRENGTH: 28 | return original_callback 29 | 30 | print("[ReSharpen] Enabled~") 31 | 32 | @torch.inference_mode() 33 | @wraps(original_callback) 34 | def hijack_callback(step, x0, x, total_steps): 35 | if not RESHARPEN_STRENGTH: 36 | return original_callback(step, x0, x, total_steps) 37 | 38 | global LATENT_CACHE 39 | if LATENT_CACHE is not None: 40 | delta = x.detach().clone() - LATENT_CACHE 41 | x += delta * RESHARPEN_STRENGTH 42 | 43 | LATENT_CACHE = x.detach().clone() 44 | return original_callback(step, x0, x, total_steps) 45 | 46 | return hijack_callback 47 | 48 | return prep_callback 49 | 50 | 51 | latent_preview.prepare_callback = hijack(ORIGINAL_PREP) 52 | 53 | 54 | class ReSharpen: 55 | @classmethod 56 | def INPUT_TYPES(s): 57 | return { 58 | "required": { 59 | "latent": ("LATENT",), 60 | "details": ( 61 | "FLOAT", 62 | {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.1}, 63 | ), 64 | } 65 | } 66 | 67 | RETURN_TYPES = ("LATENT",) 68 | FUNCTION = "hook" 69 | CATEGORY = "latent" 70 | 71 | def hook(self, latent, details: float): 72 | 73 | global RESHARPEN_STRENGTH 74 | RESHARPEN_STRENGTH = details / -10.0 75 | 76 | return (latent,) 77 | -------------------------------------------------------------------------------- /samples/-0.5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Haoming02/comfyui-resharpen/4f29c1c853b77bc069a5e23d99df151ebd47a17d/samples/-0.5.jpg -------------------------------------------------------------------------------- /samples/0.0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Haoming02/comfyui-resharpen/4f29c1c853b77bc069a5e23d99df151ebd47a17d/samples/0.0.jpg -------------------------------------------------------------------------------- /samples/0.5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Haoming02/comfyui-resharpen/4f29c1c853b77bc069a5e23d99df151ebd47a17d/samples/0.5.jpg --------------------------------------------------------------------------------