|
5 | 5 | import warnings
|
6 | 6 | from collections.abc import Callable, Sequence
|
7 | 7 | from pathlib import Path
|
8 |
| -from typing import TYPE_CHECKING, Any, Literal, Optional, cast |
| 8 | +from typing import TYPE_CHECKING, Any, Literal, cast |
| 9 | +from urllib.parse import quote |
9 | 10 |
|
10 | 11 | import numpy as np
|
11 | 12 | import PIL.Image
|
12 | 13 | from gradio_client import handle_file
|
13 | 14 | from gradio_client.documentation import document
|
14 | 15 | from PIL import ImageOps
|
15 |
| -from pydantic import ConfigDict, Field |
16 | 16 |
|
17 | 17 | from gradio import image_utils, utils
|
18 | 18 | from gradio.components.base import Component, StreamingInput
|
19 |
| -from gradio.data_classes import GradioModel |
| 19 | +from gradio.data_classes import Base64ImageData, ImageData |
20 | 20 | from gradio.events import Events
|
21 | 21 | from gradio.exceptions import Error
|
22 | 22 |
|
|
26 | 26 | PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843
|
27 | 27 |
|
28 | 28 |
|
29 |
| -class ImageData(GradioModel): |
30 |
| - path: Optional[str] = Field(default=None, description="Path to a local file") |
31 |
| - url: Optional[str] = Field( |
32 |
| - default=None, description="Publicly available url or base64 encoded image" |
33 |
| - ) |
34 |
| - size: Optional[int] = Field(default=None, description="Size of image in bytes") |
35 |
| - orig_name: Optional[str] = Field(default=None, description="Original filename") |
36 |
| - mime_type: Optional[str] = Field(default=None, description="mime type of image") |
37 |
| - is_stream: bool = Field(default=False, description="Can always be set to False") |
38 |
| - meta: dict = {"_type": "gradio.FileData"} |
39 |
| - |
40 |
| - model_config = ConfigDict( |
41 |
| - json_schema_extra={ |
42 |
| - "description": "For input, either path or url must be provided. For output, path is always provided." |
43 |
| - } |
44 |
| - ) |
45 |
| - |
46 |
| - |
47 |
| -class Base64ImageData(GradioModel): |
48 |
| - url: str = Field(description="base64 encoded image") |
49 |
| - |
50 |
| - |
51 | 29 | @document()
|
52 | 30 | class Image(StreamingInput, Component):
|
53 | 31 | """
|
@@ -112,7 +90,7 @@ def __init__(
|
112 | 90 | width: The width of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. This has no effect on the preprocessed image file or numpy array, but will affect the displayed image.
|
113 | 91 | image_mode: The pixel format and color depth that the image should be loaded and preprocessed as. "RGB" will load the image as a color image, or "L" as black-and-white. See https://pillow.readthedocs.io/en/stable/handbook/concepts.html for other supported image modes and their meaning. This parameter has no effect on SVG or GIF files. If set to None, the image_mode will be inferred from the image file type (e.g. "RGBA" for a .png image, "RGB" in most other cases).
|
114 | 92 | sources: List of sources for the image. "upload" creates a box where user can drop an image file, "webcam" allows user to take snapshot from their webcam, "clipboard" allows users to paste an image from the clipboard. If None, defaults to ["upload", "webcam", "clipboard"] if streaming is False, otherwise defaults to ["webcam"].
|
115 |
| - type: The format the image is converted before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (height, width, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image. If the image is SVG, the `type` is ignored and the filepath of the SVG is returned. To support animated GIFs in input, the `type` should be set to "filepath" or "pil". |
| 93 | + type: The format the image is converted before being passed into the prediction function. "numpy" converts the image to a numpy array with shape (height, width, 3) and values from 0 to 255, "pil" converts the image to a PIL image object, "filepath" passes a str path to a temporary file containing the image. To support animated GIFs in input, the `type` should be set to "filepath" or "pil". To support SVGs, the `type` should be set to "filepath". |
116 | 94 | label: the label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
|
117 | 95 | every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.
|
118 | 96 | inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
|
@@ -198,7 +176,7 @@ def preprocess(
|
198 | 176 | Parameters:
|
199 | 177 | payload: image data in the form of a FileData object
|
200 | 178 | Returns:
|
201 |
| - Passes the uploaded image as a `numpy.array`, `PIL.Image` or `str` filepath depending on `type`. For SVGs, the `type` parameter is ignored and the filepath of the SVG is returned. |
| 179 | + Passes the uploaded image as a `numpy.array`, `PIL.Image` or `str` filepath depending on `type`. |
202 | 180 | """
|
203 | 181 | if payload is None:
|
204 | 182 | return payload
|
@@ -227,7 +205,7 @@ def preprocess(
|
227 | 205 | if suffix.lower() == "svg":
|
228 | 206 | if self.type == "filepath":
|
229 | 207 | return str(file_path)
|
230 |
| - raise Error("SVG files are not supported as input images.") |
| 208 | + raise Error("SVG files are not supported as input images for this app.") |
231 | 209 |
|
232 | 210 | im = PIL.Image.open(file_path)
|
233 | 211 | if self.type == "filepath" and (self.image_mode in [None, im.mode]):
|
@@ -267,7 +245,11 @@ def postprocess(
|
267 | 245 | if value is None:
|
268 | 246 | return None
|
269 | 247 | if isinstance(value, str) and value.lower().endswith(".svg"):
|
270 |
| - return ImageData(path=value, orig_name=Path(value).name) |
| 248 | + svg_content = image_utils.extract_svg_content(value) |
| 249 | + return ImageData( |
| 250 | + orig_name=Path(value).name, |
| 251 | + url=f"data:image/svg+xml,{quote(svg_content)}", |
| 252 | + ) |
271 | 253 | if self.streaming:
|
272 | 254 | if isinstance(value, np.ndarray):
|
273 | 255 | return Base64ImageData(
|
|
0 commit comments