Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with using file_selector to upload an image file second time around. #2103

Closed
1 of 7 tasks
taupirho opened this issue Oct 20, 2024 · 10 comments · Fixed by #2280
Closed
1 of 7 tasks

Issue with using file_selector to upload an image file second time around. #2103

taupirho opened this issue Oct 20, 2024 · 10 comments · Fixed by #2280
Assignees
Labels
💬 Discussion Requires some discussion and decision 🖰 GUI Related to GUI 💥Malfunction Addresses an identified problem. 🟥 Priority: Critical Must be addressed as soon as possible 🔒 Staff only Can only be assigned to the Taipy R&D team

Comments

@taupirho
Copy link

taupirho commented Oct 20, 2024

What went wrong? 🤔

I use a file selecter control to allow the user to upload an image file. I also have a CLEAR button that clears the images. If I try and re-upload the same image after clicking CLEAR it doesn't work. I'm running this on a Jupyter Notebook. If I choose a different named image ile, second time around it loads OK

Expected Behavior

Would expect to be able to upload the same image twice in a row in between calls to CLEAR

Steps to Reproduce Issue

I added this function to your existing bg removal tool example

def clear_images(state):
"""
Clears the currently displayed images by setting original_image and fixed_image to None.
"""
state.original_image = None
state.fixed_image = None
state.fixed = False
state.image = None
state.path_upload = ""
print("Images cleared.")
notify(state, "info", "Images have been cleared.")

Then added a CLEAR button in the main GUI like this

               tgb.button(
                label="Clear Images",
                on_action=clear_images,
                active="{original_image is not None}",
            )

Now click Upload File button and choose an image. All works OK. Now click CLEAR button. Images are removed as expected. Now click File Upload button again and choose the same image file as before. Nothing happens

Code

from taipy.gui import Gui, notify, download
from PIL import Image
from io import BytesIO
import os
import taipy.gui.builder as tgb
import signal
from textwrap import dedent

path_upload = ""
original_image = None
image = None
fixed_image = None
fixed = False

def clear_images(state):
    """
    Clears the currently displayed images by setting `original_image` and `fixed_image` to None.
    """
    state.original_image = None
    state.fixed_image = None
    state.fixed = False
    state.image = None
    state.path_upload = None 
    print("Images cleared.")
    notify(state, "info", "Images have been cleared.")
    # Removed the problematic lines
    # state.original_image = Image.open(None)
    # reload()

def convert_webp_to_png(state):
    """
    Converts an image (WEBP, PNG, JPG) to PNG format.
    Updates the state.fixed_image with the converted image.
    """
    try:
        print(f"Converting image at path: {state.path_upload}")
        with Image.open(state.path_upload) as img:
            # Convert the image to PNG format
            buffer = BytesIO()
            img.convert("RGBA").save(buffer, format="PNG")
            buffer.seek(0)
            state.fixed_image = buffer.getvalue()
            state.fixed = True
            print("Image converted to PNG.")
            notify(state, "success", "Image converted to PNG successfully!")
    except Exception as e:
        print(f"Error in convert_webp_to_png: {e}")
        notify(state, "error", f"Error converting image: {e}")

def upload_image(state):
    """
    Handles image upload and prepares the state for displaying the image.
    Resets variables to ensure the new upload is recognized.
    """
    state.original_image = Image.open(state.path_upload)
    state.fixed = False
    print(f"Image successfully loaded from {state.path_upload}.")
    notify(state, "success", "Image uploaded successfully!")

def download_image(state):
    """
    Allows the user to download the converted PNG image.
    """
    if state.fixed_image:
        print("Initiating download of the converted image.")
        download(state, content=state.fixed_image, name="converted_image.png")

# Define common styles for a better look
common_styles = "text-align: center; width: 200px; min-height: 40px; margin: 5px 0; display: block;"

# Create the Taipy GUI layout
with tgb.Page() as page:
    tgb.toggle(theme=True)
    with tgb.layout("20 80", columns__mobile="1"):
        with tgb.part("sidebar"):
            tgb.text("### Converting **WEBP Image** to PNG", mode="md")
            with tgb.part("flex flex-col items-center"):

                tgb.file_selector(
                    "{path_upload}",
                    extensions=".webp", drop_message="Drop Image here",
                    label="Upload image",
                    on_action=upload_image,
                    style=common_styles
                )
                
                tgb.button(
                    label="Convert to PNG",
                    on_action=convert_webp_to_png,
                    active="{original_image is not None}",
                    style=common_styles
                )

                tgb.button(
                    label="Download PNG",
                    on_action=download_image,
                    active="{fixed_image is not None}",
                    style=common_styles
                )                

                tgb.button(
                    label="Clear Images",
                    on_action=clear_images,
                    active="{original_image is not None}",
                    style=common_styles
                )
                
        with tgb.part("container"):
            tgb.text("# Image **Converter**", mode="md")
            tgb.text(dedent("""
                         Upload a WEBP, JPG, or PNG image, then click the Convert button on the sidebar. When it's done, you can download the processed image from the sidebar.
                     """), mode="md",
            )
            with tgb.layout("1 1"):
                with tgb.part("card text-center", render="{path_upload is not None and os.path.isfile(path_upload)}"):
                    tgb.text("### Original WEBP Image", mode="md")
                    print(f"Rendering original image from: {path_upload}")
                    tgb.image("{path_upload}")  # Directly show the uploaded image from path
                with tgb.part("card text-center", render="{fixed_image is not None}"):
                    tgb.text("### Converted PNG Image", mode="md")
                    tgb.image("{fixed_image}")

