Skip to content

Changelog

Notable changes to pixtreme are documented in this file.

2.0.0 - 2026-10-25

Wheel validation included full test suite runs on RTX A6000 (compute capability 8.6), RTX 6000 Ada Generation (8.9), and GeForce RTX 5090 (12.0). NVIDIA driver R580 and compute capability 7.5 (Turing) have not been verified on hardware.

Added

  • Added a public C and C++ SDK: headers, libpixtreme.so.2, and a CMake package are included in the Linux wheel. C11 and C++17 applications can use pixtreme without embedding Python. Locate the package with pixtreme.core.get_cmake_dir(), use find_package(pixtreme CONFIG REQUIRED), and link pixtreme::pixtreme. Python and native consumers share the same library; keep pixtreme installed rather than copying its library.
  • The SDK provides GPU Frames with color metadata, channel parsing, borrowed pixel owners, transactional pixel replacement, shallow or deep cloning, and DLPack 1.x exchange. Operations accept a CUDA stream and an optional allocator for output and scratch memory; the default allocator uses CUDA stream-ordered memory allocation.
  • The SDK exposes token matching and canonical token constants, colorspace and reference-white definitions, and Lut / Lut1D validation. It also provides cast_dtype, recode_dtype, quantize, dequantize, full_to_legal, legal_to_full, and channel shuffle. Native shuffle requires matching colorspace and gamma; Python's shuffle(adapt=True) retains its color-conversion behavior.
  • C and C++ callers can read EXR headers and pixels, write EXR images, and write mixed HALF, FLOAT, and UINT channel groups without Python. Supported EXR options, pixel types, and color metadata follow the Python EXR APIs.
  • The shared library has a C ABI with opaque handles and size-prefixed structs, plus a header-only C++ wrapper. Within a major version, the ABI grows through added functions and trailing struct fields; programs built with earlier minor headers run against later minor libraries without rebuilding. Use pixtreme_check_abi or pixtreme::require_abi() to check the loaded library against the headers used to build the application.
  • Wheels include full license texts for bundled third-party components in dist-info/licenses/ and identify them in the SPDX License-Expression. A separate notice identifies the statically linked CUDA runtime's license.
  • GitHub Releases include an HTML documentation archive containing the API reference and the C and C++ SDK guide.

Changed

  • pixtreme.core.Frame now wraps one persistent C++ Frame. It no longer inherits pydantic.BaseModel and no longer provides model_fields, model_dump, model_construct, or model_copy. vars(frame) and frame.__dict__ are unavailable, and fields cannot be deleted with del. Read and assign the five properties instead. Validation errors are ValueError rather than pydantic.ValidationError. For migration, read the five fields directly, use the keyword-only constructor to build a Frame, and use copy.copy or copy.deepcopy to copy one. Field names and order, defaults, validation on assignment, contiguous-array identity, equality, unhashability, and pickle roundtrips are preserved. pixtreme.io.ImageHeader remains a pydantic model.
  • The Python source, tests, project metadata, and lock file now live in python/; native C++ implementations follow the corresponding Python package paths under cpp/. The build backend is scikit-build-core with setuptools-scm versions from vX.Y.Z tags and a nanobind extension. Existing Python image-processing operation names and arguments remain unchanged.
  • 2.0.0 wheels target Linux x86_64 (manylinux_2_28) with the cp312-abi3 tag for standard CPython 3.12 and newer. Free-threaded CPython builds are not supported. 2.0.0 does not provide native Windows wheels. On Windows, use the Linux wheel under WSL2, or use 1.x for native Windows. Installing and using the wheel requires no compiler or CUDA toolkit; CUDA's runtime is linked statically. PyPI and GitHub Releases distribute wheels only; source distributions are not published.
  • EXR reading and writing now use the shared C++ library, including container parsing, part and channel selection, and all ten compression modes: NONE, RLE, ZIPS, ZIP, PIZ, PXR24, B44, B44A, DWAA, and DWAB. Native implementations use C++ and CUDA. ZIP, ZIPS, and PXR24 use libdeflate for Deflate compression and decompression, and the nvidia-nvcomp-cu13 runtime dependency has been removed.
  • Floating-point results follow each operation's specified precision. Bit-for-bit equality is not guaranteed across GPU generations, CPU instruction sets, or math libraries.

Fixed

  • Fixed reading PXR24 EXR images with mixed HALF, FLOAT, and UINT channels into a float32 Frame, including scanline, tiled, and multipart files.
  • Corrected B44 and B44A pLinear HALF decoding to match OpenEXR for external EXR files, including the 0x1935 pattern decoding to 0xd1f9.
  • For EXR files without chromaticities, read_header(...).color.raw now retains an explicitly stored acesImageContainerFlag=0 as {'acesImageContainerFlag': False}.
  • white_point_simulation rejects reference whites on or within float64 roundoff of an edge of the Frame primaries' chromaticity triangle with a ValueError explaining the reason and correction. This also applies when the input and output reference whites are equal.
  • Frame cleanup releases pixels without unraisable exceptions when the active Python frame's builtins omit __import__, including garbage collection inside collections.namedtuple constructors.
  • Keeping Frames alive until Python interpreter shutdown no longer emits cleanup errors to stderr or interferes with process exit.

Migration

Frame uses five properties: data, colorspace, gamma, channels, and matrix. Replace pydantic model operations with field access and the validated keyword-only constructor.

# Before
fields = frame.model_dump()
frame = px.core.Frame.model_construct(
    data=data, colorspace="ACEScg", gamma="linear", channels="RGB", matrix=None
)

# 2.0
fields = {name: getattr(frame, name) for name in ("data", "colorspace", "gamma", "channels", "matrix")}
frame = px.core.Frame(
    data=data, colorspace="ACEScg", gamma="linear", channels="RGB", matrix=None
)

Use the standard library's copy operations. A shallow copy shares pixels, a deep copy copies pixels, and both copies have independent metadata.

# Before
shallow = frame.model_copy()
deep = frame.model_copy(deep=True)

# 2.0
import copy

shallow = copy.copy(frame)
deep = copy.deepcopy(frame)

Catch ValueError when constructing a Frame or assigning a field:

# Before
try:
    frame.gamma = gamma
except pydantic.ValidationError as error:
    print(error)

# 2.0
try:
    frame.gamma = gamma
except ValueError as error:
    print(error)

vars(frame) and frame.__dict__ are unavailable; read the five properties or create a field dictionary as above. Mutating such a dictionary does not assign Frame properties. Fields cannot be removed with del frame.colorspace or another del frame.<field> operation. Assign valid values through the properties.

