gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
33.39k stars 2.52k forks source link

[HTML] how to load local image by html output #884

Closed Olvi73 closed 2 years ago

Olvi73 commented 2 years ago

Describe the bug

When I run the gradio code, it will running on local URL: http://127.0.0.1:7860/, in this way I can't use html code like this to load a image

    html = (
            "<div >"
            + "<img  src='./tmp/1.jpg 'alt='image One'>"
            + "</div>"
    )

or use absolute path

html = (
            "<div >"
            + "<img  src='file://F:\\tmp\\1.jpg 'alt='image One'>"
            + "</div>"
    )

Reproduction


import gradio as gr

title = "test"

def inference(text):
    html = (
            "<div >"
            "<img  src='./tmp/1.jpg 'alt='image One'>"
            + "</div>"
    )
    return html

gr.Interface(
    inference,
    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,
    allow_flagging="never",

).launch(enable_queue=True)

Screenshot

Logs

No response

System Info

gradio version:2.8.9
OS: win11
browser:Chrome 99.0.4844.82

Severity

annoyance

abidlabs commented 2 years ago

Hi @Olvi73 thanks for creating this issue! We are going to take a look at it soon

abidlabs commented 2 years ago

Hi @Olvi73, you can access relative files by adding the prefix file/ to the path.

So if the code to your Gradio app is in a file called app.py, and you have an image called lion.jpg in the same directory: ---- app.py ---- lion.jpg

Then the code in app.py would look like:

import gradio as gr

title = "test"

def inference(text):
    html = (
            "<div >"
            "<img  src='file/lion.jpg' alt='image One'>"
            + "</div>"
    )
    return html

gr.Interface(
    inference,
    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,
    allow_flagging="never",

).launch(enable_queue=True)

Note that for security reasons, any file that is included in your app must be in the same directory or in a child directory of app.py.

jamsnrihk commented 1 year ago

Can i add a logo picture near title text?

AbubakrChan commented 1 year ago
    gr.inputs.Textbox(placeholder="Enter sentence here..."),
    outputs=["html"],
    title=title,

SAME QUESTIONS

LET ME KNOW IF YOU FOUND ANY SOLUTION YET!

THANKS

AbubakrChan commented 1 year ago

Can i add a logo picture near title text?

.

tlabarta commented 7 months ago

Hello, this issue still seems to exist for me, I get a 403 forbidden error. According to your response @abidlabs, it should work if I add the "file/" prefix and if both files are in the same directory, which is the case in my project. Please help.

File structure: -directoryA --testfile.py -directoryA -app.py -Fraunhofer_HHI.png -README.md

Code:

with gr.Blocks(theme=theme, css=css, head=head_js) as demo:
    gr.HTML(value="<img src='file/Fraunhofer_HHI.png'>", elem_id="img_test")

if __name__ == "__main__":
    demo.launch()

Error Message from Firefox console:

GET
http://127.0.0.1:7860/file/Fraunhofer_HHI.png
[HTTP/1.1 403 Forbidden 3ms]
freddyaboulton commented 7 months ago

Hi @tlabarta this is an old thread which predates the file access rules of gradio 4.0. You need to specify the file paths you want to show with allowed_paths. This is the latest guide on this: https://www.gradio.app/guides/sharing-your-app#security-and-file-access

tlabarta commented 6 months ago

@freddyaboulton Thank you for your reply. Unfortunately, this has not solved my issue. File structure: -app.py -static --Fraunhofer_HHI.png

No matter if I try set_static_paths or allowed_paths.

with gr.Blocks(theme=theme, css=css, head=head_js) as demo:
    gr.set_static_paths(paths=["static/Fraunhofer_HHI.png"])
    gr.Markdown("<img src='static/Fraunhofer_HHI.png' alt='Fraunhofer HHI Logo' height='100' width='400'>")

if __name__ == "__main__":
    demo.launch(allowed_paths=["static/Fraunhofer_HHI.png"])

I get:

GET
http://127.0.0.1:7860/files/static/Fraunhofer_HHI.png
[HTTP/1.1 404 Not Found 1ms]
freddyaboulton commented 6 months ago

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

tlabarta commented 6 months ago

@freddyaboulton This worked now, thanks a lot!

thormtl commented 6 months ago

Hi @tlabarta this is an old thread which predates the file access rules of gradio 4.0. You need to specify the file paths you want to show with allowed_paths. This is the latest guide on this: https://www.gradio.app/guides/sharing-your-app#security-and-file-access

Thanks so much for this comment here. Literally saved me a lot of time and headache!

freddyaboulton commented 6 months ago

It's on my plate to make this process less confusing but glad this thread is useful in the meantime!

yyxx1997 commented 6 months ago

Thank you very much for answering my questions and it worked in my project. But currently, I still face a dilemma. I hope the gradio page can display my separately written markdown document. for example, the organization of project documents is as follows:

-rootpath --assets ---pic.png --app.py --readme.md

According to your opinion, the readme.md document must use the following methods to display pic.png on the webpage:<img src='/file=assets/pic.png'> However, this will result in images not being displayed when viewing readme.md documents separately. This is a dilemma. Is there any good way to solve it?

agn-7 commented 4 months ago

I have the same issue and none of the above answers worked!

I have a simple Gradio UI and need a header loading a local image which is next to the .py file. It can be loaded using the gr.Image() but since I want to apply some changes like its size I need gr.HTML() or gr.Markdown(). However. I have the same issue for loading the image locally!

import gradio as gr

def greet(name):
    return f"Hello {name}!"

image_path = "flytask_logo.png"