if __name__ == "__main__":
    print("Starting the WebP to PNG Converter...")
    Gui(page=page).run(margin="0px", title="WebP to PNG Converter")
    print("WebP to PNG Converter has stopped.")

Runtime Environment

WSL2 Ubuntu for Window on a Jupyter notebook

Browsers

Chrome

Version of Taipy

3.1.1

Acceptance Criteria

  • A unit test reproducing the bug is added.
  • Any new code is covered by a unit tested.
  • Check code coverage is at least 90%.
  • The bug reporter validated the fix.
  • Related issue(s) in taipy-doc are created for documentation and Release Notes are updated.

Code of Conduct

  • I have checked the existing issues.
  • I am willing to work on this issue (optional)
@taupirho taupirho added the 💥Malfunction Addresses an identified problem. label Oct 20, 2024
@sravan1946
Copy link

could you provide the full code required to reproduce this issue

@taupirho
Copy link
Author

taupirho commented Oct 20, 2024

from taipy.gui import Gui, notify, download
from PIL import Image
from io import BytesIO
import os
import taipy.gui.builder as tgb
import signal
from textwrap import dedent

path_upload = ""
original_image = None
image = None
fixed_image = None
fixed = False

def clear_images(state):
    """
    Clears the currently displayed images by setting `original_image` and `fixed_image` to None.
    """
    state.original_image = None
    state.fixed_image = None
    state.fixed = False
    state.image = None
    state.path_upload = None 
    print("Images cleared.")
    notify(state, "info", "Images have been cleared.")
    # Removed the problematic lines
    # state.original_image = Image.open(None)
    # reload()

def convert_webp_to_png(state):
    """
    Converts an image (WEBP, PNG, JPG) to PNG format.
    Updates the state.fixed_image with the converted image.
    """
    try:
        print(f"Converting image at path: {state.path_upload}")
        with Image.open(state.path_upload) as img:
            # Convert the image to PNG format
            buffer = BytesIO()
            img.convert("RGBA").save(buffer, format="PNG")
            buffer.seek(0)
            state.fixed_image = buffer.getvalue()
            state.fixed = True
            print("Image converted to PNG.")
            notify(state, "success", "Image converted to PNG successfully!")
    except Exception as e:
        print(f"Error in convert_webp_to_png: {e}")
        notify(state, "error", f"Error converting image: {e}")

def upload_image(state):
    """
    Handles image upload and prepares the state for displaying the image.
    Resets variables to ensure the new upload is recognized.
    """
    state.original_image = Image.open(state.path_upload)
    state.fixed = False
    print(f"Image successfully loaded from {state.path_upload}.")
    notify(state, "success", "Image uploaded successfully!")

def download_image(state):
    """
    Allows the user to download the converted PNG image.
    """
    if state.fixed_image:
        print("Initiating download of the converted image.")
        download(state, content=state.fixed_image, name="converted_image.png")

# Define common styles for a better look
common_styles = "text-align: center; width: 200px; min-height: 40px; margin: 5px 0; display: block;"

