deflate — compression et décompression deflate

Ce module permet la compression et la décompression de données binaires avec l”algorithme DEFLATE (couramment utilisé dans la bibliothèque zlib et l’archiveur gzip). Ajouté dans MicroPython v1.21.

Disponibilité sur les cartes prises en charge par OpenMV :

Carte

Décompression

Compression

OpenMV Cam N6

Oui

Non

OpenMV AE3

Oui

Oui

OpenMV Cam RT1062

Oui

Oui

OpenMV Cam Pure Thermal

Oui

Non

OpenMV Cam M4

Oui

Non

OpenMV Cam M7

Oui

Non

OpenMV Cam H7

Oui

Non

OpenMV Cam H7 Plus

Oui

Non

Arduino Giga

Oui

Non

Arduino Portenta H7

Oui

Non

Arduino Nicla Vision

Oui

Non

Arduino Nano 33 BLE Sense

Oui

Non

Arduino Nano RP2040 Connect

Oui

Non

Classes

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

Cette classe peut être utilisée pour envelopper un stream, c’est-à-dire tout objet de type flux tel qu’un fichier, un socket ou un flux (y compris io.BytesIO). Elle est elle-même un flux et implémente les méthodes standard read/readinto/write/close.

Le stream doit être un flux bloquant. Les flux non bloquants ne sont actuellement pas pris en charge.

Le paramètre format peut prendre n’importe laquelle des constantes définies ci-dessous, et vaut par défaut AUTO qui, pour la décompression, détecte automatiquement les flux gzip ou zlib, et pour la compression génère un flux brut.

Le paramètre wbits définit le logarithme en base 2 de la taille de la fenêtre du dictionnaire DEFLATE. Par exemple, régler wbits à 10 fixe la taille de la fenêtre à 1024 octets. Les valeurs valides vont de 5 à 15 inclus (correspondant à des tailles de fenêtre de 32 à 32k octets).

Si wbits est réglé à 0 (la valeur par défaut), alors pour la compression une taille de fenêtre de 256 octets sera utilisée (comme si wbits valait 8). Pour la décompression, cela dépend du format :

  • RAW utilisera 256 octets (correspondant à wbits réglé à 8).

  • ZLIB (ou AUTO avec zlib détecté) utilisera la valeur de l’en-tête zlib.

  • GZIP (ou AUTO avec gzip détecté) utilisera 32 kilo-octets (correspondant à wbits réglé à 15).

Consultez les notes sur la taille de fenêtre ci-dessous pour plus d’informations sur la taille de fenêtre et les flux zlib et gzip.

Si close est réglé à True, alors le flux sous-jacent sera fermé automatiquement lorsque le flux deflate.DeflateIO est fermé. C’est utile si vous souhaitez renvoyer un flux deflate.DeflateIO qui enveloppe un autre flux sans que l’appelant ait besoin de gérer le flux sous-jacent.

Si la compression est activée, une instance deflate.DeflateIO donnée prend en charge à la fois la lecture et l’écriture. Par exemple, un flux bidirectionnel comme un socket peut être enveloppé, ce qui permet la compression/décompression dans les deux sens.

Constantes

Les quatre constantes format sélectionnent l’encadrement appliqué autour du flux de bits deflate brut.

deflate.AUTO: int

Pour la décompression, détecte automatiquement le format d’entrée en inspectant les premiers octets du flux (zlib ou gzip). Pour la compression, génère un flux deflate brut sans en-tête ni fin de trame (équivalent à RAW).

deflate.RAW: int

Un flux deflate brut (pas d’en-tête, pas de fin de trame, pas de somme de contrôle). Comme le flux ne contient aucune métadonnée, le décompresseur ne peut pas retrouver la taille de fenêtre à partir des données ; wbits doit donc être réglé explicitement lors de la décompression — sinon la fenêtre par défaut de 256 octets risque d’être trop petite.

deflate.ZLIB: int

Un flux deflate encapsulé en zlib tel que défini par RFC 1950 : un en-tête de 2 octets qui enregistre la taille de fenêtre, la charge utile deflate, et une somme de contrôle Adler-32 en fin de trame. Compact et auto-descriptif ; bien adapté à un usage embarqué.

deflate.GZIP: int

Un flux deflate encapsulé en gzip tel que défini par RFC 1952 : un en-tête avec des métadonnées optionnelles de nom de fichier/horodatage, la charge utile deflate, et un CRC-32 en fin de trame suivi de la longueur non compressée. C’est le format produit par l’outil en ligne de commande gzip et par gzip.GzipFile. L’en-tête n’enregistre pas la taille de fenêtre, le décompresseur doit donc supposer 32 Kio à moins que wbits ne soit défini.

Exemples

Un cas d’usage typique de deflate.DeflateIO consiste à lire ou écrire un fichier compressé depuis le stockage :

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.

Comme deflate.DeflateIO est un flux, il peut être utilisé par exemple avec json.dump() et json.load() (et partout ailleurs où des flux peuvent être utilisés) :

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)

Si vos données source ne sont pas dans un format de flux, vous pouvez utiliser io.BytesIO pour les transformer en un flux utilisable avec 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()

Taille de la fenêtre deflate

La taille de la fenêtre limite jusqu’où dans le flux le (dé)compresseur peut faire référence. Augmenter la taille de la fenêtre améliore la compression, mais nécessite plus de mémoire et rend le compresseur plus lent.

Si un flux d’entrée a été compressé avec une taille de fenêtre donnée, alors DeflateIO utilisant une taille de fenêtre plus petite échouera en cours de décompression avec OSError, mais seulement si une référence arrière renvoie effectivement plus loin que la taille de fenêtre du décompresseur. Cela signifie qu’il peut être possible de décompresser avec une taille de fenêtre plus petite. Par exemple, ce serait trivialement le cas si les données non compressées d’origine sont plus courtes que la taille de la fenêtre.

Décompression

Le format zlib comprend un en-tête qui spécifie la taille de fenêtre utilisée pour compresser les données. Cela indique la taille de fenêtre maximale requise pour décompresser ce flux. Si cette valeur d’en-tête est inférieure à la valeur wbits spécifiée (ou si wbits n’est pas défini), alors la valeur de l’en-tête sera utilisée.

Le format gzip n’inclut pas la taille de fenêtre dans l’en-tête, et suppose que tous les compresseurs gzip (par exemple l’utilitaire gzip, ou l’implémentation de gzip.GzipFile par CPython) utilisent la taille de fenêtre maximale de 32 Kio. Pour cette raison, si le paramètre wbits n’est pas défini, le décompresseur utilisera une taille de fenêtre de 32 Kio (correspondant à wbits réglé à 15). Cela signifie que pour pouvoir décompresser un flux gzip arbitraire, vous devez disposer d’au moins cette quantité de RAM. Si vous contrôlez les données source, envisagez plutôt d’utiliser le format zlib avec une taille de fenêtre plus petite.

Le format raw n’a pas d’en-tête et n’inclut donc aucune information sur la taille de fenêtre. Si wbits n’est pas défini, il prendra par défaut une taille de fenêtre de 256 octets, qui peut ne pas être suffisante pour un flux donné. Il est donc recommandé de toujours définir explicitement wbits lors de l’utilisation du format raw.

Compression

Pour la compression, MicroPython utilise par défaut une taille de fenêtre de 256 octets pour tous les formats. Cela offre un taux de compression raisonnable avec une utilisation mémoire minimale et un temps de compression rapide, et génère une sortie qui fonctionnera avec n’importe quel décompresseur.