deflate — Deflate-Komprimierung und -Dekomprimierung

Dieses Modul ermöglicht die Komprimierung und Dekomprimierung von Binärdaten mit dem DEFLATE-Algorithmus (häufig verwendet in der zlib-Bibliothek und im gzip-Archivierer). Hinzugefügt in MicroPython v1.21.

Verfügbarkeit auf den von OpenMV unterstützten Boards:

Board

Dekomprimierung

Komprimierung

OpenMV Cam N6

Ja

Nein

OpenMV AE3

Ja

Ja

OpenMV Cam RT1062

Ja

Ja

OpenMV Cam Pure Thermal

Ja

Nein

OpenMV Cam M4

Ja

Nein

OpenMV Cam M7

Ja

Nein

OpenMV Cam H7

Ja

Nein

OpenMV Cam H7 Plus

Ja

Nein

Arduino Giga

Ja

Nein

Arduino Portenta H7

Ja

Nein

Arduino Nicla Vision

Ja

Nein

Arduino Nano 33 BLE Sense

Ja

Nein

Arduino Nano RP2040 Connect

Ja

Nein

Klassen

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

Diese Klasse kann verwendet werden, um einen stream zu umhüllen, der ein beliebiges stream-like-Objekt wie eine Datei, ein Socket oder ein Stream ist (einschließlich io.BytesIO). Sie ist selbst ein Stream und implementiert die Standardmethoden read/readinto/write/close.

Der stream muss ein blockierender Stream sein. Nicht-blockierende Streams werden derzeit nicht unterstützt.

Das format kann auf eine der unten definierten Konstanten gesetzt werden und ist standardmäßig AUTO, was beim Dekomprimieren gzip- oder zlib-Streams automatisch erkennt und beim Komprimieren einen Raw-Stream erzeugt.

Der Parameter wbits legt den Logarithmus zur Basis 2 der DEFLATE-Wörterbuch-Fenstergröße fest. Setzt man wbits beispielsweise auf 10, beträgt die Fenstergröße 1024 Bytes. Gültige Werte sind 5 bis einschließlich 15 (entsprechend Fenstergrößen von 32 bis 32k Bytes).

Wird wbits auf 0 gesetzt (der Standardwert), so wird bei der Komprimierung eine Fenstergröße von 256 Bytes verwendet (als wäre wbits auf 8 gesetzt). Bei der Dekomprimierung hängt es vom Format ab:

  • RAW verwendet 256 Bytes (entsprechend wbits gleich 8).

  • ZLIB (oder AUTO mit erkanntem zlib) verwendet den Wert aus dem zlib-Header.

  • GZIP (oder AUTO mit erkanntem gzip) verwendet 32 Kilobytes (entsprechend wbits gleich 15).

Weitere Informationen zur Fenstergröße sowie zu zlib- und gzip-Streams finden Sie in den Hinweisen zur Fenstergröße weiter unten.

Wird close auf True gesetzt, so wird der zugrunde liegende Stream automatisch geschlossen, sobald der deflate.DeflateIO-Stream geschlossen wird. Dies ist nützlich, wenn Sie einen deflate.DeflateIO-Stream zurückgeben möchten, der einen anderen Stream umhüllt, ohne dass der Aufrufer die Verwaltung des zugrunde liegenden Streams kennen muss.

Wenn die Komprimierung aktiviert ist, unterstützt eine gegebene deflate.DeflateIO-Instanz sowohl Lesen als auch Schreiben. So kann beispielsweise ein bidirektionaler Stream wie ein Socket umhüllt werden, was eine Komprimierung/Dekomprimierung in beide Richtungen ermöglicht.

Konstanten

Die vier format-Konstanten wählen das Framing aus, das um den rohen Deflate-Bitstrom herum angewendet wird.

deflate.AUTO: int

Bei der Dekomprimierung wird das Eingabeformat durch Untersuchen der ersten Bytes des Streams automatisch erkannt (zlib oder gzip). Bei der Komprimierung wird ein roher Deflate-Stream ohne Header oder Trailer erzeugt (entspricht RAW).

deflate.RAW: int

Ein roher Deflate-Stream (kein Header, kein Trailer, keine Prüfsumme). Da der Stream keine Metadaten enthält, kann der Dekomprimierer die Fenstergröße nicht aus den Daten rekonstruieren, sodass wbits beim Dekomprimieren explizit gesetzt werden sollte – andernfalls könnte das standardmäßige 256-Byte-Fenster zu klein sein.

