Add show_download_button to gr.Image() (#4959)

* add show_download_button param

* add static image story

* chlog

* fix test

* typo

* add default value

Co-authored-by: Abubakar Abid <abubakar@huggingface.co>

* fix test

* fix another test

---------

Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
Hannah 2023-07-19 19:00:02 +01:00 committed by GitHub
parent fdc9ca2ddf
commit a0efc1180d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 77 additions and 11 deletions

View File

@ -4,7 +4,7 @@ No changes to highlight.
## New Features: ## New Features:
No changes to highlight. - Add `show_download_button` param to allow the download button in static Image components to be hidden by [@hannahblair](https://github.com/hannahblair) in [PR 4959](https://github.com/gradio-app/gradio/pull/4959)
## Bug Fixes: ## Bug Fixes:

View File

@ -70,6 +70,7 @@ class Image(
label: str | None = None, label: str | None = None,
every: float | None = None, every: float | None = None,
show_label: bool | None = None, show_label: bool | None = None,
show_download_button: bool = True,
container: bool = True, container: bool = True,
scale: int | None = None, scale: int | None = None,
min_width: int = 160, min_width: int = 160,
@ -97,6 +98,7 @@ class Image(
label: component name in interface. label: component name in interface.
every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute. every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
show_label: if True, will display label. show_label: if True, will display label.
show_download_button: If True, will display button to download image.
container: If True, will place the component in a container - providing some extra padding around the border. container: If True, will place the component in a container - providing some extra padding around the border.
scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer. scale: relative width compared to adjacent Components in a Row. For example, if Component A has scale=2, and Component B has scale=1, A will be twice as wide as B. Should be an integer.
min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first. min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
@ -133,6 +135,7 @@ class Image(
self.tool = tool self.tool = tool
self.invert_colors = invert_colors self.invert_colors = invert_colors
self.streaming = streaming self.streaming = streaming
self.show_download_button = show_download_button
if streaming and source != "webcam": if streaming and source != "webcam":
raise ValueError("Image streaming only available if source is 'webcam'.") raise ValueError("Image streaming only available if source is 'webcam'.")
self.select: EventListenerMethod self.select: EventListenerMethod
@ -177,6 +180,7 @@ class Image(
"brush_radius": self.brush_radius, "brush_radius": self.brush_radius,
"selectable": self.selectable, "selectable": self.selectable,
"show_share_button": self.show_share_button, "show_share_button": self.show_share_button,
"show_download_button": self.show_download_button,
**IOComponent.get_config(self), **IOComponent.get_config(self),
} }
@ -187,6 +191,7 @@ class Image(
width: int | None = None, width: int | None = None,
label: str | None = None, label: str | None = None,
show_label: bool | None = None, show_label: bool | None = None,
show_download_button: bool | None = None,
container: bool | None = None, container: bool | None = None,
scale: int | None = None, scale: int | None = None,
min_width: int | None = None, min_width: int | None = None,
@ -200,6 +205,7 @@ class Image(
"width": width, "width": width,
"label": label, "label": label,
"show_label": show_label, "show_label": show_label,
"show_download_button": show_download_button,
"container": container, "container": container,
"scale": scale, "scale": scale,
"min_width": min_width, "min_width": min_width,

View File

@ -64,6 +64,7 @@ XRAY_CONFIG = {
"min_width": 160, "min_width": 160,
"name": "image", "name": "image",
"show_share_button": False, "show_share_button": False,
"show_download_button": True,
"visible": True, "visible": True,
}, },
"serializer": "ImgSerializable", "serializer": "ImgSerializable",
@ -136,6 +137,7 @@ XRAY_CONFIG = {
"min_width": 160, "min_width": 160,
"name": "image", "name": "image",
"show_share_button": False, "show_share_button": False,
"show_download_button": True,
"visible": True, "visible": True,
}, },
"serializer": "ImgSerializable", "serializer": "ImgSerializable",
@ -382,6 +384,7 @@ XRAY_CONFIG_DIFF_IDS = {
"min_width": 160, "min_width": 160,
"name": "image", "name": "image",
"show_share_button": False, "show_share_button": False,
"show_download_button": True,
"visible": True, "visible": True,
}, },
"serializer": "ImgSerializable", "serializer": "ImgSerializable",
@ -454,6 +457,7 @@ XRAY_CONFIG_DIFF_IDS = {
"min_width": 160, "min_width": 160,
"name": "image", "name": "image",
"show_share_button": False, "show_share_button": False,
"show_download_button": True,
"visible": True, "visible": True,
}, },
"serializer": "ImgSerializable", "serializer": "ImgSerializable",

View File

@ -9,14 +9,15 @@
import type { LoadingStatus } from "../StatusTracker/types"; import type { LoadingStatus } from "../StatusTracker/types";
import UploadText from "../UploadText.svelte"; import UploadText from "../UploadText.svelte";
export let elem_id: string = ""; export let elem_id = "";
export let elem_classes: Array<string> = []; export let elem_classes: string[] = [];
export let visible: boolean = true; export let visible = true;
export let value: null | string = null; export let value: null | string = null;
export let source: "canvas" | "webcam" | "upload" = "upload"; export let source: "canvas" | "webcam" | "upload" = "upload";
export let tool: "editor" | "select" | "sketch" | "color-sketch" = "editor"; export let tool: "editor" | "select" | "sketch" | "color-sketch" = "editor";
export let label: string; export let label: string;
export let show_label: boolean; export let show_label: boolean;
export let show_download_button: boolean;
export let streaming: boolean; export let streaming: boolean;
export let pending: boolean; export let pending: boolean;
export let height: number | undefined; export let height: number | undefined;
@ -24,13 +25,13 @@
export let mirror_webcam: boolean; export let mirror_webcam: boolean;
export let shape: [number, number]; export let shape: [number, number];
export let brush_radius: number; export let brush_radius: number;
export let selectable: boolean = false; export let selectable = false;
export let container: boolean = true; export let container = true;
export let scale: number | null = null; export let scale: number | null = null;
export let min_width: number | undefined = undefined; export let min_width: number | undefined = undefined;
export let loading_status: LoadingStatus; export let loading_status: LoadingStatus;
export let mode: "static" | "dynamic"; export let mode: "static" | "dynamic";
export let show_share_button: boolean = false; export let show_share_button = false;
const dispatch = createEventDispatcher<{ const dispatch = createEventDispatcher<{
change: undefined; change: undefined;
@ -70,6 +71,7 @@
{value} {value}
{label} {label}
{show_label} {show_label}
{show_download_button}
{selectable} {selectable}
{show_share_button} {show_share_button}
/> />

View File

@ -0,0 +1,50 @@
<script>
import { Meta, Template, Story } from "@storybook/addon-svelte-csf";
import StaticImage from "./StaticImage.svelte";
</script>
<Meta
title="Components/Image"
component={Image}
argTypes={{
value: {
control: "text",
description: "The image URL or file to display",
name: "value",
value: "https://i.ibb.co/6BgKdSj/groot.jpg"
},
show_download_button: {
options: [true, false],
description: "If false, the download button will not be visible",
control: { type: "boolean" },
defaultValue: true
},
}}
/>
<Template let:args>
<div class="image-container" style="width: 300px; position: relative;border-radius: var(--radius-lg);overflow: hidden;">
<StaticImage {...args} />
</div>
</Template>
<Story
name="Static Image with label and download button"
args={{
value: "https://i.ibb.co/6BgKdSj/groot.jpg",
show_label: true,
show_download_button: true
}}
/>
<Story
name="Static Image with no label or download button"
args={{
value: "https://i.ibb.co/6BgKdSj/groot.jpg",
show_label: false,
show_download_button: false
}}
/>

View File

@ -3,7 +3,7 @@
import type { SelectData } from "@gradio/utils"; import type { SelectData } from "@gradio/utils";
import { uploadToHuggingFace } from "@gradio/utils"; import { uploadToHuggingFace } from "@gradio/utils";
import { BlockLabel, Empty, IconButton, ShareButton } from "@gradio/atoms"; import { BlockLabel, Empty, IconButton, ShareButton } from "@gradio/atoms";
import { Download, Community } from "@gradio/icons"; import { Download } from "@gradio/icons";
import { get_coordinates_of_clicked_image } from "./utils"; import { get_coordinates_of_clicked_image } from "./utils";
import { Image } from "@gradio/icons"; import { Image } from "@gradio/icons";
@ -11,8 +11,9 @@
export let value: null | string; export let value: null | string;
export let label: string | undefined = undefined; export let label: string | undefined = undefined;
export let show_label: boolean; export let show_label: boolean;
export let selectable: boolean = false; export let show_download_button = true;
export let show_share_button: boolean = false; export let selectable = false;
export let show_share_button = false;
const dispatch = createEventDispatcher<{ const dispatch = createEventDispatcher<{
change: string; change: string;
@ -21,7 +22,7 @@
$: value && dispatch("change", value); $: value && dispatch("change", value);
const handle_click = (evt: MouseEvent) => { const handle_click = (evt: MouseEvent): void => {
let coordinates = get_coordinates_of_clicked_image(evt); let coordinates = get_coordinates_of_clicked_image(evt);
if (coordinates) { if (coordinates) {
dispatch("select", { index: coordinates, value: null }); dispatch("select", { index: coordinates, value: null });
@ -34,6 +35,7 @@
<Empty unpadded_box={true} size="large"><Image /></Empty> <Empty unpadded_box={true} size="large"><Image /></Empty>
{:else} {:else}
<div class="icon-buttons"> <div class="icon-buttons">
{#if show_download_button}
<a <a
href={value} href={value}
target={window.__is_colab__ ? "_blank" : null} target={window.__is_colab__ ? "_blank" : null}
@ -41,6 +43,7 @@
> >
<IconButton Icon={Download} label="Download" /> <IconButton Icon={Download} label="Download" />
</a> </a>
{/if}
{#if show_share_button} {#if show_share_button}
<ShareButton <ShareButton
on:share on:share

View File

@ -665,6 +665,7 @@ class TestImage:
"tool": "editor", "tool": "editor",
"name": "image", "name": "image",
"show_share_button": False, "show_share_button": False,
"show_download_button": True,
"streaming": False, "streaming": False,
"show_label": True, "show_label": True,
"label": "Upload Your Image", "label": "Upload Your Image",