with gr.Blocks() as demo:
    html_header = f"""
    <div style="text-align: center;">
        <img src="{image_path}" alt="Header Image" width="200" height="100">
    </div>
    """
    gr.HTML(html_header)

    name_input = gr.Textbox(label="Enter your name:")
    submit_button = gr.Button("Submit")
    output = gr.Textbox(label="Greeting:")

    submit_button.click(fn=greet, inputs=name_input, outputs=output)

demo.launch()

I also tested with image_path = "file=flytask_logo.png" or image_path = "file/flytask_logo.png" or image_path = "/file=flytask_logo.png" without result!

songfeng commented 4 months ago

@freddyaboulton This worked now, thanks a lot!

Which version of gradio does this solution with? Thx

akudnaver commented 3 months ago

I had no luck so far adding an image to the gradio interface for my chatbot , with the below method.

Looking for a solution for this problem..

Path to the chatbot image in the Colab project directory

chatbot_image_path = "/content/chatbot_image.jpg"

Create a custom CSS string

custom_css = """ .input_box textarea { background-color: #f0f0f0; border: 1px solid #ccc; font-size: 16px; } .output_box { background-color: #e6f7ff; border: 1px solid #007bff; padding: 10px; font-size: 16px; color: #007bff; } .gr-button { background-color: #007bff; color: white; border-radius: 5px; } .chatbot-image { display: block; margin-left: auto; margin-right: auto; width: 564px; / Adjust the width as needed / height: 423x; / Maintain aspect ratio / border-radius: 50%; } """

Create Gradio interface

iface = gr.Interface( fn=chatbot_interface,

# inputs='text',
inputs=gr.Textbox(placeholder="Enter your query and get a response from the AI chatbot."),
outputs='text',
title="AI Chatbot",
# description="Enter your query and get a response from the AI chatbot.",
theme=gr.themes.Monochrome(),
css=custom_css,
description=f"""
<div style="text-align: center;">
    <img src='{chatbot_image_path}' class="chatbot-image">
</div>
"""

)

agn-7 commented 3 months ago

@akudnaver

The issue you have is related to the image path and one possible solution is using gr.set_static_paths() as follows:

gr.set_static_paths(paths=["static/images/"])
image_path = "static/images/logo.png"
gr.HTML(f"""<img src="/file={image_path}" width="100" height="100">""")

Note: you would need to create a /static folder within the root of your project.

For more details check this SO post out.

akudnaver commented 3 months ago

@agn-7 So instead of the gr.html method, I tried the gr.Markdown along with the suggestion from @freddyaboulton .

Your solution seems to work with 'gr.Markdown' method.

gr.Markdown("<img src='/file=/content/chatbot_image.jpg' alt='Chatbot Logo' height='100' width='400'>")

Thanks a lot @agn-7 , @freddyaboulton for your help.

anirbanbasu commented 2 months ago

@freddyaboulton

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

This works for me in the sense that I can request the URL: http://host:port/file=static_allowed_path_to_file but this does not render as an image (using the <img> tag in gr.HTML) when the static_allowed_path_to_file is actually an SVG. Instead, navigating to that URL (http://host:port/file=static_allowed_path_to_file) ends up downloading the correct file. Perhaps, the HTTP response headers from gradio are incorrect? Or, am I missing something?

snapfast commented 1 month ago

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

Not working anymore.

JSchmie commented 1 month ago

Hi @tlabarta , the route is /file={path} so <img src='/file=static/Fraunhofer_HHI.png'> should work

Not working anymore.

Is there a simple workaround I could try? It’s a bit frustrating that my app isn’t showing the right logo anymore. Thanks so much for any help!

snapfast commented 1 month ago

@JSchmie I did solve this, but it is little elaborate solution.

main.py

def load_css(): with open('styles.css', 'r') as file: css_content = file.read() return css_content

with gr.Blocks(css=load_css(), theme=theme) as demo: gr.Image("./images/main-logo.png", elem_classes="logo-image", interactive=False, container=False, show_share_button=False, show_download_button=False, show_fullscreen_button=False, show_label=False)


> styles.css
```css
.logo-image {
    height: 70px;
    position: absolute;
    left: 10px;
}
JSchmie commented 1 month ago

Hi @snapfast, thank you for your prompt response!

I tested the solution you provided, but I found a quicker workaround in my case. It appears that .svg images don't render properly for me, while .png images work flawlessly.

For instance, the following code doesn't display the image as expected:

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("<img src='/file=./logo.svg' alt='image One'>")

demo.launch()

However, switching to .png works without any issues:

import gradio as gr

with gr.Blocks() as demo:
    gr.HTML("<img src='/file=./logo.png' alt='image One'>")

demo.launch()

Additionally, I noticed that I don't need to set allowed_paths for this to work locally. It seems like this configuration becomes necessary only when deploying the app behind a reverse proxy, such as nginx.

@abidlabs, it would be extremely helpful if the documentation could include a brief guide on serving HTML resources, especially clarifying the behavior with different image formats and deployment scenarios.

Thanks a lot again for your help, and I just want to add that I really enjoy working with Gradio. It's an amazing tool!

abidlabs commented 1 month ago

Thanks @JSchmie for pointing that out. This has to do with how we serve svg files (for security reasons, we add a content disposition header which prevents it from being served inline). I'm looking into whether we can relax this for security reasons

0xfff010 commented 1 month ago

import base64

Function of image to string base64

def get_logo_base64(): with open("logo.png", "rb") as image_file: return "data:image/png;base64," + base64.b64encode(image_file.read()).decode('utf-8')

In front Gradio

logo_base64 = get_logo_base64() gr.HTML(f"

")

IMG_4737