opencodecs 0.1.3__tar.gz → 0.1.5__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.1.5/3rdparty/cfitsio/pliocomp.c +331 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/CHANGES.rst +148 -0
- {opencodecs-0.1.3/src/opencodecs.egg-info → opencodecs-0.1.5}/PKG-INFO +1 -1
- {opencodecs-0.1.3 → opencodecs-0.1.5}/pyproject.toml +6 -3
- {opencodecs-0.1.3 → opencodecs-0.1.5}/setup.py +100 -9
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/__init__.py +1 -1
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_eer_reader.py +35 -6
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_fits_compressed.py +34 -4
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_pyramid_build.py +66 -1
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_tiff_http.py +83 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_tiff_pyramid.py +38 -2
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_tiff_writer.py +51 -2
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/__init__.py +15 -3
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_bcdec.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_bmp.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_eer.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_hcomp.c +152 -152
- opencodecs-0.1.5/src/opencodecs/codecs/_plio.c +30037 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_png.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_qoi.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_rcomp.c +152 -152
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_rgbe.c +152 -152
- opencodecs-0.1.5/src/opencodecs/uhdr.py +209 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5/src/opencodecs.egg-info}/PKG-INFO +1 -1
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs.egg-info/SOURCES.txt +4 -1
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_eer.py +61 -9
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_fits.py +14 -5
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_omezarr.py +13 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_http.py +74 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_writer.py +68 -0
- opencodecs-0.1.5/tests/test_uhdr.py +302 -0
- opencodecs-0.1.3/tests/test_ultrahdr.py +0 -130
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/bcdec/bcdec.h +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/bitshuffle/bitshuffle_core.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/bitshuffle/iochain.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/cfitsio/fits_hdecompress.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/cfitsio/ricecomp.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/imcd_eer/eer.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/imcd_eer/eer.h +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/imcd_lzw/lzw.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/imcd_lzw/lzw.h +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/libspng/spng.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/oc_tifflzw/oc_tifflzw.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/oc_tifflzw/oc_tifflzw.h +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/3rdparty/rgbe/rgbe.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/MANIFEST.in +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/README.md +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/bench/build_libjxl.sh +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/patches/libjxl/README.md +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/setup.cfg +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_aec_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_avif_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_b2nd_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_bcn_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_bitshuffle_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_blosc2_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_bmp_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_brotli_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_brunsli_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_byteshuffle_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_bz2_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_cms_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_czi_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_czi_reader.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_czi_writer.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_deflate_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_dicomrle_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_dicomweb.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ets.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_fits.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_fits_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_gif_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_gzip_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_hdf5_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_hdf5_http.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_heif_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_htj2k_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_jpeg2k_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_jpeg_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_jpegls_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_jxl_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_lerc_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_lif_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_lif_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_lz4_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_lzma_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_mozjpeg_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_nd2_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_nd2_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ndtiff.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ndtiff_pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ndtiff_writer.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_none_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_numpy_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_oib_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_oib_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_oir_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ole2.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ome_xml.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_omezarr.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_omezarr_writer.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_packints_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_pcodec_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_png_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_predictor_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_qoi_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_quantize_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_rcomp_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_rgbe.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_rgbe_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_snappy_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_sperr_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_sz3_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_tiff_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_ultrahdr_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_vsi_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_webp_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_zarr_codecs.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_zfp_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/_zstd_codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_bitshuffle.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_bytetools.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_deflate.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_lz4.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_ndtiff.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_registry.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_tiff.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/codecs/_zstd.c +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/__init__.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/_io_helpers.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/_optional_backend.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/codec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/color.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/errors.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/io.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/core/segment_compression.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/jxl.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/parallel.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/tiff_reader.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/tifffile_patch.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs/zarr.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs.egg-info/dependency_links.txt +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs.egg-info/requires.txt +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/src/opencodecs.egg-info/top_level.txt +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_auto_pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_bcdec.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_brunsli.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_charls.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_core_codec_api.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus_codec_decode.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus_other.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus_png.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus_tiff.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_corpus_vendors.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_coverage_final.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_coverage_finishing.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_coverage_last.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_coverage_more.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_coverage_push.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_czi_fixture.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_czi_pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_czi_writer.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_data_source.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_deflate.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_dicomweb.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_edge_cases.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_encode_comprehensive.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_error_handling.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_gif.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_hdf5_http.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_hdf5_local.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_heif_avif_features.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_http_byte_savings.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_http_prefetch.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_http_unified.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_io_chunked.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_isal.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_jxl.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_lif_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_live_archives.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_mozjpeg.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_native_parity.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_nd2_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_ndtiff.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_oib_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_ome_xml.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_omezarr_sharded_range.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_open_pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_openjph.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_optional_backend.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_parallel_jxl.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_phase4_filters.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_phase5_icc.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_phase6_codecs.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_phase7_cms.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_rgbe.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_snappy.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tier1_scientific.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_codec_encode.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_native.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_pyramid.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tiff_reader.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_tifffile_patch.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_unified_api.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_vsi_oir.py +0 -0
- {opencodecs-0.1.3 → opencodecs-0.1.5}/tests/test_zarr_adapters.py +0 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/* stdlib is needed for the abs function */
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
/*
|
|
4
|
+
The following prototype code was provided by Doug Tody, NRAO, for
|
|
5
|
+
performing conversion between pixel arrays and line lists. The
|
|
6
|
+
compression technique is used in IRAF.
|
|
7
|
+
*/
|
|
8
|
+
int pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
|
|
9
|
+
int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* PL_P2L -- Convert a pixel array to a line list. The length of the list is
|
|
14
|
+
* returned as the function value.
|
|
15
|
+
*
|
|
16
|
+
* Translated from the SPP version using xc -f, f2c. 8Sep99 DCT.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#ifndef min
|
|
20
|
+
#define min(a,b) (((a)<(b))?(a):(b))
|
|
21
|
+
#endif
|
|
22
|
+
#ifndef max
|
|
23
|
+
#define max(a,b) (((a)>(b))?(a):(b))
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
int pl_p2li (int *pxsrc, int xs, short *lldst, int npix)
|
|
27
|
+
/* int *pxsrc; input pixel array */
|
|
28
|
+
/* int xs; starting index in pxsrc (?) */
|
|
29
|
+
/* short *lldst; encoded line list */
|
|
30
|
+
/* int npix; number of pixels to convert */
|
|
31
|
+
{
|
|
32
|
+
/* System generated locals */
|
|
33
|
+
int ret_val, i__1, i__2, i__3;
|
|
34
|
+
|
|
35
|
+
/* Local variables */
|
|
36
|
+
int zero, v, x1, hi, ip, dv, xe, np, op, iz, nv = 0, pv, nz;
|
|
37
|
+
|
|
38
|
+
/* Parameter adjustments */
|
|
39
|
+
--lldst;
|
|
40
|
+
--pxsrc;
|
|
41
|
+
|
|
42
|
+
/* Function Body */
|
|
43
|
+
if (! (npix <= 0)) {
|
|
44
|
+
goto L110;
|
|
45
|
+
}
|
|
46
|
+
ret_val = 0;
|
|
47
|
+
goto L100;
|
|
48
|
+
L110:
|
|
49
|
+
lldst[3] = -100;
|
|
50
|
+
lldst[2] = 7;
|
|
51
|
+
lldst[1] = 0;
|
|
52
|
+
lldst[6] = 0;
|
|
53
|
+
lldst[7] = 0;
|
|
54
|
+
xe = xs + npix - 1;
|
|
55
|
+
op = 8;
|
|
56
|
+
zero = 0;
|
|
57
|
+
/* Computing MAX */
|
|
58
|
+
i__1 = zero, i__2 = pxsrc[xs];
|
|
59
|
+
pv = max(i__1,i__2);
|
|
60
|
+
x1 = xs;
|
|
61
|
+
iz = xs;
|
|
62
|
+
hi = 1;
|
|
63
|
+
i__1 = xe;
|
|
64
|
+
for (ip = xs; ip <= i__1; ++ip) {
|
|
65
|
+
if (! (ip < xe)) {
|
|
66
|
+
goto L130;
|
|
67
|
+
}
|
|
68
|
+
/* Computing MAX */
|
|
69
|
+
i__2 = zero, i__3 = pxsrc[ip + 1];
|
|
70
|
+
nv = max(i__2,i__3);
|
|
71
|
+
if (! (nv == pv)) {
|
|
72
|
+
goto L140;
|
|
73
|
+
}
|
|
74
|
+
goto L120;
|
|
75
|
+
L140:
|
|
76
|
+
if (! (pv == 0)) {
|
|
77
|
+
goto L150;
|
|
78
|
+
}
|
|
79
|
+
pv = nv;
|
|
80
|
+
x1 = ip + 1;
|
|
81
|
+
goto L120;
|
|
82
|
+
L150:
|
|
83
|
+
goto L131;
|
|
84
|
+
L130:
|
|
85
|
+
if (! (pv == 0)) {
|
|
86
|
+
goto L160;
|
|
87
|
+
}
|
|
88
|
+
x1 = xe + 1;
|
|
89
|
+
L160:
|
|
90
|
+
L131:
|
|
91
|
+
np = ip - x1 + 1;
|
|
92
|
+
nz = x1 - iz;
|
|
93
|
+
if (! (pv > 0)) {
|
|
94
|
+
goto L170;
|
|
95
|
+
}
|
|
96
|
+
dv = pv - hi;
|
|
97
|
+
if (! (dv != 0)) {
|
|
98
|
+
goto L180;
|
|
99
|
+
}
|
|
100
|
+
hi = pv;
|
|
101
|
+
if (! (abs(dv) > 4095)) {
|
|
102
|
+
goto L190;
|
|
103
|
+
}
|
|
104
|
+
lldst[op] = (short) ((pv & 4095) + 4096);
|
|
105
|
+
++op;
|
|
106
|
+
lldst[op] = (short) (pv / 4096);
|
|
107
|
+
++op;
|
|
108
|
+
goto L191;
|
|
109
|
+
L190:
|
|
110
|
+
if (! (dv < 0)) {
|
|
111
|
+
goto L200;
|
|
112
|
+
}
|
|
113
|
+
lldst[op] = (short) (-dv + 12288);
|
|
114
|
+
goto L201;
|
|
115
|
+
L200:
|
|
116
|
+
lldst[op] = (short) (dv + 8192);
|
|
117
|
+
L201:
|
|
118
|
+
++op;
|
|
119
|
+
if (! (np == 1 && nz == 0)) {
|
|
120
|
+
goto L210;
|
|
121
|
+
}
|
|
122
|
+
v = lldst[op - 1];
|
|
123
|
+
lldst[op - 1] = (short) (v | 16384);
|
|
124
|
+
goto L91;
|
|
125
|
+
L210:
|
|
126
|
+
L191:
|
|
127
|
+
L180:
|
|
128
|
+
L170:
|
|
129
|
+
if (! (nz > 0)) {
|
|
130
|
+
goto L220;
|
|
131
|
+
}
|
|
132
|
+
L230:
|
|
133
|
+
if (! (nz > 0)) {
|
|
134
|
+
goto L232;
|
|
135
|
+
}
|
|
136
|
+
lldst[op] = (short) min(4095,nz);
|
|
137
|
+
++op;
|
|
138
|
+
/* L231: */
|
|
139
|
+
nz += -4095;
|
|
140
|
+
goto L230;
|
|
141
|
+
L232:
|
|
142
|
+
if (! (np == 1 && pv > 0)) {
|
|
143
|
+
goto L240;
|
|
144
|
+
}
|
|
145
|
+
lldst[op - 1] = (short) (lldst[op - 1] + 20481);
|
|
146
|
+
goto L91;
|
|
147
|
+
L240:
|
|
148
|
+
L220:
|
|
149
|
+
L250:
|
|
150
|
+
if (! (np > 0)) {
|
|
151
|
+
goto L252;
|
|
152
|
+
}
|
|
153
|
+
lldst[op] = (short) (min(4095,np) + 16384);
|
|
154
|
+
++op;
|
|
155
|
+
/* L251: */
|
|
156
|
+
np += -4095;
|
|
157
|
+
goto L250;
|
|
158
|
+
L252:
|
|
159
|
+
L91:
|
|
160
|
+
x1 = ip + 1;
|
|
161
|
+
iz = x1;
|
|
162
|
+
pv = nv;
|
|
163
|
+
L120:
|
|
164
|
+
;
|
|
165
|
+
}
|
|
166
|
+
/* L121: */
|
|
167
|
+
lldst[4] = (short) ((op - 1) % 32768);
|
|
168
|
+
lldst[5] = (short) ((op - 1) / 32768);
|
|
169
|
+
ret_val = op - 1;
|
|
170
|
+
goto L100;
|
|
171
|
+
L100:
|
|
172
|
+
return ret_val;
|
|
173
|
+
} /* plp2li_ */
|
|
174
|
+
|
|
175
|
+
/*
|
|
176
|
+
* PL_L2PI -- Translate a PLIO line list into an integer pixel array.
|
|
177
|
+
* The number of pixels output (always npix) is returned as the function
|
|
178
|
+
* value.
|
|
179
|
+
*
|
|
180
|
+
* Translated from the SPP version using xc -f, f2c. 8Sep99 DCT.
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix)
|
|
184
|
+
/* short *ll_src; encoded line list */
|
|
185
|
+
/* int xs; starting index in ll_src */
|
|
186
|
+
/* int *px_dst; output pixel array */
|
|
187
|
+
/* int npix; number of pixels to convert */
|
|
188
|
+
{
|
|
189
|
+
/* System generated locals */
|
|
190
|
+
int ret_val, i__1, i__2;
|
|
191
|
+
|
|
192
|
+
/* Local variables */
|
|
193
|
+
int data, sw0001, otop, i__, lllen, i1, i2, x1, x2, ip, xe, np,
|
|
194
|
+
op, pv, opcode, llfirt;
|
|
195
|
+
int skipwd;
|
|
196
|
+
|
|
197
|
+
/* Parameter adjustments */
|
|
198
|
+
--px_dst;
|
|
199
|
+
--ll_src;
|
|
200
|
+
|
|
201
|
+
/* Function Body */
|
|
202
|
+
if (! (ll_src[3] > 0)) {
|
|
203
|
+
goto L110;
|
|
204
|
+
}
|
|
205
|
+
lllen = ll_src[3];
|
|
206
|
+
llfirt = 4;
|
|
207
|
+
goto L111;
|
|
208
|
+
L110:
|
|
209
|
+
lllen = (ll_src[5] << 15) + ll_src[4];
|
|
210
|
+
llfirt = ll_src[2] + 1;
|
|
211
|
+
L111:
|
|
212
|
+
if (! (npix <= 0 || lllen <= 0)) {
|
|
213
|
+
goto L120;
|
|
214
|
+
}
|
|
215
|
+
ret_val = 0;
|
|
216
|
+
goto L100;
|
|
217
|
+
L120:
|
|
218
|
+
xe = xs + npix - 1;
|
|
219
|
+
skipwd = 0;
|
|
220
|
+
op = 1;
|
|
221
|
+
x1 = 1;
|
|
222
|
+
pv = 1;
|
|
223
|
+
i__1 = lllen;
|
|
224
|
+
for (ip = llfirt; ip <= i__1; ++ip) {
|
|
225
|
+
if (! skipwd) {
|
|
226
|
+
goto L140;
|
|
227
|
+
}
|
|
228
|
+
skipwd = 0;
|
|
229
|
+
goto L130;
|
|
230
|
+
L140:
|
|
231
|
+
opcode = ll_src[ip] / 4096;
|
|
232
|
+
data = ll_src[ip] & 4095;
|
|
233
|
+
sw0001 = opcode;
|
|
234
|
+
goto L150;
|
|
235
|
+
L160:
|
|
236
|
+
x2 = x1 + data - 1;
|
|
237
|
+
i1 = max(x1,xs);
|
|
238
|
+
i2 = min(x2,xe);
|
|
239
|
+
np = i2 - i1 + 1;
|
|
240
|
+
if (! (np > 0)) {
|
|
241
|
+
goto L170;
|
|
242
|
+
}
|
|
243
|
+
otop = op + np - 1;
|
|
244
|
+
if (! (opcode == 4)) {
|
|
245
|
+
goto L180;
|
|
246
|
+
}
|
|
247
|
+
i__2 = otop;
|
|
248
|
+
for (i__ = op; i__ <= i__2; ++i__) {
|
|
249
|
+
px_dst[i__] = pv;
|
|
250
|
+
/* L190: */
|
|
251
|
+
}
|
|
252
|
+
/* L191: */
|
|
253
|
+
goto L181;
|
|
254
|
+
L180:
|
|
255
|
+
i__2 = otop;
|
|
256
|
+
for (i__ = op; i__ <= i__2; ++i__) {
|
|
257
|
+
px_dst[i__] = 0;
|
|
258
|
+
/* L200: */
|
|
259
|
+
}
|
|
260
|
+
/* L201: */
|
|
261
|
+
if (! (opcode == 5 && i2 == x2)) {
|
|
262
|
+
goto L210;
|
|
263
|
+
}
|
|
264
|
+
px_dst[otop] = pv;
|
|
265
|
+
L210:
|
|
266
|
+
L181:
|
|
267
|
+
op = otop + 1;
|
|
268
|
+
L170:
|
|
269
|
+
x1 = x2 + 1;
|
|
270
|
+
goto L151;
|
|
271
|
+
L220:
|
|
272
|
+
pv = (ll_src[ip + 1] << 12) + data;
|
|
273
|
+
skipwd = 1;
|
|
274
|
+
goto L151;
|
|
275
|
+
L230:
|
|
276
|
+
pv += data;
|
|
277
|
+
goto L151;
|
|
278
|
+
L240:
|
|
279
|
+
pv -= data;
|
|
280
|
+
goto L151;
|
|
281
|
+
L250:
|
|
282
|
+
pv += data;
|
|
283
|
+
goto L91;
|
|
284
|
+
L260:
|
|
285
|
+
pv -= data;
|
|
286
|
+
L91:
|
|
287
|
+
if (! (x1 >= xs && x1 <= xe)) {
|
|
288
|
+
goto L270;
|
|
289
|
+
}
|
|
290
|
+
px_dst[op] = pv;
|
|
291
|
+
++op;
|
|
292
|
+
L270:
|
|
293
|
+
++x1;
|
|
294
|
+
goto L151;
|
|
295
|
+
L150:
|
|
296
|
+
++sw0001;
|
|
297
|
+
if (sw0001 < 1 || sw0001 > 8) {
|
|
298
|
+
goto L151;
|
|
299
|
+
}
|
|
300
|
+
switch ((int)sw0001) {
|
|
301
|
+
case 1: goto L160;
|
|
302
|
+
case 2: goto L220;
|
|
303
|
+
case 3: goto L230;
|
|
304
|
+
case 4: goto L240;
|
|
305
|
+
case 5: goto L160;
|
|
306
|
+
case 6: goto L160;
|
|
307
|
+
case 7: goto L250;
|
|
308
|
+
case 8: goto L260;
|
|
309
|
+
}
|
|
310
|
+
L151:
|
|
311
|
+
if (! (x1 > xe)) {
|
|
312
|
+
goto L280;
|
|
313
|
+
}
|
|
314
|
+
goto L131;
|
|
315
|
+
L280:
|
|
316
|
+
L130:
|
|
317
|
+
;
|
|
318
|
+
}
|
|
319
|
+
L131:
|
|
320
|
+
i__1 = npix;
|
|
321
|
+
for (i__ = op; i__ <= i__1; ++i__) {
|
|
322
|
+
px_dst[i__] = 0;
|
|
323
|
+
/* L290: */
|
|
324
|
+
}
|
|
325
|
+
/* L291: */
|
|
326
|
+
ret_val = npix;
|
|
327
|
+
goto L100;
|
|
328
|
+
L100:
|
|
329
|
+
return ret_val;
|
|
330
|
+
} /* pll2pi_ */
|
|
331
|
+
|
|
@@ -10,6 +10,154 @@ 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.1.5 (2026-05-31)
|
|
14
|
+
------------------
|
|
15
|
+
|
|
16
|
+
**New codecs**
|
|
17
|
+
|
|
18
|
+
* ``opencodecs.uhdr`` — Ultra-HDR / ISO 21496-1 (gainmap JPEG) via a
|
|
19
|
+
direct Cython binding to Google's libultrahdr. ``encode(hdr, ...)``
|
|
20
|
+
wraps libuhdr's full pipeline; ``encode_native(hdr, sdr=None, ...)``
|
|
21
|
+
is a fused-Cython fast path that computes SDR base + gain map in
|
|
22
|
+
``nogil`` kernels (IEEE-754 polynomial log2/pow, cross-platform —
|
|
23
|
+
no Apple Accelerate intrinsics), JPEG-encodes both layers in
|
|
24
|
+
parallel via a 3-worker ThreadPoolExecutor, then hands the
|
|
25
|
+
pre-encoded JPEGs to libuhdr's api-4 for container assembly.
|
|
26
|
+
Measured 31 ms median for a 2000² float HDR on M-series Mac vs
|
|
27
|
+
~173 ms for the libuhdr reference path — 5.5× faster. The
|
|
28
|
+
``sdr=`` argument lets callers (notably tilescan pipelines) supply
|
|
29
|
+
their own SDR base instead of accepting the peak-normalised default.
|
|
30
|
+
|
|
31
|
+
* ``PLIO_1`` — IRAF run-length mask coding closes the last FITS
|
|
32
|
+
tile-compression gap. Vendors cfitsio's ``pliocomp.c`` (Doug Tody /
|
|
33
|
+
NRAO, public-domain) and adds the tiny
|
|
34
|
+
``opencodecs.codecs._plio.decode_raw`` shim. Round-trip tested
|
|
35
|
+
against astropy. The ``COMPRESSED_DATA`` BINTABLE column walker
|
|
36
|
+
now tracks per-column element byte width so the ``1PI`` (int16
|
|
37
|
+
opcodes) layout PLIO uses works alongside the ``1PB`` byte VLA the
|
|
38
|
+
other compressors use.
|
|
39
|
+
|
|
40
|
+
**New API**
|
|
41
|
+
|
|
42
|
+
* ``EerReader.sum(start, stop, *, weights=None, dtype=...)`` —
|
|
43
|
+
per-frame dose curve. ``weights[k]`` multiplies the k-th frame in
|
|
44
|
+
the requested range; output promotes to float64 when weights are
|
|
45
|
+
given so fractional contributions don't truncate. Use case:
|
|
46
|
+
beam-induced-motion correction and temporal-binning schemes that
|
|
47
|
+
emphasise different exposures across the acquisition.
|
|
48
|
+
|
|
49
|
+
**Bug fixes**
|
|
50
|
+
|
|
51
|
+
* HEIF encode against libheif ≥ 1.18 — newer libheif calls
|
|
52
|
+
``strlen()`` on the user write-callback's ``heif_error.message``
|
|
53
|
+
even on success and rejects a ``NULL`` pointer with *"heif_writer
|
|
54
|
+
callback returned a null error text"*. The callback now hands back
|
|
55
|
+
a static empty string on success and a descriptive string on OOM.
|
|
56
|
+
Six tests (``test_heif_*``, ``test_phase5_icc.py[heif]``) go back
|
|
57
|
+
to green across every CI matrix entry.
|
|
58
|
+
|
|
59
|
+
**CI / build**
|
|
60
|
+
|
|
61
|
+
* ``bench/build_codec_libs.sh`` — the ``is_built`` cache-marker now
|
|
62
|
+
records the install dir alongside the version and re-verifies the
|
|
63
|
+
install dir exists before short-circuiting a recipe. Without this,
|
|
64
|
+
cibuildwheel's manylinux cache (which only covers ``/cibw-jxl-prefix``)
|
|
65
|
+
preserved the marker for recipes that install to
|
|
66
|
+
``~/.cache/opencodecs/<lib>/`` outside the cached prefix —
|
|
67
|
+
``lerc``, ``mozjpeg``, ``brotli``, ``zstd``, ``giflib`` — so the
|
|
68
|
+
recipe thought it was done while the actual library files were
|
|
69
|
+
gone. ``_lerc`` + ``_mozjpeg`` had been silently dropped from
|
|
70
|
+
Linux wheels for this reason; the fix restores them.
|
|
71
|
+
|
|
72
|
+
* ``test_omezarr.py`` skips at module level on zarr-python < 3 —
|
|
73
|
+
fixtures use the v3 API surface, which doesn't exist on the v2
|
|
74
|
+
branch pip resolves on Python 3.10.
|
|
75
|
+
|
|
76
|
+
* ``test_eer_imagecodecs_cross_validate`` is now symmetric on
|
|
77
|
+
decoder error: if either implementation raises, both must raise
|
|
78
|
+
for the combo to count. Tolerates imagecodecs ≥ 2026.5's tighter
|
|
79
|
+
output-buffer sizing.
|
|
80
|
+
|
|
81
|
+
0.1.4 (2026-05-25)
|
|
82
|
+
------------------
|
|
83
|
+
|
|
84
|
+
**libvips-inspired streaming improvements**
|
|
85
|
+
|
|
86
|
+
* ``HTTPDataSource(access='sequential', sequential_chunk_bytes=4*1024*1024)``
|
|
87
|
+
— opt-in libvips-style sequential read mode. Replaces the LRU +
|
|
88
|
+
adaptive read-ahead with a single rolling buffer that slides forward
|
|
89
|
+
as the caller reads. Memory stays bounded to one chunk regardless of
|
|
90
|
+
file size. Target workload: tile-by-tile raster scan over a huge
|
|
91
|
+
COG / OME-TIFF served over HTTP. Backward seeks still work but
|
|
92
|
+
invalidate the buffer; ``stats['sequential_backward_seeks']`` tracks
|
|
93
|
+
the count so users can spot a workload that's actually random and
|
|
94
|
+
would benefit from ``access='random'``.
|
|
95
|
+
|
|
96
|
+
* ``TiffPyramidReader.read_region`` now parallelises tile decode
|
|
97
|
+
across a thread pool (default ``min(cpu_count(), 8)``). The
|
|
98
|
+
compressed-tile decoders (JPEG, JPEG-2000, deflate, zstd, LZW, WebP,
|
|
99
|
+
LERC) all release the GIL in their C path, so threads scale across
|
|
100
|
+
cores on CPython. Kicks in only when the region covers 4+ tiles —
|
|
101
|
+
fewer than that and thread-pool spin-up cost dominates. Pass
|
|
102
|
+
``num_decode_workers=1`` to force the serial path for benchmarks /
|
|
103
|
+
regression-diff.
|
|
104
|
+
|
|
105
|
+
* ``TiffWriter.write_pyramid_auto`` gained ``stream_levels=True``
|
|
106
|
+
(default for COG layout). Computes and writes one level at a time
|
|
107
|
+
via a new ``iter_pyramid_levels`` generator, dropping each finished
|
|
108
|
+
level before computing the next. Peak memory drops from
|
|
109
|
+
``~1.33 × level0`` (entire geometric series materialised) to
|
|
110
|
+
``~2 × current_level``. Useful when level 0 already dominates RAM
|
|
111
|
+
(whole-slide pathology, cryo-EM tomograms). Output file is
|
|
112
|
+
byte-identical to the materialize-all path. SubIFD layout
|
|
113
|
+
(``subifds=True``) still uses the materialize path because that
|
|
114
|
+
layout writes sub-resolution IFD offsets into the main IFD's tag
|
|
115
|
+
330 — sub-level offsets have to be known up front.
|
|
116
|
+
|
|
117
|
+
Validated via tests:
|
|
118
|
+
``test_http_sequential_serves_from_rolling_buffer``,
|
|
119
|
+
``test_http_sequential_backward_seek_counted``,
|
|
120
|
+
``test_pyramid_reader_parallel_decode_matches_serial``,
|
|
121
|
+
``test_pyramid_auto_stream_matches_materialize``,
|
|
122
|
+
``test_iter_pyramid_levels_matches_make_pyramid_levels``.
|
|
123
|
+
|
|
124
|
+
**MozJPEG ships on every wheel**
|
|
125
|
+
|
|
126
|
+
* Added MozJPEG (Mozilla's libjpeg-turbo fork) to the cibuildwheel
|
|
127
|
+
codec-lib build set on Linux, macOS, and Windows. MozJPEG produces
|
|
128
|
+
JPEG files ~10-15% smaller than baseline libjpeg-turbo at the same
|
|
129
|
+
quality setting (progressive encoding + trellis quantization +
|
|
130
|
+
better quantization tables). The ``_mozjpeg`` extension has shipped
|
|
131
|
+
on macOS wheels for a while via brew; v0.1.4 brings it to
|
|
132
|
+
Linux + Windows so the codec is available everywhere.
|
|
133
|
+
* New ``build_mozjpeg`` recipe in ``bench/build_codec_libs.sh``
|
|
134
|
+
installs into a keg-style ``mozjpeg/`` subdir under the prefix
|
|
135
|
+
(rather than the shared ``$PREFIX/{include,lib}``) to avoid the
|
|
136
|
+
libturbojpeg / libjpeg name collision with the libjpeg-turbo 3.x
|
|
137
|
+
install. setup.py's mozjpeg probe was extended to recognise the
|
|
138
|
+
new candidate paths on Linux (``~/.cache/opencodecs/mozjpeg``),
|
|
139
|
+
Windows (``$CONDA_PREFIX/Library/mozjpeg``), and the Windows
|
|
140
|
+
fallback (no ``nm``: trust the keg-style directory name).
|
|
141
|
+
* Locally validated on win-vm (MSVC 14.44 — same as CI) and
|
|
142
|
+
kevin-tower (Linux x86_64): ``bash bench/build_codec_libs.sh
|
|
143
|
+
--only=mozjpeg`` followed by ``setup.py build_ext --inplace``
|
|
144
|
+
produces ``_mozjpeg.{pyd,so}`` cleanly. Per the new lesson in
|
|
145
|
+
CLAUDE.md, this iteration was validated end-to-end through the
|
|
146
|
+
same script CI runs, with the same env vars, before any push.
|
|
147
|
+
|
|
148
|
+
**Post-publish wheel coverage check (CI hardening)**
|
|
149
|
+
|
|
150
|
+
* New ``ci/check_wheel_contents.py`` runs in the wheel-build job
|
|
151
|
+
immediately after ``cibuildwheel`` produces each wheel. It unzips
|
|
152
|
+
the wheel, walks ``opencodecs/codecs/``, and asserts every codec
|
|
153
|
+
in the ``MUST_SHIP_ALL_PLATFORMS`` set has a ``.pyd``/``.so``
|
|
154
|
+
present. Missing codec → matrix job fails → publish step gated.
|
|
155
|
+
* Catches the v0.1.2-style "changelog overclaim" silent-drop class
|
|
156
|
+
of bugs at build time instead of after publish. v0.1.2's Windows
|
|
157
|
+
wheels shipped without ``_sperr``/``_brunsli`` despite the
|
|
158
|
+
changelog claim; this check would have failed that build.
|
|
159
|
+
|
|
160
|
+
|
|
13
161
|
0.1.3 (2026-05-22)
|
|
14
162
|
------------------
|
|
15
163
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opencodecs"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.5"
|
|
8
8
|
description = "Streaming, network-aware image codecs for scientific imaging (prototype: JPEG XL)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -142,7 +142,7 @@ before-all = [
|
|
|
142
142
|
# bench/build_codec_libs.sh into the cached /cibw-jxl-prefix mount.
|
|
143
143
|
# Skips encoders (aom, x265) — wheel ships decode-only AVIF/HEIF to
|
|
144
144
|
# keep build < 12 min cold + avoid GPL x265.
|
|
145
|
-
"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'",
|
|
145
|
+
"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'",
|
|
146
146
|
"bash bench/build_libjxl.sh",
|
|
147
147
|
]
|
|
148
148
|
# Don't set OPENCODECS_*_PREFIX here — build_wheels.yml's
|
|
@@ -159,8 +159,11 @@ before-all = [
|
|
|
159
159
|
# cache by bench/build_codec_libs.sh. brunsli vendors brotli as a
|
|
160
160
|
# submodule so the brew brotli isn't required at link time.
|
|
161
161
|
before-all = [
|
|
162
|
+
# mozjpeg removed from this brew install — the formula ships libjpeg
|
|
163
|
+
# only, not libturbojpeg, so the _mozjpeg probe couldn't find what it
|
|
164
|
+
# needed. Source-build via build_codec_libs.sh produces both libs.
|
|
162
165
|
"brew install jpeg-xl libavif libheif webp libpng jpeg-turbo openjpeg zstd brotli c-blosc2 lz4 libdeflate libaec liblerc zfp rust cmake ninja",
|
|
163
|
-
"bash bench/build_codec_libs.sh --only=SZ3,pcodec,SPERR,brunsli",
|
|
166
|
+
"bash bench/build_codec_libs.sh --only=SZ3,pcodec,SPERR,brunsli,mozjpeg",
|
|
164
167
|
]
|
|
165
168
|
# macos-latest is now macOS 15 (Sequoia) on arm64. Homebrew formulas are
|
|
166
169
|
# compiled for 15.x, so any wheel target lower than 15 fails the delocate
|
|
@@ -638,12 +638,30 @@ def _maybe_build_mozjpeg_ext() -> list[Extension]:
|
|
|
638
638
|
# by symbol absence alone. For generic system prefixes like /usr or
|
|
639
639
|
# /usr/local we additionally require a ``mozjpeg/`` include subdir
|
|
640
640
|
# so we don't misidentify vanilla libjpeg-turbo as MozJPEG.
|
|
641
|
-
|
|
641
|
+
# Keg-style per-user cache install from
|
|
642
|
+
# bench/build_codec_libs.sh::build_mozjpeg (Linux/macOS) and the
|
|
643
|
+
# cibuildwheel Windows install (under $OPENCODECS_CODEC_LIBS_PREFIX
|
|
644
|
+
# or $CONDA_PREFIX/Library). All "keg-style" — no mozjpeg/ include
|
|
645
|
+
# subdir needed because the prefix itself is mozjpeg-only.
|
|
646
|
+
candidates: list[tuple[Path, bool]] = [
|
|
647
|
+
(_OC_USER_CACHE / "mozjpeg", False),
|
|
642
648
|
(Path("/opt/homebrew/opt/mozjpeg"), False),
|
|
643
649
|
(Path("/usr/local/opt/mozjpeg"), False),
|
|
650
|
+
]
|
|
651
|
+
_libs_prefix_env = os.environ.get("OPENCODECS_CODEC_LIBS_PREFIX")
|
|
652
|
+
if _libs_prefix_env:
|
|
653
|
+
_libs_prefix_path = Path(_libs_prefix_env)
|
|
654
|
+
candidates.append((_libs_prefix_path / "mozjpeg", False))
|
|
655
|
+
# Conda Library/ layout: $CONDA_PREFIX/Library/mozjpeg
|
|
656
|
+
candidates.append((_libs_prefix_path / "Library" / "mozjpeg", False))
|
|
657
|
+
_conda = os.environ.get("CONDA_PREFIX")
|
|
658
|
+
if _conda:
|
|
659
|
+
candidates.append((Path(_conda) / "mozjpeg", False))
|
|
660
|
+
candidates.append((Path(_conda) / "Library" / "mozjpeg", False))
|
|
661
|
+
candidates.extend([
|
|
644
662
|
(Path("/usr"), True),
|
|
645
663
|
(Path("/usr/local"), True),
|
|
646
|
-
]
|
|
664
|
+
])
|
|
647
665
|
prefix = None
|
|
648
666
|
lib_subdir = None # "lib" or "lib/x86_64-linux-gnu" etc.
|
|
649
667
|
lib_filename = None
|
|
@@ -653,24 +671,41 @@ def _maybe_build_mozjpeg_ext() -> list[Extension]:
|
|
|
653
671
|
if not (c / "include" / "turbojpeg.h").exists():
|
|
654
672
|
continue
|
|
655
673
|
# Find the actual lib file. Linux multiarch ships under
|
|
656
|
-
# lib/<triple>/, plain /usr/local installs use lib
|
|
674
|
+
# lib/<triple>/, plain /usr/local installs use lib/, and
|
|
675
|
+
# AlmaLinux/RHEL (manylinux_2_28) puts 64-bit libs under lib64/
|
|
676
|
+
# by default — that's the GNU autoconf convention on those
|
|
677
|
+
# distros, and mozjpeg's CMake picks it up.
|
|
657
678
|
lib_candidates = [
|
|
658
679
|
("lib", "libturbojpeg.dylib"),
|
|
659
680
|
("lib", "libturbojpeg.so"),
|
|
660
681
|
("lib", "libturbojpeg.so.0"),
|
|
682
|
+
("lib64", "libturbojpeg.so"),
|
|
683
|
+
("lib64", "libturbojpeg.so.0"),
|
|
661
684
|
("lib/x86_64-linux-gnu", "libturbojpeg.so"),
|
|
662
685
|
("lib/x86_64-linux-gnu", "libturbojpeg.so.0"),
|
|
663
686
|
("lib/aarch64-linux-gnu", "libturbojpeg.so"),
|
|
664
687
|
("lib/aarch64-linux-gnu", "libturbojpeg.so.0"),
|
|
688
|
+
# Windows MSVC build (mozjpeg's CMake produces turbojpeg.lib
|
|
689
|
+
# import library next to turbojpeg.dll in bin/).
|
|
690
|
+
("lib", "turbojpeg.lib"),
|
|
665
691
|
]
|
|
666
692
|
for subdir, name in lib_candidates:
|
|
667
693
|
libpath = c / subdir / name
|
|
668
694
|
if not libpath.exists():
|
|
669
695
|
continue
|
|
670
696
|
# MozJPEG branches off libjpeg-turbo 1.x — it lacks the v3
|
|
671
|
-
# tj3* API.
|
|
672
|
-
#
|
|
673
|
-
|
|
697
|
+
# tj3* API. Three cases for accepting a candidate:
|
|
698
|
+
# (a) require_mozjpeg_subdir=True (generic /usr or /usr/local
|
|
699
|
+
# with a mozjpeg/ include subdir) — trust the layout.
|
|
700
|
+
# (b) prefix path is named '.../mozjpeg' or '.../mozjpeg/'
|
|
701
|
+
# (homebrew keg, our per-user cache build, conda env
|
|
702
|
+
# subdir) — the dedicated dir name is the signal; skip
|
|
703
|
+
# symbol probing. This is required on Windows where nm
|
|
704
|
+
# isn't on PATH and on minimal Linux runners that don't
|
|
705
|
+
# ship binutils.
|
|
706
|
+
# (c) otherwise: probe libturbojpeg's symbol table with nm
|
|
707
|
+
# to confirm it's a MozJPEG build (lacks tj3Compress8).
|
|
708
|
+
if require_mozjpeg_subdir or c.name == "mozjpeg":
|
|
674
709
|
prefix = c
|
|
675
710
|
lib_subdir = subdir
|
|
676
711
|
lib_filename = name
|
|
@@ -702,9 +737,18 @@ def _maybe_build_mozjpeg_ext() -> list[Extension]:
|
|
|
702
737
|
],
|
|
703
738
|
library_dirs=[str(prefix / lib_subdir)],
|
|
704
739
|
# Use absolute path on macOS to dodge the SDK-stub issue we
|
|
705
|
-
# hit with zlib-ng-compat.
|
|
740
|
+
# hit with zlib-ng-compat. On macOS we ALSO add the lib dir
|
|
741
|
+
# to LC_RPATH because mozjpeg's libturbojpeg has
|
|
742
|
+
# install_name=@rpath/libturbojpeg.0.dylib; without an rpath
|
|
743
|
+
# to a keg-only prefix like /opt/homebrew/opt/mozjpeg/lib,
|
|
744
|
+
# delocate can't resolve the LC_LOAD_DYLIB and the wheel
|
|
745
|
+
# repair fails with "@rpath/libturbojpeg.0.dylib not found".
|
|
706
746
|
libraries=[],
|
|
707
|
-
extra_link_args=
|
|
747
|
+
extra_link_args=(
|
|
748
|
+
[str(prefix / lib_subdir / lib_filename)]
|
|
749
|
+
+ ([f"-Wl,-rpath,{prefix / lib_subdir}"]
|
|
750
|
+
if sys.platform == "darwin" else [])
|
|
751
|
+
),
|
|
708
752
|
define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
|
|
709
753
|
language="c",
|
|
710
754
|
)]
|
|
@@ -1081,6 +1125,36 @@ extensions = [
|
|
|
1081
1125
|
extra_link_args=extra_link_args,
|
|
1082
1126
|
language="c",
|
|
1083
1127
|
),
|
|
1128
|
+
# libultrahdr (Ultra-HDR / ISO 21496-1). Links against system libuhdr.
|
|
1129
|
+
# macOS: `brew install libultrahdr` -> /opt/homebrew/{include,lib}.
|
|
1130
|
+
# Linux: build from https://github.com/google/libultrahdr.
|
|
1131
|
+
# If the header/dylib aren't present, the Extension still appears in
|
|
1132
|
+
# the wheel build plan -- the public opencodecs.uhdr module catches
|
|
1133
|
+
# ImportError and substitutes a clear "install libultrahdr" stub.
|
|
1134
|
+
Extension(
|
|
1135
|
+
name="opencodecs.codecs._uhdr",
|
|
1136
|
+
sources=["src/opencodecs/codecs/_uhdr.pyx"],
|
|
1137
|
+
include_dirs=[
|
|
1138
|
+
str(PKG_CODECS),
|
|
1139
|
+
numpy.get_include(),
|
|
1140
|
+
*_resolve_include_dirs("ultrahdr_api.h"),
|
|
1141
|
+
],
|
|
1142
|
+
library_dirs=[],
|
|
1143
|
+
libraries=["uhdr"],
|
|
1144
|
+
define_macros=[
|
|
1145
|
+
("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION"),
|
|
1146
|
+
],
|
|
1147
|
+
# Aggressive optimisation is critical for the gain-map kernel
|
|
1148
|
+
# to auto-vectorise (NEON on Apple Silicon, AVX2 on x86). The
|
|
1149
|
+
# polynomial log2 in _gain_map_kernel only beats numpy's
|
|
1150
|
+
# vectorised log2 when the compiler turns it into SIMD.
|
|
1151
|
+
extra_compile_args=[
|
|
1152
|
+
"-O3",
|
|
1153
|
+
"-ffast-math", # fine for gain-map output (uint8, ~1% tolerance)
|
|
1154
|
+
"-fno-math-errno",
|
|
1155
|
+
],
|
|
1156
|
+
language="c",
|
|
1157
|
+
),
|
|
1084
1158
|
# QOI: vendored single-header (3rdparty/qoi/qoi.h). Compile the impl
|
|
1085
1159
|
# via QOI_IMPLEMENTATION; no external library needed.
|
|
1086
1160
|
Extension(
|
|
@@ -1771,6 +1845,23 @@ extensions = [
|
|
|
1771
1845
|
define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
|
|
1772
1846
|
language="c",
|
|
1773
1847
|
),
|
|
1848
|
+
# PLIO_1 decode for IRAF segmentation-mask tiles (ZCMPTYPE=
|
|
1849
|
+
# 'PLIO_1'). Vendored cfitsio pliocomp.c (Doug Tody / NRAO,
|
|
1850
|
+
# public-domain — see 3rdparty/cfitsio/License.txt).
|
|
1851
|
+
Extension(
|
|
1852
|
+
name="opencodecs.codecs._plio",
|
|
1853
|
+
sources=[
|
|
1854
|
+
"src/opencodecs/codecs/_plio.pyx",
|
|
1855
|
+
"3rdparty/cfitsio/pliocomp.c",
|
|
1856
|
+
],
|
|
1857
|
+
include_dirs=[
|
|
1858
|
+
str(PKG_CODECS),
|
|
1859
|
+
numpy.get_include(),
|
|
1860
|
+
str(HERE / "3rdparty" / "cfitsio"),
|
|
1861
|
+
],
|
|
1862
|
+
define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
|
|
1863
|
+
language="c",
|
|
1864
|
+
),
|
|
1774
1865
|
# Radiance HDR (RGBE) — Bruce Walter / Greg Ward C library, vendored
|
|
1775
1866
|
# as a single .c/.h pair. Public-domain origin (Greg Ward, LBL); the
|
|
1776
1867
|
# vendored port carries the "USE AT YOUR OWN RISK" disclaimer in
|
|
@@ -1837,7 +1928,7 @@ _REQUIRED_HEADERS = {
|
|
|
1837
1928
|
"opencodecs.codecs._snappy": ("snappy-c.h",),
|
|
1838
1929
|
"opencodecs.codecs._pcodec": ("cpcodec.h",),
|
|
1839
1930
|
"opencodecs.codecs._jpeg": ("turbojpeg.h",),
|
|
1840
|
-
"opencodecs.codecs.
|
|
1931
|
+
"opencodecs.codecs._uhdr": ("ultrahdr_api.h",),
|
|
1841
1932
|
"opencodecs.codecs._isal": ("isa-l/igzip_lib.h",),
|
|
1842
1933
|
"opencodecs.codecs._webp": ("webp/encode.h",),
|
|
1843
1934
|
"opencodecs.codecs._jpeg2k": ("openjpeg-2.5/openjpeg.h", "openjpeg-2.4/openjpeg.h"),
|