toshas commited on
Commit
9bd6338
·
1 Parent(s): c5419ae

support heic and heif

Browse files

add pip freeze and environ printing at the beginning of the demo
add image_utils patch that intercepts large heic images and forces their downsampling

app.py CHANGED
@@ -63,12 +63,19 @@ class ImageFiltersApp(DualVisionApp):
63
  Process an input image into multiple modalities using the provided arguments or default settings.
64
  Returns two dictionaries: one containing the modalities and another with the actual settings.
65
  """
 
 
 
 
 
66
  filter_size = kwargs.get("filter_size", self.DEFAULT_FILTER_SIZE)
67
 
 
68
  image_out_gray = image_in.convert("L")
69
  image_out_gaussian = image_in.filter(ImageFilter.GaussianBlur(filter_size // 2))
70
  image_out_median = image_in.filter(ImageFilter.MedianFilter(filter_size))
71
 
 
72
  out_modalities = {
73
  "Gray": image_out_gray,
74
  "Gaussian": image_out_gaussian,
 
63
  Process an input image into multiple modalities using the provided arguments or default settings.
64
  Returns two dictionaries: one containing the modalities and another with the actual settings.
65
  """
66
+ # Downscale the image to 1024px on the longer side
67
+ scale = min(1.0, 1024 / max(image_in.width, image_in.height))
68
+ image_in = image_in.resize((round(image_in.width * scale), round(image_in.height * scale)), Image.LANCZOS)
69
+
70
+ # Read settings from kwargs or use default
71
  filter_size = kwargs.get("filter_size", self.DEFAULT_FILTER_SIZE)
72
 
73
+ # Process the input image in a variety of ways
74
  image_out_gray = image_in.convert("L")
75
  image_out_gaussian = image_in.filter(ImageFilter.GaussianBlur(filter_size // 2))
76
  image_out_median = image_in.filter(ImageFilter.MedianFilter(filter_size))
77
 
78
+ # Return the results and current settings to update the UI
79
  out_modalities = {
80
  "Gray": image_out_gray,
81
  "Gaussian": image_out_gaussian,
gradio_dualvision/app_template.py CHANGED
@@ -21,11 +21,18 @@
21
  # https://github.com/prs-eth/Marigold-DC#-citation
22
  # https://github.com/prs-eth/rollingdepth#-citation
23
  # --------------------------------------------------------------------------
 
 
 
 
24
  import glob
25
  import json
26
- import os
27
  import re
28
 
 
 
 
 
29
  import gradio as gr
30
  from .version import __version__
31
 
@@ -39,6 +46,7 @@ import spaces
39
  from PIL import Image as PILImage
40
  from gradio import Component, ImageSlider
41
 
 
42
  from .gradio_patches.examples import Examples
43
  from .gradio_patches.gallery import Gallery
44
  from .gradio_patches.image import Image
 
21
  # https://github.com/prs-eth/Marigold-DC#-citation
22
  # https://github.com/prs-eth/rollingdepth#-citation
23
  # --------------------------------------------------------------------------
24
+ import os
25
+ print("\n".join(f"{k}={v}" for k, v in os.environ.items()))
26
+ os.system("pip freeze")
27
+
28
  import glob
29
  import json
 
30
  import re
31
 
32
+ from pi_heif import register_heif_opener
33
+ register_heif_opener()
34
+
35
+
36
  import gradio as gr
37
  from .version import __version__
38
 
 
46
  from PIL import Image as PILImage
47
  from gradio import Component, ImageSlider
48
 
49
+ from .gradio_patches import image_utils
50
  from .gradio_patches.examples import Examples
51
  from .gradio_patches.gallery import Gallery
52
  from .gradio_patches.image import Image
gradio_dualvision/gradio_patches/image_utils.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import warnings
4
+ from pathlib import Path
5
+ from typing import Literal, cast
6
+
7
+ import gradio
8
+ from gradio.image_utils import decode_base64_to_file, decode_base64_to_image, decode_base64_to_image_array, format_image
9
+ import numpy as np
10
+ import PIL.Image
11
+ from PIL import ImageOps
12
+
13
+ from gradio import processing_utils
14
+ from gradio.data_classes import ImageData
15
+ from gradio.exceptions import Error
16
+
17
+ PIL.Image.init() # fixes https://github.com/gradio-app/gradio/issues/2843 (remove when requiring Pillow 9.4+)
18
+
19
+
20
+ def patched_preprocess_image(
21
+ payload: ImageData | None,
22
+ cache_dir: str,
23
+ format: str,
24
+ image_mode: Literal[
25
+ "1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "LAB", "HSV", "I", "F"
26
+ ]
27
+ | None,
28
+ type: Literal["numpy", "pil", "filepath"],
29
+ ) -> np.ndarray | PIL.Image.Image | str | None:
30
+ if payload is None:
31
+ return payload
32
+ if payload.url and payload.url.startswith("data:"):
33
+ if type == "pil":
34
+ print("Preprocessing payload as PIL image")
35
+ return decode_base64_to_image(payload.url)
36
+ elif type == "numpy":
37
+ print("Preprocessing payload as numpy array")
38
+ return decode_base64_to_image_array(payload.url)
39
+ elif type == "filepath":
40
+ print("Preprocessing payload as file path")
41
+ return decode_base64_to_file(payload.url, cache_dir, format)
42
+ if payload.path is None:
43
+ raise ValueError("Image path is None.")
44
+ file_path = Path(payload.path)
45
+ if payload.orig_name:
46
+ p = Path(payload.orig_name)
47
+ name = p.stem
48
+ suffix = p.suffix.replace(".", "")
49
+ if suffix in ["jpg", "jpeg"]:
50
+ suffix = "jpeg"
51
+ else:
52
+ name = "image"
53
+ suffix = "webp"
54
+
55
+ if suffix.lower() == "svg":
56
+ if type == "filepath":
57
+ return str(file_path)
58
+ raise Error("SVG files are not supported as input images for this app.")
59
+
60
+ # Check for heif or heic suffix, treat it as a special case and drop resolution immediately
61
+ if suffix.lower() in ["heif", "heic"] and type == "filepath":
62
+ im = PIL.Image.open(file_path).convert("RGB")
63
+ scale = min(1.0, 1024 / max(im.width, im.height))
64
+ im = im.resize((round(im.width * scale), round(im.height * scale)), PIL.Image.BILINEAR)
65
+ file_path = processing_utils.save_pil_to_cache(im, cache_dir=cache_dir)
66
+
67
+ im = PIL.Image.open(file_path)
68
+ if type == "filepath" and (image_mode in [None, im.mode]):
69
+ return str(file_path)
70
+
71
+ exif = im.getexif()
72
+ # 274 is the code for image rotation and 1 means "correct orientation"
73
+ if exif.get(274, 1) != 1 and hasattr(ImageOps, "exif_transpose"):
74
+ try:
75
+ im = ImageOps.exif_transpose(im)
76
+ except Exception:
77
+ warnings.warn(f"Failed to transpose image {file_path} based on EXIF data.")
78
+ if suffix.lower() != "gif" and im is not None:
79
+ with warnings.catch_warnings():
80
+ warnings.simplefilter("ignore")
81
+ if image_mode is not None:
82
+ im = im.convert(image_mode)
83
+ return format_image(
84
+ im,
85
+ type=cast(Literal["numpy", "pil", "filepath"], type),
86
+ cache_dir=cache_dir,
87
+ name=name,
88
+ format=suffix,
89
+ )
90
+
91
+
92
+ gradio.image_utils.preprocess_image = patched_preprocess_image
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  gradio==5.29.0
2
  gradio_client==1.10.0
 
3
  spaces==0.36.0
 
1
  gradio==5.29.0
2
  gradio_client==1.10.0
3
+ pi_heif==1.1.1
4
  spaces==0.36.0