Skip to content

Conversation

@brucew4yn3rp
Copy link
Collaborator

@brucew4yn3rp brucew4yn3rp commented Jul 6, 2025

@trsommer

Revamped the MaskEditor UI and changed it to an Image Canvas. The context menu name has also been renamed accordingly.

Cleaner PR of 2921

The interface now supports drawing on the image itself (on the image layer) in addition to covering the area with a mask. Users can select a color or use an eyedropper tool for color matching. This is a powerful tool to guide the image generation process post-masking (e.g., inpainting). Speaking with ComfyUI users for months, this has been highly desired addition.

The tools on the left sidebar have been updated accordingly. The top one, is the existing mask brush, and has a matching mask logo. The second one is the image painting brush.

image

image

Some relevant context from the old PR

I need a way to only erase the drawing or the mask part. The easiest solution would be to make the layer clickable to select which layer to work on.

Layer buttons have been implemented. Also, right click will only apply to erasing whichever tool is activated. Additionally, the eraser tool will only erase on the active layer. Selecting the mask tool automatically activates the mask layer, and selecting the Paint tool automatically activates the Paint layer.

Thank you very much for your help in getting this over the line @duckcomfy. I had some issues with the prior PR so decided to close it and initiate a new, cleaner PR.

@brucew4yn3rp brucew4yn3rp marked this pull request as ready for review July 6, 2025 00:54
@brucew4yn3rp brucew4yn3rp requested review from a team and trsommer as code owners July 6, 2025 00:54
@brucew4yn3rp
Copy link
Collaborator Author

@christian-byrne @webfiltered Tagging you in case you have a chance to take a look.

@brucew4yn3rp brucew4yn3rp changed the title Changed MaskEditor to an Image Canvas [Feature] Changed MaskEditor to an Image Canvas Jul 7, 2025
@brucew4yn3rp brucew4yn3rp changed the title [Feature] Changed MaskEditor to an Image Canvas [Feature] Enhanced MaskEditor to an Image Canvas Jul 7, 2025
Copy link
Collaborator

@trsommer trsommer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried it. There seems to be a problem where the resulting layers are still split into 2 images in the load image preview. I tried it in both chrome and firefox and just painting on the canvas with the paint tool results in 2 images in the load image node
image
image

after reloading, it seems to be combined:
image

If you run the workflow, the correct image seems to be handed over. The core process seems to work, just the previews in the load image node are wrong

UI fixes, not that important:
when the user selects the mask or paint tool, auto select the mask or image layer. It does not make sense for the user paint/mask without a selected layer

@brucew4yn3rp
Copy link
Collaborator Author

Thanks @trsommer. I think with the current infrastructure across the frontend, for the user to be able to edit the painting after closing out and re-opening the interface, the node has to have the images separate.

@duckcomfy Changing the rendering of the LoadImage node doesn't seem to work well. Let me know if you have any other ideas.

@duckcomfy
Copy link
Contributor

duckcomfy commented Jul 7, 2025

Thank you for your quick review @trsommer.
@brucew4yn3rp Please note, if it helps understanding the issue at hand, that when refreshing the page, although the correct preview is displayed, the paint layer is no longer editable.
I'm going to have a look and try to understand how the Load Image node knows what to preview, how the Mask Editor loads the different layers, and why the Load Image node contents are different when refreshing the page. If you have any insight to share on these topics please do.

@brucew4yn3rp
Copy link
Collaborator Author

@duckcomfy As it stands, in app.ts, we are pushing RGBCanvas and CombinedCanvas to node.imgs. This is important because (if I remember correctly) when the MaskEditor is initialized, it accesses its images and adds the relevant painted pixels to the paint layer. That functionality is, as far as I can see with the current infrastructure, the only way to allow for continued editing. We cannot leverage the mask’s logic because it would not work across all RGB colors.

It is interesting that upon refresh of the page, the node defaults to the combined, flattened image. My guess is that it is displaying the last saved image in the input/clipspace folder.

I’m happy to discuss on Discord for easier communication if you’d like (@batman.76)

@asagi4
Copy link

asagi4 commented Jul 7, 2025

I gave this a quick try as well. Seems to work well enough and definitely solves a pain point with ComfyUI.

I did find a bug: the brush shape seems to be stuck to circular. If I select the rectangular brush, it'll show a rectangular outline but still make circular marks.

brucew4yn3rp and others added 3 commits July 8, 2025 07:04
Also comes with a refactor of the associated code to be more DRY and maintainable.

In order to explain the new UX let me first explain what I'll call the different tools, as the names we previously used are now ambiguous.

- "Mask Pen": Previously named "Pen" internally, this is an existing tool lets you paint a mask on the image.
- "Paint Pen": New tool which lets you paint colored pixels on the image.
- "Eraser": Exising tool which lets you erase parts of your mask. As of @brucew4yn3rp's PR, you can also erase parts of your painted pixels, depending on which layer is active.
- "Mask Bucket": Previously named "Paint Bucket" internally, this is an existing tool which lets you take a mask that's just an outline, and fill in the inside of your mask outline with a full masked area. Equivalent functionality for the Paint layer is NOT implemented.
- "Mask Color Fill": Previously named "Color Select" internally, this is an existing tool which can turn pixels into a masked area, based on color similarity in contiguous pixels on the base image. Equivalent functionality for the Paint layer is NOT implemented.

New UX:

- The "Mask" layer is now selected when you open the Mask Editor, instead of no layer selected.
- Selecting the "Mask Pen", "Mask Bucket", or "Mask Color Fill" tool automatically selects the Mask layer.
- Selecting the "Paint Pen" tool automatically selects the Paint layer.
- Selecting the "Mask" layer while the "Paint Pen" tool is selected automatically selects the "Mask Pen" tool.
- Selecting the "Paint" layer while the "Mask Pen", "Mask Bucket", or "Mask Color Fill" tool is selected automatically selects the "Paint Pen" tool.
- Changing the selected layer while the "Eraser" tool is selected has no additional effect, because Eraser supports both layers.
- Switching to the "Eraser" tool has no additional effect, because Eraser supports both layers.
duckcomfy and others added 5 commits July 13, 2025 09:27
…e their url from the main image url, which also ensures the layers can be opened even if the page is refreshed
refactor: address review items on main Image Editor PR
@brucew4yn3rp brucew4yn3rp requested a review from a team as a code owner July 13, 2025 13:45
@brucew4yn3rp brucew4yn3rp requested a review from webfiltered July 13, 2025 13:45
duckcomfy and others added 2 commits July 13, 2025 15:58
@brucew4yn3rp
Copy link
Collaborator Author

Hi @webfiltered, thanks for the attentiveness on this - I know there's lots going on.

All of your comments have been addressed in the latest commits. We discussed offline a way to circumvent the need to store images within the node. Therefore, we no longer need the data-nopreview workaround either.

Originally, I had implemented the storing of images in node.imgs as it was the only way I'd found to be able to persist which correct files to reference for each layer upon closing and re-opening of the canvas.

Now, the timestamp has been unified across all the related files, allowing us to derive the names of each layer's saved file from the final filename that gets saved to the node/workflow. As a byproduct, this allows editability to persist through refreshes because deriving the filenames is static (as opposed to node.imgs which did not persist through app refresh),

This seems to work well, and without the additional clog in retaining images within the node, which you mentioned may be a strain for future maintainability. To that end, @duckcomfy has also added a maskeditor.test.ts file that will assist in ensuring the new functionality does not break in the future.

Copy link

@PabloWiedemann PabloWiedemann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@comfy-pr-bot comfy-pr-bot requested a review from snomiao July 16, 2025 04:52
@kevinpaik1
Copy link

@brucew4yn3rp once your PR gets merged, would you please write into me at bounty@comfy.org? i'd love to compensate you as a thank you for your significant effort here!

@webfiltered webfiltered merged commit 83aa887 into Comfy-Org:main Jul 24, 2025
10 of 11 checks passed
@christian-byrne christian-byrne mentioned this pull request Jul 24, 2025
@kevinpaik1
Copy link

Hi @trsommer — we’d like to propose adding @brucew4yn3rp as a CODEOWNER for the MaskEditor component, based on:

  1. The recent refactoring work in this PR
  2. He’s expressed interest in helping review future contributions in this area

@christian-byrne mentioned you're currently listed as the CODEOWNER here, so I wanted to check with you. Would you be open to adding @brucew4yn3rp alongside you? Thanks in advance for considering!

@avc
Copy link

avc commented Aug 29, 2025

I found a bug I think may be related to this implementation #5251. The mask editor is now anti-aliasing even at max hardness, making fills not fill completely and cleanly.

@silveroxides
Copy link
Contributor

@brucew4yn3rp You did not notice how this completely broke the right side tool configuration menu for now 2 months? It is supposed to change when selecting the color select tool with the dropper icon to the left. Code is still there, just that this was so sloppily implemented and completely lacked quality control and even the mere basic manual testing.

@trsommer
Copy link
Collaborator

@brucew4yn3rp You did not notice how this completely broke the right side tool configuration menu for now 2 months? It is supposed to change when selecting the color select tool with the dropper icon to the left. Code is still there, just that this was so sloppily implemented and completely lacked quality control and even the mere basic manual testing.

I have fixed paint bucket and color select tool settings not showing up in #5733 , I think that was the issue you were talking about. I have no idea why @brucew4yn3rp removed this. I did not notice because I only tested the new features implemented

@silveroxides
Copy link
Contributor

@trsommer
Thank you. This was most likely an oversight and the lack of manual testing led to it not being detected.
I don't know how much @brucew4yn3rp actually uses the mask editor himself when using ComfyUI but I would expect that if someone is set as codeowner for a feature, then they ought to be dogfooding said feature.

@brucew4yn3rp
Copy link
Collaborator Author

Thank you @trsommer for the quick fix. That was indeed an oversight during the UI redesign. The PR went through multiple iterations covering both new functionalities and the UI (including the sidebar), so given the scope it’s unfortunate but not surprising that this slipped through during the rebuild. Again, given the scope and difficulty of implementing the new functions, I was also admittedly focused on making sure the new features worked well and missed the regression which probably happened early on.

just that this was so sloppily implemented and completely lacked quality control and even the mere basic manual testing.

@silveroxides, instead of assuming “sloppy implementation” or lack of testing, it would be more constructive to check the PR history, which clearly shows extensive review and collaboration over several months. In a refactor of this size, oversights are inevitable, which is why collaboration exists. If you run into issues in the future, the most helpful approach is to either open an issue or submit a PR. And if you remain convinced this reflects “sloppy” work, you’re always free to continue using the old mask editor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Design Used to request Product feedback on design decisions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants