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.
Files changed (446) hide show
  1. {opencodecs-0.2.0 → opencodecs-0.3.1}/CHANGES.rst +143 -3
  2. {opencodecs-0.2.0 → opencodecs-0.3.1}/MANIFEST.in +1 -0
  3. {opencodecs-0.2.0/src/opencodecs.egg-info → opencodecs-0.3.1}/PKG-INFO +110 -30
  4. {opencodecs-0.2.0 → opencodecs-0.3.1}/README.md +109 -29
  5. {opencodecs-0.2.0 → opencodecs-0.3.1}/THIRD-PARTY.md +1 -1
  6. {opencodecs-0.2.0 → opencodecs-0.3.1}/pyproject.toml +3 -3
  7. {opencodecs-0.2.0 → opencodecs-0.3.1}/setup.py +38 -0
  8. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/__init__.py +1 -1
  9. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_aec_codec.py +5 -2
  10. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_avif_codec.py +40 -11
  11. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_b2nd_codec.py +70 -4
  12. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bitshuffle_codec.py +7 -3
  13. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_blosc2_codec.py +8 -3
  14. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_brotli_codec.py +5 -2
  15. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_brunsli_codec.py +6 -5
  16. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_byteshuffle_codec.py +2 -1
  17. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_cms_codec.py +88 -2
  18. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_czi_codec.py +14 -2
  19. opencodecs-0.3.1/src/opencodecs/_czi_reader.py +2375 -0
  20. opencodecs-0.3.1/src/opencodecs/_czi_writer.py +841 -0
  21. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_deflate_codec.py +6 -4
  22. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom.py +162 -1
  23. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom_pyramid.py +32 -29
  24. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicomrle_codec.py +44 -64
  25. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicomweb.py +56 -5
  26. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_eer_reader.py +20 -5
  27. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_emd.py +5 -2
  28. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits.py +14 -9
  29. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits_codec.py +6 -3
  30. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_fits_compressed.py +62 -20
  31. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_gif_codec.py +64 -22
  32. opencodecs-0.3.1/src/opencodecs/_h5_common.py +203 -0
  33. opencodecs-0.3.1/src/opencodecs/_hdf5_codec.py +216 -0
  34. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_heif_codec.py +67 -21
  35. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_htj2k_codec.py +4 -2
  36. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_imaris.py +8 -3
  37. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg2k_codec.py +33 -6
  38. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg_codec.py +12 -2
  39. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpegls_codec.py +2 -1
  40. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jxl_codec.py +26 -5
  41. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lerc_codec.py +5 -2
  42. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lz4_codec.py +5 -2
  43. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mozjpeg_codec.py +12 -2
  44. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc_codec.py +6 -11
  45. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc_writer.py +53 -32
  46. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_n5.py +25 -4
  47. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nd2_native.py +6 -2
  48. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff.py +65 -36
  49. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff_writer.py +175 -132
  50. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti_codec.py +6 -10
  51. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti_writer.py +23 -18
  52. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_none_codec.py +15 -2
  53. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_numpy_codec.py +23 -7
  54. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oib_codec.py +9 -2
  55. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oib_native.py +56 -7
  56. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_oir_codec.py +42 -8
  57. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_omezarr.py +337 -87
  58. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_omezarr_writer.py +171 -213
  59. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_packints_codec.py +40 -6
  60. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_pcodec_codec.py +5 -2
  61. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_png_codec.py +12 -1
  62. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_predictor_codec.py +77 -59
  63. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_qoi_codec.py +6 -3
  64. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rcomp_codec.py +24 -1
  65. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rgbe_codec.py +2 -1
  66. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_snappy_codec.py +5 -2
  67. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_sperr_codec.py +4 -3
  68. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_sz3_codec.py +5 -2
  69. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_codec.py +100 -66
  70. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_http.py +177 -141
  71. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_pyramid.py +96 -146
  72. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_tiff_writer.py +197 -141
  73. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_vsi_pyramid.py +53 -16
  74. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_webp_codec.py +11 -4
  75. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zfp_codec.py +46 -26
  76. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zstd_codec.py +7 -3
  77. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/__init__.py +1 -0
  78. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_avif.pyx +58 -8
  79. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_b2nd.pyx +103 -3
  80. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_blosc2.pyx +55 -50
  81. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_brotli.pyx +102 -0
  82. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_brunsli.pyx +45 -55
  83. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bytetools.pyx +73 -1
  84. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_gif.pyx +16 -0
  85. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_heif.pyx +132 -22
  86. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jpeg.pyx +41 -5
  87. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jpeg2k.pyx +122 -30
  88. opencodecs-0.3.1/src/opencodecs/codecs/_jpegxr.pyx +138 -0
  89. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_jxl.pyx +38 -27
  90. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_lz4.pyx +118 -0
  91. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_mozjpeg.pyx +40 -4
  92. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_png.pyx +258 -1
  93. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_rcomp.pyx +20 -6
  94. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_sperr.pyx +3 -2
  95. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_tiff.pyx +21 -20
  96. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_zfp.pyx +1 -1
  97. opencodecs-0.3.1/src/opencodecs/codecs/_zstd.pyx +598 -0
  98. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/avif.pxd +14 -1
  99. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd.pxd +7 -0
  100. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd_helpers.c +44 -1
  101. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/b2nd_helpers.h +11 -1
  102. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/blosc2.pxd +19 -1
  103. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/brotli.pxd +17 -1
  104. opencodecs-0.3.1/src/opencodecs/codecs/byteplanes.h +49 -0
  105. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/heif.pxd +12 -1
  106. opencodecs-0.3.1/src/opencodecs/codecs/jpegxr_shim.c +125 -0
  107. opencodecs-0.3.1/src/opencodecs/codecs/jpegxr_shim.h +32 -0
  108. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/lz4.pxd +11 -0
  109. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjpeg.pxd +3 -2
  110. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/spng.pxd +16 -0
  111. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zstd.pxd +24 -0
  112. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_io_helpers.py +2 -1
  113. opencodecs-0.3.1/src/opencodecs/core/_range_index.py +76 -0
  114. opencodecs-0.3.1/src/opencodecs/core/_write_helpers.py +75 -0
  115. opencodecs-0.3.1/src/opencodecs/core/buffers.py +97 -0
  116. opencodecs-0.3.1/src/opencodecs/core/checksums.py +38 -0
  117. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/codec.py +45 -4
  118. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/io.py +13 -8
  119. opencodecs-0.3.1/src/opencodecs/core/native_source.py +87 -0
  120. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/parallel.py +81 -4
  121. opencodecs-0.3.1/src/opencodecs/core/pipeline.py +198 -0
  122. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/pyramid.py +124 -0
  123. opencodecs-0.3.1/src/opencodecs/core/rows.py +167 -0
  124. opencodecs-0.3.1/src/opencodecs/core/scratch.py +35 -0
  125. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/segment_compression.py +84 -5
  126. opencodecs-0.3.1/src/opencodecs/core/streaming.py +180 -0
  127. opencodecs-0.3.1/src/opencodecs/core/tile_cache.py +129 -0
  128. opencodecs-0.3.1/src/opencodecs/core/verification.py +222 -0
  129. {opencodecs-0.2.0 → opencodecs-0.3.1/src/opencodecs.egg-info}/PKG-INFO +110 -30
  130. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/SOURCES.txt +65 -1
  131. opencodecs-0.3.1/tests/test_b2nd_file_reader.py +78 -0
  132. opencodecs-0.3.1/tests/test_blosc2_threads.py +52 -0
  133. opencodecs-0.3.1/tests/test_bounded_pipeline.py +54 -0
  134. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_capability_manifest.py +24 -21
  135. opencodecs-0.3.1/tests/test_container_pipeline.py +152 -0
  136. opencodecs-0.3.1/tests/test_container_streaming.py +249 -0
  137. opencodecs-0.3.1/tests/test_czi_bounded_iteration.py +161 -0
  138. opencodecs-0.3.1/tests/test_czi_direct_decode.py +238 -0
  139. opencodecs-0.3.1/tests/test_czi_mixed_subblocks.py +82 -0
  140. opencodecs-0.3.1/tests/test_czi_parallel_write.py +210 -0
  141. opencodecs-0.3.1/tests/test_czi_read_dispatch.py +199 -0
  142. opencodecs-0.3.1/tests/test_czi_read_out.py +105 -0
  143. opencodecs-0.3.1/tests/test_czi_region_index.py +431 -0
  144. opencodecs-0.3.1/tests/test_czi_region_windows.py +305 -0
  145. opencodecs-0.3.1/tests/test_czi_segment_parts.py +180 -0
  146. opencodecs-0.3.1/tests/test_czi_slide_geometry.py +209 -0
  147. opencodecs-0.3.1/tests/test_czi_verification.py +323 -0
  148. opencodecs-0.3.1/tests/test_czi_write_pipeline.py +107 -0
  149. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_writer.py +38 -2
  150. opencodecs-0.3.1/tests/test_czi_writer_shuffle.py +188 -0
  151. opencodecs-0.3.1/tests/test_dicom_slide_selection.py +138 -0
  152. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicomweb.py +149 -75
  153. opencodecs-0.3.1/tests/test_direct_filter_outputs.py +94 -0
  154. opencodecs-0.3.1/tests/test_eer_worker_budget.py +50 -0
  155. opencodecs-0.3.1/tests/test_filter_scratch.py +51 -0
  156. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_remote.py +5 -3
  157. opencodecs-0.3.1/tests/test_incremental_byte_codecs.py +165 -0
  158. opencodecs-0.3.1/tests/test_jpegxr.py +157 -0
  159. opencodecs-0.3.1/tests/test_native_output_sinks.py +117 -0
  160. opencodecs-0.3.1/tests/test_native_source_callbacks.py +181 -0
  161. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nd2_native.py +24 -0
  162. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_ndtiff.py +7 -1
  163. opencodecs-0.3.1/tests/test_nrrd_iteration.py +50 -0
  164. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_omezarr.py +2 -0
  165. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_omezarr_sharded_range.py +30 -1
  166. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_open_pyramid.py +6 -18
  167. opencodecs-0.3.1/tests/test_owned_color_context.py +44 -0
  168. opencodecs-0.3.1/tests/test_owned_image_decoders.py +73 -0
  169. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase7_cms.py +0 -10
  170. opencodecs-0.3.1/tests/test_pipeline_budget.py +109 -0
  171. opencodecs-0.3.1/tests/test_pipeline_catalog.py +86 -0
  172. opencodecs-0.3.1/tests/test_pipeline_executor.py +116 -0
  173. opencodecs-0.3.1/tests/test_png_row_sessions.py +141 -0
  174. opencodecs-0.3.1/tests/test_public_output_buffers.py +203 -0
  175. opencodecs-0.3.1/tests/test_pyramid_batched_regions.py +227 -0
  176. opencodecs-0.3.1/tests/test_range_pipeline_completion.py +151 -0
  177. opencodecs-0.3.1/tests/test_segment_encoder_binding.py +24 -0
  178. opencodecs-0.3.1/tests/test_shared_io_regressions.py +255 -0
  179. opencodecs-0.3.1/tests/test_source_pool_lifetime.py +146 -0
  180. opencodecs-0.3.1/tests/test_tiff_pipeline.py +150 -0
  181. opencodecs-0.3.1/tests/test_tiff_spool.py +29 -0
  182. opencodecs-0.3.1/tests/test_tiff_writer_float_predictor.py +114 -0
  183. opencodecs-0.3.1/tests/test_tiff_writer_verification.py +183 -0
  184. opencodecs-0.3.1/tests/test_tile_cache.py +235 -0
  185. opencodecs-0.3.1/tests/test_verified_encoding.py +252 -0
  186. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_writer_contract.py +56 -0
  187. opencodecs-0.3.1/tests/test_writer_pipeline_completion.py +266 -0
  188. opencodecs-0.3.1/tests/test_writer_verification.py +139 -0
  189. opencodecs-0.3.1/tests/test_zarr_region_fast_path.py +99 -0
  190. opencodecs-0.3.1/tests/test_zstd_owned_output.py +36 -0
  191. opencodecs-0.2.0/src/opencodecs/_czi_reader.py +0 -1001
  192. opencodecs-0.2.0/src/opencodecs/_czi_writer.py +0 -522
  193. opencodecs-0.2.0/src/opencodecs/_h5_common.py +0 -44
  194. opencodecs-0.2.0/src/opencodecs/_hdf5_codec.py +0 -366
  195. opencodecs-0.2.0/src/opencodecs/codecs/_zstd.pyx +0 -255
  196. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/VENDOR.toml +0 -0
  197. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/LICENSE +0 -0
  198. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/README.md +0 -0
  199. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bcdec/bcdec.h +0 -0
  200. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/LICENSE +0 -0
  201. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/README.rst +0 -0
  202. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle.c +0 -0
  203. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle.h +0 -0
  204. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_core.c +0 -0
  205. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_core.h +0 -0
  206. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/bitshuffle_internals.h +0 -0
  207. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/iochain.c +0 -0
  208. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/bitshuffle/iochain.h +0 -0
  209. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/License.txt +0 -0
  210. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hcompress.c +0 -0
  211. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hdecompress.c +0 -0
  212. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fits_hdecompress_api.h +0 -0
  213. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/fitsio2.h +0 -0
  214. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/pliocomp.c +0 -0
  215. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/ricecomp.c +0 -0
  216. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/cfitsio/ricecomp.h +0 -0
  217. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/LICENSE +0 -0
  218. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/spng.c +0 -0
  219. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/libspng/spng.h +0 -0
  220. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/LICENSE +0 -0
  221. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/oc_eer.c +0 -0
  222. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_eer/oc_eer.h +0 -0
  223. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/LICENSE +0 -0
  224. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/oc_giflzw.c +0 -0
  225. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_giflzw/oc_giflzw.h +0 -0
  226. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/LICENSE +0 -0
  227. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/oc_tifflzw.c +0 -0
  228. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/oc_tifflzw/oc_tifflzw.h +0 -0
  229. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/qoi/LICENSE +0 -0
  230. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/qoi/qoi.h +0 -0
  231. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.c +0 -0
  232. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.h +0 -0
  233. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/rgbe/rgbe.txt +0 -0
  234. {opencodecs-0.2.0 → opencodecs-0.3.1}/3rdparty/vendor_hashes.json +0 -0
  235. {opencodecs-0.2.0 → opencodecs-0.3.1}/LICENSE +0 -0
  236. {opencodecs-0.2.0 → opencodecs-0.3.1}/bench/build_libjxl.sh +0 -0
  237. {opencodecs-0.2.0 → opencodecs-0.3.1}/patches/libjxl/README.md +0 -0
  238. {opencodecs-0.2.0 → opencodecs-0.3.1}/setup.cfg +0 -0
  239. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bcn_codec.py +0 -0
  240. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bmp_codec.py +0 -0
  241. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_bz2_codec.py +0 -0
  242. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dicom_codec.py +0 -0
  243. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dm.py +0 -0
  244. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_dm_codec.py +0 -0
  245. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_emd_codec.py +0 -0
  246. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ets.py +0 -0
  247. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_gzip_codec.py +0 -0
  248. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_hdf5_http.py +0 -0
  249. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_htj2k_pyramid.py +0 -0
  250. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg2k_pyramid.py +0 -0
  251. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_jpeg_pyramid.py +0 -0
  252. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lif_codec.py +0 -0
  253. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lif_native.py +0 -0
  254. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_lzma_codec.py +0 -0
  255. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mozjpeg_pyramid.py +0 -0
  256. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_mrc.py +0 -0
  257. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nd2_codec.py +0 -0
  258. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ndtiff_pyramid.py +0 -0
  259. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nifti.py +0 -0
  260. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nrrd.py +0 -0
  261. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_nrrd_codec.py +0 -0
  262. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_numpy_reader.py +0 -0
  263. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ole2.py +0 -0
  264. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ome_xml.py +0 -0
  265. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_pyramid_build.py +0 -0
  266. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_quantize_codec.py +0 -0
  267. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_rgbe.py +0 -0
  268. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_scaled_pyramid.py +0 -0
  269. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_ultrahdr_codec.py +0 -0
  270. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_vsi_codec.py +0 -0
  271. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/_zarr_codecs.py +0 -0
  272. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_aec.pyx +0 -0
  273. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bcdec.pyx +0 -0
  274. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bitshuffle.pyx +0 -0
  275. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_bmp.pyx +0 -0
  276. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_charls.pyx +0 -0
  277. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_deflate.pyx +0 -0
  278. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_eer.pyx +0 -0
  279. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_hcomp.pyx +0 -0
  280. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_isal.pyx +0 -0
  281. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_lerc.pyx +0 -0
  282. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_ndtiff.pyx +0 -0
  283. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_openjph.pyx +0 -0
  284. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_pcodec.pyx +0 -0
  285. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_plio.pyx +0 -0
  286. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_qoi.pyx +0 -0
  287. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_registry.py +0 -0
  288. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_rgbe.pyx +0 -0
  289. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_snappy.pyx +0 -0
  290. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_sz3.pyx +0 -0
  291. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_uhdr.pyx +0 -0
  292. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/_webp.pyx +0 -0
  293. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/bcdec.pxd +0 -0
  294. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/bitshuffle.pxd +0 -0
  295. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/brunsli.pxd +0 -0
  296. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/charls.pxd +0 -0
  297. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/eer.pxd +0 -0
  298. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/giflib.pxd +0 -0
  299. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/heif_shim.h +0 -0
  300. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/isal_shim.c +0 -0
  301. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/lerc.pxd +0 -0
  302. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libaec.pxd +0 -0
  303. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libjxl.pxd +0 -0
  304. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/libuhdr.pxd +0 -0
  305. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/mozjpeg.pxd +0 -0
  306. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph.pxd +0 -0
  307. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph_shim.cpp +0 -0
  308. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/openjph_shim.h +0 -0
  309. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/pcodec.pxd +0 -0
  310. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/qoi.pxd +0 -0
  311. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/rgbe.pxd +0 -0
  312. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/snappy.pxd +0 -0
  313. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/sperr.pxd +0 -0
  314. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/sz3c.pxd +0 -0
  315. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/turbojpeg.pxd +0 -0
  316. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp.pxd +0 -0
  317. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp_shim.c +0 -0
  318. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/webp_shim.h +0 -0
  319. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zfp.pxd +0 -0
  320. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/codecs/zlib_h.pxd +0 -0
  321. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/__init__.py +0 -0
  322. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_optional_backend.py +0 -0
  323. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/_sidecar_header.py +0 -0
  324. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/color.py +0 -0
  325. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/core/errors.py +0 -0
  326. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/jxl.py +0 -0
  327. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/parallel.py +0 -0
  328. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/tiff_reader.py +0 -0
  329. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/tifffile_patch.py +0 -0
  330. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/uhdr.py +0 -0
  331. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs/zarr.py +0 -0
  332. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/dependency_links.txt +0 -0
  333. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/requires.txt +0 -0
  334. {opencodecs-0.2.0 → opencodecs-0.3.1}/src/opencodecs.egg-info/top_level.txt +0 -0
  335. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_auto_pyramid.py +0 -0
  336. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_avif_sequence.py +0 -0
  337. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_bcdec.py +0 -0
  338. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_bcn_bands.py +0 -0
  339. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_blosc2_partial.py +0 -0
  340. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_brunsli.py +0 -0
  341. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_charls.py +0 -0
  342. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_chunked_means_cheap.py +0 -0
  343. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_codec_registry.py +0 -0
  344. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_core_codec_api.py +0 -0
  345. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus.py +0 -0
  346. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_codec_decode.py +0 -0
  347. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_manifest.py +0 -0
  348. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_native_fixtures.py +0 -0
  349. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_other.py +0 -0
  350. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_png.py +0 -0
  351. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_tiff.py +0 -0
  352. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_corpus_vendors.py +0 -0
  353. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_final.py +0 -0
  354. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_finishing.py +0 -0
  355. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_last.py +0 -0
  356. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_more.py +0 -0
  357. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_coverage_push.py +0 -0
  358. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_fixture.py +0 -0
  359. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_czi_pyramid.py +0 -0
  360. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_data_source.py +0 -0
  361. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_decode_releases_gil.py +0 -0
  362. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_deflate.py +0 -0
  363. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_delta_parity.py +0 -0
  364. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom.py +0 -0
  365. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_encodings.py +0 -0
  366. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_parallel.py +0 -0
  367. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dicom_wsi_pyramid.py +0 -0
  368. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm.py +0 -0
  369. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm_offsets.py +0 -0
  370. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_dm_synthetic.py +0 -0
  371. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_edge_cases.py +0 -0
  372. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_eer.py +0 -0
  373. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_eer_parallel.py +0 -0
  374. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_emd.py +0 -0
  375. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_encode_comprehensive.py +0 -0
  376. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_error_handling.py +0 -0
  377. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_fits.py +0 -0
  378. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_fits_parallel.py +0 -0
  379. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_gif.py +0 -0
  380. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_gzip_presized.py +0 -0
  381. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_http.py +0 -0
  382. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_local.py +0 -0
  383. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_hdf5_parallel.py +0 -0
  384. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_heif_avif_features.py +0 -0
  385. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_heif_multi_image.py +0 -0
  386. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_htj2k_conformance.py +0 -0
  387. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_byte_savings.py +0 -0
  388. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_prefetch.py +0 -0
  389. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_http_unified.py +0 -0
  390. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_imaris.py +0 -0
  391. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_io_chunked.py +0 -0
  392. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_isal.py +0 -0
  393. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_jpeg2k_region.py +0 -0
  394. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_jxl.py +0 -0
  395. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_lif_indexing.py +0 -0
  396. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_lif_native.py +0 -0
  397. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_live_archives.py +0 -0
  398. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mozjpeg.py +0 -0
  399. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc.py +0 -0
  400. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc_mrcz_http.py +0 -0
  401. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_mrc_nifti_writers.py +0 -0
  402. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_n5.py +0 -0
  403. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_native_parity.py +0 -0
  404. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nifti.py +0 -0
  405. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nrrd.py +0 -0
  406. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_nrrd_slices.py +0 -0
  407. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_offset_readers.py +0 -0
  408. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_oib_indexing.py +0 -0
  409. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_oib_native.py +0 -0
  410. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_ome_xml.py +0 -0
  411. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_openjph.py +0 -0
  412. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_optional_backend.py +0 -0
  413. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_parallel_jxl.py +0 -0
  414. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase4_filters.py +0 -0
  415. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase5_icc.py +0 -0
  416. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_phase6_codecs.py +0 -0
  417. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_rcomp_truncated_input.py +0 -0
  418. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_contract.py +0 -0
  419. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_source_kinds.py +0 -0
  420. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reader_streaming.py +0 -0
  421. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_reference_parity.py +0 -0
  422. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_rgbe.py +0 -0
  423. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_scaled_pyramid.py +0 -0
  424. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_sidecar_header.py +0 -0
  425. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_snappy.py +0 -0
  426. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_streaming_means_streaming.py +0 -0
  427. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tier1_scientific.py +0 -0
  428. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_codec_encode.py +0 -0
  429. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_http.py +0 -0
  430. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_native.py +0 -0
  431. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_parallel_decode.py +0 -0
  432. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_pyramid.py +0 -0
  433. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_read_path.py +0 -0
  434. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_reader.py +0 -0
  435. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tiff_writer.py +0 -0
  436. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_tifffile_patch.py +0 -0
  437. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_uhdr.py +0 -0
  438. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_unified_api.py +0 -0
  439. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_url_sources.py +0 -0
  440. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vendor_provenance.py +0 -0
  441. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_version_consistency.py +0 -0
  442. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vsi_oir.py +0 -0
  443. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_vsi_pyramid.py +0 -0
  444. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_webp_animation.py +0 -0
  445. {opencodecs-0.2.0 → opencodecs-0.3.1}/tests/test_zarr_adapters.py +0 -0
  446. {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. Per the new lesson in
1033
- CLAUDE.md, this iteration was validated end-to-end through the
1034
- same script CI runs, with the same env vars, before any push.
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.2.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) and 6 (ZSTDHDR) — the entire
301
- modern Zen archive. JPEG-XR sub-blocks (rare in 2022+ output) raise
302
- `NotImplementedError`. The reader exposes `metadata_bytes` and
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`, macOS M1 Ultra, vs `imagecodecs` / `tifffile` / `ndstorage`):
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 M3 | Threadripper x86_64 |
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, so the reader-only backends
400
- (Imaris, OME-Zarr, NDTiff, N5) are not in it; they are listed in the
401
- tables above and reached through `open_pyramid` / their own classes.
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–3.13 on macOS (arm64),
547
- Linux (x86_64 + aarch64), and Windows (amd64). Each wheel
548
- bundles libjxl, libavif, libheif, libwebp, libdeflate,
549
- c-blosc2, and friends — no system dependencies needed.
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.1.1** on PyPI (May 2026). Core API stable; **1066 tests passing**
573
- on Mac M1 Ultra + Linux x86_64/aarch64 + Windows VM
574
- - Native readers + writers for the common scientific containers
575
- (TIFF, BigTIFF, OME-TIFF, CZI, NDTiff, HDF5, JXL, FITS,
576
- OME-Zarr v2 + v3 sharded)
577
- - Cross-platform bench coverage: Mac arm64 (canonical), Windows 11 LTSC
578
- (libvirt VM), Linux x86_64 (Threadripper-class)
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
- - **Windows wheels currently miss `_sz3`, `_pcodec`, `_sperr`, `_brunsli`**
589
- — toolchain mismatch (conda's bash picks GCC over MSVC for CMake);
590
- v0.1.2 will restore them. macOS + Linux wheels have the full set.
591
- - CCITT Fax3/Fax4 encode — legacy fax; zero scientific users
592
- - JPEG-XR — abandoned format outside niche DICOM
593
- - libspng `filter_sum` SIMD — off the bench-tracked workload (`h2h_png_4mp_rgb`
594
- is at 1.14× already); filter-bound PNG-encode users could see another 2-3×
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) and 6 (ZSTDHDR) — the entire
249
- modern Zen archive. JPEG-XR sub-blocks (rare in 2022+ output) raise
250
- `NotImplementedError`. The reader exposes `metadata_bytes` and
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`, macOS M1 Ultra, vs `imagecodecs` / `tifffile` / `ndstorage`):
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 M3 | Threadripper x86_64 |
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, so the reader-only backends
348
- (Imaris, OME-Zarr, NDTiff, N5) are not in it; they are listed in the
349
- tables above and reached through `open_pyramid` / their own classes.
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–3.13 on macOS (arm64),
495
- Linux (x86_64 + aarch64), and Windows (amd64). Each wheel
496
- bundles libjxl, libavif, libheif, libwebp, libdeflate,
497
- c-blosc2, and friends — no system dependencies needed.
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.1.1** on PyPI (May 2026). Core API stable; **1066 tests passing**
521
- on Mac M1 Ultra + Linux x86_64/aarch64 + Windows VM
522
- - Native readers + writers for the common scientific containers
523
- (TIFF, BigTIFF, OME-TIFF, CZI, NDTiff, HDF5, JXL, FITS,
524
- OME-Zarr v2 + v3 sharded)
525
- - Cross-platform bench coverage: Mac arm64 (canonical), Windows 11 LTSC
526
- (libvirt VM), Linux x86_64 (Threadripper-class)
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
- - **Windows wheels currently miss `_sz3`, `_pcodec`, `_sperr`, `_brunsli`**
537
- — toolchain mismatch (conda's bash picks GCC over MSVC for CMake);
538
- v0.1.2 will restore them. macOS + Linux wheels have the full set.
539
- - CCITT Fax3/Fax4 encode — legacy fax; zero scientific users
540
- - JPEG-XR — abandoned format outside niche DICOM
541
- - libspng `filter_sum` SIMD — off the bench-tracked workload (`h2h_png_4mp_rgb`
542
- is at 1.14× already); filter-bound PNG-encode users could see another 2-3×
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.1 | BSD-3-Clause |
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.2.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