jxl
jxl is a JPEG XL decoder and lossless Modular encoder written in Ruby without native extensions.
Installation
bundle add jxl
Ruby 3.2 or newer is required. YJIT is recommended for large images.
Decode
require "jxl"
image = JXL.decode(File.binread("input.jxl"), max_pixels: 100_000_000)
File.binwrite("output.png", JXL::IO::PNG.dump(image))
JXL.decode accepts pixel_format, color_space, desired_scale, max_pixels, max_memory, strict,
apply_orientation, and render_spot_colors. Packed pixel data is available through Image#to_rgba8,
#to_rgba16, and #to_float; pixel_format validates the requested format for API compatibility.
Output writers support PNG, PPM/PGM, PAM, PFM, grayscale PGX, and multi-frame NPY.
For incremental input, use JXL::Decoder#feed, drain #next_event, and call #finish at end of input.
decoder = JXL::Decoder.new.subscribe(:basic_info, :frame, :full_image)
File.open("input.jxl", "rb") { |file| decoder.feed(chunk) while (chunk = file.read(65_536)) }
decoder.finish
loop do
event = decoder.next_event
break if event.nil? || event.type == :full_image
end
The command-line decoder is also available:
djxl input.jxl output.png
Encode
The encoder writes lossless RGB Modular codestreams using RCT6, a Gradient predictor, and prefix entropy coding.
bytes = JXL.encode(image, bits_per_sample: 8)
File.binwrite("output.jxl", bytes)
The CLI accepts binary PPM/PGM and non-interlaced 8-bit PNG input:
cjxl input.png output.jxl
Development
bundle exec rake
bundle exec rake fuzz:truncate
bundle exec rake bench
Set JXL_CONFORMANCE_CASES to the conformance suite's main_level5.txt to enable full reference comparisons.
After running the official conformance runner with --results, print its measured results with:
JXL_CONFORMANCE_RESULTS=results.json bundle exec rake conformance:report
Support
Version 1.0 decodes Level 5 raw codestreams and jxlc/jxlp containers, including Modular and VarDCT,
progressive frames, animation and blending, all transform strategies, restoration filters, image features,
extra channels, orientation, standardized transfer functions, and embedded ICC profiles. The lossless encoder
writes RGB Modular codestreams that round-trip through this gem and libjxl.
The current upstream Level 5 conformance manifest has 23 cases; all 23 pass the official runner in lax pixel
mode. JPEG bitstream reconstruction from jbrd and Brotli-compressed brob metadata are optional next-version
features. Preview rendering is not exposed, the event decoder buffers the complete compressed image before
emitting frame pixels, and strict: false only replaces non-finite decoded samples; structural corruption still
raises JXL::Error.
License
MIT