Merge pull request #139 from tiqi-group/chore/remove_pillow_dependency

removes Pillow dependency, updates Image component
This commit is contained in:
Mose Müller 2024-07-09 08:42:02 +02:00 committed by GitHub
commit b719684702
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 653 additions and 563 deletions

1160
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,7 @@ uvicorn = "^0.27.0"
toml = "^0.10.2"
python-socketio = "^5.8.0"
confz = "^2.0.0"
pint = "^0.22"
pillow = "^10.0.0"
pint = "^0.24"
websocket-client = "^1.7.0"
aiohttp = "^3.9.3"

View File

@ -5,8 +5,6 @@ from pathlib import Path
from typing import TYPE_CHECKING
from urllib.request import urlopen
import PIL.Image # type: ignore[import-untyped]
from pydase.data_service.data_service import DataService
if TYPE_CHECKING:
@ -16,9 +14,7 @@ logger = logging.getLogger(__name__)
class Image(DataService):
def __init__(
self,
) -> None:
def __init__(self) -> None:
super().__init__()
self._value: str = ""
self._format: str = ""
@ -32,8 +28,14 @@ class Image(DataService):
return self._format
def load_from_path(self, path: Path | str) -> None:
with PIL.Image.open(path) as image:
self._load_from_pil(image)
with open(path, "rb") as image_file:
image_data = image_file.read()
format_ = self._get_image_format_from_bytes(image_data)
if format_ is None:
logger.error("Unsupported image format. Skipping...")
return
value_ = base64.b64encode(image_data)
self._load_from_base64(value_, format_)
def load_from_matplotlib_figure(self, fig: "Figure", format_: str = "png") -> None:
buffer = io.BytesIO()
@ -42,12 +44,18 @@ class Image(DataService):
self._load_from_base64(value_, format_)
def load_from_url(self, url: str) -> None:
image = PIL.Image.open(urlopen(url))
self._load_from_pil(image)
with urlopen(url) as response:
image_data = response.read()
format_ = self._get_image_format_from_bytes(image_data)
if format_ is None:
logger.error("Unsupported image format. Skipping...")
return
value_ = base64.b64encode(image_data)
self._load_from_base64(value_, format_)
def load_from_base64(self, value_: bytes, format_: str | None = None) -> None:
if format_ is None:
format_ = self._get_image_format_from_bytes(value_)
format_ = self._get_image_format_from_bytes(base64.b64decode(value_))
if format_ is None:
logger.warning(
"Format of passed byte string could not be determined. Skipping..."
@ -60,19 +68,14 @@ class Image(DataService):
self._value = value
self._format = format_
def _load_from_pil(self, image: PIL.Image.Image) -> None:
if image.format is not None:
format_ = image.format
buffer = io.BytesIO()
image.save(buffer, format=format_)
value_ = base64.b64encode(buffer.getvalue())
self._load_from_base64(value_, format_)
else:
logger.error("Image format is 'None'. Skipping...")
def _get_image_format_from_bytes(self, value_: bytes) -> str | None:
image_data = base64.b64decode(value_)
# Create a writable memory buffer for the image
image_buffer = io.BytesIO(image_data)
# Read the image from the buffer and return format
return PIL.Image.open(image_buffer).format
format_map = {
b"\xff\xd8": "JPEG",
b"\x89PNG": "PNG",
b"GIF": "GIF",
b"RIFF": "WEBP",
}
for signature, format_name in format_map.items():
if value_.startswith(signature):
return format_name
return None