1.9.3 - 2026-10-17

pixtreme 1.9.3 fixes reading DWAA and DWAB EXR images. Public operation names, arguments, accepted names, and return shapes remain compatible.

Fixed

  • Fixed reading DWAA and DWAB EXR images with Deflate-compressed AC coefficients, including small tiles written by OpenEXR. Unsupported legacy DWA versions now report how to re-encode the image.

1.9.2 - 2026-10-17

pixtreme 1.9.2 fixes reading DWAA and DWAB EXR images. Public operation names, arguments, accepted names, and return shapes remain compatible.

Fixed

  • Fixed reading DWAA and DWAB EXR images with nvCOMP 6.0.
  • Fixed reading some DWAA and DWAB EXR images that previously failed during decompression.

1.9.1 - 2026-10-16

pixtreme 1.9.1 does not change library behavior: the pixtreme package code is the same as in 1.9.0. Public operation names, arguments, accepted names, and return shapes remain compatible. This release changes how the documentation site and the development tooling in the source distribution are produced.

Changed

  • The documentation site is built and published to GitHub Pages by a GitHub Actions workflow in the public repository. The documentation build dependencies (mkdocs-material, mkdocstrings) form a separate docs dependency group, which the dev group includes.
  • The token sheet generator scripts under tests/ require --output-dir instead of writing to a default directory.

1.9.0 - 2026-10-15

pixtreme 1.9.0 moves its GPU dependencies from the CUDA 12 builds to the CUDA 13 builds, including CuPy (cupy-cuda13x). It requires NVIDIA driver R580 or newer and an NVIDIA GPU with compute capability 7.5 or higher; use pixtreme 1.8.0 for CUDA 12 environments. Public operation names, arguments, accepted names, and return shapes remain compatible. The published performance report (docs/performance.md) and README performance table still show the earlier CUDA 12.9 baseline measured at commit 260fe6e; CUDA 13 measurements have not been taken for this release.

Changed

  • pixtreme now requires CUDA 13 builds of its GPU dependencies, NVIDIA driver R580 or newer, and an NVIDIA GPU with compute capability 7.5 or higher. Applications pinned to CUDA 12 dependency builds must migrate to CUDA 13; drivers older than R580 and GPUs with compute capability 7.0 or lower are no longer supported.

1.8.0 - 2026-10-06

pixtreme 1.8.0 allows separately installed font packages to contribute subpackages beneath pixtreme.fonts. px.io.to_v210 now writes zero to sample slots with no corresponding pixel in the last six-pixel group of a row; encoded bytes change for widths not divisible by six, while pixel data and px.io.from_v210 results stay the same. px.metrics.ssim and px.metrics.ssim_map have about 34% lower median runtimes in the measured FHD case, and EXR decoding has internal speed improvements. Public operation names, arguments, accepted names, and return shapes remain compatible. The published performance report (docs/performance.md) and README performance table still show the earlier 210-case baseline measured at commit 260fe6e; the SSIM improvements below were measured separately and those tables have not been regenerated.

Added

  • pixtreme.fonts is now a package, allowing a separately installed font package to contribute a pixtreme/fonts/<name>/ subtree and import it as pixtreme.fonts.<name>. The existing px.fonts.available() and px.fonts.font_path(name) operations and entry-point font discovery retain their behavior.

Changed

  • px.metrics.ssim and px.metrics.ssim_map use a separable window calculation with compensated accumulation. On an NVIDIA RTX A6000 with FHD fp32 RGB inputs and data_range=1.0, the medians across three targeted runs fell from 2.014 to 1.328 ms and 2.025 to 1.342 ms, respectively (about 34%). Results remain within the existing 4e-5 tolerance against the independent float64 oracle.
  • EXR decoding avoids repeated construction of channel rows and combines chunk replacements, improving its internal read path without changing the public API.

Fixed

  • px.io.to_v210 now zeros unused Y, Cb, and Cr sample slots in the last six-pixel group of rows whose widths are not divisible by six. Encoded bytes for these widths differ from 1.7.0; samples that represent pixels, row padding, and px.io.from_v210 results are unchanged.

1.7.0 - 2026-10-04

pixtreme 1.7.0 adds two public capabilities. The first is the px.io.from_p210 / px.io.to_p210 pair, the tenth named-format pair, which exchanges 10-bit 4:2:2 semi-planar frames (a uint16 Y plane followed by a uint16 interleaved Cb Cr plane, with the code in the upper 10 bits of each word) as one C-contiguous device array under the existing 4:2:2 rules; the io module grows to 31 operations and the public API to 102. The second is the DCI reference-white token for the SMPTE RP 431-2 D-Cinema white, accepted by px.color.chromatic_adaptation and px.color.white_point_simulation. Both are additions: existing operations, signatures, defaults, and token spellings are unchanged, and there are no breaking changes to the public API. The EXR reader and writer are reorganized internally by compression, and corrupt-chunk errors now name the compression that failed. The published performance baseline (docs/performance.md and the README table) is carried over from 1.6.0 unchanged and does not yet cover the P210 pair.

Added

  • Added the DCI reference-white token for the SMPTE RP 431-2 D-Cinema white (0.3140, 0.3510). px.color.chromatic_adaptation and px.color.white_point_simulation now accept it in either white argument. This adds no operation; the public API remains at 102 operations.
  • Added px.io.from_p210 and px.io.to_p210, the tenth named-format pair. P210 is 10-bit 4:2:2 semi-planar (a uint16 Y plane followed by a uint16 interleaved Cb Cr plane) exchanged as a C-contiguous 1D device array. Each word carries a fixed 10 effective code bits in its upper 10 bits with no bit_depth argument; import ignores the lower six padding bits and export writes them as zero. range uses the H.273 mapping for n = 10, export rounds half away from zero and clips only to the code range [0, 1023], and the even-width constraint, horizontally co-sited chroma at full vertical resolution, and the interpolation tokens follow the existing 4:2:2 rules. The io module now exposes 31 operations and the public API 102.

Changed

  • EXR corrupt-chunk errors for RLE, PXR24, B44, B44A, and PIZ now name the compression whose chunk failed. The exception types and the situations that raise them are unchanged.

1.6.0 - 2026-09-23

