deflate --- การบีบอัดและคลายการบีบอัด deflate

โมดูลนี้รองรับการบีบอัดและคลายการบีบอัดข้อมูลไบนารีด้วย อัลกอริทึม DEFLATE (ที่ใช้กันทั่วไปใน zlib library และโปรแกรม 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, /)

คลาสนี้สามารถใช้ห่อหุ้ม stream ซึ่งเป็นออบเจกต์ คล้าย stream เช่น ไฟล์, socket หรือ stream (รวมถึง io.BytesIO) คลาสนี้เองก็เป็น stream และรองรับเมธอด read/readinto/write/close มาตรฐาน

stream ต้องเป็น blocking stream ปัจจุบันยังไม่รองรับ non-blocking stream

format สามารถกำหนดเป็นค่าคงที่ใดก็ได้ที่นิยามไว้ด้านล่าง และค่าเริ่มต้นคือ AUTO ซึ่งสำหรับการคลายการบีบอัดจะตรวจจับรูปแบบ gzip หรือ zlib โดยอัตโนมัติ และสำหรับการบีบอัดจะสร้าง raw stream

พารามิเตอร์ wbits กำหนดลอการิทึมฐาน 2 ของขนาดหน้าต่าง DEFLATE dictionary เช่น การตั้ง wbits เป็น 10 จะกำหนดขนาดหน้าต่างเป็น 1024 ไบต์ ค่าที่ถูกต้องคือ 5 ถึง 15 รวม (สอดคล้องกับขนาดหน้าต่าง 32 ถึง 32k ไบต์)

ถ้า wbits ถูกตั้งเป็น 0 (ค่าเริ่มต้น) สำหรับการบีบอัดจะใช้ขนาดหน้าต่าง 256 ไบต์ (เหมือนกับตั้ง wbits เป็น 8) สำหรับการคลายการบีบอัดขึ้นอยู่กับรูปแบบ:

  • RAW จะใช้ 256 ไบต์ (สอดคล้องกับ wbits ที่ตั้งเป็น 8)

  • ZLIB (หรือ AUTO เมื่อตรวจจับ zlib ได้) จะใช้ค่าจาก zlib header

  • GZIP (หรือ AUTO เมื่อตรวจจับ gzip ได้) จะใช้ 32 กิโลไบต์ (สอดคล้องกับ wbits ที่ตั้งเป็น 15)

ดูหมายเหตุ ขนาดหน้าต่าง ด้านล่างสำหรับข้อมูลเพิ่มเติมเกี่ยวกับขนาดหน้าต่าง, zlib และ gzip stream

ถ้า close ถูกตั้งเป็น True stream ต้นแบบจะถูกปิดโดยอัตโนมัติเมื่อปิด stream deflate.DeflateIO สิ่งนี้มีประโยชน์เมื่อต้องการคืนค่า stream deflate.DeflateIO ที่ห่อหุ้ม stream อื่น โดยไม่ต้องให้ผู้เรียกจัดการ stream ต้นแบบเอง

ถ้าเปิดใช้งานการบีบอัด อินสแตนซ์ deflate.DeflateIO ที่กำหนดรองรับทั้งการอ่านและเขียน เช่น สามารถห่อหุ้ม stream สองทิศทางอย่าง socket เพื่อบีบอัด/คลายการบีบอัดในทั้งสองทิศทาง

ค่าคงที่

ค่าคงที่ format ทั้งสี่เลือกการกรอบที่ใช้กับ raw deflate bit-stream

deflate.AUTO: int

สำหรับการคลายการบีบอัด ตรวจจับรูปแบบอินพุตโดยอัตโนมัติด้วยการตรวจสอบไบต์แรกของ stream (zlib หรือ gzip) สำหรับการบีบอัด สร้าง raw deflate stream โดยไม่มี header หรือ trailer (เทียบเท่า RAW)

deflate.RAW: int

Raw deflate stream (ไม่มี header, ไม่มี trailer, ไม่มี checksum) เนื่องจาก stream ไม่มี metadata ตัวคลายการบีบอัดไม่สามารถกู้คืนขนาดหน้าต่างจากข้อมูล ดังนั้นควรตั้ง wbits อย่างชัดเจนเมื่อคลายการบีบอัด มิฉะนั้นค่าเริ่มต้น 256 ไบต์อาจน้อยเกินไป

deflate.ZLIB: int

A zlib-wrapped deflate stream ตามที่นิยามใน RFC 1950: header 2 ไบต์ที่บันทึกขนาดหน้าต่าง, deflate payload และ checksum Adler-32 ท้าย กะทัดรัดและอธิบายตัวเองได้; เหมาะสำหรับการใช้งานแบบ embedded