# Create the Taipy GUI layout
with tgb.Page() as page:
    tgb.toggle(theme=True)
    with tgb.layout("20 80", columns__mobile="1"):
        with tgb.part("sidebar"):
            tgb.text("### Converting **WEBP Image** to PNG", mode="md")
            with tgb.part("flex flex-col items-center"):

                tgb.file_selector(
                    "{path_upload}",
                    extensions=".webp", drop_message="Drop Image here",
                    label="Upload image",
                    on_action=upload_image,
                    style=common_styles
                )
                
                tgb.button(
                    label="Convert to PNG",
                    on_action=convert_webp_to_png,
                    active="{original_image is not None}",
                    style=common_styles
                )

                tgb.button(
                    label="Download PNG",
                    on_action=download_image,
                    active="{fixed_image is not None}",
                    style=common_styles
                )                

                tgb.button(
                    label="Clear Images",
                    on_action=clear_images,
                    active="{original_image is not None}",
                    style=common_styles
                )
                
        with tgb.part("container"):
            tgb.text("# Image **Converter**", mode="md")
            tgb.text(dedent("""
                         Upload a WEBP, JPG, or PNG image, then click the Convert button on the sidebar. When it's done, you can download the processed image from the sidebar.
                     """), mode="md",
            )
            with tgb.layout("1 1"):
                with tgb.part("card text-center", render="{path_upload is not None and os.path.isfile(path_upload)}"):
                    tgb.text("### Original WEBP Image", mode="md")
                    print(f"Rendering original image from: {path_upload}")
                    tgb.image("{path_upload}")  # Directly show the uploaded image from path
                with tgb.part("card text-center", render="{fixed_image is not None}"):
                    tgb.text("### Converted PNG Image", mode="md")
                    tgb.image("{fixed_image}")

if __name__ == "__main__":
    print("Starting the WebP to PNG Converter...")
    Gui(page=page).run(margin="0px", title="WebP to PNG Converter")
    print("WebP to PNG Converter has stopped.")

@sravan1946
Copy link

please use codeblocks when sharing code

@taupirho
Copy link
Author

Can you use what I provided or do you want me to re-send

@sravan1946
Copy link

you can edit or re-send it as all the indentation and formatting is gone

@taupirho
Copy link
Author

taupirho commented Oct 20, 2024

from taipy.gui import Gui, notify, download
from PIL import Image
from io import BytesIO
import os
import taipy.gui.builder as tgb
import signal
from textwrap import dedent

path_upload = ""
original_image = None
image = None
fixed_image = None
fixed = False

def clear_images(state):
    """
    Clears the currently displayed images by setting `original_image` and `fixed_image` to None.
    """
    state.original_image = None
    state.fixed_image = None
    state.fixed = False
    state.image = None
    state.path_upload = None 
    print("Images cleared.")
    notify(state, "info", "Images have been cleared.")
    # Removed the problematic lines
    # state.original_image = Image.open(None)
    # reload()

def convert_webp_to_png(state):
    """
    Converts an image (WEBP, PNG, JPG) to PNG format.
    Updates the state.fixed_image with the converted image.
    """
    try:
        print(f"Converting image at path: {state.path_upload}")
        with Image.open(state.path_upload) as img:
            # Convert the image to PNG format
            buffer = BytesIO()
            img.convert("RGBA").save(buffer, format="PNG")
            buffer.seek(0)
            state.fixed_image = buffer.getvalue()
            state.fixed = True
            print("Image converted to PNG.")
            notify(state, "success", "Image converted to PNG successfully!")
    except Exception as e:
        print(f"Error in convert_webp_to_png: {e}")
        notify(state, "error", f"Error converting image: {e}")

def upload_image(state):
    """
    Handles image upload and prepares the state for displaying the image.
    Resets variables to ensure the new upload is recognized.
    """
    state.original_image = Image.open(state.path_upload)
    state.fixed = False
    print(f"Image successfully loaded from {state.path_upload}.")
    notify(state, "success", "Image uploaded successfully!")

def download_image(state):
    """
    Allows the user to download the converted PNG image.
    """
    if state.fixed_image:
        print("Initiating download of the converted image.")
        download(state, content=state.fixed_image, name="converted_image.png")

# Define common styles for a better look
common_styles = "text-align: center; width: 200px; min-height: 40px; margin: 5px 0; display: block;"

# Create the Taipy GUI layout
with tgb.Page() as page:
    tgb.toggle(theme=True)
    with tgb.layout("20 80", columns__mobile="1"):
        with tgb.part("sidebar"):
            tgb.text("### Converting **WEBP Image** to PNG", mode="md")
            with tgb.part("flex flex-col items-center"):

                tgb.file_selector(
                    "{path_upload}",
                    extensions=".webp", drop_message="Drop Image here",
                    label="Upload image",
                    on_action=upload_image,
                    style=common_styles
                )
                
                tgb.button(
                    label="Convert to PNG",
                    on_action=convert_webp_to_png,
                    active="{original_image is not None}",
                    style=common_styles
                )

                tgb.button(
                    label="Download PNG",
                    on_action=download_image,
                    active="{fixed_image is not None}",
                    style=common_styles
                )                

                tgb.button(
                    label="Clear Images",
                    on_action=clear_images,
                    active="{original_image is not None}",
                    style=common_styles
                )
                
        with tgb.part("container"):
            tgb.text("# Image **Converter**", mode="md")
            tgb.text(dedent("""
                         Upload a WEBP, JPG, or PNG image, then click the Convert button on the sidebar. When it's done, you can download the processed image from the sidebar.
                     """), mode="md",
            )
            with tgb.layout("1 1"):
                with tgb.part("card text-center", render="{path_upload is not None and os.path.isfile(path_upload)}"):
                    tgb.text("### Original WEBP Image", mode="md")
                    print(f"Rendering original image from: {path_upload}")
                    tgb.image("{path_upload}")  # Directly show the uploaded image from path
                with tgb.part("card text-center", render="{fixed_image is not None}"):
                    tgb.text("### Converted PNG Image", mode="md")
                    tgb.image("{fixed_image}")

