Skip to content

Commit

Permalink
Fix PIL imports (#7236)
Browse files Browse the repository at this point in the history
* Only do PIL.Image.init() fix once (image_utils is always imported when dealing with images)

* Normalize import style for `PIL.Image`

Follows up on #7116

---------

Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
  • Loading branch information
akx and abidlabs committed Feb 1, 2024
1 parent 5d24c35 commit dec6a71
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/major-zoos-write.md
@@ -0,0 +1,5 @@
---
"gradio": minor
---

feat:Fix PIL imports
2 changes: 0 additions & 2 deletions gradio/components/annotated_image.py
Expand Up @@ -15,8 +15,6 @@

set_documentation_group("component")

PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843


class Annotation(GradioModel):
image: FileData
Expand Down
2 changes: 0 additions & 2 deletions gradio/components/base.py
Expand Up @@ -15,7 +15,6 @@
from typing import TYPE_CHECKING, Any, Callable

from gradio_client.documentation import set_documentation_group
from PIL import Image as _Image # using _ to minimize namespace pollution

from gradio import utils
from gradio.blocks import Block, BlockContext
Expand All @@ -34,7 +33,6 @@ class DataframeData(TypedDict):


set_documentation_group("component")
_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843


class _Keywords(Enum):
Expand Down
12 changes: 6 additions & 6 deletions gradio/components/gallery.py
Expand Up @@ -7,9 +7,9 @@
from urllib.parse import urlparse

import numpy as np
import PIL.Image
from gradio_client.documentation import document, set_documentation_group
from gradio_client.utils import is_http_url_like
from PIL import Image as _Image # using _ to minimize namespace pollution

from gradio import processing_utils, utils
from gradio.components.base import Component
Expand All @@ -19,7 +19,7 @@
set_documentation_group("component")


GalleryImageType = Union[np.ndarray, _Image.Image, Path, str]
GalleryImageType = Union[np.ndarray, PIL.Image.Image, Path, str]
CaptionedGalleryImageType = Tuple[GalleryImageType, str]


Expand Down Expand Up @@ -47,7 +47,7 @@ class Gallery(Component):

def __init__(
self,
value: list[np.ndarray | _Image.Image | str | Path | tuple]
value: list[np.ndarray | PIL.Image.Image | str | Path | tuple]
| Callable
| None = None,
*,
Expand Down Expand Up @@ -137,7 +137,7 @@ def preprocess(
self, payload: GalleryData | None
) -> (
List[tuple[str, str | None]]
| List[tuple[_Image.Image, str | None]]
| List[tuple[PIL.Image.Image, str | None]]
| List[tuple[np.ndarray, str | None]]
| None
):
Expand Down Expand Up @@ -179,7 +179,7 @@ def postprocess(
img, cache_dir=self.GRADIO_CACHE
)
file_path = str(utils.abspath(file))
elif isinstance(img, _Image.Image):
elif isinstance(img, PIL.Image.Image):
file = processing_utils.save_pil_to_cache(
img, cache_dir=self.GRADIO_CACHE
)
Expand Down Expand Up @@ -209,7 +209,7 @@ def convert_to_type(img: str, type: Literal["filepath", "numpy", "pil"]):
if type == "filepath":
return img
else:
converted_image = _Image.open(img)
converted_image = PIL.Image.open(img)
if type == "numpy":
converted_image = np.array(converted_image)
return converted_image
Expand Down
1 change: 0 additions & 1 deletion gradio/components/image.py
Expand Up @@ -18,7 +18,6 @@
from gradio.events import Events

set_documentation_group("component")
PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843


@document()
Expand Down
15 changes: 7 additions & 8 deletions gradio/components/image_editor.py
Expand Up @@ -8,8 +8,8 @@
from typing import Any, Iterable, List, Literal, Optional, TypedDict, Union, cast

import numpy as np
import PIL.Image
from gradio_client.documentation import document, set_documentation_group
from PIL import Image as _Image # using _ to minimize namespace pollution

import gradio.image_utils as image_utils
from gradio import utils
Expand All @@ -18,10 +18,9 @@
from gradio.events import Events

set_documentation_group("component")
_Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843


ImageType = Union[np.ndarray, _Image.Image, str]
ImageType = Union[np.ndarray, PIL.Image.Image, str]


class EditorValue(TypedDict):
Expand Down Expand Up @@ -218,11 +217,11 @@ def __init__(
def convert_and_format_image(
self,
file: FileData | None,
) -> np.ndarray | _Image.Image | str | None:
) -> np.ndarray | PIL.Image.Image | str | None:
if file is None:
return None

im = _Image.open(file.path)
im = PIL.Image.open(file.path)

if file.orig_name:
p = Path(file.orig_name)
Expand Down Expand Up @@ -282,7 +281,7 @@ def postprocess(self, value: EditorValue | ImageType | None) -> EditorData | Non
return None
elif isinstance(value, dict):
pass
elif isinstance(value, (np.ndarray, _Image.Image, str)):
elif isinstance(value, (np.ndarray, PIL.Image.Image, str)):
value = {"background": value, "layers": [], "composite": value}
else:
raise ValueError(
Expand All @@ -293,7 +292,7 @@ def postprocess(self, value: EditorValue | ImageType | None) -> EditorData | Non
[
FileData(
path=image_utils.save_image(
cast(Union[np.ndarray, _Image.Image, str], layer),
cast(Union[np.ndarray, PIL.Image.Image, str], layer),
self.GRADIO_CACHE,
)
)
Expand All @@ -312,7 +311,7 @@ def postprocess(self, value: EditorValue | ImageType | None) -> EditorData | Non
layers=layers,
composite=FileData(
path=image_utils.save_image(
cast(Union[np.ndarray, _Image.Image, str], value["composite"]),
cast(Union[np.ndarray, PIL.Image.Image, str], value["composite"]),
self.GRADIO_CACHE,
)
)
Expand Down
14 changes: 7 additions & 7 deletions gradio/image_utils.py
Expand Up @@ -4,20 +4,20 @@
from typing import Literal

import numpy as np
from PIL import Image as _Image # using _ to minimize namespace pollution
import PIL.Image

from gradio import processing_utils

_Image.init()
PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843 (remove when requiring Pillow 9.4+)


def format_image(
im: _Image.Image | None,
im: PIL.Image.Image | None,
type: Literal["numpy", "pil", "filepath"],
cache_dir: str,
name: str = "image",
format: str = "png",
) -> np.ndarray | _Image.Image | str | None:
) -> np.ndarray | PIL.Image.Image | str | None:
"""Helper method to format an image based on self.type"""
if im is None:
return im
Expand Down Expand Up @@ -51,12 +51,12 @@ def format_image(
)


def save_image(y: np.ndarray | _Image.Image | str | Path, cache_dir: str):
def save_image(y: np.ndarray | PIL.Image.Image | str | Path, cache_dir: str):
# numpy gets saved to png as default format
# PIL gets saved to its original format if possible
if isinstance(y, np.ndarray):
path = processing_utils.save_img_array_to_cache(y, cache_dir=cache_dir)
elif isinstance(y, _Image.Image):
elif isinstance(y, PIL.Image.Image):
fmt = y.format
try:
path = processing_utils.save_pil_to_cache(
Expand All @@ -81,7 +81,7 @@ def save_image(y: np.ndarray | _Image.Image | str | Path, cache_dir: str):
return path


def crop_scale(img: _Image.Image, final_width: int, final_height: int):
def crop_scale(img: PIL.Image.Image, final_width: int, final_height: int):
original_width, original_height = img.size
target_aspect_ratio = final_width / final_height

Expand Down
8 changes: 4 additions & 4 deletions gradio/templates.py
Expand Up @@ -4,7 +4,7 @@
from typing import Any, Callable, Iterable, Literal

import numpy as np
from PIL import Image as _Image # using _ to minimize namespace pollution
import PIL.Image

from gradio import components
from gradio.components.audio import WaveformOptions
Expand Down Expand Up @@ -79,7 +79,7 @@ class Sketchpad(components.ImageEditor):

def __init__(
self,
value: str | _Image.Image | np.ndarray | None = None,
value: str | PIL.Image.Image | np.ndarray | None = None,
*,
height: int | str | None = None,
width: int | str | None = None,
Expand Down Expand Up @@ -148,7 +148,7 @@ class Paint(components.ImageEditor):

def __init__(
self,
value: str | _Image.Image | np.ndarray | None = None,
value: str | PIL.Image.Image | np.ndarray | None = None,
*,
height: int | str | None = None,
width: int | str | None = None,
Expand Down Expand Up @@ -215,7 +215,7 @@ class ImageMask(components.ImageEditor):

def __init__(
self,
value: str | _Image.Image | np.ndarray | None = None,
value: str | PIL.Image.Image | np.ndarray | None = None,
*,
height: int | None = None,
width: int | str | None = None,
Expand Down

0 comments on commit dec6a71

Please sign in to comment.