Metadata-Version: 2.4
Name: pixtreme
Version: 2.12.0
Summary: GPU-first image processing library for Python, built on CUDA and CuPy
Author-Email: minamik <mia@sync.dev>
License-Expression: MIT AND BSD-3-Clause AND Apache-2.0 AND Unicode-3.0 AND OFL-1.1 AND BSD-2-Clause-Patent AND IJG
License-File: LICENSE
License-File: LICENSES/cuda-runtime.txt
License-File: LICENSES/dlpack.txt
License-File: LICENSES/libdeflate.txt
License-File: LICENSES/libjpeg-turbo-ijg.txt
License-File: LICENSES/libjpeg-turbo.txt
License-File: LICENSES/libvmaf.txt
License-File: LICENSES/libwebp-patents.txt
License-File: LICENSES/libwebp.txt
License-File: LICENSES/nanobind.txt
License-File: LICENSES/rfc6386.txt
License-File: LICENSES/robin_map.txt
License-File: LICENSES/unicode.txt
License-File: src/pixtreme/data/fonts/LICENSE-NotoSansCJK
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: GPU :: NVIDIA CUDA :: 13
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Software Development :: Libraries
Project-URL: documentation, https://sync-dev-org.github.io/pixtreme/docs/
Project-URL: repository, https://github.com/sync-dev-org/pixtreme
Project-URL: issues, https://github.com/sync-dev-org/pixtreme/issues
Requires-Python: >=3.12
Requires-Dist: cupy-cuda13x[ctk]>=14.1
Requires-Dist: freetype-py>=2.5.1
Requires-Dist: numpy
Requires-Dist: pydantic>=2.9
Requires-Dist: uharfbuzz>=0.55.0
Description-Content-Type: text/markdown

# pixtreme

