deflate — deflate-compressie en -decompressie

Deze module maakt compressie en decompressie van binaire data mogelijk met het DEFLATE-algoritme (veelgebruikt in de zlib-bibliotheek en de gzip-archiver). Toegevoegd in MicroPython v1.21.

Beschikbaarheid op door OpenMV ondersteunde boards:

Board

Decompressie

Compressie

OpenMV Cam N6

Ja

Nee

OpenMV AE3

Ja

Ja

OpenMV Cam RT1062

Ja

Ja

OpenMV Cam Pure Thermal

Ja

Nee

OpenMV Cam M4

Ja

Nee

OpenMV Cam M7

Ja

Nee

OpenMV Cam H7

Ja

Nee

OpenMV Cam H7 Plus

Ja

Nee

Arduino Giga

Ja

Nee

Arduino Portenta H7

Ja

Nee

Arduino Nicla Vision

Ja

Nee

Arduino Nano 33 BLE Sense

Ja

Nee

Arduino Nano RP2040 Connect

Ja

Nee

Klassen

class deflate.DeflateIO(stream: Any, format: int = AUTO, wbits: int = 0, close: bool = False, /)

Deze klasse kan worden gebruikt om een stream te omhullen, wat elk stream-achtig object kan zijn, zoals een bestand, socket of stream (waaronder io.BytesIO). Het is zelf een stream en implementeert de standaardmethoden read/readinto/write/close.

De stream moet een blokkerende stream zijn. Niet-blokkerende streams worden momenteel niet ondersteund.

De format kan worden ingesteld op een van de hieronder gedefinieerde constanten, en is standaard AUTO, wat bij decompressie automatisch gzip- of zlib-streams detecteert, en bij compressie een ruwe stream genereert.

De parameter wbits stelt de logaritme met grondtal 2 van de venstergrootte van het DEFLATE-woordenboek in. Door wbits bijvoorbeeld op 10 te zetten, wordt de venstergrootte op 1024 bytes ingesteld. Geldige waarden zijn 5 tot en met 15 (overeenkomend met venstergroottes van 32 tot 32k bytes).

Als wbits op 0 is ingesteld (de standaardwaarde), wordt bij compressie een venstergrootte van 256 bytes gebruikt (alsof wbits op 8 was ingesteld). Bij decompressie hangt het af van het formaat:

  • RAW gebruikt 256 bytes (overeenkomend met wbits ingesteld op 8).

  • ZLIB (of AUTO met zlib gedetecteerd) gebruikt de waarde uit de zlib-header.

  • GZIP (of AUTO met gzip gedetecteerd) gebruikt 32 kilobytes (overeenkomend met wbits ingesteld op 15).

Zie de opmerkingen over de venstergrootte hieronder voor meer informatie over de venstergrootte en zlib- en gzip-streams.

Als close op True is ingesteld, wordt de onderliggende stream automatisch gesloten wanneer de deflate.DeflateIO-stream wordt gesloten. Dit is handig als je een deflate.DeflateIO-stream wilt teruggeven die een andere stream omhult, zonder dat de aanroeper het beheer van de onderliggende stream hoeft te kennen.

Als compressie is ingeschakeld, ondersteunt een gegeven deflate.DeflateIO-instantie zowel lezen als schrijven. Zo kan bijvoorbeeld een bidirectionele stream zoals een socket worden omhuld, wat compressie/decompressie in beide richtingen mogelijk maakt.

Constanten

De vier format-constanten selecteren de framing die rond de ruwe deflate-bitstream wordt toegepast.

deflate.AUTO: int

Detecteer bij decompressie automatisch het invoerformaat door de eerste bytes van de stream te inspecteren (zlib of gzip). Genereer bij compressie een ruwe deflate-stream zonder header of trailer (gelijkwaardig aan RAW).

deflate.RAW: int

Een ruwe deflate-stream (geen header, geen trailer, geen checksum). Omdat de stream geen metadata bevat, kan de decompressor de venstergrootte niet uit de data herstellen, dus moet wbits expliciet worden ingesteld bij decompressie – anders kan het standaardvenster van 256 bytes te klein zijn.

deflate.ZLIB: int

Een in zlib verpakte deflate-stream zoals gedefinieerd door RFC 1950: een header van 2 bytes die de venstergrootte vastlegt, de deflate-payload en een afsluitende Adler-32-checksum. Compact en zelfbeschrijvend; goed geschikt voor embedded gebruik.

deflate.GZIP: int

