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.