pixtreme 1.6.0 adds two public capabilities. The first is the px.io.from_p216 / px.io.to_p216 pair, the ninth named-format pair, which exchanges 16-bit 4:2:2 semi-planar frames (a uint16 Y plane followed by a uint16 interleaved Cb Cr plane) as one C-contiguous device array under the existing 4:2:2 planar rules; the io module grows to 29 operations and the public API to 100. The second is the keyword-only preserve_shaper option of px.io.read_lut and px.io.decode_lut, which evaluates a nonidentity .3dl shaper strictly in one GPU kernel instead of the default same-edge bake. Both are independent additions: existing token spellings, aliases, signatures, and float32 results are unchanged, and there are no breaking changes to the public API. The published performance baseline (docs_site/performance.md and the README table) is regenerated from a single same-run measurement of the current implementation on an NVIDIA RTX A6000 (WSL2, CUDA runtime 12.9, CuPy 14.1.1) and now covers 210 cases, including the P216 pair and the shaper-aware LUT cases.

Added

  • Added px.io.from_p216 and px.io.to_p216, the ninth named-format pair. P216 is 16-bit 4:2:2 semi-planar (a uint16 Y plane followed by a uint16 interleaved Cb Cr plane) exchanged as a C-contiguous 1D device array. The effective code depth is fixed at 16 bits with no bit_depth argument; range, rounding, clipping, the even-width constraint, horizontally co-sited chroma at full vertical resolution, and the interpolation tokens follow the existing 4:2:2 planar rules. The io module now exposes 29 operations and the public API 100.
  • Added the keyword-only preserve_shaper option to px.io.read_lut and px.io.decode_lut. For nonidentity .3dl spacing, opting in retains a shared shaper on px.core.Lut and evaluates its linear stage with the existing trilinear or tetrahedral cube stage in one GPU kernel. The default remains the existing same-edge baked approximation. Writing a shaped LUT as Cube performs the same-edge bake on the GPU; the independent shaper and strict between-node evaluation are not recoverable from that output.

1.5.0 - 2026-09-10

pixtreme 1.5.0 adds six public capabilities and changes two raster decode defaults. The additions are the per-channel px.color.grade operation, the px.fonts module and its pixtreme.fonts entry-point contract for installable font packages, H.273 chroma sample location types 3 through 5 for the 4:2:0 wire formats, embedded ICC profile inspection with the Adobe-RGB, ProPhoto-RGB, and Gamma-1.8 tokens, px.io.write_exr_channels for mixed-dtype EXR output, and the antialiased lanczos2-aa / lanczos3-aa / lanczos4-aa resize tokens. The two default changes are that a mappable embedded ICC profile now sets file-explicit colorspace and gamma metadata, and that JPEG, PNG, TIFF, and WebP decodes now apply EXIF orientation; both keep pixel decoding unchanged, both carry a migration note below, and both can be restored to the former behavior with explicit keyword arguments. Existing token spellings, aliases, signatures, and float32 results are otherwise unchanged, and there are no breaking changes to the public API. Frame construction no longer repeats validation on the common output path, which removes most of the per-call host overhead introduced by the 1.3.0 token acceptance layer, and the published performance baseline (docs_site/performance.md and the README table) is regenerated from a single same-run measurement of the current implementation on an NVIDIA RTX A6000 (WSL2, CUDA runtime 12.9, CuPy 14.1.1).

Added

  • Added px.color.grade, a per-channel Lift / Gamma / Gain operation that applies z = gain * x + lift * (1 - x) followed by a sign-preserving pure power 1 / gamma to every stored sample without clipping. Each parameter accepts a scalar that broadcasts to every storage channel or a mapping keyed by exact channel labels that leaves unspecified channels bit-preserved. Parameters are converted to binary32 and validated before pixel processing; Frame metadata is inherited unchanged. The affine-power core matches Nuke Grade on its default-control 0 <= z <= 1 interval and converts to ASC CDL slope / offset / power; DaVinci Resolve numeric compatibility is not claimed.

  • Added H.273 chroma sample location types 3 through 5 as the canonical ChromaSiting tokens top, bottomleft, and bottom. The NV12, P010, and planar YUV420 input and output boundaries now accept all six progressive-frame positions while retaining the existing left default and existing-token output bits.

  • Added embedded ICC profile inspection for PNG iCCP, JPEG APP2, TIFF InterColorProfile, and WebP ICCP at read_image, decode_image, and read_header. RGB matrix/TRC profiles are mapped numerically to existing colorspace and gamma vocabulary without transforming pixel values. The five canonical additions are the Adobe-RGB and ProPhoto-RGB colorspace tokens, the same two gamma tokens, and pure-power Gamma-1.8.

  • Added px.fonts, whose available() and font_path(name) functions expose bundled fonts and filesystem assets declared by installed font packages through the pixtreme.fonts entry-point contract. Discovery is lazy, atomic, deterministic, and cached for the process lifetime. Existing px.draw.text sans / mono tokens and their rendering behavior remain unchanged.

  • px.io.write_exr_channels(path, frames, *, compression=None, dwa_level=None) writes same-shape, same-device, same-colorspace float16, float32, and uint32 Frame channel groups into one single-part scanline EXR while retaining each channel's native HALF, FLOAT, or UINT storage. All ten EXR compression modes operate per channel, so exact UINT object IDs can share a file with HALF or FLOAT imagery. Existing px.io.write_image and px.io.encode_image remain single-Frame, single-output-dtype APIs.

  • px.transform.resize accepts three new interpolation tokens, lanczos2-aa, lanczos3-aa, and lanczos4-aa. They are Lanczos kernels whose support widens by the reduction scale on each shrinking axis (the Pillow / ImageMagick family), with replicate edges and normalized weights; on a same-size or enlarging axis they are bit-identical to lanczos2 / lanczos3 / lanczos4. Existing tokens and the automatic area / lanczos4 choice are unchanged, and no other API accepts the new tokens.

