use webp images

This commit is contained in:
Jennifer Player 2024-03-06 13:53:05 -05:00 committed by Kent Keirsey
parent 8411029d93
commit aa88fadc30
8 changed files with 88 additions and 78 deletions

View File

@ -287,21 +287,18 @@ async def update_model_record(
"description": "The model image was fetched successfully", "description": "The model image was fetched successfully",
}, },
400: {"description": "Bad request"}, 400: {"description": "Bad request"},
404: {"description": "The model could not be found"}, 404: {"description": "The model image could not be found"}
}, },
status_code=200, status_code=200,
) )
async def get_model_image( async def get_model_image(
key: str = Path(description="The name of model image file to get"), key: str = Path(description="The name of model image file to get"),
) -> FileResponse: ) -> FileResponse:
"""Gets a full-resolution image file""" """Gets an image file that previews the model"""
try: try:
path = ApiDependencies.invoker.services.model_images.get_path(key) path = ApiDependencies.invoker.services.model_images.get_path(key)
if not path:
raise HTTPException(status_code=404)
response = FileResponse( response = FileResponse(
path, path,
media_type="image/png", media_type="image/png",

View File

@ -12,13 +12,13 @@ class ModelImagesBase(ABC):
pass pass
@abstractmethod @abstractmethod
def get_path(self, model_key: str) -> Path | None: def get_path(self, model_key: str) -> Path:
"""Gets the internal path to a model image.""" """Gets the internal path to a model image."""
pass pass
@abstractmethod @abstractmethod
def get_url(self, model_key: str) -> str | None: def get_url(self, model_key: str) -> str | None:
"""Gets the URL to a model image.""" """Gets the URL to fetch a model image."""
pass pass
@abstractmethod @abstractmethod
@ -27,7 +27,7 @@ class ModelImagesBase(ABC):
image: PILImageType, image: PILImageType,
model_key: str, model_key: str,
) -> None: ) -> None:
"""Saves a model image. Returns a tuple of the image name and created timestamp.""" """Saves a model image."""
pass pass
@abstractmethod @abstractmethod

View File

@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
from typing import Union from typing import Union
from PIL import Image, PngImagePlugin from PIL import Image
from PIL.Image import Image as PILImageType from PIL.Image import Image as PILImageType
from send2trash import send2trash from send2trash import send2trash
@ -45,25 +45,16 @@ class ModelImagesService(ModelImagesBase):
) -> None: ) -> None:
try: try:
self.__validate_storage_folders() self.__validate_storage_folders()
logger = self.__invoker.services.logger image_path = self.__model_images_folder / (model_key + '.webp')
image_path = self.__model_images_folder / (model_key + '.png')
logger.debug(f"Saving image for model {model_key} to image_path {image_path}")
pnginfo = PngImagePlugin.PngInfo()
image = make_thumbnail(image, 256) image = make_thumbnail(image, 256)
image.save( image.save(image_path, format="webp")
image_path,
"PNG",
pnginfo=pnginfo,
compress_level=self.__invoker.services.configuration.png_compress_level,
)
except Exception as e: except Exception as e:
raise ModelImageFileSaveException from e raise ModelImageFileSaveException from e
def get_path(self, model_key: str) -> Path: def get_path(self, model_key: str) -> Path:
path = self.__model_images_folder / (model_key + '.png') path = self.__model_images_folder / (model_key + '.webp')
return path return path

View File

@ -20,7 +20,6 @@ Validation errors will raise an InvalidModelConfigException error.
""" """
from pathlib import Path
import time import time
from enum import Enum from enum import Enum
from typing import Literal, Optional, Type, Union from typing import Literal, Optional, Type, Union

View File

@ -1,6 +0,0 @@
{
"name": "frontend",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

View File

@ -9,7 +9,7 @@ type Props = {
const ModelImage = ({ image_url }: Props) => { const ModelImage = ({ image_url }: Props) => {
if (!image_url) return <Box height="50px" width="50px" />; if (!image_url) return <Box height="50px" minWidth="50px" />;
return ( return (
<Image <Image
@ -18,6 +18,8 @@ const ModelImage = ({ image_url }: Props) => {
objectPosition="50% 50%" objectPosition="50% 50%"
height="50px" height="50px"
width="50px" width="50px"
minHeight="50px"
minWidth="50px"
borderRadius="base" borderRadius="base"
/> />
); );

View File

@ -64,7 +64,7 @@ type Props = {
if (!model_key) { if (!model_key) {
return; return;
} }
setImage(undefined); setImage(null);
deleteModelImage(model_key) deleteModelImage(model_key)
.unwrap() .unwrap()
.then(() => { .then(() => {
@ -102,11 +102,11 @@ type Props = {
position="relative" position="relative"
> >
<Image <Image
onError={() => setImage(undefined)}
src={image} src={image}
objectFit="contain" objectFit="cover"
maxW="full" objectPosition="50% 50%"
maxH="100px" height="100px"
width="100px"
borderRadius="base" borderRadius="base"
/> />
<IconButton <IconButton

File diff suppressed because one or more lines are too long