81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
"""Image processing and serving functions."""
|
|
|
|
import logging
|
|
import struct
|
|
import tempfile
|
|
|
|
from PIL import Image
|
|
from aiohttp import hdrs, web
|
|
from homeassistant.components.http.static import CACHE_HEADERS
|
|
from homeassistant.components.http.view import HomeAssistantView
|
|
import requests
|
|
|
|
from .const import DATA_IMAGES, DOMAIN
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def image_to_rgb565(in_image, size):
|
|
"""Transform image to rgb565 format according to LVGL requirements."""
|
|
try:
|
|
if in_image.startswith("http"):
|
|
im = Image.open(requests.get(in_image, stream=True).raw)
|
|
else:
|
|
im = Image.open(in_image)
|
|
except Exception:
|
|
_LOGGER.error("Failed to open %s", in_image)
|
|
return None
|
|
|
|
original_width, original_height = im.size
|
|
width, height = size
|
|
|
|
width = min(w for w in [width, original_width] if w is not None and w > 0)
|
|
height = min(h for h in [height, original_height] if h is not None and h > 0)
|
|
|
|
im.thumbnail((height, width), Image.ANTIALIAS)
|
|
width, height = im.size # actual size after resize
|
|
|
|
out_image = tempfile.NamedTemporaryFile(mode="w+b")
|
|
|
|
out_image.write(struct.pack("I", height << 21 | width << 10 | 4))
|
|
|
|
img = im.convert("RGB")
|
|
|
|
for pix in img.getdata():
|
|
r = (pix[0] >> 3) & 0x1F
|
|
g = (pix[1] >> 2) & 0x3F
|
|
b = (pix[2] >> 3) & 0x1F
|
|
out_image.write(struct.pack("H", (r << 11) | (g << 5) | b))
|
|
|
|
_LOGGER.debug("image_to_rgb565 out_image: %s", out_image.name)
|
|
|
|
out_image.flush()
|
|
|
|
return out_image
|
|
|
|
|
|
class ImageServeView(HomeAssistantView):
|
|
"""View to download images."""
|
|
|
|
url = "/api/openhasp/serve/{image_id}"
|
|
name = "api:openhasp:serve"
|
|
requires_auth = False
|
|
|
|
def __init__(self) -> None:
|
|
"""Initialize image serve view."""
|
|
|
|
async def get(self, request: web.Request, image_id: str):
|
|
"""Serve image."""
|
|
|
|
hass = request.app["hass"]
|
|
target_file = hass.data[DOMAIN][DATA_IMAGES].get(image_id)
|
|
if target_file is None:
|
|
_LOGGER.error("Unknown image_id %s", image_id)
|
|
return web.HTTPNotFound()
|
|
|
|
_LOGGER.debug("Get Image %s form %s", image_id, target_file.name)
|
|
|
|
return web.FileResponse(
|
|
target_file.name, headers={**CACHE_HEADERS, hdrs.CONTENT_TYPE: "image/bmp"}
|
|
)
|