Changed

  • Frame construction on the common metadata-inheriting output path and in px.io.from_array now skips the duplicate pydantic validation pass when the output array and metadata are already verified at construction time, and canonical token spellings return early from normalization. This removes most of the per-call host overhead that the token acceptance layer added in 1.3.0 for small frames; public API, accepted and rejected inputs, exception types, output bits, and attribute-assignment validation are unchanged.

  • Raster images with a supported embedded ICC profile now receive file-explicit colorspace and gamma metadata instead of the sRGB defaults. Decoded pixel samples are unchanged, but later color transforms driven by Frame metadata can now produce a different result that follows the file's intended color representation. Unmappable selected metadata warns once and falls back component by component unless the caller supplies an explicit claim. Migration note: existing code that reads PNG, JPEG, TIFF, or WebP files carrying an Adobe-RGB, ProPhoto-RGB, or other mappable RGB matrix/TRC profile and then converts by Frame metadata (for example px.color.rgb_to_rgb or px.color.rgb_to_grayscale without explicit source tokens) now produces different output for those files; files without a mappable profile are unaffected. To keep the previous behavior, pass the former defaults explicitly, read_image(path, colorspace="sRGB", gamma="sRGB") or the same keywords on decode_image; explicit tokens always override file metadata. read_header(path).color.mappable reports whether a file carries mappable profile metadata.

  • px.io.read_image and px.io.decode_image now expose a trailing keyword-only apply_exif_orientation: bool = True argument. JPEG, PNG, TIFF, and WebP apply EXIF orientation 1 through 8 by default; invalid optional orientation metadata emits a warning and falls back to identity, while False preserves stored pixel order.

  • ImageHeader now includes orientation, defaulting to 1. For JPEG, PNG, TIFF, and WebP, width and height now describe the default oriented decode, so orientations 5 through 8 exchange the former stored-dimension meaning. Migration note: existing code that reads JPEG, PNG, TIFF, or WebP files whose EXIF orientation is 2 through 8 now receives rotated or flipped pixels, and for orientations 5 through 8 the Frame and ImageHeader width and height are exchanged relative to the stored raster; files with orientation 1 or without orientation metadata are unaffected. To keep the previous behavior, pass apply_exif_orientation=False to read_image or decode_image, which preserves the stored pixel order. The stored dimensions of a file can be recovered from read_header by exchanging width and height when orientation is 5 through 8.

Fixed

  • px.io.from_array now validates the matrix token at the entry, together with layout, colorspace, gamma, and channels, before any repacking kernel, contiguity conversion, or copy runs. An unknown or non-string matrix raises a plain actionable ValueError instead of a pydantic ValidationError after the GPU pass. The accepted spellings, their canonical results, and every other argument contract are unchanged.

1.4.0 - 2026-09-07

pixtreme 1.4.0 widens the colour vocabulary from 18 to 27 colorspace tokens and from 19 to 33 gamma tokens by adding 23 tokens across the Canon, Panasonic, DJI, Fujifilm, Nikon, Leica, Apple, and Samsung camera families and the P3 / SMPTE-C / ACEScc / ACEScct / Gamma-2.5 standard set. Every new token is an independent addition: existing token spellings, aliases, and float32 results are unchanged, and there are no breaking changes to the public API. The published performance baseline (docs_site/performance.md and the README table) is regenerated from a single same-run measurement of the current kernels on an NVIDIA RTX A6000 (WSL2, CUDA runtime 12.9, CuPy 14.1.1), replacing figures that predated the 1.3.0 kernel fusions.

Added

  • Added the independent Apple-Wide-Gamut colorspace and N-Log, L-Log, Apple-Log, and Samsung-Log transfers. N-Log uses the maximum-real-root branch intersection, L-Log uses the printed cut's tangent, Apple Log preserves its published lower collapse, and Samsung Log derives its lower offset at the upper-branch cut and extends that branch without the vendor codec collapse. These numeric identities intentionally have non-parity with printed cuts, ACES CTL, OpenColorIO-family evaluation, or codec clipping where those definitions differ. Apple Wide Gamut uses its published primaries and D65 with the shared Bradford production path; its CAT02 ACES matrix remains an auxiliary check. Existing gamma and colorspace results remain float32 bit-identical.

  • Added the independent D-Gamut and F-Gamut-C colorspaces and D-Log, F-Log, and F-Log2 transfers. The transfers apply the vendor-published linear and logarithmic branches directly to reflectance, using each branch intersection's maximum real root and separately rounded binary64 encode/decode cuts. Printed cuts, the rounded D-Log inverse, ACES CTL, OpenColorIO-Config-ACES, and vendor IDTs are explicit non-parity targets. D-Gamut and F-Gamut-C use their published primaries with D65 and the shared Bradford production path; vendor and CAT02 matrices remain auxiliary checks. Existing gamma and colorspace results remain float32 bit-identical.

  • Added the independent P3-DCI, P3-D60, P3-D65, and SMPTE-C colorspaces and ACEScc, ACEScct, and Gamma-2.5 transfers. P3-D60 uses ACES white to align with the public ACES/OpenColorIO ecosystem; SMPTE EG 432-1's distinct nominal D60 is an auxiliary comparison and Resolve parity is not claimed. Gamma-2.5 is the conventional sign-preserving pure power because Resolve publishes no formula. ACEScc and ACEScct evaluate the Academy AP1 analytic curves without an upper 65504 clip (a documented no-upper-clip extension); ACEScg supplies the standard AP1 colorimetry independently. ACEScc intentionally collapses nonpositive encode inputs, so ACEScct is the path for preserving negative components. Existing token results remain float32 bit-identical.

  • Added the independent V-Gamut colorspace and V-Log gamma tokens. V-Gamut uses Panasonic's published CIE 1931 xy primaries with D65 and the shared Bradford adaptation path. V-Log applies Panasonic's public logarithmic branch directly to reflectance and uses the cut-derived tangent for a C1-continuous lower branch, matching current OpenColorIO. Panasonic's printed linear branch, vendor IDT, and ACES CSC are not bit-parity targets. The external Panasonic V-Gamut / Panasonic V-Log labels, combined labels, and V-Log L remain outside the alias guarantee. Existing token results remain float32 bit-identical.

  • Added the independent Canon-Cinema-Gamut colorspace and Canon-Log, Canon-Log-2, and Canon-Log-3 gamma tokens. The gamut uses Canon's published CIE 1931 xy primaries with D65 and the shared Bradford adaptation path. The transfers use the Canon 2018 full-range equations after mapping public reflectance with x = r / 0.9, extend their published signed branches without clipping or sign/magnitude mirroring, and retain values above 1. Canon Raw decoding and proprietary capture-gamut or OETF recovery remain outside the guarantee. Existing token results remain float32 bit-identical.

Changed

  • DPX writes tag frames whose gamma is Canon-Log, Canon-Log-2, Canon-Log-3, V-Log, D-Log, F-Log, F-Log2, N-Log, L-Log, Apple-Log, Samsung-Log, ACEScc, or ACEScct with the logarithmic transfer characteristic in the file header, matching the existing camera-log tokens. Pixel encoding is unchanged.

1.3.0 - 2026-09-03

pixtreme 1.3.0 widens the camera and working colour vocabulary from 7 to 18 colorspace tokens and from 12 to 19 gamma tokens (Sony, ARRI, Blackmagic Design, DaVinci, and RED families), canonicalizes token spellings behind a case- and separator-insensitive runtime that keeps every earlier spelling as a permanent alias, removes the pre-baked LUT tonemap tokens in favour of the analytic ACES renderings, adds optional px.infer / px.transport companion namespaces, and ships a round of bit-identical GPU kernel fusions. Absolute performance figures below are same-run medians on an NVIDIA RTX A6000 (WSL2, CUDA runtime 12.9, CuPy 14.1.1) at 1920x1080 fp32 RGB unless stated.

Added

  • Added the independent RED colorspace tokens REDWideGamutRGB, DRAGONcolor, DRAGONcolor2, REDcolor2, REDcolor3, and REDcolor4, plus the RED-Log3G10 and REDlogFilm gamma tokens. RED-Log3G10 uses RED's published piecewise curve without clipping or sign/magnitude mirroring. REDlogFilm is float32 bit-identical to Cineon while preserving independent metadata. All six gamuts use coordinate-derived normalized primary matrices, production D65, shared Bradford adaptation, and independent gamma selection. Existing token results remain bit-identical.

  • Added the independent canonical colorspace tokens Blackmagic-Wide-Gamut-Gen-5 and DaVinci-Wide-Gamut, plus the Blackmagic-Film-Gen-5 and DaVinci-Intermediate gamma tokens. The two gamuts use their published primaries with production D65 and remain independent from gamma selection. Film Gen 5 uses Blackmagic Design's natural-log transfer and published anchors; DaVinci Intermediate uses its base-2 transfer and the decode threshold derived from its linear branch. Both curves extend directly to negative values and leave scene overshoot unclipped. Existing camera-log token results remain bit-identical.

  • Added explicit optional companion namespaces for px.infer and px.transport. Separately installed pixtreme-infer and pixtreme-transport distributions can contribute their matching pixtreme subpackages while the root package keeps its existing constant public surface. Accessing an absent companion reports its matching pip install command.

  • Added the independent canonical colorspace tokens ARRI-Wide-Gamut-3 and ARRI-Wide-Gamut-4, plus the ARRI-LogC3 gamma token. ARRI-LogC3 is fixed to ARRI's EI 800 relative scene-exposure curve, maps 18% gray to 400 / 1023, extends its tangent-derived lower linear branch to negative values, and leaves scene overshoot unclipped. The two gamut tokens publish their ARRI primaries with D65 white and remain independent from gamma selection. Existing ARRI-LogC4 remains bit-identical.

  • Added the independent canonical tokens S-Gamut, S-Log, and S-Log2. S-Log and S-Log2 use Sony's published scene-linear IRE equations with public reflectance normalization and legal-range code embedding; the S-Log negative forward branch is the algebraic inverse of Sony's published decoder linear branch, not a separately published Sony forward equation. Their 0% / 18% / 90% reflection anchors round to 90 / 394 / 636 and 90 / 347 / 582, respectively. S-Gamut is numerically identical to S-Gamut3 while retaining separate metadata identity. S-Gamut3 and S-Log3 remain unchanged.

Breaking

  • Removed the pre-baked LUT tonemap tokens aces-1.3-lut and aces-2.0-lut from px.color.rgb_to_rgb, together with their four bundled 65^3 LUT archives (13,280,928 bytes) and the view-transform LUT runtime. The tonemap vocabulary is now ACES-1.3, ACES-2.0, and BT.2408 with six supply pairs (Rec.709 / BT.1886 and sRGB / sRGB for both ACES renderings, Rec.2020 / HLG and Rec.2020 / PQ for BT.2408). The analytic paths keep their float32 output bits for negative, reference-white, super-white, and saturated inputs. Passing a removed token raises the existing closed-vocabulary ValueError before any pixel work, listing the six valid pairs.

  • The pre-release intermediate canonical gamma tokens LogC3 and LogC4 are renamed to ARRI-LogC3 and ARRI-LogC4 before publication. No LogC3 compatibility alias is added. Relative to v1.2.1, runtime input logc4 remains accepted through its permanent alias, canonical output changes from logc4 to ARRI-LogC4, and the static Literal aliases and public signatures replace logc4 with ARRI-LogC4. Both ARRI curves retain the same equations, branches, signed extensions, anchors, and float32 output bits.

  • S-Log3 and ARRI-LogC4 now apply their vendor-published piecewise equations directly to signed inputs instead of sign/magnitude mirroring. S-Log3 applies the Sony piecewise formula directly to signed inputs, including the lower linear branch below zero. ARRI-LogC4 applies the ARRI piecewise formula directly to signed inputs, selecting its log branch at and above the negative cut and its lower linear branch below it. Negative encoded ARRI-LogC4 values decode linearly. Negative-input results change. Results for nonnegative inputs remain float32 bit-identical.

  • Canonical token spellings now preserve standards and proper-name typography. Static Literal aliases, public signatures, defaults, Frame metadata, representations, return values, and error recovery candidates expose only the canonical spellings below. Runtime validation is case-insensitive and treats U+0020 SPACE, ., -, and _ as interchangeable separators. All earlier spellings are permanent runtime aliases.

Family Earlier spelling Canonical spelling
Gamma srgb sRGB
Gamma rec709 Rec.709
Gamma bt1886 BT.1886
Gamma pq PQ
Gamma hlg HLG
Gamma s-log3 S-Log3
Gamma logc4 ARRI-LogC4
Gamma cineon Cineon
Gamma 2.2 Gamma-2.2
Gamma 2.4 Gamma-2.4
Gamma 2.6 Gamma-2.6
Matrix bt601 BT.601
Matrix bt709 BT.709
Matrix bt2020 BT.2020
ChromaticAdaptation bradford Bradford
ChromaticAdaptation cat02 CAT02
ChromaticAdaptation cat16 CAT16
ChromaticAdaptation von-kries von-Kries
ReferenceWhite d65 D65
ReferenceWhite d93 D93
ReferenceWhite d50 D50
ReferenceWhite aces ACES
Tonemap aces-1.3 ACES-1.3
Tonemap aces-2.0 ACES-2.0
Tonemap bt2408 BT.2408
ColorBarsStandard arib-std-b28 ARIB-STD-B28
ColorBarsStandard smpte-rp219 SMPTE-RP219
ColorBarsStandard bt2111-hlg BT.2111-HLG
ColorBarsStandard bt2111-pq BT.2111-PQ
ColorBarsStandard bt2111-pq-full BT.2111-PQ-full

The three numeric gamma spellings remain permanent runtime aliases. Their transfer implementation and GPU kernels are unchanged. BT.1886 is the Annex 1 ideal-black specialization and is numerically equivalent to Gamma-2.4, while the two canonical tokens retain distinct meanings and metadata identities.

Changed

  • px.color.rgb_to_rgb with tonemap="ACES-2.0" moves the hue-dependent algorithm table from CUDA constant memory to read-only global memory, reuses the CAM response powers, and resolves cusp intervals in two fixed steps. FHD RGB shortens from 1.270 ms to 0.141 ms (Rec.709 / BT.1886) and from 1.276 ms to 0.144 ms (sRGB / sRGB); outputs are bit-identical and the OCIO corpus statistics are unchanged. tonemap="ACES-1.3" moves its spline coefficient arrays to packed read-only global memory; divergent FHD inputs shorten from 0.201 ms to 0.146 ms with bit-identical output.
  • px.values.recode_dtype runs every conversion pair that involves an integer dtype in one fused RawKernel; same-dtype and float-to-float pairs keep the cast_dtype delegation. All 25 dtype pairs remain bit-identical to the previous composition, including NaN payloads and the uint32 NaN code. Formerly multi-pass pairs shorten by up to 7.4 times (uint16 to uint8 7.39x, uint8 to uint16 7.32x, uint32 to uint16 6.22x, float32 to uint32 4.53x); the uint8 / float32 registry cases shorten from 0.104 ms and 0.097 ms to 0.083 ms.
  • EXR UINT channel decoding reuses the shared unpack RawKernel instead of a per-chunk CuPy composition. The unpack stage shortens from 94.55 ms to 0.48 ms for an FHD-sized UINT scanline image and a full ZIP decode of the same container from 98.90 ms to 22.33 ms; decoded bits are unchanged across all ten compressions.
  • Raster decode (channel gather, cast, normalization) and raster write (recode, canonical gather) boundary stages each run as one fused RawKernel launch for every raster format. The boundary stages shorten by 2.2 to 3.0 times with bit-identical results (signed zero and non-finite values included); end-to-end PNG timing is within measurement noise because the codec dominates.
  • px.channel.shuffle assembles its output in one routing kernel launch instead of one full-frame pass per output channel. FHD fp32 reorder shortens from 0.297 ms to 0.119 ms, multi-source with fill from 0.400 ms to 0.203 ms, and adapt=True from 0.383 ms to 0.244 ms; the routing copies float32 bit patterns verbatim.
  • EXR DWAA / DWAB write fuses normalization, HALF rounding, forward transfer, mirror gather, and RGB to YCbCr into one kernel, and read fuses YCbCr to RGB, inverse transfer, and HALF selection. Encoded bytes and decoded bits are unchanged across compression levels, channel layouts, and input dtypes. Dedicated-GPU FHD medians shorten by 4.8% for DWAA / DWAB read and by 2.2% / 3.3% for DWAA / DWAB write.

1.2.1 - 2026-08-17

pixtreme 1.2.1 shortens seven morphology operations by 25 to 48 times, cuts match_template FFT-path runtime nearly in half, and reduces long-path blur, procedural noise, LUT text serialization, and white-management host composition times by 22 to 71 percent. Public signatures, observable behavior, and output bits are unchanged; measured outputs are byte-identical to 1.2.0 across independent verification. Absolute figures below were remeasured on an NVIDIA RTX A6000 (WSL2, CUDA runtime 12.9, CuPy 14.1.1) with GPU 0 dedicated to a single full-suite uv run pytest -m performance run at commit 5f71032.

Changed

  • px.morphology.erosion(), dilation(), opening(), closing(), morphological_gradient(), white_tophat(), and black_tophat() now load an output tile with radius halo into shared memory once per block, reduce from that shared substrate, and select disk membership from an integer row-limit cache keyed on (device, radius). morphological_gradient() fuses the min/max into a single pass and the tophat pair fuses the trailing subtraction. FHD RGB radius-5 disk cases shorten by 25 to 48 times (morphological_gradient from 17.16 ms to 0.36 ms; erosion and dilation from 8.65 ms to 0.34 ms). Channel counts above 4 or tiles exceeding 48 KiB fall back to the original global kernel unchanged.
  • px.feature.match_template() fuses the FFT-path response reduction, centering, denominator construction, zero-variance handling, square root, and division into one RawKernel for channel counts 1 through 3. FHD RGB with a 64x64 template at ccoeff_normed shortens from 24.72 ms to 13.10 ms (47.0%). Channel counts 4 and above retain the original composition path.
  • px.generate.grain() at size=1 uses a lattice-aligned kernel that evaluates only the two contributing z-layer lattice values per channel. px.generate.fractal_noise() and px.generate.turbulent_noise() at scale >= 16 use a per-block shared gradient kernel that reuses at most 32 lattice gradients across each 16x16 output block. FHD RGB grain at intensity=0.1 shortens from 12.35 ms to 3.60 ms (70.9%); FHD scale=64, octaves=4 fractal and turbulent cases each shorten from about 4.4 ms to 2.16 ms (roughly 50%).
  • px.filter.directional_blur(), zoom_blur(), spin_blur(), and vector_blur() use a noinline global fast-gather for path sample counts of 65 and above; shorter paths retain the shared-memory loop with the original gather via macro separation. Representative long-path FHD RGB cases shorten by 22 to 32% (vector_blur uniform |v|=128 from 10.78 ms to 7.30 ms; directional_blur length=128 from 11.00 ms to 7.52 ms; zoom_blur amount=0.2 from 12.29 ms to 9.14 ms; spin_blur angle=10 from 10.38 ms to 8.07 ms).
  • px.color.chromatic_adaptation(), px.color.white_balance(), and px.color.white_point_simulation() memoize their pure host matrix composition in a bounded LRU (128 identities per operation) keyed on the resolved binary64 x/y values, Frame colorspace, and CAT token. FHD RGB cases shorten by 27 to 49% (white_point_simulation from 0.266 ms to 0.137 ms, white_balance from 0.281 ms to 0.157 ms, chromatic_adaptation from 0.238 ms to 0.148 ms), reaching the effective bandwidth of the same-shape px.color.rgb_to_rgb operation.
  • px.io.write_lut(), px.io.read_lut(), and px.io.decode_lut() avoid full data-row materialization during Cube sniffing, replace repeated directive scans with a single finditer pass, and serialize Cube rows through a bulk zipped %s operation that preserves the str(numpy.float32) shortest round-trip spelling. FHD RGB 65^3 Cube write shortens from 918.76 ms to 323.92 ms (64.7%), decode from 452.96 ms to 154.03 ms (66.0%), and read from 294.87 ms to 138.60 ms (53.0%).

1.2.0 - 2026-08-16

