What is OpenZL and GeoZL?
OpenZL is a new compression framework that treats compression as a graph of codecs. Each frame carries the recipe needed to decode it, which lets a universal OpenZL decoder follow the graph without knowing how the data was originally encoded.
That model works well for one-dimensional streams, but it does not know that a raster has spatial structure. GeoZL adds that missing spatial layer.
A GeoZL codec is an OpenZL graph node that understands raster tiles. It transforms a typed numeric stream, stores the metadata needed to reverse that transform in the codec header, and lets the rest of the OpenZL graph continue as usual.
If you want to implement a new codec, see docs/adding-a-codec.md.
Status
GeoZL is experimental.
[!WARNING] GeoZL codecs are not part of OpenZL.
They are registered at runtime as OpenZL custom transforms and use CTids in the
0x72D700-0x72D7FFrange. A frame that uses GeoZL codecs can only be decoded by a reader that has GeoZL registered. Frames that use only built-in OpenZL codecs remain portable OpenZL frames.
Install
pip install geozl
Example
GeoZL has two entry points: a high-level API that compresses a tile in one call, and a low-level API that places individual codecs in an OpenZL graph.
High-level API
geozl.profile measures a set of candidate graphs on your tile and ranks them, geozl.compress runs the one you name and returns the frame. It never searches, so the slow call happens once and the fast one happens on every tile after that. geozl.decompress reverses the frame back to a tile.
import numpy as np
import geozl
tile = np.random.randint(0, 4096, (1024, 1024), dtype=np.uint16)
rows = geozl.profile(tile) # the slow call, run once
best = rows[0]["graph"] # e.g. "planar>zigzag>transpose>entropy"
frame = geozl.compress(tile, method=best) # the fast call, run always
frame = geozl.compress(tile, method=best, error="LINEAR:MAX_ERROR=2") # near-lossless
frame = geozl.compress(tile, method=best, error="LOG:MAX_ERROR=1%") # bound follows the value
back = geozl.decompress(frame, dtype="uint16", width=1024)
Low-level API
For anything else, place the codecs in an openzl.ext graph yourself, alongside regular OpenZL nodes.
import openzl.ext as zl
import geozl
c = zl.Compressor()
g = zl.graphs.Compress()
g = zl.nodes.Zigzag()(c, g)
g = geozl.lossless.Planar(width=512)(c, g)
c.select_starting_graph(g)
Decoding
Either way, a reader has to register the geozl decoders before it can follow the frame.
import openzl.ext as zl
import geozl
d = zl.DCtx()
geozl.register_decoders(d)
tile = d.decompress(frame)[0].content.as_nparray()
Codecs
| codec | CTid | what it does |
|---|---|---|
delta_w |
0x72D701 |
residual against the west neighbour |
delta_n |
0x72D702 |
residual against the north neighbour |
planar |
0x72D703 |
predicts each pixel from W + N - NW |
deinterleave |
0x72D704 |
separates a two-lane interleaved stream |
med |
0x72D705 |
median edge detector predictor |
average |
0x72D706 |
floor average of the west and north neighbours |
wp_static |
0x72D707 |
fits a weighted predictor and stores the weights in the frame |
nodata |
0x72D70C |
pulls missing samples into a validity mask and fills the holes |
quant_linear |
0x72D781 |
uniform grid, fixed absolute bound, LINEAR:MAX_ERROR=V |
quant_log |
0x72D782 |
logarithmic grid, bound is a fraction of the value, LOG:MAX_ERROR=P% |
quant_sqrt |
0x72D783 |
square root grid, bound grows with the sensor noise, SQRT:MAX_ERROR=VN |
SQRT counts sigmas of the sensor curve a + b*x. Left out of the recipe, that
curve is fitted from whatever raster is being compressed, so neighbouring tiles
land on different grids. Measure it once over the product instead.
noise = geozl.lossy.fit_noise(stack) # (N, H, W), or any sequence of rasters
frame = geozl.compress(tile, method=best, error=noise.recipe(0.5))
License
BSD-3-Clause
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file geozl-0.8.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: geozl-0.8.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 8.3 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59fbcad2e8cb060191d68cb1afbd4e87a64fdd7acff16bdb62e23befdc1fb9db
|
|
| MD5 |
ef2cf1395d7a5da7b1bdd9909356777e
|
|
| BLAKE2b-256 |
5f896585e837e1828ee938bc68c07bcdffe1d519a19ff4d1877e94867ef217b0
|
Provenance
The following attestation bundles were made for geozl-0.8.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:
Publisher:
release.yml on asterisk-labs/geozl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geozl-0.8.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
59fbcad2e8cb060191d68cb1afbd4e87a64fdd7acff16bdb62e23befdc1fb9db - Sigstore transparency entry: 2340911375
- Sigstore integration time:
-
Permalink:
asterisk-labs/geozl@2ec84b690e19f2a8a5cda0492ca05e6632429ee2 -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/asterisk-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2ec84b690e19f2a8a5cda0492ca05e6632429ee2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file geozl-0.8.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: geozl-0.8.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.3 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a49a01a396ae0a1bd5c58ac3ee99544c4e09e698b8ae3ff608fbbfc3638dffec
|
|
| MD5 |
2a695cc0e7aeffa83d6cbe8125739e27
|
|
| BLAKE2b-256 |
e8b66167aee78c069771ffcb7a287cc60a4368e194d15edbe70addc863d1d83b
|
Provenance
The following attestation bundles were made for geozl-0.8.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on asterisk-labs/geozl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
geozl-0.8.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
a49a01a396ae0a1bd5c58ac3ee99544c4e09e698b8ae3ff608fbbfc3638dffec - Sigstore transparency entry: 2340911369
- Sigstore integration time:
-
Permalink:
asterisk-labs/geozl@2ec84b690e19f2a8a5cda0492ca05e6632429ee2 -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/asterisk-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2ec84b690e19f2a8a5cda0492ca05e6632429ee2 -
Trigger Event:
push
-
Statement type: