deflate — compressão e descompressão deflate

Este módulo permite a compressão e descompressão de dados binários com o algoritmo DEFLATE (utilizado frequentemente na biblioteca zlib e no arquivador gzip). Adicionado no MicroPython v1.21.

Disponibilidade nas placas suportadas pela OpenMV:

Placa

Descompressão

Compressão

OpenMV Cam N6

Sim

Não

OpenMV AE3

Sim

Sim

OpenMV Cam RT1062

Sim

Sim

OpenMV Cam Pure Thermal

Sim

Não

OpenMV Cam M4

Sim

Não

OpenMV Cam M7

Sim

Não

OpenMV Cam H7

Sim

Não

OpenMV Cam H7 Plus

Sim

Não

Arduino Giga

Sim

Não

Arduino Portenta H7

Sim

Não

Arduino Nicla Vision

Sim

Não

Arduino Nano 33 BLE Sense

Sim

Não

Arduino Nano RP2040 Connect

Sim

Não

Classes

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

Esta classe pode ser usada para envolver um stream que pode ser qualquer objeto semelhante a um stream, como um ficheiro, socket ou stream (incluindo io.BytesIO). É ela própria um stream e implementa os métodos padrão read/readinto/write/close.

O stream deve ser um stream bloqueante. Streams não bloqueantes não são atualmente suportados.

O format pode ser definido para qualquer uma das constantes definidas abaixo, e assume o valor predefinido AUTO, que para descompressão deteta automaticamente streams gzip ou zlib, e para compressão gera um stream bruto.

O parâmetro wbits define o logaritmo de base 2 do tamanho da janela do dicionário DEFLATE. Por exemplo, definir wbits como 10 define o tamanho da janela para 1024 bytes. Os valores válidos são 5 a 15 inclusive (correspondendo a tamanhos de janela de 32 a 32k bytes).

Se wbits for definido como 0 (o valor predefinido), então para compressão será utilizado um tamanho de janela de 256 bytes (como se wbits fosse definido como 8). Para descompressão, depende do formato:

  • RAW utilizará 256 bytes (correspondendo a wbits definido como 8).

  • ZLIB (ou AUTO com zlib detetado) utilizará o valor do cabeçalho zlib.

  • GZIP (ou AUTO com gzip detetado) utilizará 32 kilobytes (correspondendo a wbits definido como 15).

Consulte as notas sobre o tamanho da janela abaixo para mais informações sobre o tamanho da janela, streams zlib e gzip.

Se close for definido como True, o stream subjacente será fechado automaticamente quando o stream deflate.DeflateIO for fechado. Isto é útil quando se pretende retornar um stream deflate.DeflateIO que envolve outro stream sem que o chamador precise de gerir o stream subjacente.

Se a compressão estiver ativada, uma dada instância de deflate.DeflateIO suporta leitura e escrita. Por exemplo, um stream bidirecional como um socket pode ser envolvido, permitindo compressão/descompressão em ambas as direções.

Constantes

As quatro constantes format selecionam o enquadramento aplicado em torno do fluxo de bits deflate bruto.

deflate.AUTO: int

Para descompressão, detetar automaticamente o formato de entrada inspecionando os primeiros bytes do stream (zlib ou gzip). Para compressão, gerar um stream deflate bruto sem cabeçalho ou rodapé (equivalente a RAW).

deflate.RAW: int

Um stream deflate bruto (sem cabeçalho, sem rodapé, sem soma de verificação). Como o stream não contém metadados, o descompressor não consegue recuperar o tamanho da janela a partir dos dados, pelo que wbits deve ser definido explicitamente na descompressão — caso contrário, a janela predefinida de 256 bytes pode ser demasiado pequena.

deflate.ZLIB: int

Um stream deflate encapsulado em zlib conforme definido pela RFC 1950: um cabeçalho de 2 bytes que regista o tamanho da janela, o payload deflate e uma soma de verificação Adler-32 final. Compacto e autodescritivo; adequado para uso em sistemas embebidos.

deflate.GZIP: int

Um stream deflate encapsulado em gzip conforme definido pela RFC 1952: um cabeçalho com metadados opcionais de nome de ficheiro/marca temporal, o payload deflate, e um CRC-32 final mais o comprimento descomprimido. Este é o formato produzido pela ferramenta de linha de comandos gzip e por gzip.GzipFile. O cabeçalho não regista o tamanho da janela, pelo que o descompressor deve assumir 32 KiB a menos que wbits seja definido.

Exemplos

Um caso de uso típico para deflate.DeflateIO é ler ou escrever um ficheiro comprimido a partir do armazenamento:

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.

Como deflate.DeflateIO é um stream, pode ser utilizado, por exemplo, com json.dump() e json.load() (e em qualquer outro lugar onde streams possam ser usados):

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)

Se os dados de origem não estiverem em formato de stream, pode usar io.BytesIO para os converter num stream adequado para utilização com 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()

Tamanho da janela Deflate

O tamanho da janela limita o quão atrás no stream o (des)compressor pode fazer referência. Aumentar o tamanho da janela melhorará a compressão, mas exigirá mais memória e tornará o compressor mais lento.

Se um stream de entrada foi comprimido com um determinado tamanho de janela, então um DeflateIO com tamanho de janela menor falhará a meio da descompressão com OSError, mas apenas se uma referência retrospetiva apontar para além da janela do descompressor. Isso significa que pode ser possível descomprimir com um tamanho de janela menor. Por exemplo, este seria trivialmente o caso se os dados originais descomprimidos forem mais curtos do que o tamanho da janela.

Descompressão

O formato zlib inclui um cabeçalho que especifica o tamanho da janela usado para comprimir os dados. Isto indica o tamanho máximo de janela necessário para descomprimir este stream. Se este valor do cabeçalho for menor que o valor wbits especificado (ou se wbits não estiver definido), então o valor do cabeçalho será usado.

O formato gzip não inclui o tamanho da janela no cabeçalho, e assume que todos os compressores gzip (por ex., o utilitário gzip, ou a implementação CPython de gzip.GzipFile) utilizam o tamanho máximo de janela de 32kiB. Por essa razão, se o parâmetro wbits não estiver definido, o descompressor utilizará um tamanho de janela de 32 KiB (correspondendo a wbits definido como 15). Isso significa que para poder descomprimir um stream gzip arbitrário, é necessário ter pelo menos esta quantidade de RAM disponível. Se controlar os dados de origem, considere utilizar o formato zlib com um tamanho de janela menor.

O formato bruto não tem cabeçalho e, portanto, não inclui qualquer informação sobre o tamanho da janela. Se wbits não estiver definido, o valor predefinido será um tamanho de janela de 256 bytes, o que pode não ser suficiente para um dado stream. Por isso, recomenda-se que wbits seja sempre definido explicitamente ao usar o formato bruto.

Compressão

Para compressão, o MicroPython usa por predefinição um tamanho de janela de 256 bytes para todos os formatos. Isto proporciona uma quantidade razoável de compressão com utilização mínima de memória e tempo de compressão rápido, e irá gerar saída compatível com qualquer descompressor.