Een in gzip verpakte deflate-stream zoals gedefinieerd door RFC 1952: een header met optionele metadata zoals bestandsnaam/tijdstempel, de deflate-payload, en een afsluitende CRC-32 plus ongecomprimeerde lengte. Dit is het formaat dat wordt geproduceerd door de opdrachtregeltool gzip en door gzip.GzipFile. De header legt de venstergrootte niet vast, dus de decompressor moet 32 KiB aannemen tenzij wbits is ingesteld.

Voorbeelden

Een typisch gebruiksscenario voor deflate.DeflateIO is het lezen of schrijven van een gecomprimeerd bestand vanaf opslag:

import deflate

# Writing a zlib-compressed stream (uses the default window size of 256 bytes).
with open("data.z", "wb") as f:
    with deflate.DeflateIO(f, deflate.ZLIB) as d:
        # Use d.write(...) etc

# Reading a zlib-compressed stream (auto-detect window size).
with open("data.z", "rb") as f:
    with deflate.DeflateIO(f, deflate.ZLIB) as d:
        # Use d.read(), d.readinto(), etc.

Omdat deflate.DeflateIO een stream is, kan het bijvoorbeeld worden gebruikt met json.dump() en json.load() (en op alle andere plaatsen waar streams kunnen worden gebruikt):

import deflate, json

# Write a dictionary as JSON in gzip format, with a
# small (64 byte) window size.
config = { ... }
with open("config.gz", "wb") as f:
    with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
        json.dump(config, f)

# Read back that dictionary.
with open("config.gz", "rb") as f:
    with deflate.DeflateIO(f, deflate.GZIP, 6) as f:
        config = json.load(f)

Als je brondata niet in een streamformaat is, kun je io.BytesIO gebruiken om er een stream van te maken die geschikt is voor gebruik met deflate.DeflateIO:

import deflate, io

# Decompress a bytes/bytearray value.
compressed_data = get_data_z()
with deflate.DeflateIO(io.BytesIO(compressed_data), deflate.ZLIB) as d:
    decompressed_data = d.read()

# Compress a bytes/bytearray value.
uncompressed_data = get_data()
stream = io.BytesIO()
with deflate.DeflateIO(stream, deflate.ZLIB) as d:
    d.write(uncompressed_data)
compressed_data = stream.getvalue()

Deflate-venstergrootte

De venstergrootte beperkt hoe ver terug in de stream de (de)compressor kan refereren. Het vergroten van de venstergrootte verbetert de compressie, maar vereist meer geheugen en maakt de compressor trager.

Als een invoerstream met een bepaalde venstergrootte werd gecomprimeerd, dan zal DeflateIO met een kleinere venstergrootte halverwege de decompressie mislukken met OSError, maar alleen als een terugverwijzing daadwerkelijk verder terug verwijst dan de venstergrootte van de decompressor. Dit betekent dat decompressie met een kleinere venstergrootte mogelijk kan zijn. Dit zou bijvoorbeeld triviaal het geval zijn als de oorspronkelijke ongecomprimeerde data korter is dan de venstergrootte.

Decompressie

Het zlib-formaat bevat een header die de venstergrootte aangeeft die werd gebruikt om de data te comprimeren. Dit geeft de maximale venstergrootte aan die nodig is om deze stream te decomprimeren. Als deze headerwaarde kleiner is dan de opgegeven wbits-waarde (of als wbits niet is ingesteld), wordt de headerwaarde gebruikt.

Het gzip-formaat bevat de venstergrootte niet in de header en gaat ervan uit dat alle gzip-compressors (bijv. het hulpprogramma gzip of CPython’s implementatie van gzip.GzipFile) de maximale venstergrootte van 32 KiB gebruiken. Om deze reden gebruikt de decompressor, als de parameter wbits niet is ingesteld, een venstergrootte van 32 KiB (overeenkomend met wbits ingesteld op 15). Dit betekent dat je minstens zoveel RAM beschikbaar moet hebben om een willekeurige gzip-stream te kunnen decomprimeren. Als je controle hebt over de brondata, overweeg dan in plaats daarvan het zlib-formaat met een kleinere venstergrootte.

Het ruwe formaat heeft geen header en bevat daarom geen informatie over de venstergrootte. Als wbits niet is ingesteld, wordt standaard een venstergrootte van 256 bytes gebruikt, wat mogelijk niet groot genoeg is voor een bepaalde stream. Daarom wordt aanbevolen wbits altijd expliciet in te stellen bij gebruik van het ruwe formaat.

Compressie

Voor compressie gebruikt MicroPython standaard een venstergrootte van 256 bytes voor alle formaten. Dit biedt een redelijke mate van compressie met minimaal geheugengebruik en een snelle compressietijd, en genereert uitvoer die met elke decompressor werkt.