API: use ImageData type
This commit is contained in:
parent
af08917155
commit
60a417dc64
2 changed files with 54 additions and 26 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import base64
|
||||
import itertools
|
||||
import random
|
||||
import re
|
||||
|
|
@ -5,9 +6,9 @@ from datetime import date, datetime, timedelta
|
|||
from io import BytesIO
|
||||
from typing import Any, Awaitable, Callable, Iterable, Self, Sequence, TypeVar
|
||||
|
||||
from fastapi.responses import StreamingResponse
|
||||
from PIL import Image as PILImage
|
||||
from PIL.Image import Image, Resampling
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .config import get_config
|
||||
from .dav.webdav import WebDAV
|
||||
|
|
@ -115,25 +116,51 @@ async def load_image(file_name: str) -> Image:
|
|||
return PILImage.open(BytesIO(await WebDAV.read_bytes(file_name)))
|
||||
|
||||
|
||||
async def api_return_ico(img: Image) -> StreamingResponse:
|
||||
class ImageData(BaseModel):
|
||||
width: int
|
||||
height: int
|
||||
aspect_ratio: float
|
||||
data_url: str
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
*,
|
||||
media_type: str,
|
||||
content: BytesIO,
|
||||
width: int,
|
||||
height: int,
|
||||
) -> Self:
|
||||
img_data = base64.b64encode(content.getvalue()).decode("utf-8")
|
||||
|
||||
return cls(
|
||||
width=width,
|
||||
height=height,
|
||||
aspect_ratio=width / height,
|
||||
data_url=f"data:{media_type};base64,{img_data}",
|
||||
)
|
||||
|
||||
|
||||
async def api_return_ico(img: Image) -> ImageData:
|
||||
"""
|
||||
ICO-Bild mit API zurückgeben
|
||||
"""
|
||||
|
||||
# JPEG-Daten in Puffer speichern
|
||||
# ICO-Daten in Puffer speichern (256px)
|
||||
img_buffer = BytesIO()
|
||||
img.resize(size=(256, 256), resample=Resampling.LANCZOS)
|
||||
img.save(img_buffer, format="ICO")
|
||||
img_buffer.seek(0)
|
||||
|
||||
# zurückgeben
|
||||
return StreamingResponse(
|
||||
return ImageData.create(
|
||||
media_type="image/x-icon",
|
||||
content=img_buffer,
|
||||
width=img.width,
|
||||
height=img.height,
|
||||
)
|
||||
|
||||
|
||||
async def api_return_jpeg(img: Image) -> StreamingResponse:
|
||||
async def api_return_jpeg(img: Image) -> ImageData:
|
||||
"""
|
||||
JPEG-Bild mit API zurückgeben
|
||||
"""
|
||||
|
|
@ -141,12 +168,13 @@ async def api_return_jpeg(img: Image) -> StreamingResponse:
|
|||
# JPEG-Daten in Puffer speichern
|
||||
img_buffer = BytesIO()
|
||||
img.save(img_buffer, format="JPEG", quality=85)
|
||||
img_buffer.seek(0)
|
||||
|
||||
# zurückgeben
|
||||
return StreamingResponse(
|
||||
return ImageData.create(
|
||||
media_type="image/jpeg",
|
||||
content=img_buffer,
|
||||
width=img.width,
|
||||
height=img.height,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,31 @@
|
|||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.responses import StreamingResponse
|
||||
from PIL.Image import Image
|
||||
|
||||
from ..core.calendar_config import CalendarConfig, DoorsSaved, get_calendar_config
|
||||
from ..core.calendar_config import (
|
||||
CalendarConfig,
|
||||
DoorsSaved,
|
||||
get_calendar_config,
|
||||
)
|
||||
from ..core.config import Config, Site, get_config
|
||||
from ..core.depends import get_all_event_dates, get_day_image
|
||||
from ..core.helpers import EventDates, api_return_ico, api_return_jpeg, load_image
|
||||
from ..core.helpers import (
|
||||
EventDates,
|
||||
ImageData,
|
||||
api_return_ico,
|
||||
api_return_jpeg,
|
||||
load_image,
|
||||
)
|
||||
from ._security import user_can_view_day, user_is_admin, user_visible_days
|
||||
|
||||
router = APIRouter(prefix="/user", tags=["user"])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/background_image",
|
||||
response_class=StreamingResponse,
|
||||
)
|
||||
@router.get("/background_image")
|
||||
async def get_background_image(
|
||||
cal_cfg: CalendarConfig = Depends(get_calendar_config),
|
||||
) -> StreamingResponse:
|
||||
) -> ImageData:
|
||||
"""
|
||||
Hintergrundbild laden
|
||||
"""
|
||||
|
|
@ -27,13 +33,10 @@ async def get_background_image(
|
|||
return await api_return_jpeg(await load_image(f"files/{cal_cfg.background}"))
|
||||
|
||||
|
||||
@router.get(
|
||||
"/favicon",
|
||||
response_class=StreamingResponse,
|
||||
)
|
||||
@router.get("/favicon")
|
||||
async def get_favicon(
|
||||
cal_cfg: CalendarConfig = Depends(get_calendar_config),
|
||||
) -> StreamingResponse:
|
||||
) -> ImageData:
|
||||
"""
|
||||
Favicon laden
|
||||
"""
|
||||
|
|
@ -68,15 +71,12 @@ async def get_doors(
|
|||
return [door for door in cal_cfg.doors if door.day in visible_days]
|
||||
|
||||
|
||||
@router.get(
|
||||
"/image_{day}",
|
||||
response_class=StreamingResponse,
|
||||
)
|
||||
@router.get("/image_{day}")
|
||||
async def get_image_for_day(
|
||||
user_can_view: bool = Depends(user_can_view_day),
|
||||
is_admin: bool = Depends(user_is_admin),
|
||||
image: Image | None = Depends(get_day_image),
|
||||
) -> StreamingResponse:
|
||||
) -> ImageData:
|
||||
"""
|
||||
Bild für einen Tag erstellen
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue