PictureSharp.Jxl
0.8.6
See the version list below for details.
dotnet add package PictureSharp.Jxl --version 0.8.6
NuGet\Install-Package PictureSharp.Jxl -Version 0.8.6
<PackageReference Include="PictureSharp.Jxl" Version="0.8.6" />
<PackageVersion Include="PictureSharp.Jxl" Version="0.8.6" />
<PackageReference Include="PictureSharp.Jxl" />
paket add PictureSharp.Jxl --version 0.8.6
#r "nuget: PictureSharp.Jxl, 0.8.6"
#:package PictureSharp.Jxl@0.8.6
#addin nuget:?package=PictureSharp.Jxl&version=0.8.6
#tool nuget:?package=PictureSharp.Jxl&version=0.8.6
PictureSharp.Jxl
JPEG XL for PictureSharp, in pure C# with no native dependencies. Requires .NET 10+ and PictureSharp 0.9.0+.
Install from NuGet:
dotnet add package PictureSharp.Jxl
Usage
Register the format once, then load and save .jxl files like any other image:
using PictureSharp;
using PictureSharp.Formats.Jxl;
ImageConfiguration.Default = ImageConfiguration.Default.ToBuilder().AddFormat(new JxlFormat()).Build();
using var image = Image.Load("photo.jxl", new DecoderOptions { ApplyExifOrientation = true });
image.Mutate(x => x.Resize(1600, 0));
image.SaveAsJxl("small.jxl");
Loading keeps the ICC profile, EXIF and XMP; saving writes them back. Saving is lossy at distance 1.0 like cjxl
by default; new JxlEncoderOptions { Quality = 100 } (or Distance = 0) saves losslessly. Image.EditMetadata changes
the metadata without touching the frames.
To preserve an existing JPEG exactly, use the separate transcoder without loading its pixels:
JxlTranscoder.FromJpeg("original.jpg", "archived.jxl");
JxlTranscoder.ToJpeg("archived.jxl", "restored.jpg"); // byte-identical to original.jpg
// Stream and buffer overloads are also available, e.g. FromJpeg(jpegStream, jxlStream).
Keep 16-bit samples
using Image scan = Image.Load("scan.png", new DecoderOptions { PreserveBitDepth = true });
scan.SaveAsJxl("scan.jxl", new JxlEncoderOptions { Distance = 0 });
This preserves every 16-bit sample, including alpha. Default loading returns 8-bit pixels; enable PreserveBitDepth
when reading the result too.
Support
- Read: still images as
cjxlproduces them: lossy (VarDCT) and lossless (Modular), recompressed JPEGs, progressive files, patches; RGB and grayscale with alpha, up to 16 bits per sample (Rgba64withPreserveBitDepth, otherwise reduced to 8). - Write: lossy VarDCT with
Quality/DistanceandEffort1–9, about as small ascjxlat the same settings (patches included); lossless 8-bit or 16-bit gray or RGB with alpha, with libjxl's effort tiers and about as small ascjxl -d 0at the same effort. - Metadata: ICC, EXIF, XMP (also Brotli-compressed), colour description and orientation; read, written and edited in place (editing files with JPEG reconstruction data is unsupported).
- JPEG transcoding:
JxlTranscoder.FromJpegstores sequential or progressive 8-bit Huffman JPEG (gray or YCbCr 4:4:4/4:2:2/4:2:0);ToJpegreconstructs the original JPEG byte for byte, including metadata. - Not supported yet: animations, layers, photon noise and splines, float samples, CMYK
(
NotSupportedException); writing animations; transcoding RGB, CMYK/YCCK, arithmetic or 12-bit JPEG.
Pixels match djxl (libjxl 0.12.0): lossless images exactly, lossy ones within 1 of 255 in a few samples. Files this package writes decode with djxl the same way.
Status: early development (0.8.6). Not for production use yet; the API may change. CI runs on Linux, including a Native AOT build.
Guides: decoding · encoding · JPEG transcoding · metadata · architecture · release notes
Performance
- SIMD: AVX2/FMA and SSE4.1 kernels with a scalar fallback; all paths produce identical output.
- Native AOT: publish with
-p:IlcInstructionSet=x86-64-v3(ornative) to get the AVX2/FMA kernels; the default target uses SSE4.1 only. - Threads: decoding, encoding and JPEG transcoding run independent groups in parallel. Set
MaxDegreeOfParallelism(-1 = all cores, the default; 1 = single-threaded) onDecoderOptions,JxlEncoderOptionsorJxlTranscoderOptions. The output does not depend on it. - Encoding effort: lower
Effortis faster; lossless efforts 1–3 are several times faster than 7. - Memory: a 12 MP image needs about 180 MiB (JPEG-recompressed decode) to 860 MiB (lossless encode) at its peak, including the 48 MB output or input image.
Measurements: speed.
License
MIT. Ported libjxl sources are listed in THIRD-PARTY-NOTICES.txt.
Build
dotnet build -c Release
dotnet test -c Release
dotnet pack src/PictureSharp.Jxl -c Release --no-build -o artifacts
bash scripts/verify-package-consumer.sh
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- PictureSharp (>= 0.9.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.8.16 | 102 | 11/2/2026 |
| 0.8.15 | 100 | 11/2/2026 |
| 0.8.14 | 90 | 11/2/2026 |
| 0.8.13 | 93 | 11/2/2026 |
| 0.8.12 | 91 | 11/2/2026 |
| 0.8.11 | 94 | 11/2/2026 |
| 0.8.10 | 93 | 11/2/2026 |
| 0.8.9 | 103 | 10/31/2026 |
| 0.8.8 | 103 | 10/31/2026 |
| 0.8.7 | 95 | 10/30/2026 |
| 0.8.6 | 91 | 10/30/2026 |
| 0.8.5 | 91 | 10/30/2026 |
| 0.8.4 | 89 | 10/30/2026 |
| 0.8.3 | 95 | 10/29/2026 |
| 0.8.2 | 94 | 10/29/2026 |
| 0.8.1 | 97 | 10/29/2026 |
| 0.8.0 | 102 | 10/29/2026 |
| 0.7.10 | 91 | 10/28/2026 |
| 0.7.9 | 95 | 10/28/2026 |
| 0.7.8 | 97 | 10/28/2026 |
0.8.6: less memory for large images, with identical output: JPEG-recompressed 4:2:0 images are upsampled and converted per row band while writing pixels, lossless encoding transforms group copies and records predictor errors in its token storage, lossy encoding releases its working image early, Modular decoding and JPEG reconstruction no longer allocate per block. Per 12 MP image: JPEG decode peak 332 to 180 MiB (1.9x faster with 16 threads), lossless encode 1192 to 864 MiB and 976 to 576 MB allocated, 16-bit lossless decode allocates half as much. No API changes. See docs/releases/release-0.8.6.md and docs/benchmarks/speed.md.