Skip to content

Fix ImageEditor brush preview dead area on vertical images#12981

Open
MaxwellCalkin wants to merge 1 commit intogradio-app:mainfrom
MaxwellCalkin:fix/imageeditor-brush-preview-dead-area
Open

Fix ImageEditor brush preview dead area on vertical images#12981
MaxwellCalkin wants to merge 1 commit intogradio-app:mainfrom
MaxwellCalkin:fix/imageeditor-brush-preview-dead-area

Conversation

@MaxwellCalkin
Copy link

Summary

Fixes #12380

When a new image is loaded into the ImageEditor, the canvas dimensions change but the brush stroke/preview textures are not recreated. This causes a "dead area" where the real-time brush preview doesn't render — the user can draw (the stroke appears on mouse release) but cannot see the preview while drawing.

Root cause

BrushTool.set_tool() only reinitializes brush textures when the draw/erase mode changes or textures are not yet initialized. When an image is loaded and set_tool("draw") is called again (from ImageEditor.reset()), neither condition is true — the mode hasn't changed and textures are already initialized from the initial setup. So the textures keep their old dimensions (from the initial canvas size), and the preview_sprite only covers part of the image.

This is most visible with vertical (portrait) images because the canvas height increases significantly beyond the initial canvas size, leaving a large dead zone at the bottom of the image.

Fix

  • In BrushTool.set_tool(), add a dimension check: compare the current image_container.getLocalBounds() against the stored texture dimensions. If they differ, reinitialize the textures.
  • Also fix BrushTextures.reinitialize() to use getLocalBounds() instead of image_container.width/height, which includes the container's scale transform and would give incorrect comparisons.

Changes

  • js/imageeditor/shared/brush/brush.ts: Add dimensions_changed check in set_tool() to trigger texture reinitialization when canvas dimensions change.
  • js/imageeditor/shared/brush/brush-textures.ts: Fix reinitialize() to correctly compare local bounds dimensions instead of scale-affected container dimensions.

Test plan

  • Load a vertical (portrait) image into gr.ImageEditor
  • Select the brush tool and draw across the entire image
  • Verify the real-time brush preview is visible everywhere, including the bottom of the image
  • Verify that drawing on horizontal images still works correctly
  • Verify that switching between brush and eraser tools works correctly after loading an image
  • Verify undo/redo still works correctly

Reproduction script from the issue:

import gradio as gr
def buildImageEditorUI():
    inputImage = gr.Image(elem_classes=["mcww-hidden", "editor-input-image"])
    editor = gr.ImageEditor(type="pil", label="Editor", height="80vh",
        show_download_button=False, elem_classes=["helpers-editor"])
    with gr.Row():
        result = gr.Image(interactive=False, label="Result", height="220px", format="png")
    inputImage.change(
        fn=lambda x: x,
        inputs=[inputImage],
        outputs=[editor],
    )
    editor.change(
        fn=lambda x: x['composite'],
        inputs=[editor],
        outputs=[result],
    )
with gr.Blocks() as demo:
    buildImageEditorUI()
demo.launch()

When a new image is loaded into the ImageEditor, the canvas dimensions
change but the brush stroke/preview textures are not recreated. This
causes a 'dead area' where the real-time brush preview doesn't render,
because the preview sprite's texture is smaller than the actual image.

The bug is most visible with vertical (portrait) images, where the
canvas height increases significantly beyond the initial canvas size.
The bottom portion of the image becomes a dead zone where drawing still
works (visible on mouse release) but the real-time preview is clipped
to the old texture dimensions.

Fix: In BrushTool.set_tool(), detect when the image container's local
bounds differ from the stored texture dimensions and reinitialize the
textures. Also fix BrushTextures.reinitialize() to correctly compare
local bounds instead of the scale-affected container width/height.

Fixes gradio-app#12380
@iwr-redmond
Copy link

cc @pngwn

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: ImageEditor dead area in vertical images for brush real-time preview

2 participants