opencodecs 0.2.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opencodecs-0.2.0 → opencodecs-0.3.1}/CHANGES.rst +143 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/MANIFEST.in +1 -0
- {opencodecs-0.2.0/src/opencodecs.egg-info → opencodecs-0.3.1}/PKG-INFO +110 -30
- {opencodecs-0.2.0 → opencodecs-0.3.1}/README.md +109 -29
- {opencodecs-0.2.0 → opencodecs-0.3.1}/THIRD-PARTY.md +1 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/pyproject.toml +3 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/setup.py +38 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/__init__.py +1 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_aec_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_avif_codec.py +40 -11
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_b2nd_codec.py +70 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bitshuffle_codec.py +7 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_blosc2_codec.py +8 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_brotli_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_brunsli_codec.py +6 -5
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_byteshuffle_codec.py +2 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_cms_codec.py +88 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_czi_codec.py +14 -2
- opencodecs-0.3.1/src/opencodecs/_czi_reader.py +2375 -0
- opencodecs-0.3.1/src/opencodecs/_czi_writer.py +841 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_deflate_codec.py +6 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom.py +162 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom_pyramid.py +32 -29
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicomrle_codec.py +44 -64
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicomweb.py +56 -5
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_eer_reader.py +20 -5
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_emd.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits.py +14 -9
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits_codec.py +6 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits_compressed.py +62 -20
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_gif_codec.py +64 -22
- opencodecs-0.3.1/src/opencodecs/_h5_common.py +203 -0
- opencodecs-0.3.1/src/opencodecs/_hdf5_codec.py +216 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_heif_codec.py +67 -21
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_htj2k_codec.py +4 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_imaris.py +8 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg2k_codec.py +33 -6
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg_codec.py +12 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpegls_codec.py +2 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jxl_codec.py +26 -5
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lerc_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lz4_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mozjpeg_codec.py +12 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc_codec.py +6 -11
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc_writer.py +53 -32
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_n5.py +25 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nd2_native.py +6 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff.py +65 -36
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff_writer.py +175 -132
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti_codec.py +6 -10
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti_writer.py +23 -18
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_none_codec.py +15 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_numpy_codec.py +23 -7
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oib_codec.py +9 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oib_native.py +56 -7
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oir_codec.py +42 -8
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_omezarr.py +337 -87
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_omezarr_writer.py +171 -213
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_packints_codec.py +40 -6
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_pcodec_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_png_codec.py +12 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_predictor_codec.py +77 -59
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_qoi_codec.py +6 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rcomp_codec.py +24 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rgbe_codec.py +2 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_snappy_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_sperr_codec.py +4 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_sz3_codec.py +5 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_codec.py +100 -66
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_http.py +177 -141
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_pyramid.py +96 -146
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_writer.py +197 -141
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_vsi_pyramid.py +53 -16
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_webp_codec.py +11 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zfp_codec.py +46 -26
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zstd_codec.py +7 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/__init__.py +1 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_avif.pyx +58 -8
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_b2nd.pyx +103 -3
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_blosc2.pyx +55 -50
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_brotli.pyx +102 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_brunsli.pyx +45 -55
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bytetools.pyx +73 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_gif.pyx +16 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_heif.pyx +132 -22
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jpeg.pyx +41 -5
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jpeg2k.pyx +122 -30
- opencodecs-0.3.1/src/opencodecs/codecs/_jpegxr.pyx +138 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jxl.pyx +38 -27
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_lz4.pyx +118 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_mozjpeg.pyx +40 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_png.pyx +258 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_rcomp.pyx +20 -6
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_sperr.pyx +3 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_tiff.pyx +21 -20
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_zfp.pyx +1 -1
- opencodecs-0.3.1/src/opencodecs/codecs/_zstd.pyx +598 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/avif.pxd +14 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd.pxd +7 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd_helpers.c +44 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd_helpers.h +11 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/blosc2.pxd +19 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/brotli.pxd +17 -1
- opencodecs-0.3.1/src/opencodecs/codecs/byteplanes.h +49 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/heif.pxd +12 -1
- opencodecs-0.3.1/src/opencodecs/codecs/jpegxr_shim.c +125 -0
- opencodecs-0.3.1/src/opencodecs/codecs/jpegxr_shim.h +32 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/lz4.pxd +11 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjpeg.pxd +3 -2
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/spng.pxd +16 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zstd.pxd +24 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_io_helpers.py +2 -1
- opencodecs-0.3.1/src/opencodecs/core/_range_index.py +76 -0
- opencodecs-0.3.1/src/opencodecs/core/_write_helpers.py +75 -0
- opencodecs-0.3.1/src/opencodecs/core/buffers.py +97 -0
- opencodecs-0.3.1/src/opencodecs/core/checksums.py +38 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/codec.py +45 -4
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/io.py +13 -8
- opencodecs-0.3.1/src/opencodecs/core/native_source.py +87 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/parallel.py +81 -4
- opencodecs-0.3.1/src/opencodecs/core/pipeline.py +198 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/pyramid.py +124 -0
- opencodecs-0.3.1/src/opencodecs/core/rows.py +167 -0
- opencodecs-0.3.1/src/opencodecs/core/scratch.py +35 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/segment_compression.py +84 -5
- opencodecs-0.3.1/src/opencodecs/core/streaming.py +180 -0
- opencodecs-0.3.1/src/opencodecs/core/tile_cache.py +129 -0
- opencodecs-0.3.1/src/opencodecs/core/verification.py +222 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1/src/opencodecs.egg-info}/PKG-INFO +110 -30
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/SOURCES.txt +65 -1
- opencodecs-0.3.1/tests/test_b2nd_file_reader.py +78 -0
- opencodecs-0.3.1/tests/test_blosc2_threads.py +52 -0
- opencodecs-0.3.1/tests/test_bounded_pipeline.py +54 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_capability_manifest.py +24 -21
- opencodecs-0.3.1/tests/test_container_pipeline.py +152 -0
- opencodecs-0.3.1/tests/test_container_streaming.py +249 -0
- opencodecs-0.3.1/tests/test_czi_bounded_iteration.py +161 -0
- opencodecs-0.3.1/tests/test_czi_direct_decode.py +238 -0
- opencodecs-0.3.1/tests/test_czi_mixed_subblocks.py +82 -0
- opencodecs-0.3.1/tests/test_czi_parallel_write.py +210 -0
- opencodecs-0.3.1/tests/test_czi_read_dispatch.py +199 -0
- opencodecs-0.3.1/tests/test_czi_read_out.py +105 -0
- opencodecs-0.3.1/tests/test_czi_region_index.py +431 -0
- opencodecs-0.3.1/tests/test_czi_region_windows.py +305 -0
- opencodecs-0.3.1/tests/test_czi_segment_parts.py +180 -0
- opencodecs-0.3.1/tests/test_czi_slide_geometry.py +209 -0
- opencodecs-0.3.1/tests/test_czi_verification.py +323 -0
- opencodecs-0.3.1/tests/test_czi_write_pipeline.py +107 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_writer.py +38 -2
- opencodecs-0.3.1/tests/test_czi_writer_shuffle.py +188 -0
- opencodecs-0.3.1/tests/test_dicom_slide_selection.py +138 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicomweb.py +149 -75
- opencodecs-0.3.1/tests/test_direct_filter_outputs.py +94 -0
- opencodecs-0.3.1/tests/test_eer_worker_budget.py +50 -0
- opencodecs-0.3.1/tests/test_filter_scratch.py +51 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_remote.py +5 -3
- opencodecs-0.3.1/tests/test_incremental_byte_codecs.py +165 -0
- opencodecs-0.3.1/tests/test_jpegxr.py +157 -0
- opencodecs-0.3.1/tests/test_native_output_sinks.py +117 -0
- opencodecs-0.3.1/tests/test_native_source_callbacks.py +181 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nd2_native.py +24 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_ndtiff.py +7 -1
- opencodecs-0.3.1/tests/test_nrrd_iteration.py +50 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_omezarr.py +2 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_omezarr_sharded_range.py +30 -1
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_open_pyramid.py +6 -18
- opencodecs-0.3.1/tests/test_owned_color_context.py +44 -0
- opencodecs-0.3.1/tests/test_owned_image_decoders.py +73 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase7_cms.py +0 -10
- opencodecs-0.3.1/tests/test_pipeline_budget.py +109 -0
- opencodecs-0.3.1/tests/test_pipeline_catalog.py +86 -0
- opencodecs-0.3.1/tests/test_pipeline_executor.py +116 -0
- opencodecs-0.3.1/tests/test_png_row_sessions.py +141 -0
- opencodecs-0.3.1/tests/test_public_output_buffers.py +203 -0
- opencodecs-0.3.1/tests/test_pyramid_batched_regions.py +227 -0
- opencodecs-0.3.1/tests/test_range_pipeline_completion.py +151 -0
- opencodecs-0.3.1/tests/test_segment_encoder_binding.py +24 -0
- opencodecs-0.3.1/tests/test_shared_io_regressions.py +255 -0
- opencodecs-0.3.1/tests/test_source_pool_lifetime.py +146 -0
- opencodecs-0.3.1/tests/test_tiff_pipeline.py +150 -0
- opencodecs-0.3.1/tests/test_tiff_spool.py +29 -0
- opencodecs-0.3.1/tests/test_tiff_writer_float_predictor.py +114 -0
- opencodecs-0.3.1/tests/test_tiff_writer_verification.py +183 -0
- opencodecs-0.3.1/tests/test_tile_cache.py +235 -0
- opencodecs-0.3.1/tests/test_verified_encoding.py +252 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_writer_contract.py +56 -0
- opencodecs-0.3.1/tests/test_writer_pipeline_completion.py +266 -0
- opencodecs-0.3.1/tests/test_writer_verification.py +139 -0
- opencodecs-0.3.1/tests/test_zarr_region_fast_path.py +99 -0
- opencodecs-0.3.1/tests/test_zstd_owned_output.py +36 -0
- opencodecs-0.2.0/src/opencodecs/_czi_reader.py +0 -1001
- opencodecs-0.2.0/src/opencodecs/_czi_writer.py +0 -522
- opencodecs-0.2.0/src/opencodecs/_h5_common.py +0 -44
- opencodecs-0.2.0/src/opencodecs/_hdf5_codec.py +0 -366
- opencodecs-0.2.0/src/opencodecs/codecs/_zstd.pyx +0 -255
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/VENDOR.toml +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/README.md +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/bcdec.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/README.rst +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_core.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_core.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_internals.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/iochain.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/iochain.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/License.txt +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hcompress.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hdecompress.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hdecompress_api.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fitsio2.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/pliocomp.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/ricecomp.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/ricecomp.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/spng.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/spng.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/oc_eer.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/oc_eer.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/oc_giflzw.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/oc_giflzw.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/oc_tifflzw.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/oc_tifflzw.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/qoi/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/qoi/qoi.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.txt +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/vendor_hashes.json +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/LICENSE +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/bench/build_libjxl.sh +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/patches/libjxl/README.md +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/setup.cfg +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bcn_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bmp_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bz2_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dm.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dm_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_emd_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ets.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_gzip_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_hdf5_http.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_htj2k_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg2k_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lif_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lif_native.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lzma_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mozjpeg_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nd2_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nrrd.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nrrd_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_numpy_reader.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ole2.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ome_xml.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_pyramid_build.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_quantize_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rgbe.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_scaled_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ultrahdr_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_vsi_codec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zarr_codecs.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_aec.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bcdec.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bitshuffle.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bmp.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_charls.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_deflate.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_eer.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_hcomp.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_isal.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_lerc.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_ndtiff.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_openjph.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_pcodec.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_plio.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_qoi.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_registry.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_rgbe.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_snappy.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_sz3.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_uhdr.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_webp.pyx +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/bcdec.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/bitshuffle.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/brunsli.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/charls.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/eer.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/giflib.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/heif_shim.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/isal_shim.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/lerc.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libaec.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libjxl.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libuhdr.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/mozjpeg.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph_shim.cpp +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph_shim.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/pcodec.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/qoi.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/rgbe.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/snappy.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/sperr.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/sz3c.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/turbojpeg.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp_shim.c +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp_shim.h +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zfp.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zlib_h.pxd +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/__init__.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_optional_backend.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_sidecar_header.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/color.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/errors.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/jxl.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/parallel.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/tiff_reader.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/tifffile_patch.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/uhdr.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/zarr.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/dependency_links.txt +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/requires.txt +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/top_level.txt +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_auto_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_avif_sequence.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_bcdec.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_bcn_bands.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_blosc2_partial.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_brunsli.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_charls.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_chunked_means_cheap.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_codec_registry.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_core_codec_api.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_codec_decode.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_manifest.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_native_fixtures.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_other.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_png.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_tiff.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_vendors.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_final.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_finishing.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_last.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_more.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_push.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_fixture.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_data_source.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_decode_releases_gil.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_deflate.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_delta_parity.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_encodings.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_parallel.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_wsi_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm_offsets.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm_synthetic.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_edge_cases.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_eer.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_eer_parallel.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_emd.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_encode_comprehensive.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_error_handling.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_fits.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_fits_parallel.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_gif.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_gzip_presized.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_http.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_local.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_parallel.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_heif_avif_features.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_heif_multi_image.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_htj2k_conformance.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_byte_savings.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_prefetch.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_unified.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_imaris.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_io_chunked.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_isal.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_jpeg2k_region.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_jxl.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_lif_indexing.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_lif_native.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_live_archives.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mozjpeg.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc_mrcz_http.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc_nifti_writers.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_n5.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_native_parity.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nifti.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nrrd.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nrrd_slices.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_offset_readers.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_oib_indexing.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_oib_native.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_ome_xml.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_openjph.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_optional_backend.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_parallel_jxl.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase4_filters.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase5_icc.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase6_codecs.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_rcomp_truncated_input.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_contract.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_source_kinds.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_streaming.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reference_parity.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_rgbe.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_scaled_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_sidecar_header.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_snappy.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_streaming_means_streaming.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tier1_scientific.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_codec_encode.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_http.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_native.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_parallel_decode.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_read_path.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_reader.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_writer.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tifffile_patch.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_uhdr.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_unified_api.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_url_sources.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vendor_provenance.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_version_consistency.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vsi_oir.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vsi_pyramid.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_webp_animation.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_zarr_adapters.py +0 -0
- {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_zfp_blocks.py +0 -0
|
@@ -10,6 +10,146 @@ Versions follow the same ``YYYY.M.D`` cadence as upstream when we
|
|
|
10
10
|
publish; the entries below cluster work by date rather than by
|
|
11
11
|
release because most of it has shipped continuously to ``main``.
|
|
12
12
|
|
|
13
|
+
0.3.1 (2026-09-28)
|
|
14
|
+
------------------
|
|
15
|
+
|
|
16
|
+
A CZI read scheduling fix, and a clear refusal for the files that cannot
|
|
17
|
+
stack. Figures compare against 0.3.0 on the same machines.
|
|
18
|
+
|
|
19
|
+
**CZI whole-stack reads hand out work by bytes**
|
|
20
|
+
|
|
21
|
+
``read`` derived its batch size from the worker count, giving each worker
|
|
22
|
+
``ceil(n/workers)`` consecutive sub-blocks. That makes the read wait on
|
|
23
|
+
that many sub-blocks even when most workers have already finished: nine
|
|
24
|
+
8 MiB sub-blocks over eight workers is two rounds, and measured 15.1 ms
|
|
25
|
+
against 7.9 ms for nine one-sub-block tasks. Tasks are now sized by
|
|
26
|
+
output bytes, about 8 MiB each, so a large sub-block gets a task to
|
|
27
|
+
itself and small ones ride together. That keeps the reason batching
|
|
28
|
+
existed, which is that a 0.7 MiB tile cannot pay for its own future,
|
|
29
|
+
without paying the rounding. ``_READ_MAX_WORKERS`` goes 8 to 32: the old
|
|
30
|
+
value was measured against the dispatch above, where extra workers could
|
|
31
|
+
not help. With byte-sized tasks, 20 to 32 measured fastest on both a
|
|
32
|
+
20-core arm64 Mac and a 128-core x86-64 Linux host, and past 32 the Linux
|
|
33
|
+
host gives it back to memory-bandwidth contention. A semaphore keeps the
|
|
34
|
+
resolved worker count a real bound when the byte sizing yields more tasks
|
|
35
|
+
than that.
|
|
36
|
+
|
|
37
|
+
Eight files of 2000 x 2000 uint16 ZSTDHDR sub-blocks, read back to back:
|
|
38
|
+
22.1 to about 15 ms per file on macOS, which moves a whole-stack read
|
|
39
|
+
from a little behind aicspylibczi to about 1.3x ahead of it.
|
|
40
|
+
|
|
41
|
+
**A mixed sub-block CZI says so, instead of failing inside the codec**
|
|
42
|
+
|
|
43
|
+
``read`` stacks every sub-block into one array, and sized that array from
|
|
44
|
+
the first sub-block, which is wrong for any file whose sub-blocks differ:
|
|
45
|
+
a pyramidal slide scan interleaves down-scaled sub-blocks with
|
|
46
|
+
full-resolution ones, and a mosaic can clip its edge tiles. The decode
|
|
47
|
+
destination check then failed with an element count the caller never
|
|
48
|
+
chose, naming neither the file's shape mix nor a way forward. It now
|
|
49
|
+
refuses up front, listing the shapes it cannot stack and the APIs that do
|
|
50
|
+
work (``CziPyramidReader.read_region``, ``entries_at_level``,
|
|
51
|
+
``read_tile`` and ``iter_tiles``), and the new ``CziReader.is_uniform``
|
|
52
|
+
lets a caller branch before asking. Decoding was never at fault: JPEG XR
|
|
53
|
+
sub-blocks are pixel-exact against aicspylibczi.
|
|
54
|
+
|
|
55
|
+
0.3.0 (2026-09-27)
|
|
56
|
+
------------------
|
|
57
|
+
|
|
58
|
+
Mostly a speed release. Figures below compare against 0.2.0 unless they
|
|
59
|
+
say otherwise; the README's Performance section has the full table for a
|
|
60
|
+
Mac and a Linux workstation.
|
|
61
|
+
|
|
62
|
+
**Shared bounded pipeline across readers and writers**
|
|
63
|
+
|
|
64
|
+
A common layer in ``opencodecs.core`` now carries the work that each
|
|
65
|
+
format used to do its own way: ordered, byte-bounded parallel
|
|
66
|
+
scheduling (``core.pipeline.map_bounded``) with a shared worker
|
|
67
|
+
budget, per-worker scratch buffers, caller-owned output buffers and
|
|
68
|
+
sinks for the native codecs, stateful streaming iterators for seven
|
|
69
|
+
byte codecs, native PNG row sessions, selective range sources, and
|
|
70
|
+
opt-in bit-exact verification of written segments. Each piece of work
|
|
71
|
+
is recorded, with its measured limits, in ``pipeline_catalog.toml``
|
|
72
|
+
and checked by ``ci/check_pipeline_catalog.py``.
|
|
73
|
+
|
|
74
|
+
**Zarr, TIFF and blosc2 under many threads**
|
|
75
|
+
|
|
76
|
+
- Zarr regional reads can run in parallel, with ``num_workers`` on
|
|
77
|
+
``read_region`` or ``OmeZarrArray``; the default stays serial. Chunks
|
|
78
|
+
are grouped into tasks of about 2 MiB on a persistent pool, chunk files
|
|
79
|
+
are read with os-level calls, and plain zstd chunks decompress straight
|
|
80
|
+
into the output. A 4096 x 4096 array in 256 x 256 chunks, 0.2.0's serial
|
|
81
|
+
read against eight workers: zstd 72.9 to 19.6 ms on Linux (50.1 to
|
|
82
|
+
14.9 ms on macOS), zlib 184 to 38.8 ms (80.5 to 25.9 ms).
|
|
83
|
+
- Zarr v2 ``blosc`` chunks decode through the native blosc2 extension
|
|
84
|
+
instead of numcodecs, whose binding serializes calls across threads:
|
|
85
|
+
the default serial read goes 37.5 to 20.0 ms on macOS and 35.1 to
|
|
86
|
+
29.4 ms on Linux.
|
|
87
|
+
- Fix: blosc2 encode selected its compressor through process-global
|
|
88
|
+
state, so concurrent encodes could use another thread's compressor.
|
|
89
|
+
Encode, decode and partial decode now each use a context of their own,
|
|
90
|
+
which also stops them queuing on blosc2's global mutex: from eight
|
|
91
|
+
threads, 64 chunks of 1 MiB decode 6.2 to 6.5x and encode 6.6 to 7.1x
|
|
92
|
+
faster. Chunks written with item size 1 and shuffle carry slightly
|
|
93
|
+
different header flags; old and new chunks decode in both versions.
|
|
94
|
+
- TIFF tiles with the horizontal predictor decode into a writable array,
|
|
95
|
+
so the predictor no longer copies each tile first (1.1 to 1.2x on a
|
|
96
|
+
tiled 4096 x 4096 deflate image).
|
|
97
|
+
|
|
98
|
+
**CZI: faster reads and writes, and real slides read correctly**
|
|
99
|
+
|
|
100
|
+
- JPEG XR sub-blocks (compression 4, used by most Zeiss slide scans) now
|
|
101
|
+
decode through a new optional ``_jpegxr`` extension over jxrlib, built
|
|
102
|
+
when jxrlib is installed. Every tile of the Axioscan corpus slide and its
|
|
103
|
+
whole 20684 x 32751 level 0 match czifile exactly. The wheels build
|
|
104
|
+
jxrlib from source (conda-forge on Windows) and link it statically.
|
|
105
|
+
- Fix: overlapping mosaic tiles composed in directory order. Zen writes
|
|
106
|
+
tiles out of mosaic-index order, and libCZI and czifile draw the higher
|
|
107
|
+
mosaic index on top; each level now composes in that order, which on the
|
|
108
|
+
corpus slide changes 8.9 million overlap pixels at level 0.
|
|
109
|
+
- Fix: ``CziPyramidReader`` took sub-block starts as level pixels.
|
|
110
|
+
Zen stores them in full-resolution slide coordinates, often far from
|
|
111
|
+
zero and negative, so a real slide reported every level as ``(N, 0)``.
|
|
112
|
+
Levels now count from the slide origin (``reader.origin``, matching
|
|
113
|
+
czifile) and divide positions by the level's scale.
|
|
114
|
+
- Sub-blocks decode straight into their destination. Whole-stack
|
|
115
|
+
``read`` accepts ``out=`` (``numpy.memmap`` included). zstd
|
|
116
|
+
decompression and the byte unshuffle run as one native call, which
|
|
117
|
+
let several threads decode small tiles at once: a stack read with eight
|
|
118
|
+
workers goes 12.0 to 3.9 ms on Linux (2.5 to 1.7 ms on macOS).
|
|
119
|
+
- Regional reads use a lazily built spatial index and write each tile
|
|
120
|
+
straight into the output; overlapping tiles still resolve to the
|
|
121
|
+
later one in the directory. ``PyramidReader.read_regions`` decodes
|
|
122
|
+
the union of a batch of boxes once, and ``decoded_cache_bytes`` adds
|
|
123
|
+
an opt-in decoded-tile cache.
|
|
124
|
+
- Opening is faster: the directory parses in about a third of the
|
|
125
|
+
time and the pyramid reader no longer rescans it per level (180 ms to
|
|
126
|
+
3 ms on a 12k-sub-block slide).
|
|
127
|
+
- ``read_regions`` on CZI decodes each tile shared by several boxes once,
|
|
128
|
+
straight into every box's output: 50 disjoint crops take 5.1 ms on
|
|
129
|
+
Linux against 29.8 ms one call at a time in 0.2.0 (3.1 against 17.2 ms
|
|
130
|
+
on macOS).
|
|
131
|
+
- The writer shuffles natively, emits sub-blocks as parts without
|
|
132
|
+
copying unverified payloads, and ``write_many`` compresses frames on
|
|
133
|
+
workers while keeping the file byte-identical to sequential writes.
|
|
134
|
+
Eight 2048 x 2048 frames with zstd: 189 to 89 ms one frame at a time on
|
|
135
|
+
Linux and 41 ms with ``write_many`` (82 to 54 and 20 ms on macOS).
|
|
136
|
+
- ``CziWriter(background_encode=True)`` compresses frames of 1 MiB or
|
|
137
|
+
more on a background thread while the caller prepares the next one.
|
|
138
|
+
Opt-in: with work between frames it wrote 1.44 to 1.46x faster, with
|
|
139
|
+
frames ready and nothing to overlap it was 0.87 to 0.96x.
|
|
140
|
+
|
|
141
|
+
**Build and tests**
|
|
142
|
+
|
|
143
|
+
- Every wheel now carries the same 40 compiled extensions, the 39 of
|
|
144
|
+
0.2.0 plus ``_jpegxr``, and ``ci/check_wheel_contents.py`` requires it.
|
|
145
|
+
- SZ3 3.3.2, since upstream deleted the 3.3.1 tag.
|
|
146
|
+
- The DICOMweb client is tested over HTTP against a local server
|
|
147
|
+
(``tests/_dicomweb_server.py``) serving a synthetic study written by
|
|
148
|
+
reference encoders, instead of a public demo server.
|
|
149
|
+
- Fix: the pipeline catalog check accepted a rooted evidence path such
|
|
150
|
+
as ``/etc/passwd`` on Windows, where ``Path.is_absolute()`` needs a
|
|
151
|
+
drive letter.
|
|
152
|
+
|
|
13
153
|
0.2.0 (2026-09-09)
|
|
14
154
|
------------------
|
|
15
155
|
|
|
@@ -1029,9 +1169,9 @@ streaming write-out without changing their code.
|
|
|
1029
1169
|
* Locally validated on a Windows VM (MSVC 14.44 — same as CI) and
|
|
1030
1170
|
a Linux x86_64 host: ``bash bench/build_codec_libs.sh
|
|
1031
1171
|
--only=mozjpeg`` followed by ``setup.py build_ext --inplace``
|
|
1032
|
-
produces ``_mozjpeg.{pyd,so}`` cleanly.
|
|
1033
|
-
|
|
1034
|
-
|
|
1172
|
+
produces ``_mozjpeg.{pyd,so}`` cleanly. This iteration was validated
|
|
1173
|
+
end-to-end through the same script CI runs, with the same env vars,
|
|
1174
|
+
before any push.
|
|
1035
1175
|
|
|
1036
1176
|
**Post-publish wheel coverage check (CI hardening)**
|
|
1037
1177
|
|
|
@@ -21,6 +21,7 @@ recursive-include src/opencodecs *.pyx *.pxd *.h *.hpp
|
|
|
21
21
|
include src/opencodecs/codecs/b2nd_helpers.c
|
|
22
22
|
include src/opencodecs/codecs/isal_shim.c
|
|
23
23
|
include src/opencodecs/codecs/webp_shim.c
|
|
24
|
+
include src/opencodecs/codecs/jpegxr_shim.c
|
|
24
25
|
include src/opencodecs/codecs/openjph_shim.cpp
|
|
25
26
|
recursive-include 3rdparty *.c *.h *.hpp *.md *.rst *.txt *.toml *.json
|
|
26
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opencodecs
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Streaming, network-aware image codecs for scientific imaging (prototype: JPEG XL)
|
|
5
5
|
Author: Kevin Cutler
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -297,9 +297,14 @@ with open_remote_hdf5("https://bucket.s3.amazonaws.com/big.h5") as f:
|
|
|
297
297
|
arr = f["img"][:1024, :1024] # all from cache
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
-
`czi` decodes types 0 (uncompressed)
|
|
301
|
-
|
|
302
|
-
`
|
|
300
|
+
`czi` decodes compression types 0 (uncompressed), 5 (zstd), 6 (ZSTDHDR)
|
|
301
|
+
and 4 (JPEG XR). JPEG XR, which most Zeiss slide scans use, needs the
|
|
302
|
+
optional `_jpegxr` extension, built when jxrlib is installed (Homebrew
|
|
303
|
+
`jxrlib`, conda-forge `jxrlib`, Debian/Ubuntu `libjxr-dev`). The wheels
|
|
304
|
+
carry it from 0.3.0 on, statically linked on every platform. A JPEG XR
|
|
305
|
+
sub-block without it raises `CziError`. Pyramid levels are placed from the slide origin and scale, and
|
|
306
|
+
overlapping mosaic tiles compose with the higher mosaic index on top, as
|
|
307
|
+
libCZI and czifile do. The reader exposes `metadata_bytes` and
|
|
303
308
|
`metadata_xml` as lazy zero-copy accessors.
|
|
304
309
|
|
|
305
310
|
### zarr v3 codecs
|
|
@@ -320,8 +325,66 @@ z = zarr.create_array(
|
|
|
320
325
|
|
|
321
326
|
## Performance
|
|
322
327
|
|
|
328
|
+
### 0.3.0 against 0.2.0
|
|
329
|
+
|
|
330
|
+
0.3.0 is mostly a speed release. Each row below ran both versions in fresh
|
|
331
|
+
processes on the same inputs, alternating which went first, and counts only
|
|
332
|
+
where both returned identical pixels. Medians in milliseconds, on a 20-core
|
|
333
|
+
Apple silicon Mac and a 64-core x86-64 Linux workstation.
|
|
334
|
+
|
|
335
|
+
| Workload | Mac 0.2.0 | Mac 0.3.0 | Mac speedup | Linux 0.2.0 | Linux 0.3.0 | Linux speedup |
|
|
336
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
337
|
+
| CZI | | | | | | |
|
|
338
|
+
| Open a whole-slide file | 77.6 | 27.9 | 2.8x | 88.4 | 48.7 | 1.8x |
|
|
339
|
+
| Open it and read the first crop | 255 | 39.1 | 6.5x | 267 | 58.7 | 4.6x |
|
|
340
|
+
| Build the pyramid reader | 174 | 3.4 | 51.1x | 164 | 4.7 | 35.0x |
|
|
341
|
+
| Read a 20 x 20 tile mosaic | 23.9 | 10.1 | 2.4x | 55.8 | 18.4 | 3.0x |
|
|
342
|
+
| Small crops of the mosaic | 69.5 | 26.6 | 2.6x | 121 | 54.7 | 2.2x |
|
|
343
|
+
| 50 disjoint crops, one call each | 17.2 | 6.7 | 2.6x | 29.8 | 11.3 | 2.6x |
|
|
344
|
+
| 50 disjoint crops, `read_regions` | 17.2 | 3.1 | 5.5x | 29.8 | 5.1 | 5.9x |
|
|
345
|
+
| Stack read, 8 workers | 2.5 | 1.7 | 1.5x | 12.0 | 3.9 | 3.1x |
|
|
346
|
+
| Write 8 frames, zstd | 82.1 | 53.9 | 1.5x | 189 | 89.3 | 2.1x |
|
|
347
|
+
| Write 8 frames, zstd, `write_many` | 82.1 | 19.9 | 4.1x | 189 | 40.9 | 4.6x |
|
|
348
|
+
| Write 8 frames, uncompressed | 28.9 | 10.1 | 2.8x | 226 | 38.3 | 5.9x |
|
|
349
|
+
| Zarr, 4096 x 4096 uint16 in 256 x 256 chunks, whole array | | | | | | |
|
|
350
|
+
| v2 zstd, default | 50.1 | 45.6 | 1.1x | 72.9 | 62.2 | 1.2x |
|
|
351
|
+
| v2 zstd, `num_workers=8` | 50.1 | 14.9 | 3.4x | 72.9 | 19.6 | 3.7x |
|
|
352
|
+
| v2 zlib, `num_workers=8` | 80.5 | 25.9 | 3.1x | 184 | 38.8 | 4.7x |
|
|
353
|
+
| v2 blosc, default | 37.5 | 20.0 | 1.9x | 35.1 | 29.4 | 1.2x |
|
|
354
|
+
| v3 zstd, `num_workers=8` | 51.3 | 14.6 | 3.5x | 62.1 | 19.4 | 3.2x |
|
|
355
|
+
| blosc2 from 8 threads, 64 chunks of 1 MiB | | | | | | |
|
|
356
|
+
| Decode | 25.4 | 3.9 | 6.5x | 38.0 | 6.1 | 6.2x |
|
|
357
|
+
| Encode | 32.9 | 5.0 | 6.6x | 47.9 | 6.8 | 7.1x |
|
|
358
|
+
| TIFF | | | | | | |
|
|
359
|
+
| Tiled, deflate with horizontal predictor, 4096 x 4096 | 20.5 | 17.5 | 1.2x | 25.4 | 23.4 | 1.1x |
|
|
360
|
+
|
|
361
|
+
Rows that name `num_workers=8`, `read_regions` or `write_many` use options
|
|
362
|
+
new in 0.3.0; they are compared with the only way 0.2.0 could do the same
|
|
363
|
+
work. Zarr regional reads stay serial unless you pass `num_workers`
|
|
364
|
+
(to `read_region` or `OmeZarrArray`).
|
|
365
|
+
|
|
366
|
+
Where it comes from:
|
|
367
|
+
|
|
368
|
+
- **CZI**: the directory parses with precompiled structs, pyramid levels
|
|
369
|
+
are grouped once instead of per level, and each tile is decompressed,
|
|
370
|
+
unshuffled and written into the output in one native call that releases
|
|
371
|
+
the GIL once. Separate calls made threads queue for the GIL between
|
|
372
|
+
steps. Regional reads use a spatial index and decode only the tiles a
|
|
373
|
+
box touches; `read_regions` decodes a tile shared by several boxes once.
|
|
374
|
+
- **Zarr**: parallel regional reads are new, with consecutive chunks
|
|
375
|
+
batched into tasks of about 2 MiB, plain zstd chunks decompressed
|
|
376
|
+
straight into the output, and v2 blosc chunks decoded through the native
|
|
377
|
+
blosc2 extension rather than numcodecs, whose binding serializes calls
|
|
378
|
+
across threads.
|
|
379
|
+
- **blosc2**: each call now has its own compression context. The old path
|
|
380
|
+
selected the compressor through process-global state behind a global
|
|
381
|
+
mutex, which serialized every thread and could hand one thread another's
|
|
382
|
+
compressor (a correctness bug, also fixed).
|
|
383
|
+
|
|
384
|
+
### Across releases
|
|
385
|
+
|
|
323
386
|
Headline numbers from the latest bench run (`bench/run_benchmarks.py
|
|
324
|
-
--fast`,
|
|
387
|
+
--fast`, Apple silicon Mac, vs `imagecodecs` / `tifffile` / `ndstorage`):
|
|
325
388
|
|
|
326
389
|
| Workload | opencodecs | reference | ratio |
|
|
327
390
|
|---|---:|---:|---:|
|
|
@@ -354,7 +417,7 @@ to 8× wall-clock).
|
|
|
354
417
|
Scientific microscopy CZI (66 MB, 14 sub-blocks of 2000×2000 uint16,
|
|
355
418
|
ZSTDHDR), single-file warm cache:
|
|
356
419
|
|
|
357
|
-
| Reader | Mac
|
|
420
|
+
| Reader | Apple silicon Mac | x86-64 Linux |
|
|
358
421
|
|---------------|-------:|--------------------:|
|
|
359
422
|
| czifile (Python ref) | 148 ms | 414 ms |
|
|
360
423
|
| aicspylibczi (C++) | 17 ms | 140 ms |
|
|
@@ -396,9 +459,12 @@ caps = tomllib.load(open("capabilities.toml", "rb"))["codec"]
|
|
|
396
459
|
[c["name"] for c in caps if c["pyramid"]] # codecs with a pyramid reader
|
|
397
460
|
```
|
|
398
461
|
|
|
399
|
-
The manifest covers the codec registry
|
|
400
|
-
(
|
|
401
|
-
|
|
462
|
+
The runtime manifest covers the codec registry. The companion
|
|
463
|
+
[pipeline catalog](pipeline_catalog.toml) also covers direct adapters such as
|
|
464
|
+
Imaris, OME-Zarr, NDTiff and N5, and maps shared optimization work across all
|
|
465
|
+
registered codecs. See the [implementation plan](docs/pipeline_optimization_plan.md)
|
|
466
|
+
for priorities, source evidence, correctness prerequisites and acceptance tests.
|
|
467
|
+
Run `python ci/check_pipeline_catalog.py report` for the current worklist.
|
|
402
468
|
|
|
403
469
|
### Codec registry
|
|
404
470
|
|
|
@@ -543,10 +609,12 @@ prefix = jxl.thumbnail_bytes("scan.jxl")
|
|
|
543
609
|
pip install opencodecs
|
|
544
610
|
```
|
|
545
611
|
|
|
546
|
-
Wheels are published for CPython 3.10
|
|
547
|
-
Linux (x86_64 + aarch64), and Windows (amd64).
|
|
548
|
-
|
|
549
|
-
c-blosc2, and friends
|
|
612
|
+
Wheels are published for CPython 3.10 to 3.13 on macOS 15+ (arm64),
|
|
613
|
+
Linux (x86_64 + aarch64, manylinux_2_28), and Windows (amd64). Every
|
|
614
|
+
platform ships the same 39 compiled extensions, bundling libjxl,
|
|
615
|
+
libavif, libheif, libwebp, libdeflate, c-blosc2, CharLS and friends,
|
|
616
|
+
so no system dependencies are needed. Intel Macs and macOS releases
|
|
617
|
+
older than 15 install from the sdist instead.
|
|
550
618
|
|
|
551
619
|
For a source install, system development headers, or to build a
|
|
552
620
|
tuned local libjxl, see [INSTALL.md](INSTALL.md). Wheel publishing
|
|
@@ -569,29 +637,41 @@ build).
|
|
|
569
637
|
|
|
570
638
|
## Status
|
|
571
639
|
|
|
572
|
-
- **v0.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
640
|
+
- **v0.3.0** on PyPI (September 2026). Every wheel carries the same 40
|
|
641
|
+
compiled extensions, and `ci/check_wheel_contents.py` fails the
|
|
642
|
+
release build if one goes missing.
|
|
643
|
+
- About 4,000 tests locally, including a 40-dataset conformance corpus;
|
|
644
|
+
CI runs the corpus-independent suite on macOS, Linux and Windows for
|
|
645
|
+
Python 3.10 and 3.13.
|
|
646
|
+
- Native readers and writers for the common scientific containers
|
|
647
|
+
(TIFF, BigTIFF, OME-TIFF, CZI, NDTiff, HDF5, JXL, FITS, OME-Zarr v2 +
|
|
648
|
+
v3 sharded), and pyramid readers for TIFF/COG/SVS, OME-Zarr, CZI,
|
|
649
|
+
Imaris, DICOM VL Whole Slide Microscopy and Olympus VSI/ETS
|
|
650
|
+
- Shared source adapters support paths, buffers, file objects and remote URLs.
|
|
651
|
+
Indexed readers use checked range requests, covering caches and adaptive
|
|
652
|
+
read-ahead; whole-stream codecs retain their documented eager input paths.
|
|
653
|
+
- Multi-frame AVIF, animated WebP and GIF decode to a frame stack; HEIF
|
|
654
|
+
exposes every top-level image
|
|
579
655
|
- Compression backend auto-detect (libdeflate → zlib-ng-compat → stdlib)
|
|
580
|
-
- Cloud I/O primitives (`HTTPDataSource` with covering-cache + adaptive
|
|
581
|
-
read-ahead) wired into TIFF / HDF5 / DICOMweb / CZI / FITS / Zarr v3
|
|
582
|
-
readers
|
|
583
656
|
- `tifffile_patch` opt-in shim reroutes tifffile's codec dispatch through
|
|
584
657
|
opencodecs for users who want only a partial swap
|
|
658
|
+
- `capabilities.toml` records what each codec actually supports, checked
|
|
659
|
+
against the built extensions, with no open gaps
|
|
585
660
|
|
|
586
661
|
Deferred work (see [`docs/TODO_DEFERRED.md`](docs/TODO_DEFERRED.md)):
|
|
587
662
|
|
|
588
|
-
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
-
|
|
594
|
-
|
|
663
|
+
- CCITT Fax3/Fax4 encode: legacy fax, zero scientific users
|
|
664
|
+
- JPEG XR encode (decode exists for CZI; see above)
|
|
665
|
+
|
|
666
|
+
GIF and JPEG XL destination writers now drain encoded frame output before close.
|
|
667
|
+
The shared pipeline also supplies bounded independent-piece scheduling, seven
|
|
668
|
+
stateful byte-codec iterators, native PNG row sessions, selective native sources,
|
|
669
|
+
and checked caller-owned destinations.
|
|
670
|
+
|
|
671
|
+
Shared streaming, buffering, and overlap mechanisms and remaining integration
|
|
672
|
+
work are documented in [the pipeline catalog](docs/shared_pipeline_capabilities.md).
|
|
673
|
+
|
|
674
|
+
See [CHANGES.rst](CHANGES.rst) for release history.
|
|
595
675
|
|
|
596
676
|
## License
|
|
597
677
|
|
|
@@ -245,9 +245,14 @@ with open_remote_hdf5("https://bucket.s3.amazonaws.com/big.h5") as f:
|
|
|
245
245
|
arr = f["img"][:1024, :1024] # all from cache
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
-
`czi` decodes types 0 (uncompressed)
|
|
249
|
-
|
|
250
|
-
`
|
|
248
|
+
`czi` decodes compression types 0 (uncompressed), 5 (zstd), 6 (ZSTDHDR)
|
|
249
|
+
and 4 (JPEG XR). JPEG XR, which most Zeiss slide scans use, needs the
|
|
250
|
+
optional `_jpegxr` extension, built when jxrlib is installed (Homebrew
|
|
251
|
+
`jxrlib`, conda-forge `jxrlib`, Debian/Ubuntu `libjxr-dev`). The wheels
|
|
252
|
+
carry it from 0.3.0 on, statically linked on every platform. A JPEG XR
|
|
253
|
+
sub-block without it raises `CziError`. Pyramid levels are placed from the slide origin and scale, and
|
|
254
|
+
overlapping mosaic tiles compose with the higher mosaic index on top, as
|
|
255
|
+
libCZI and czifile do. The reader exposes `metadata_bytes` and
|
|
251
256
|
`metadata_xml` as lazy zero-copy accessors.
|
|
252
257
|
|
|
253
258
|
### zarr v3 codecs
|
|
@@ -268,8 +273,66 @@ z = zarr.create_array(
|
|
|
268
273
|
|
|
269
274
|
## Performance
|
|
270
275
|
|
|
276
|
+
### 0.3.0 against 0.2.0
|
|
277
|
+
|
|
278
|
+
0.3.0 is mostly a speed release. Each row below ran both versions in fresh
|
|
279
|
+
processes on the same inputs, alternating which went first, and counts only
|
|
280
|
+
where both returned identical pixels. Medians in milliseconds, on a 20-core
|
|
281
|
+
Apple silicon Mac and a 64-core x86-64 Linux workstation.
|
|
282
|
+
|
|
283
|
+
| Workload | Mac 0.2.0 | Mac 0.3.0 | Mac speedup | Linux 0.2.0 | Linux 0.3.0 | Linux speedup |
|
|
284
|
+
|---|---:|---:|---:|---:|---:|---:|
|
|
285
|
+
| CZI | | | | | | |
|
|
286
|
+
| Open a whole-slide file | 77.6 | 27.9 | 2.8x | 88.4 | 48.7 | 1.8x |
|
|
287
|
+
| Open it and read the first crop | 255 | 39.1 | 6.5x | 267 | 58.7 | 4.6x |
|
|
288
|
+
| Build the pyramid reader | 174 | 3.4 | 51.1x | 164 | 4.7 | 35.0x |
|
|
289
|
+
| Read a 20 x 20 tile mosaic | 23.9 | 10.1 | 2.4x | 55.8 | 18.4 | 3.0x |
|
|
290
|
+
| Small crops of the mosaic | 69.5 | 26.6 | 2.6x | 121 | 54.7 | 2.2x |
|
|
291
|
+
| 50 disjoint crops, one call each | 17.2 | 6.7 | 2.6x | 29.8 | 11.3 | 2.6x |
|
|
292
|
+
| 50 disjoint crops, `read_regions` | 17.2 | 3.1 | 5.5x | 29.8 | 5.1 | 5.9x |
|
|
293
|
+
| Stack read, 8 workers | 2.5 | 1.7 | 1.5x | 12.0 | 3.9 | 3.1x |
|
|
294
|
+
| Write 8 frames, zstd | 82.1 | 53.9 | 1.5x | 189 | 89.3 | 2.1x |
|
|
295
|
+
| Write 8 frames, zstd, `write_many` | 82.1 | 19.9 | 4.1x | 189 | 40.9 | 4.6x |
|
|
296
|
+
| Write 8 frames, uncompressed | 28.9 | 10.1 | 2.8x | 226 | 38.3 | 5.9x |
|
|
297
|
+
| Zarr, 4096 x 4096 uint16 in 256 x 256 chunks, whole array | | | | | | |
|
|
298
|
+
| v2 zstd, default | 50.1 | 45.6 | 1.1x | 72.9 | 62.2 | 1.2x |
|
|
299
|
+
| v2 zstd, `num_workers=8` | 50.1 | 14.9 | 3.4x | 72.9 | 19.6 | 3.7x |
|
|
300
|
+
| v2 zlib, `num_workers=8` | 80.5 | 25.9 | 3.1x | 184 | 38.8 | 4.7x |
|
|
301
|
+
| v2 blosc, default | 37.5 | 20.0 | 1.9x | 35.1 | 29.4 | 1.2x |
|
|
302
|
+
| v3 zstd, `num_workers=8` | 51.3 | 14.6 | 3.5x | 62.1 | 19.4 | 3.2x |
|
|
303
|
+
| blosc2 from 8 threads, 64 chunks of 1 MiB | | | | | | |
|
|
304
|
+
| Decode | 25.4 | 3.9 | 6.5x | 38.0 | 6.1 | 6.2x |
|
|
305
|
+
| Encode | 32.9 | 5.0 | 6.6x | 47.9 | 6.8 | 7.1x |
|
|
306
|
+
| TIFF | | | | | | |
|
|
307
|
+
| Tiled, deflate with horizontal predictor, 4096 x 4096 | 20.5 | 17.5 | 1.2x | 25.4 | 23.4 | 1.1x |
|
|
308
|
+
|
|
309
|
+
Rows that name `num_workers=8`, `read_regions` or `write_many` use options
|
|
310
|
+
new in 0.3.0; they are compared with the only way 0.2.0 could do the same
|
|
311
|
+
work. Zarr regional reads stay serial unless you pass `num_workers`
|
|
312
|
+
(to `read_region` or `OmeZarrArray`).
|
|
313
|
+
|
|
314
|
+
Where it comes from:
|
|
315
|
+
|
|
316
|
+
- **CZI**: the directory parses with precompiled structs, pyramid levels
|
|
317
|
+
are grouped once instead of per level, and each tile is decompressed,
|
|
318
|
+
unshuffled and written into the output in one native call that releases
|
|
319
|
+
the GIL once. Separate calls made threads queue for the GIL between
|
|
320
|
+
steps. Regional reads use a spatial index and decode only the tiles a
|
|
321
|
+
box touches; `read_regions` decodes a tile shared by several boxes once.
|
|
322
|
+
- **Zarr**: parallel regional reads are new, with consecutive chunks
|
|
323
|
+
batched into tasks of about 2 MiB, plain zstd chunks decompressed
|
|
324
|
+
straight into the output, and v2 blosc chunks decoded through the native
|
|
325
|
+
blosc2 extension rather than numcodecs, whose binding serializes calls
|
|
326
|
+
across threads.
|
|
327
|
+
- **blosc2**: each call now has its own compression context. The old path
|
|
328
|
+
selected the compressor through process-global state behind a global
|
|
329
|
+
mutex, which serialized every thread and could hand one thread another's
|
|
330
|
+
compressor (a correctness bug, also fixed).
|
|
331
|
+
|
|
332
|
+
### Across releases
|
|
333
|
+
|
|
271
334
|
Headline numbers from the latest bench run (`bench/run_benchmarks.py
|
|
272
|
-
--fast`,
|
|
335
|
+
--fast`, Apple silicon Mac, vs `imagecodecs` / `tifffile` / `ndstorage`):
|
|
273
336
|
|
|
274
337
|
| Workload | opencodecs | reference | ratio |
|
|
275
338
|
|---|---:|---:|---:|
|
|
@@ -302,7 +365,7 @@ to 8× wall-clock).
|
|
|
302
365
|
Scientific microscopy CZI (66 MB, 14 sub-blocks of 2000×2000 uint16,
|
|
303
366
|
ZSTDHDR), single-file warm cache:
|
|
304
367
|
|
|
305
|
-
| Reader | Mac
|
|
368
|
+
| Reader | Apple silicon Mac | x86-64 Linux |
|
|
306
369
|
|---------------|-------:|--------------------:|
|
|
307
370
|
| czifile (Python ref) | 148 ms | 414 ms |
|
|
308
371
|
| aicspylibczi (C++) | 17 ms | 140 ms |
|
|
@@ -344,9 +407,12 @@ caps = tomllib.load(open("capabilities.toml", "rb"))["codec"]
|
|
|
344
407
|
[c["name"] for c in caps if c["pyramid"]] # codecs with a pyramid reader
|
|
345
408
|
```
|
|
346
409
|
|
|
347
|
-
The manifest covers the codec registry
|
|
348
|
-
(
|
|
349
|
-
|
|
410
|
+
The runtime manifest covers the codec registry. The companion
|
|
411
|
+
[pipeline catalog](pipeline_catalog.toml) also covers direct adapters such as
|
|
412
|
+
Imaris, OME-Zarr, NDTiff and N5, and maps shared optimization work across all
|
|
413
|
+
registered codecs. See the [implementation plan](docs/pipeline_optimization_plan.md)
|
|
414
|
+
for priorities, source evidence, correctness prerequisites and acceptance tests.
|
|
415
|
+
Run `python ci/check_pipeline_catalog.py report` for the current worklist.
|
|
350
416
|
|
|
351
417
|
### Codec registry
|
|
352
418
|
|
|
@@ -491,10 +557,12 @@ prefix = jxl.thumbnail_bytes("scan.jxl")
|
|
|
491
557
|
pip install opencodecs
|
|
492
558
|
```
|
|
493
559
|
|
|
494
|
-
Wheels are published for CPython 3.10
|
|
495
|
-
Linux (x86_64 + aarch64), and Windows (amd64).
|
|
496
|
-
|
|
497
|
-
c-blosc2, and friends
|
|
560
|
+
Wheels are published for CPython 3.10 to 3.13 on macOS 15+ (arm64),
|
|
561
|
+
Linux (x86_64 + aarch64, manylinux_2_28), and Windows (amd64). Every
|
|
562
|
+
platform ships the same 39 compiled extensions, bundling libjxl,
|
|
563
|
+
libavif, libheif, libwebp, libdeflate, c-blosc2, CharLS and friends,
|
|
564
|
+
so no system dependencies are needed. Intel Macs and macOS releases
|
|
565
|
+
older than 15 install from the sdist instead.
|
|
498
566
|
|
|
499
567
|
For a source install, system development headers, or to build a
|
|
500
568
|
tuned local libjxl, see [INSTALL.md](INSTALL.md). Wheel publishing
|
|
@@ -517,29 +585,41 @@ build).
|
|
|
517
585
|
|
|
518
586
|
## Status
|
|
519
587
|
|
|
520
|
-
- **v0.
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
588
|
+
- **v0.3.0** on PyPI (September 2026). Every wheel carries the same 40
|
|
589
|
+
compiled extensions, and `ci/check_wheel_contents.py` fails the
|
|
590
|
+
release build if one goes missing.
|
|
591
|
+
- About 4,000 tests locally, including a 40-dataset conformance corpus;
|
|
592
|
+
CI runs the corpus-independent suite on macOS, Linux and Windows for
|
|
593
|
+
Python 3.10 and 3.13.
|
|
594
|
+
- Native readers and writers for the common scientific containers
|
|
595
|
+
(TIFF, BigTIFF, OME-TIFF, CZI, NDTiff, HDF5, JXL, FITS, OME-Zarr v2 +
|
|
596
|
+
v3 sharded), and pyramid readers for TIFF/COG/SVS, OME-Zarr, CZI,
|
|
597
|
+
Imaris, DICOM VL Whole Slide Microscopy and Olympus VSI/ETS
|
|
598
|
+
- Shared source adapters support paths, buffers, file objects and remote URLs.
|
|
599
|
+
Indexed readers use checked range requests, covering caches and adaptive
|
|
600
|
+
read-ahead; whole-stream codecs retain their documented eager input paths.
|
|
601
|
+
- Multi-frame AVIF, animated WebP and GIF decode to a frame stack; HEIF
|
|
602
|
+
exposes every top-level image
|
|
527
603
|
- Compression backend auto-detect (libdeflate → zlib-ng-compat → stdlib)
|
|
528
|
-
- Cloud I/O primitives (`HTTPDataSource` with covering-cache + adaptive
|
|
529
|
-
read-ahead) wired into TIFF / HDF5 / DICOMweb / CZI / FITS / Zarr v3
|
|
530
|
-
readers
|
|
531
604
|
- `tifffile_patch` opt-in shim reroutes tifffile's codec dispatch through
|
|
532
605
|
opencodecs for users who want only a partial swap
|
|
606
|
+
- `capabilities.toml` records what each codec actually supports, checked
|
|
607
|
+
against the built extensions, with no open gaps
|
|
533
608
|
|
|
534
609
|
Deferred work (see [`docs/TODO_DEFERRED.md`](docs/TODO_DEFERRED.md)):
|
|
535
610
|
|
|
536
|
-
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
-
|
|
542
|
-
|
|
611
|
+
- CCITT Fax3/Fax4 encode: legacy fax, zero scientific users
|
|
612
|
+
- JPEG XR encode (decode exists for CZI; see above)
|
|
613
|
+
|
|
614
|
+
GIF and JPEG XL destination writers now drain encoded frame output before close.
|
|
615
|
+
The shared pipeline also supplies bounded independent-piece scheduling, seven
|
|
616
|
+
stateful byte-codec iterators, native PNG row sessions, selective native sources,
|
|
617
|
+
and checked caller-owned destinations.
|
|
618
|
+
|
|
619
|
+
Shared streaming, buffering, and overlap mechanisms and remaining integration
|
|
620
|
+
work are documented in [the pipeline catalog](docs/shared_pipeline_capabilities.md).
|
|
621
|
+
|
|
622
|
+
See [CHANGES.rst](CHANGES.rst) for release history.
|
|
543
623
|
|
|
544
624
|
## License
|
|
545
625
|
|
|
@@ -165,7 +165,7 @@ each library.
|
|
|
165
165
|
| libaec | 1.1.6 | BSD-2-Clause |
|
|
166
166
|
| lerc | 4.1.0 | Apache-2.0 |
|
|
167
167
|
| zfp | 1.0.1 | BSD-3-Clause |
|
|
168
|
-
| SZ3 | 3.3.
|
|
168
|
+
| SZ3 | 3.3.2 | BSD-3-Clause |
|
|
169
169
|
| SPERR | 0.8.5 | Apache-2.0 |
|
|
170
170
|
| pcodec | 1.0.2 | Apache-2.0 |
|
|
171
171
|
| brunsli | master | MIT |
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "opencodecs"
|
|
10
|
-
version = "0.
|
|
10
|
+
version = "0.3.1"
|
|
11
11
|
description = "Streaming, network-aware image codecs for scientific imaging (prototype: JPEG XL)"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.10"
|
|
@@ -194,7 +194,7 @@ before-all = [
|
|
|
194
194
|
# bench/build_codec_libs.sh into the cached /cibw-jxl-prefix mount.
|
|
195
195
|
# Skips encoders (aom, x265) — wheel ships decode-only AVIF/HEIF to
|
|
196
196
|
# keep build < 12 min cold + avoid GPL x265.
|
|
197
|
-
"bash -c 'PATH=$HOME/.cargo/bin:$PATH bash bench/build_codec_libs.sh --only=libjpeg-turbo,c-blosc2,libde265,dav1d,libavif,libheif,libaec,lerc,zfp,SZ3,pcodec,SPERR,brunsli,mozjpeg,libultrahdr,openjph,CharLS'",
|
|
197
|
+
"bash -c 'PATH=$HOME/.cargo/bin:$PATH bash bench/build_codec_libs.sh --only=libjpeg-turbo,c-blosc2,libde265,dav1d,libavif,libheif,libaec,lerc,zfp,SZ3,pcodec,SPERR,brunsli,mozjpeg,libultrahdr,openjph,CharLS,jxrlib'",
|
|
198
198
|
"bash bench/build_libjxl.sh",
|
|
199
199
|
]
|
|
200
200
|
# Don't set OPENCODECS_*_PREFIX here — build_wheels.yml's
|
|
@@ -215,7 +215,7 @@ before-all = [
|
|
|
215
215
|
# only, not libturbojpeg, so the _mozjpeg probe couldn't find what it
|
|
216
216
|
# needed. Source-build via build_codec_libs.sh produces both libs.
|
|
217
217
|
"brew install jpeg-xl libavif libheif webp libpng jpeg-turbo openjpeg zstd brotli c-blosc2 lz4 libdeflate libaec liblerc zfp rust cmake ninja libultrahdr giflib snappy charls isa-l",
|
|
218
|
-
"bash bench/build_codec_libs.sh --only=SZ3,pcodec,SPERR,brunsli,mozjpeg,openjph",
|
|
218
|
+
"bash bench/build_codec_libs.sh --only=SZ3,pcodec,SPERR,brunsli,mozjpeg,openjph,jxrlib",
|
|
219
219
|
]
|
|
220
220
|
# macos-latest is now macOS 15 (Sequoia) on arm64. Homebrew formulas are
|
|
221
221
|
# compiled for 15.x, so any wheel target lower than 15 fails the delocate
|