deflate.GZIP: int

A gzip-wrapped deflate stream ตามที่นิยามใน RFC 1952: header พร้อม metadata ชื่อไฟล์/timestamp ที่เป็นตัวเลือก, deflate payload และ CRC-32 พร้อมความยาวที่ไม่บีบอัดท้าย นี่คือรูปแบบที่สร้างโดยเครื่องมือคำสั่ง gzip และ gzip.GzipFile header ไม่บันทึกขนาดหน้าต่าง ดังนั้นตัวคลายการบีบอัดต้องสมมติ 32 KiB เว้นแต่จะตั้ง wbits

ตัวอย่าง

กรณีใช้งานทั่วไปของ 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 เป็น stream จึงสามารถใช้ร่วมกับ json.dump() และ json.load() (และที่อื่น ๆ ที่ใช้ stream ได้) ตัวอย่างเช่น:

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)

ถ้าข้อมูลต้นทางไม่อยู่ในรูปแบบ stream สามารถใช้ io.BytesIO เพื่อแปลงเป็น stream ที่เหมาะสำหรับใช้กับ 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

ขนาดหน้าต่างจำกัดว่าตัว (คลาย)บีบอัดสามารถอ้างอิงย้อนกลับได้ไกลแค่ไหนใน stream การเพิ่มขนาดหน้าต่างจะปรับปรุงการบีบอัด แต่ต้องการหน่วยความจำมากขึ้นและทำให้การบีบอัดช้าลง

ถ้า input stream ถูกบีบอัดด้วยขนาดหน้าต่างที่กำหนด การใช้ DeflateIO ที่มีขนาดหน้าต่างน้อยกว่าจะล้มเหลวระหว่างการคลายการบีบอัดด้วย OSError แต่เฉพาะเมื่อมีการอ้างอิงย้อนกลับที่เกินขนาดหน้าต่างของตัวคลายการบีบอัด ซึ่งหมายความว่าอาจสามารถคลายการบีบอัดด้วยขนาดหน้าต่างน้อยกว่าได้ เช่น จะเป็นไปได้ง่ายหากข้อมูลต้นฉบับที่ไม่บีบอัดสั้นกว่าขนาดหน้าต่าง

การคลายการบีบอัด

รูปแบบ zlib มี header ที่ระบุขนาดหน้าต่างที่ใช้บีบอัดข้อมูล ค่านี้บ่งบอกขนาดหน้าต่างสูงสุดที่ต้องการเพื่อคลายการบีบอัด stream นี้ ถ้าค่า header นี้น้อยกว่าค่า wbits ที่ระบุ (หรือถ้าไม่ได้ตั้ง wbits) ค่าใน header จะถูกใช้แทน

รูปแบบ gzip ไม่รวมขนาดหน้าต่างใน header และสมมติว่าตัวบีบอัด gzip ทั้งหมด (เช่น ยูทิลิตี gzip หรือการใช้งาน gzip.GzipFile ของ CPython) ใช้ขนาดหน้าต่างสูงสุด 32kiB ด้วยเหตุนี้ ถ้าไม่ตั้งพารามิเตอร์ wbits ตัวคลายการบีบอัดจะใช้ขนาดหน้าต่าง 32 kiB (สอดคล้องกับ wbits ที่ตั้งเป็น 15) หมายความว่าหากต้องการคลายการบีบอัด gzip stream ใด ๆ จำเป็นต้องมี RAM อย่างน้อยเท่านี้ หากควบคุมข้อมูลต้นทางได้ ควรพิจารณาใช้รูปแบบ zlib ที่มีขนาดหน้าต่างน้อยกว่าแทน

รูปแบบ raw ไม่มี header จึงไม่มีข้อมูลเกี่ยวกับขนาดหน้าต่าง ถ้าไม่ตั้ง wbits จะใช้ขนาดหน้าต่าง 256 ไบต์เป็นค่าเริ่มต้น ซึ่งอาจไม่พอสำหรับบาง stream จึงแนะนำให้ตั้ง wbits อย่างชัดเจนเสมอเมื่อใช้รูปแบบ raw

การบีบอัด

สำหรับการบีบอัด MicroPython จะใช้ขนาดหน้าต่าง 256 ไบต์เป็นค่าเริ่มต้นสำหรับทุกรูปแบบ ซึ่งให้การบีบอัดในระดับที่เหมาะสมโดยใช้หน่วยความจำน้อยและเวลาบีบอัดรวดเร็ว และจะสร้างผลลัพธ์ที่ใช้งานได้กับตัวคลายการบีบอัดทุกตัว