deflate.ZLIB: int

Ein zlib-umhüllter Deflate-Stream gemäß RFC 1950: ein 2-Byte-Header, der die Fenstergröße aufzeichnet, die Deflate-Nutzlast und eine abschließende Adler-32-Prüfsumme. Kompakt und selbstbeschreibend; gut für den Einsatz in eingebetteten Systemen geeignet.

deflate.GZIP: int

Ein gzip-umhüllter Deflate-Stream gemäß RFC 1952: ein Header mit optionalen Metadaten wie Dateiname/Zeitstempel, die Deflate-Nutzlast und eine abschließende CRC-32-Prüfsumme nebst unkomprimierter Länge. Dies ist das Format, das vom Kommandozeilentool gzip und von gzip.GzipFile erzeugt wird. Der Header zeichnet die Fenstergröße nicht auf, sodass der Dekomprimierer 32 KiB annehmen muss, sofern wbits nicht gesetzt ist.

Beispiele

Ein typischer Anwendungsfall für deflate.DeflateIO ist das Lesen oder Schreiben einer komprimierten Datei aus dem Speicher:

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.

Da deflate.DeflateIO ein Stream ist, kann es zum Beispiel mit json.dump() und json.load() verwendet werden (und an allen anderen Stellen, an denen Streams verwendet werden können):

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)

Falls Ihre Quelldaten nicht im Stream-Format vorliegen, können Sie io.BytesIO verwenden, um sie in einen Stream umzuwandeln, der sich für deflate.DeflateIO eignet:

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-Fenstergröße

Die Fenstergröße begrenzt, wie weit der (De-)Komprimierer im Stream zurückreferenzieren kann. Eine Vergrößerung der Fenstergröße verbessert die Komprimierung, erfordert jedoch mehr Speicher und macht den Komprimierer langsamer.

Wenn ein Eingabestream mit einer bestimmten Fenstergröße komprimiert wurde, schlägt DeflateIO mit einer kleineren Fenstergröße mitten in der Dekomprimierung mit OSError fehl, allerdings nur, wenn eine Rückreferenz tatsächlich weiter zurückverweist als die Fenstergröße des Dekomprimierers. Das bedeutet, dass eine Dekomprimierung mit einer kleineren Fenstergröße durchaus möglich sein kann. Dies wäre beispielsweise trivialerweise der Fall, wenn die ursprünglichen unkomprimierten Daten kürzer als die Fenstergröße sind.

Dekomprimierung

Das zlib-Format enthält einen Header, der die zur Komprimierung der Daten verwendete Fenstergröße angibt. Dies gibt die maximale Fenstergröße an, die zum Dekomprimieren dieses Streams erforderlich ist. Wenn dieser Header-Wert kleiner als der angegebene wbits-Wert ist (oder wenn wbits nicht gesetzt ist), wird der Header-Wert verwendet.

Das gzip-Format enthält die Fenstergröße nicht im Header und geht davon aus, dass alle gzip-Komprimierer (z. B. das Dienstprogramm gzip oder CPythons Implementierung von gzip.GzipFile) die maximale Fenstergröße von 32 KiB verwenden. Aus diesem Grund verwendet der Dekomprimierer, falls der Parameter wbits nicht gesetzt ist, eine Fenstergröße von 32 KiB (entsprechend wbits gleich 15). Das bedeutet, dass Sie mindestens so viel RAM verfügbar haben müssen, um einen beliebigen gzip-Stream dekomprimieren zu können. Wenn Sie die Kontrolle über die Quelldaten haben, sollten Sie stattdessen das zlib-Format mit einer kleineren Fenstergröße in Erwägung ziehen.

Das Raw-Format hat keinen Header und enthält daher keinerlei Informationen über die Fenstergröße. Wenn wbits nicht gesetzt ist, wird standardmäßig eine Fenstergröße von 256 Bytes verwendet, die für einen gegebenen Stream möglicherweise nicht ausreichend groß ist. Daher wird empfohlen, wbits bei Verwendung des Raw-Formats stets explizit zu setzen.

Komprimierung

Bei der Komprimierung verwendet MicroPython standardmäßig für alle Formate eine Fenstergröße von 256 Bytes. Dies bietet ein angemessenes Maß an Komprimierung bei minimalem Speicherverbrauch und kurzer Komprimierungszeit und erzeugt eine Ausgabe, die mit jedem Dekomprimierer funktioniert.