pixtreme 1.2.0 adds user-supplied fonts for text drawing, expands LUT support with 1D LUTs, new file formats, and bytes/write entry points, and introduces a white-management trio: chromatic adaptation, temperature/tint white balance, and physical white point simulation with named reference whites. The release is purely additive; public signatures and existing behavior are unchanged.

Added

  • px.draw.Font and Font.from_file(path, face_index=0) load user OpenType/TrueType fonts (static faces, variable fonts, and collections). px.draw.text() accepts a Font in place of the bundled font tokens, maps weight to the font's real wght axis and variations to its other axes, and renders missing glyphs with the selected face's .notdef glyph without fallback lookup.
  • px.core.Lut1D is a public 1D LUT type with per-channel domains. px.color.apply_lut() accepts Lut | Lut1D and a new linear interpolation token; interpolation defaults stay tetrahedral for 3D and linear for 1D.
  • px.io.read_lut() additionally reads .cube 1D, .3dl (Lustre and headerless dialects), .spi1d, and .spi3d files. px.io.decode_lut() parses LUT bytes with signature sniffing, and px.io.write_lut() writes deterministic .cube text for both LUT types with full float32 round-trip preservation.
  • px.color.chromatic_adaptation() adapts a float32 RGB Frame between CIE 1931 xy white points using px.core.ChromaticAdaptation CAT tokens (bradford, cat02, cat16, von-kries; default cat02).
  • px.color.white_balance() corrects a source illuminant described by temperature (Kelvin on the Planckian locus) and tint (signed Duv offset, positive toward green).
  • px.color.white_point_simulation() physically re-encodes absolute colorimetry between display device whites (the ICC absolute-colorimetric-intent analogue) without chromatic adaptation, reducing to per-channel gain for same-primaries device pairs.
  • px.core.ReferenceWhite names the reference-white tokens d65, d93, d50, and aces, accepted by white_point_simulation() and chromatic_adaptation() alongside direct CIE 1931 xy pairs.

1.1.1 - 2026-08-14

pixtreme 1.1.1 hardens the public error contract. Out-of-contract inputs that previously leaked raw interpreter exceptions now raise the documented actionable ValueError diagnostics. Public signatures and successful-path behavior are unchanged.

Fixed

  • px.io.to_array() and the eight wire-format exporters now reject non-Frame inputs with actionable ValueError diagnostics instead of leaking attribute errors.
  • px.io.read_image(), write_image(), read_header(), and read_lut() now translate invalid path types into actionable ValueError diagnostics while retaining the underlying cause.
  • px.transform.resize() now rejects non-finite or unrepresentable factor-derived dimensions before rounding or allocation and guides callers to a smaller factor or explicit dimensions.
  • px.composite.merge() now names its actual public path when guiding callers after a non-Frame input.
  • Shared finite-real validation now translates numeric conversion failures into the parameter's actionable ValueError instead of leaking OverflowError.
  • The px.io.to_array() docstring now describes its function input and links to px.values.quantize() correctly.

1.1.0 - 2026-08-13

pixtreme 1.1.0 reshapes the public namespace into 13 responsibility modules with a single canonical path per operation, adds uint32 as the fifth Frame storage dtype with end-to-end EXR UINT support, and completes the source-fixed EXR lanes so OpenEXR is no longer a runtime dependency. It is a breaking release within the 1.x line; the Migration section below maps every removed path to its canonical replacement. A hosted API reference covering the full public surface accompanies this release.

Added

  • px.io.write_image() has a keyword-only dtype option for EXR output. It accepts float16, float32, or uint32; explicitly passing it for another format raises ValueError.
  • uint32 is the fifth Frame storage dtype. px.core.Frame, px.io.from_array(), px.io.to_array(frame, ...), px.values.cast_dtype(), and px.values.recode_dtype() preserve or convert it under the same five-dtype contracts.
  • EXR UINT channels are supported end to end. Default reads convert integer values literally to float32, with documented precision loss possible above 2^24; unchanged=True preserves the original uint32 sample bits.
  • The EXR reader handles tiled ONE_LEVEL, MIPMAP, and RIPMAP images at full-resolution level 0, flat multi-part images, and subsampled channels. Flat channels remain readable in mixed deep/flat files; explicitly selecting a deep channel reports the unsupported part and channel.

Changed

  • Breaking: Frame construction and data assignment now reject zero height, width, or channel count with ValueError. Values operations no longer accept zero-sized Frames because such Frames cannot be constructed.
  • Breaking: px.transform.resize() now rejects non-float32 Frame storage with ValueError and public value-conversion guidance instead of silently converting the input to float32.
  • The seven px.draw operations and px.filter.gaussian_blur(), box_blur(), median_blur(), bilateral_blur(), directional_blur(), zoom_blur(), spin_blur(), vector_blur(), lens_blur(), and convolve_box() now reject non-float32 Frame storage with ValueError and public value-conversion guidance, before any identity shortcut. vector_blur() applies the same check to its vector Frame. These inputs previously reached fp32 CUDA paths with undefined behavior.
  • Breaking: omitting dtype when writing a float32 Frame to EXR now writes HALF instead of FLOAT. Pass dtype="float32" to preserve FLOAT output. A uint32 Frame is the only dtype that defaults to native UINT.
  • px.io.write_image() and px.io.encode_image() accept all five Frame storage dtypes for every supported output format. Non-EXR native container matches are preserved; other non-EXR inputs are full-scale recoded to the format's default storage. EXR uses the Frame-dependent defaults or explicit dtype selection described above.
  • Breaking: the package root now exposes only 13 responsibility modules and __version__. Types, helpers, and all 89 operations use a single canonical px.<module>.<leaf> path, without compatibility aliases or deprecation shims. Publishing this breaking change within the 1.x line is an intentional departure from semantic-versioning major-version rules.
  • I/O boundaries are grouped under px.io; blur operations are grouped under px.filter; quality metrics and image features are split into px.metrics and px.feature; histogram equalization and CLAHE are grouped under px.color.
  • Frame-to-array and Frame-to-wire-format exits are px.io.to_array(frame, ...) and px.io.to_<format>(frame, ...) functions. px.core.Frame no longer has operation methods.
  • EXR read and write use source-fixed pixtreme GPU or CPU lanes for all ten compression modes: NONE, RLE, ZIPS, ZIP, PIZ, PXR24, B44, B44A, DWAA, and DWAB. OpenEXR is no longer a runtime dependency or fallback; it remains a development dependency only as a test and fixture oracle.
  • Reading a subsampled channel by itself now returns its stored dimensions and samples. It no longer places samples at the start of a full-resolution buffer with an uninitialized remainder.
  • Known trade-off: the current GPU writers produce larger files for ZIP (+11.5% / +28.8%), ZIPS (+4.0% / +10.3%), PXR24 (+25.2% / +38.6%), and DWA (+2.8% / +4.0%), for fp16 / fp32 respectively. Other codecs are effectively unchanged; reducing these differences is future work.

Fixed

  • The GPU PIZ writer now serializes Huffman code-length tables with canonical zero-run tokens instead of writing every zero length literally. Files written by earlier versions remain valid and readable; new files are byte-identical to the canonical form and smaller for sparse code-length tables.

Removed

  • Breaking: root-level Frame, Lut, ImageHeader, channels, and the 15 root-level I/O functions were removed.
  • Breaking: px.blur and px.analyze were removed; their operations are available only from their new canonical modules.
  • Breaking: Frame.to_array() and the eight Frame.to_<format>() wire-format methods were removed.

Migration

  • Pass dtype="float32" to px.io.write_image() when EXR FLOAT precision must be preserved; omission now selects HALF for every Frame storage dtype except uint32.
  • Keep object IDs and other exact integers in a uint32 Frame. Omit dtype or pass dtype="uint32" to write native EXR UINT, and use unchanged=True to read the original bits. Default reads return literal float32 values and can lose integer precision above 2^24.
  • OpenEXR no longer needs to be installed in runtime environments. Keep it only in development environments that run the EXR oracle tests or generate fixtures.
Previous path New canonical path
px.Frame / px.Lut / px.channels px.core.Frame / px.core.Lut / px.core.channels
px.ImageHeader px.io.ImageHeader
px.read_image / px.write_image / px.read_header / px.read_lut px.io.read_image / px.io.write_image / px.io.read_header / px.io.read_lut
px.decode_image / px.encode_image / px.from_array px.io.decode_image / px.io.encode_image / px.io.from_array
px.from_uyvy422 / px.from_v210 px.io.from_uyvy422 / px.io.from_v210
px.from_nv12 / px.from_p010 px.io.from_nv12 / px.io.from_p010
px.from_yuv420p / px.from_yuv422p px.io.from_yuv420p / px.io.from_yuv422p
px.from_yuv444p / px.from_yuva444p px.io.from_yuv444p / px.io.from_yuva444p
frame.to_array(...) / frame.to_<format>(...) px.io.to_array(frame, ...) / px.io.to_<format>(frame, ...)
px.blur.<name> px.filter.<name>
px.filter.equalize_histogram / px.filter.clahe px.color.equalize_histogram / px.color.clahe
px.analyze.psnr / px.analyze.ssim / px.analyze.ssim_map px.metrics.psnr / px.metrics.ssim / px.metrics.ssim_map
px.analyze.corner_harris / px.analyze.match_template px.feature.corner_harris / px.feature.match_template

1.0.1 - 2026-08-06

pixtreme 1.0.1 is the first supported release of the 1.x line, a ground-up rewrite. It does not provide a compatibility layer for the 0.x API, so applications upgrading from 0.9.0 should treat 1.x as a new public API.

Added

  • A single pixtreme distribution centered on a metadata-bearing GPU Frame, with operations grouped into 12 focused modules: io, color, blur, filter, analyze, morphology, transform, draw, generate, channel, values, and composite.
  • Analytic ACES 1.3 and ACES 2.0 output transforms, explicit pre-baked LUT variants, and BT.2408 direct mapping for supported Rec.2020 HLG and PQ outputs.
  • Explicit GPU format boundaries for UYVY422, v210, NV12, P010, YUV420p, YUV422p, YUV444p, and YUVA444p, alongside file, encoded-byte, and device-array boundaries.
  • GPU drawing primitives including CJK text, morphology and image-analysis modules, and histogram equalization and CLAHE operations.
  • A reproducible performance report covering the public GPU operation and I/O registry.

Changed

  • The 0.x component distributions pixtreme-core, pixtreme-aces, pixtreme-filter, pixtreme-draw, and pixtreme-upscale are discontinued. Version 1.0 ships only as the single pixtreme distribution.
  • Frame replaces raw arrays as the primary value passed between image operations. It carries colorspace, transfer, channel, and YCbCr-matrix claims with HWC GPU data.
  • Public operations now use canonical module paths. The package root exports only Frame, Lut, ImageHeader, and channels; it no longer aggregates operation aliases from installed component packages.
  • Frame methods are limited to exits from the Frame domain: to_array() and eight to_<format>() methods. Image processing remains in module functions.
  • The default channel order returned by image reading is RGB. Version 0.x returned BGR by default following the OpenCV convention; callers with BGR-specific indexing or conversion steps must update them.
  • Named option tokens are case-sensitive and validated immediately. They replace the 0.x pattern of root-level interpolation, codec, template-matching, and border constants where the corresponding 1.0 operation exists.
  • Floating-point working values are not implicitly clipped to [0, 1]. Negative scene values, highlights above 1.0, and filter overshoot remain valid until an explicit quantization or clipping boundary.
  • CUDA array interoperability uses CuPy arrays and the DLPack protocol. io.from_array() accepts CUDA producers, and Frame and to_array() provide the device-array exit; CPU NumPy arrays are not accepted by this boundary.

Removed

  • The 0.x compatibility surface, including legacy root-level operation exports and import paths under pixtreme_core, pixtreme_aces, pixtreme_filter, pixtreme_draw, and pixtreme_upscale.
  • Built-in ONNX Runtime, PyTorch, and TensorRT upscalers and model-conversion utilities. Super-resolution and inference runtime integration now belong in application-side packages built on pixtreme's DLPack and array boundaries.
  • GUI lifecycle helpers such as imshow, waitkey, and destroy_all_windows.
  • Dedicated to_numpy, to_tensor, and to_cupy conversion helpers. Host transfer uses CuPy's APIs; CUDA tensor exchange uses DLPack.

Migration

  • Replace component-package dependencies and imports with the single pixtreme distribution and canonical module paths such as px.io.read_image, px.color.rgb_to_rgb, and px.transform.resize.
  • Pass Frame values between operations, and cross array or encoded-format boundaries explicitly with px.io.from_* and Frame.to_*.
  • Audit every image-reading call site for the BGR-to-RGB default change.
  • Replace integer option constants and permissive aliases with the documented named tokens, and quantize or clip only at the intended output boundary.

1.0.0 - 2026-08-06 (yanked)

Yanked shortly after publication. Use 1.0.1 instead; the changes above describe the 1.x line.