Support PIL Images in pc.image (#1096)
This commit is contained in:
parent
e3914136f8
commit
507f406230
@ -1,10 +1,12 @@
|
|||||||
"""An image component."""
|
"""An image component."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional, Set
|
from typing import Any, Optional, Set
|
||||||
|
|
||||||
from pynecone.components.component import Component
|
from pynecone.components.component import Component
|
||||||
from pynecone.components.libs.chakra import ChakraComponent
|
from pynecone.components.libs.chakra import ChakraComponent
|
||||||
|
from pynecone.components.tags import Tag
|
||||||
|
from pynecone.utils import format, types
|
||||||
from pynecone.vars import Var
|
from pynecone.vars import Var
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ class Image(ChakraComponent):
|
|||||||
loading: Var[str]
|
loading: Var[str]
|
||||||
|
|
||||||
# The image src attribute.
|
# The image src attribute.
|
||||||
src: Var[str]
|
src: Var[Any]
|
||||||
|
|
||||||
# The image srcset attribute.
|
# The image srcset attribute.
|
||||||
src_set: Var[str]
|
src_set: Var[str]
|
||||||
@ -50,3 +52,11 @@ class Image(ChakraComponent):
|
|||||||
The event triggers.
|
The event triggers.
|
||||||
"""
|
"""
|
||||||
return super().get_triggers() | {"on_error", "on_load"}
|
return super().get_triggers() | {"on_error", "on_load"}
|
||||||
|
|
||||||
|
def _render(self) -> Tag:
|
||||||
|
# If the src is an image, convert it to a base64 string.
|
||||||
|
if types.is_image(type(self.src)):
|
||||||
|
self.src = Var.create(format.format_image_data(self.src)) # type: ignore
|
||||||
|
|
||||||
|
# Render the table.
|
||||||
|
return super()._render()
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -359,6 +361,22 @@ def format_dataframe_values(value: Type) -> List[Any]:
|
|||||||
return format_data
|
return format_data
|
||||||
|
|
||||||
|
|
||||||
|
def format_image_data(value: Type) -> str:
|
||||||
|
"""Format image data.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The value to format.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Format data
|
||||||
|
"""
|
||||||
|
buff = io.BytesIO()
|
||||||
|
value.save(buff, format="PNG")
|
||||||
|
image_bytes = buff.getvalue()
|
||||||
|
base64_image = base64.b64encode(image_bytes).decode("utf-8")
|
||||||
|
return f"data:image/png;base64,{base64_image}"
|
||||||
|
|
||||||
|
|
||||||
def format_state(value: Any) -> Dict:
|
def format_state(value: Any) -> Dict:
|
||||||
"""Recursively format values in the given state.
|
"""Recursively format values in the given state.
|
||||||
|
|
||||||
@ -390,6 +408,10 @@ def format_state(value: Any) -> Dict:
|
|||||||
"data": format_dataframe_values(value),
|
"data": format_dataframe_values(value),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Convert Image objects to base64.
|
||||||
|
if types.is_image(type(value)):
|
||||||
|
return format_image_data(value) # type: ignore
|
||||||
|
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
"State vars must be primitive Python types, "
|
"State vars must be primitive Python types, "
|
||||||
"or subclasses of pc.Base. "
|
"or subclasses of pc.Base. "
|
||||||
|
@ -141,6 +141,20 @@ def is_dataframe(value: Type) -> bool:
|
|||||||
return value.__name__ == "DataFrame"
|
return value.__name__ == "DataFrame"
|
||||||
|
|
||||||
|
|
||||||
|
def is_image(value: Type) -> bool:
|
||||||
|
"""Check if the given value is a pillow image. By checking if the value subclasses PIL.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The value to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Whether the value is a pillow image.
|
||||||
|
"""
|
||||||
|
if is_generic_alias(value) or value == typing.Any:
|
||||||
|
return False
|
||||||
|
return "PIL" in value.__module__
|
||||||
|
|
||||||
|
|
||||||
def is_figure(value: Type) -> bool:
|
def is_figure(value: Type) -> bool:
|
||||||
"""Check if the given value is a figure.
|
"""Check if the given value is a figure.
|
||||||
|
|
||||||
@ -162,7 +176,12 @@ def is_valid_var_type(var: Type) -> bool:
|
|||||||
Returns:
|
Returns:
|
||||||
Whether the value is a valid prop type.
|
Whether the value is a valid prop type.
|
||||||
"""
|
"""
|
||||||
return _issubclass(var, StateVar) or is_dataframe(var) or is_figure(var)
|
return (
|
||||||
|
_issubclass(var, StateVar)
|
||||||
|
or is_dataframe(var)
|
||||||
|
or is_figure(var)
|
||||||
|
or is_image(var)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_backend_variable(name: str) -> bool:
|
def is_backend_variable(name: str) -> bool:
|
||||||
|
Loading…
Reference in New Issue
Block a user