deflate --- deflate 圧縮および展開

このモジュールは、DEFLATE アルゴリズム(zlib ライブラリや gzip アーカイバで一般的に使用されます)を用いてバイナリデータを圧縮・展開できます。MicroPython v1.21 で追加されました。

OpenMV 対応ボードでの利用可否:

ボード

展開

圧縮

OpenMV Cam N6

対応

非対応

OpenMV AE3

対応

対応

OpenMV Cam RT1062

対応

対応

OpenMV Cam Pure Thermal

対応

非対応

OpenMV Cam M4

対応

非対応

OpenMV Cam M7

対応

非対応

OpenMV Cam H7

対応

非対応

OpenMV Cam H7 Plus

対応

非対応

Arduino Giga

対応

非対応

Arduino Portenta H7

対応

非対応

Arduino Nicla Vision

対応

非対応

Arduino Nano 33 BLE Sense

対応

非対応

Arduino Nano RP2040 Connect

対応

非対応

クラス

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

このクラスは、ファイル、ソケット、ストリーム(io.BytesIO を含む)などの任意の ストリーム類似 オブジェクトである stream をラップするために使用できます。それ自体がストリームであり、標準の read/readinto/write/close メソッドを実装しています。

stream はブロッキングストリームである必要があります。ノンブロッキングストリームは現在サポートされていません。

format は以下で定義される定数のいずれかに設定でき、デフォルトは AUTO です。展開時には gzip または zlib ストリームを自動検出し、圧縮時には raw ストリームを生成します。

wbits パラメータは DEFLATE 辞書ウィンドウサイズの 2 を底とする対数を設定します。たとえば wbits10 に設定すると、ウィンドウサイズは 1024 バイトになります。有効な値は 5 から 15 まで(ウィンドウサイズの 32 バイトから 32k バイトに対応)です。

wbits0(デフォルト)に設定すると、圧縮では 256 バイトのウィンドウサイズが使用されます(wbits を 8 に設定した場合と同じ)。展開では、フォーマットによって異なります:

  • RAW は 256 バイトを使用します(wbits を 8 に設定した場合に対応)。

  • ZLIB(または zlib が検出された AUTO)は zlib ヘッダーの値を使用します。

  • GZIP(または gzip が検出された AUTO)は 32 キロバイトを使用します(wbits を 15 に設定した場合に対応)。

ウィンドウサイズ、zlib、gzip ストリームの詳細については、以下の ウィンドウサイズ に関する注記を参照してください。

closeTrue に設定すると、deflate.DeflateIO ストリームが閉じられる際に、基になるストリームが自動的に閉じられます。これは、別のストリームをラップする deflate.DeflateIO ストリームを返したいが、呼び出し側に基になるストリームの管理を意識させたくない場合に便利です。

圧縮が有効な場合、特定の deflate.DeflateIO インスタンスは読み込みと書き込みの両方をサポートします。たとえば、ソケットのような双方向ストリームをラップでき、両方向での圧縮・展開が可能になります。

定数

4 つの format 定数は、raw deflate ビットストリームの周囲に適用されるフレーミングを選択します。

deflate.AUTO: int

展開では、ストリームの先頭バイトを調べて入力フォーマット(zlib または gzip)を自動検出します。圧縮では、ヘッダーやトレーラーのない raw deflate ストリームを生成します(RAW と同等)。

deflate.RAW: int

raw deflate ストリーム(ヘッダー、トレーラー、チェックサムなし)。ストリームにはメタデータが含まれないため、展開側はデータからウィンドウサイズを復元できません。したがって展開時には wbits を明示的に設定する必要があります。設定しないと、デフォルトの 256 バイトのウィンドウが小さすぎる場合があります。

deflate.ZLIB: int

RFC 1950 で定義された zlib でラップされた deflate ストリーム。ウィンドウサイズを記録する 2 バイトのヘッダー、deflate ペイロード、そして末尾の Adler-32 チェックサムで構成されます。コンパクトで自己記述的であり、組み込み用途に適しています。

deflate.GZIP: int

RFC 1952 で定義された gzip でラップされた deflate ストリーム。オプションのファイル名/タイムスタンプのメタデータを持つヘッダー、deflate ペイロード、そして末尾の CRC-32 と非圧縮長で構成されます。これは gzip コマンドラインツールや gzip.GzipFile が生成するフォーマットです。ヘッダーにはウィンドウサイズが記録されないため、wbits が設定されていない限り、展開側は 32 KiB を仮定する必要があります。

deflate.DeflateIO の典型的なユースケースは、ストレージから圧縮ファイルを読み書きすることです:

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.

deflate.DeflateIO はストリームであるため、たとえば json.dump()json.load()(およびストリームを使用できるその他の場所)と組み合わせて使用できます:

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)

ソースデータがストリーム形式でない場合は、io.BytesIO を使って、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 のウィンドウサイズ

ウィンドウサイズは、(展開・圧縮側が)ストリーム内をどれだけ遡って参照できるかを制限します。ウィンドウサイズを大きくすると圧縮率は向上しますが、より多くのメモリを必要とし、圧縮処理は遅くなります。

入力ストリームが特定のウィンドウサイズで圧縮された場合、より小さいウィンドウサイズを使用する DeflateIO は展開の途中で OSError により失敗します。ただしこれは、後方参照が実際に展開側のウィンドウサイズより遠くを参照した場合に限ります。つまり、より小さいウィンドウサイズでも展開できる可能性があります。たとえば、元の非圧縮データがウィンドウサイズより短い場合は、明らかにそうなります。

展開

zlib フォーマットには、データの圧縮に使用されたウィンドウサイズを指定するヘッダーが含まれます。これは、このストリームの展開に必要な最大ウィンドウサイズを示します。このヘッダー値が指定された wbits 値より小さい場合(または wbits が未設定の場合)、ヘッダー値が使用されます。

gzip フォーマットはヘッダーにウィンドウサイズを含まず、すべての gzip 圧縮器(たとえば gzip ユーティリティや CPython の gzip.GzipFile の実装)が最大ウィンドウサイズの 32 KiB を使用することを前提としています。このため、wbits パラメータが設定されていない場合、展開側は 32 KiB のウィンドウサイズを使用します(wbits を 15 に設定した場合に対応)。つまり、任意の gzip ストリームを展開できるようにするには、少なくともこれだけの RAM が利用可能である必要があります。ソースデータを自分で制御できる場合は、代わりにより小さいウィンドウサイズの zlib フォーマットを使用することを検討してください。

raw フォーマットにはヘッダーがなく、したがってウィンドウサイズに関する情報を一切含みません。wbits が設定されていない場合、デフォルトで 256 バイトのウィンドウサイズになりますが、これは特定のストリームに対して十分な大きさでない可能性があります。そのため、raw フォーマットを使用する場合は常に wbits を明示的に設定することを推奨します。

圧縮

圧縮の場合、MicroPython はすべてのフォーマットでデフォルトで 256 バイトのウィンドウサイズを使用します。これにより、最小限のメモリ使用量と高速な圧縮時間で妥当な圧縮率が得られ、どの展開器でも動作する出力が生成されます。