[![PyPI](https://img.shields.io/pypi/v/pixtreme.svg)](https://pypi.org/project/pixtreme/)
![Python](https://img.shields.io/badge/Python-%E2%89%A53.12-3776AB.svg)
![CUDA](https://img.shields.io/badge/CUDA-13.x-76B900.svg)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sync-dev-org/pixtreme/blob/main/LICENSE)

GPU-first image processing for Python, built on CUDA and CuPy.

**[API reference and documentation](https://sync-dev-org.github.io/pixtreme/docs/)** — the complete public API (14 modules, 89 operations) with per-function contracts, plus the full performance report.

## Why pixtreme

pixtreme keeps image data on the NVIDIA GPU and makes a metadata-bearing `Frame` the common value passed between
operations. A `Frame` holds HWC GPU pixels together with colorspace, transfer, channel, and YCbCr-matrix claims,
so color meaning travels with pixels instead of living in ambient configuration.

Frame and `px.NDArray` provide `view()` to share pixels with an independent description,
and `clone(stream=None)` to duplicate pixels. Python `copy.copy` and `copy.deepcopy`
also duplicate pixels; use `view()` when sharing is intended.

Use `cupy.from_dlpack(frame)` or `torch.from_dlpack(frame)` to share writable pixels.
DLPack orders the consumer stream after recorded writers and keeps the pixel owner alive.
Read shape and dtype through `frame.shape` and `frame.dtype`. To replace the pixel storage,
construct a new `px.core.Frame` and copy its colorspace, gamma, channels, matrix, range, and bit_depth.

- Purpose-built `RawKernel` implementations and CuPy operations avoid unnecessary host round trips.
- Color conversion, format conversion, channel routing, and affine numeric transforms fuse work into a single pass
  where their contracts allow it.
- Floating-point working values are not clipped to `[0, 1]`: negative values, highlights above 1.0, and filter
  overshoot remain valid scene data until an explicit quantization or clipping boundary.
- The package root exposes 14 focused modules, including `core`, and `__version__`. Named tokens match
  case-insensitively and separator-insensitively (`Rec.709`, `rec 709`, and `REC_709` name the same token; see the
  [token reference](https://sync-dev-org.github.io/pixtreme/tokens/)), are validated immediately, and have no
  environment-dependent defaults.
- `Frame` is the working currency; device arrays and encoded/file formats cross explicit `from_*`, `to_*`,
  `read`/`write`, and `decode`/`encode` boundaries.

## Performance

The current package requires CUDA 13, NVIDIA driver R580 or newer, and a GPU with compute capability 7.5 or higher.
The table below records the earlier CUDA 12.9 baseline. The DWA and WebP cases of the full performance report
were measured separately with CUDA 13.

The following measurements are selected from the original 210-case FHD report, taken from the single full run at
commit `260fe6e`. GPU cases use at least 1,000 FHD frames and 3 seconds after warmup, while file boundaries use at
least 20 iterations and the same 3-second floor. The test system used an NVIDIA RTX A6000, CUDA 12.9, CuPy 14.1.1, and
Python 3.12 under WSL2.

The current packed-pixel API uses [PixelBuffer conversions](docs/reference/io.md).
See [the performance report](docs/performance.md) for its measurements. The `from_tensor` row below
uses the [native tensor comparison](docs/performance.md#native-tensor-conversion) on CUDA 13.2 instead of the earlier baseline.

| Operation | Representative parameters | Median (ms) | FPS | Effective GB/s |
|---|---|---:|---:|---:|
| `resize` | 1920x1080 -> 960x540, `nearest` | 0.074 | 13579.6 | 422.4 |
| `resize` | 1920x1080 -> 3840x2160, `lanczos4` | 0.980 | 1020.2 | 126.9 |
| `from_tensor` | CHW uint16, 10-bit -> float32 HWC | 0.122 | 8222.3 | 306.9 |
| YUVA444P packing (legacy API) | 12-bit legal, alpha full | 0.117 | 8563.1 | 426.2 |
| `rgb_to_rgb` | ACEScg linear -> sRGB sRGB | 0.141 | 7106.3 | 353.7 |
| `rgb_to_hsv` | label-driven scene values | 0.121 | 8276.1 | 411.9 |
| `rgb_to_rgb` | BT.2408 direct mapping -> Rec.2020 pq | 0.173 | 5793.1 | 288.3 |
| `apply_lut` | 65^3 LUT, tetrahedral | 0.367 | 2726.8 | 135.7 |
| `text` | single-line CJK, size 64, one outline, 4x supersampling | 0.401 | 2496.5 | 124.2 |
| `color_bars` | FHD ARIB STD-B28 normalized | 0.091 | 10969.6 | 273.0 |
| `read_image` | FHD HALF RGB EXR ZIP, unchanged, temporary-file I/O included | 40.758 | 24.5 | 0.6 |
| `write_image` | FHD fp32 RGB to EXR ZIP/HALF, dtype omitted, temporary-file I/O included | 40.572 | 24.6 | 0.9 |

These figures describe this system and workload, not a hardware-independent guarantee. File and encoded-byte
boundaries have different I/O-inclusive conditions. See [the full performance report](https://sync-dev-org.github.io/pixtreme/performance/) for every
case, distribution statistics, and the complete methodology.

EXR reads support scanline and tiled, single- and multipart files across all ten compression tokens; writes produce
single-part scanline files for the same ten tokens. Every path uses a pixtreme-owned implementation, with no OpenEXR
runtime dependency or fallback. Routing is fixed in source rather than benchmarked at runtime: NONE uses the native
read lane; ZIP, ZIPS, and PXR24 use custom CPU reads; the remaining reads and every write use GPU lanes. A float32
Frame written without `dtype` stores HALF by default; pass `dtype="float32"` for explicit FLOAT storage. On the system
above, the default ZIP/HALF path measured 40.758 ms to read unchanged and 40.572 ms to write, including temporary-file
I/O.

**Faster WebP decoding in 2.1.0.** WebP file reads and decoding from bytes now use pixtreme's C++ and CUDA decoder
(VP8, VP8L, and alpha), writing pixels directly into a GPU Frame. In same-session comparisons with the former
libwebp decode path, RGB and lossless RGBA were about 1.4–1.5 times as fast, and lossy RGBA about 1.1 times as fast.
For FHD (1920×1080) uint8 images on an RTX A6000 with CUDA 13.2 under WSL2, read/decode medians were
22.137/20.515 ms for lossless RGB, 23.300/20.903 ms for lossless RGBA, and 92.719/91.988 ms for lossy RGBA.
File reads include temporary-file I/O; bytes decoding includes host-byte exchange, and both include synchronization
until GPU output is ready. See the [WebP performance comparison](https://sync-dev-org.github.io/pixtreme/performance/#webp-decoder-replacement)
for the baseline CPU builds, inputs, and sampling conditions. Still-image I/O supports RGBA with alpha. Malformed
WebP input identified under RFC 6386 or RFC 9649 is rejected with a reason and a remedy. Encoding uses statically
linked libwebp on the CPU and accepts `method` and `quality`.

## Requirements

- Linux x86_64; Windows users run the Linux package under WSL2
- Python 3.12 or newer
- CUDA 13.x
- NVIDIA driver R580 or newer
- An NVIDIA GPU with compute capability 7.5 or higher

The 2.x wheels target Linux x86_64 (`manylinux_2_28`) and CPython 3.12 or newer through the stable ABI.
2.x does not provide native Windows wheels. On Windows, use the Linux wheel under WSL2, or use 1.x for native Windows.
Binary wheels need no C++ compiler or CUDA toolkit. Source builds require a C++17 compiler, the CUDA 13 toolkit,
and the zlib headers and shared library. DWA compression uses native CPU workers. DWA reads decode entropy streams
on the CPU and reconstruct dense colour blocks on the supplied CUDA stream. When `stream` is omitted, they use
the C++ interface's default stream. Subsequent image processing continues on the GPU.

WSL2 is supported with the Windows NVIDIA driver and a working CUDA device. Depending on the WSL installation,
`nvidia-smi` may be available at `/usr/lib/wsl/lib/nvidia-smi` rather than on the default `PATH`.

## Installation

With pip:

```console
python -m pip install pixtreme
```

With uv:

```console
uv add pixtreme
```

Upgrading from 0.x? The 1.x series is a ground-up rewrite — see the [changelog](https://sync-dev-org.github.io/pixtreme/changelog/) for the migration summary.

## Release packages

Download wheels and `SHA256SUMS` from [GitHub Releases](https://github.com/sync-dev-org/pixtreme/releases).
The [C and C++ SDK guide](https://sync-dev-org.github.io/pixtreme/cpp/) explains how to use the headers,
shared library, and CMake package included in the Linux wheel.

## Quickstart

Read an image into GPU memory, work in scene-linear ACEScg, and quantize only at the file boundary:

```python
import pixtreme as px

frame = px.io.read_image("input.png")
working = px.color.rgb_to_rgb(frame, output_colorspace="ACEScg", output_gamma="linear")
working = px.filter.sharpen(working, amount=0.5)
output = px.color.rgb_to_rgb(working, output_colorspace="sRGB", output_gamma="sRGB")
px.io.write_image("output.png", px.values.quantize(output, bit_depth=8))
```

`px.io.read_image` returns a `px.core.Frame` whose pixels already reside on the GPU. Processing remains float32 and
unclipped; `px.values.quantize` is the explicit normalized-float-to-integer boundary required by PNG.

## API tour

The package root exposes the feature modules, `Lut1D`, `Lut3D`, `NDArray`, `PixelBuffer`, `PixelBufferLayout` and `__version__`.
The 89 operations live under their feature modules; the count excludes `core`, types and query helpers.
`Frame` has no operation methods.

Packed pixels use [`px.PixelBuffer`](https://sync-dev-org.github.io/pixtreme/reference/io/#pixelbuffer), which holds GPU byte storage together with
format, dimensions, plane offsets and pitches, and color declarations. The `px.io` conversion functions exchange
pixels between a PixelBuffer and a Frame.

| Namespace | Public members | Responsibility |
|---|---|---|
| `px.core` | `Frame`, `Lut3D`, `Lut1D`, `Stream`, `Event`, `Graph`, `capture_begin`, `capture_end`, `channels`, and the named-token `Literal` aliases | Core types, CUDA graph capture, channel normalization, and closed vocabulary |
| `px.io` | `read_image`, `write_image`, `write_exr_channels`, `encode_exr_channels`, `read_header`, `read_lut`, `decode_lut`, `write_lut`, `decode_image`, `encode_image`, `from_tensor`, `to_tensor`, `from_pixel_buffer`, `to_pixel_buffer`, `repack_pixel_buffer`, `read_image_as_pixel_buffer`, `decode_image_as_pixel_buffer`, `write_image_from_pixel_buffer`, `encode_image_from_pixel_buffer` | File, byte, device-array, LUT, and PixelBuffer conversion boundaries |
| `px.color` | `apply_lut`, `gamma_to_linear`, `hsv_to_rgb`, `linear_to_gamma`, `rgb_to_grayscale`, `rgb_to_hsv`, `rgb_to_rgb`, `rgb_to_ycbcr`, `ycbcr_to_rgb`, `ycbcr_to_ycbcr`, `equalize_histogram`, `clahe`, `chromatic_adaptation`, `white_balance`, `white_point_simulation`, `grade` | Colorimetry, transfer functions, YCbCr/HSV, LUTs, histogram operations, white-point adaptation, per-channel Lift / Gamma / Gain, and explicit tonemapping |
| `px.filter` | `gaussian_blur`, `box_blur`, `median_blur`, `bilateral_blur`, `directional_blur`, `zoom_blur`, `spin_blur`, `vector_blur`, `lens_blur`, `sobel`, `laplacian`, `difference_of_gaussians`, `canny`, `sharpen`, `unsharp_mask`, `convolve_box` | Blur, derivatives, edges, sharpening, and convolution |
| `px.transform` | `resize`, `warp_affine`, `stack` | Geometry and multi-image layout |
| `px.draw` | `line`, `polyline`, `rectangle`, `circle`, `ellipse`, `polygon`, `text`, and the `Font` type | Shape and text drawing |
| `px.generate` | `ramp`, `grid`, `checkerboard`, `color_bars`, `fractal_noise`, `turbulent_noise`, `grain` | Procedural frames, test patterns, and noise |
| `px.morphology` | `erosion`, `dilation`, `opening`, `closing`, `morphological_gradient`, `white_tophat`, `black_tophat` | Morphological image operations |
| `px.metrics` | `psnr`, `ssim`, `ssim_map`, `vmaf` | Image and video quality scores and response maps |
| `px.feature` | `corner_harris`, `match_template` | Image-feature response maps |
| `px.values` | `quantize`, `dequantize`, `cast_dtype`, `recode_dtype` | Pixel-value scale conversion, quantization, and storage representation |
| `px.channel` | `shuffle` | Channel routing and assembly without implicit color meaning changes |
| `px.composite` | `merge` | Transform-aware multi-image compositing |
| `px.fonts` | `font_path`, `available` | Bundled and installed font-file discovery |

Render the Quickstart's scene-linear `working` frame through the analytic ACES 2.0 Output Transform:

```python
display = px.color.rgb_to_rgb(
    working,
    output_colorspace="sRGB",
    output_gamma="sRGB",
    tonemap="ACES-2.0",
)
```

The bytes boundary mirrors the file boundary without inventing a host-array API:

```python
png_bytes = px.io.encode_image(
    px.values.quantize(display, bit_depth=8),
    format="png",
    compression_level=4,
)
round_trip = px.io.decode_image(png_bytes)
```

Text shaping supports bundled CJK fonts, user OpenType/TrueType fonts through `px.draw.Font`, and an opt-in 4x
supersampled raster path:

```python
captioned = px.draw.text(
    display,
    text="極彩",
    position=(48, 96),
    size=64,
    color=(1.0, 0.8, 0.2),
    supersample=True,
)
```

## Full performance

[the full performance report](https://sync-dev-org.github.io/pixtreme/performance/) contains the recorded measured cases, including mean, median, FPS, p5, p95,
effective bandwidth, parameters, and the 97 cases whose median exceeds 1 ms. It also separates GPU-device throughput
from temporary-file and encoded-byte I/O measurements.

## Color management

Color processing is explicit, metadata-aware, and designed to preserve scene values until a declared output boundary.

- The closed vocabulary carries 31 colorspace tokens and 37 transfer (gamma) tokens: the sRGB, Rec.709, Rec.2020,
  P3, Rec.601-525, Rec.601-625, Adobe RGB, ProPhoto RGB, and ACES families plus the Sony, ARRI, Blackmagic Design, DaVinci, RED, Canon, Panasonic, DJI,
  Fujifilm, Nikon, Leica, Apple, and Samsung camera encodings, plus `CIE-XYZ` and `DCDM`. Each token is derived from its published
  specification and documented with its provenance and domain-extension rules in the
  [token reference](https://sync-dev-org.github.io/pixtreme/tokens/).
- The analytic ACES 2.0 SDR 100-nit Output Transform evaluates the complete AP1 limit, Hellwig JMh, tone, chroma,
  gamut-compression, limiting-RGB, reference-range, and display-encoding chain in one fused CUDA pass. Its 363-record
  hue table is an algorithm parameter, not an RGB-grid output approximation; runtime evaluation uses no LUT
  interpolation and matches direct OpenColorIO 2.5.2 reference evaluation with `rtol=0`, `atol=2e-4`.
- ACES 1.3 is also available as a formula-based one-pass transform. Both ACES generations are exposed only through
  their analytic tonemap tokens.
- BT.2408 direct mapping places SDR reference white at 203 cd/m2 for Rec.2020 HLG or PQ output.
- RGB/YCbCr conversion, legal/full-range code positions, and chroma siting follow H.273-aligned contracts, with the
  matrix basis carried in `Frame` metadata.
- Broadcast test-pattern generation covers ARIB STD-B28, SMPTE RP 219-1, and ITU-R BT.2111-2 HLG/PQ variants,
  including exact 10-bit code output.

## Status & license

The 2.x series is under development, with native C++ support behind the existing Python API. The 1.x series remains
the current release line and continues to receive fixes for native Windows users. The 1.x implementation
is a ground-up rewrite and does not connect to the 0.x codebase. The
final 0.x release remains available as [pixtreme 0.9.0 on PyPI](https://pypi.org/project/pixtreme/0.9.0/). See the [changelog](https://sync-dev-org.github.io/pixtreme/changelog/) for the
1.0 migration-impact summary.

pixtreme is released under the [MIT License](https://github.com/sync-dev-org/pixtreme/blob/main/LICENSE).
JPEG decoding includes libjpeg-turbo components under the IJG License. This software is based in part on
the work of the Independent JPEG Group. The wheel includes the complete third-party license texts in its
distribution metadata.