if __name__ == "__main__":
    print("Starting the WebP to PNG Converter...")
    Gui(page=page).run(margin="0px", title="WebP to PNG Converter")
    print("WebP to PNG Converter has stopped.")

@taupirho
Copy link
Author

taupirho commented Oct 20, 2024 via email

@taupirho
Copy link
Author

taupirho commented Oct 21, 2024 via email

@jrobinAV jrobinAV added 🖰 GUI Related to GUI 🟨 Priority: Medium Not blocking but should be addressed 🔒 Staff only Can only be assigned to the Taipy R&D team 💬 Discussion Requires some discussion and decision labels Oct 25, 2024
@FlorianJacta
Copy link
Member

Hi @taupirho, we are looking through your issue. I have reproduced it like this:

from taipy.gui import Gui, notify
from PIL import Image
import taipy.gui.builder as tgb

path_upload = ""
original_image = None
image = None
fixed_image = None
fixed = False


def clear_images(state):
    """
    Clears the currently displayed images by setting `original_image` and `fixed_image` to None.
    """
    state.original_image = None
    state.fixed_image = None
    state.fixed = False
    state.image = None
    state.path_upload = ""
    print("Images cleared.")
    notify(state, "info", "Images have been cleared.")


def upload_image(state):
    """
    Handles image upload and prepares the state for displaying the image.
    Resets variables to ensure the new upload is recognized.
    """
    state.original_image = Image.open(state.path_upload)
    state.fixed = False
    print(f"Image successfully loaded from {state.path_upload}.")
    notify(state, "success", "Image uploaded successfully!")


# Create the Taipy GUI layout
with tgb.Page() as page:
    tgb.text(
        lambda original_image: f"Is there an image? " + str(original_image is not None)
    )
    tgb.file_selector(
        "{path_upload}",
        extensions=".webp",
        drop_message="Drop Image here",
        label="Upload image",
        on_action=upload_image,
    )

    tgb.button(
        label="Clear Images",
        on_action=clear_images,
        active="{original_image is not None}",
    )


if __name__ == "__main__":
    Gui(page=page).run(margin="0px", title="WebP to PNG Converter")

There seems to be a proper issue here.

  • Uploading then Clearing and reuploading does not work. This only happens if the same file is uploaded.
C:\Users\jacta\.conda\envs\4.0\Lib\site-packages\taipy\gui\utils\_attributes.py:58: ResourceWarning: unclosed file <_io.BufferedReader name='C:\\Users\\jacta\\AppData\\Local\\Temp\\DALLE_2024-06-18_14.09.50_-_A_minimalist_illustration_showcasing_the_concept_of_long-running_callbacks_in_a_web_application._The_image_should_depict_a_web_browser_window_with_a_r.2.webp'>
  setattr(obj, var_name_split[-1], value)

@FlorianJacta FlorianJacta added 🟧 Priority: High Must be addressed as soon and removed 🟨 Priority: Medium Not blocking but should be addressed labels Nov 14, 2024
@FlorianJacta
Copy link
Member

We encountered this issue with a client

@FlorianJacta FlorianJacta removed their assignment Nov 22, 2024
@jrobinAV jrobinAV added 🟥 Priority: Critical Must be addressed as soon as possible and removed 🟧 Priority: High Must be addressed as soon labels Nov 22, 2024
@FredLL-Avaiga FredLL-Avaiga self-assigned this Nov 25, 2024
FredLL-Avaiga pushed a commit that referenced this issue Nov 25, 2024
disable number input arrows
resolves #2103
FredLL-Avaiga pushed a commit that referenced this issue Nov 25, 2024
FredLL-Avaiga added a commit that referenced this issue Nov 26, 2024
* reset file selector input after upload
disable number input arrows
resolves #2103

* lint

---------

Co-authored-by: Fred Lefévère-Laoide <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💬 Discussion Requires some discussion and decision 🖰 GUI Related to GUI 💥Malfunction Addresses an identified problem. 🟥 Priority: Critical Must be addressed as soon as possible 🔒 Staff only Can only be assigned to the Taipy R&D team
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants