10.2. Returnera en stillbild

En statusslutpunkt är bra, men anledningen till att kameran finns är linsen. Lägg till en slutpunkt som returnerar JPEG-bilden av vad sensorn än tittar på just nu.

import csi
from microdot import Response

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)

@app.get('/snapshot.jpg')
async def snapshot(request):
    img = csi0.snapshot().compress(quality=85)
    return Response(
        body=img.bytearray(),
        headers={'Content-Type': 'image/jpeg'},
    )

Besök http://<cam-ip>/snapshot.jpg från en webbläsare så fyller en JPEG av den aktuella vyn fliken. Uppdatera så får du en ny.

10.2.1. Response-objektet

En hanterare som returnerar en dict låter microdot sköta resten. JPEG-byte kräver den långa formen: en microdot.Response som konstrueras explicit. Argumentet body tar emot vilket bytes-liknande värde som helst – kamerans image.Image-buffert exponeras via bytearray(), så samma buffert som sensorn skrev in i går direkt till socketen.

Content-Type: image/jpeg är det som talar om för webbläsaren att rendera kroppen som en bild. Utan det skulle webbläsaren försöka visa JPEG-byten som text och du skulle se en skärmfull av skräp.

image.Image.compress() kör JPEG-kodning på den befintliga bildbufferten på plats och returnerar samma bild (nu i JPEG-format) så att dess byte kan skickas som de är. quality=85 är det vanliga standardvärdet – tillräckligt högt för att bilden ska vara skarp, tillräckligt lågt för att filen ska passa genom en långsam länk.

10.2.2. Inspelning blockerar loopen

csi.CSI.snapshot() väntar på att sensorn ska bli klar med att exponera och DMA:a en bildruta innan den returnerar. Inuti en async-hanterare innebär det att händelseloopen stannar under exponeringens varaktighet – tio, tjugo, femtio millisekunder beroende på belysningen. Med en klient som frågar efter en rutt åt gången är detta osynligt; med flera klienter, eller en inspelningskorutin som körs vid sidan av, skulle det blockera allt annat.

En icke-blockerande variant av snapshot() finns för fallet med flera korutiner (blocking=False returnerar nästa färdiga bildruta eller None). För en stillbild per begäran fungerar standardanropet med blockering bra.

Ägaren kan nu peta på en URL och få en färsk bildruta.