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 rows, columns, neighbours, or 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.compress takes a tile and returns a frame. With the default method it sweeps every predictor and keeps the smallest one.
import numpy as np
import geozl
tile = np.random.randint(0, 4096, (1024, 1024), dtype=np.uint16)
frame = geozl.compress(tile) # sweep, keep the smallest frame
frame = geozl.compress(tile, method="med") # or name one predictor
frame = geozl.compress(tile, max_error=2) # near-lossless, absolute bound
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
geozl currently provides two codec families:
- near-lossless codecs, under
geozl.lossy - lossless codecs, under
geozl.lossless
Both families are registered as OpenZL custom codecs and can be chained with other OpenZL graph nodes.
The call column shows the Python call used to place the codec in a graph.
Near-lossless codecs
Near-lossless codecs quantize the tile once, then store enough information in the frame to report and bound the reconstruction error. A near-lossless frame is no longer bit-exact, it declares the bound it holds to instead.
A frame carries at most one near-lossless codec, as the head transform, so the loss happens once and every stage after it is lossless.
| codec | call | CTid | error |
|---|---|---|---|
quant_linear |
geozl.lossy.QuantLinear(max_error, dtype) |
0x72D780 |
every value reconstructs within max_error, an absolute tolerance |
Lossless codecs
Lossless codecs are bit-exact transforms over a raster tile. After decoding, the reconstructed tile is identical to the original input.
Predictors replace each sample with its residual against a prediction from neighbours the decoder already holds. They take the row width, and one successor.
| codec | call | CTid | what it does |
|---|---|---|---|
delta_w |
geozl.lossless.DeltaW(width) |
0x72D701 |
stores each value as a difference from its west neighbour |
delta_n |
geozl.lossless.DeltaN(width) |
0x72D702 |
stores each value as a difference from its north neighbour |
planar |
geozl.lossless.Planar(width) |
0x72D703 |
predicts each pixel from W + N - NW |
med |
geozl.lossless.Med(width) |
0x72D705 |
uses the median edge detector predictor |
average |
geozl.lossless.Average(width) |
0x72D706 |
predicts from the floor average of west and north neighbours |
wp_static |
geozl.lossless.WpStatic(width) |
0x72D707 |
fits a static weighted predictor and stores the weights in the frame |
Splits cut one stream into two lanes, so they take two successors, one per lane, and each lane can go on to its own graph.
| codec | call | CTid | lanes | what it does |
|---|---|---|---|---|
deinterleave |
geozl.lossless.Deinterleave() |
0x72D704 |
both to one successor | separates a two-lane interleaved stream; for complex, view the tile through geozl.lossless.component_dtype first, OpenZL has no complex type |
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.7.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.
File metadata
- Download URL: geozl-0.7.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
- Upload date:
- Size: 8.1 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d14237158968a82105a337976d3b8ae862a09acdf55ea67b1cf5af37b776334
|
|
| MD5 |
16e0b493fc0493622efcb332a82d4d53
|
|
| BLAKE2b-256 |
b95dea3b3861cbfedf3e2fa63b5a41e883fb945bbb5e9ad7e87f3fc9f33070c1
|
Provenance
The following attestation bundles were made for geozl-0.7.5-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.7.5-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl -
Subject digest:
5d14237158968a82105a337976d3b8ae862a09acdf55ea67b1cf5af37b776334 - Sigstore transparency entry: 2222009082
- Sigstore integration time:
-
Permalink:
asterisk-labs/geozl@726afb5d3fa66140ed67cfd468feb99a38a78dde -
Branch / Tag:
refs/tags/v0.7.5 - Owner: https://github.com/asterisk-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@726afb5d3fa66140ed67cfd468feb99a38a78dde -
Trigger Event:
push
-
Statement type:
File details
Details for the file geozl-0.7.5-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: geozl-0.7.5-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.2 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
601131130ccd71cb5fedf9867c0b7315082c8c4144ec947b9e74f76f92261897
|
|
| MD5 |
05c363073b6ab5969d0b18c3e9123957
|
|
| BLAKE2b-256 |
f20b1abc8b1ae970e38bf41311f7932c9ae273dc2cd17b009a80a5717535b793
|
Provenance
The following attestation bundles were made for geozl-0.7.5-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.7.5-py3-none-macosx_11_0_arm64.whl -
Subject digest:
601131130ccd71cb5fedf9867c0b7315082c8c4144ec947b9e74f76f92261897 - Sigstore transparency entry: 2222008577
- Sigstore integration time:
-
Permalink:
asterisk-labs/geozl@726afb5d3fa66140ed67cfd468feb99a38a78dde -
Branch / Tag:
refs/tags/v0.7.5 - Owner: https://github.com/asterisk-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@726afb5d3fa66140ed67cfd468feb99a38a78dde -
Trigger Event:
push
-
Statement type: