diff --git a/.gitignore b/.gitignore
index face367..4f5cc1c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,5 @@ sweep.timestamp
build/
lcov.info
.pijul
+compile_commands.json
+.cache/
diff --git a/.gitmodules b/.gitmodules
index fd4337c..33ba59e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
[submodule "libjxl"]
path = jpegxl-src/libjxl
url = https://github.com/libjxl/libjxl
- branch = refs/tags/v0.10.3
+ branch = refs/tags/v0.11.0
diff --git a/Cargo.lock b/Cargo.lock
index 44890ee..d5f550d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -434,7 +434,7 @@ dependencies = [
[[package]]
name = "jpegxl-rs"
-version = "0.10.4+libjxl-0.10.3"
+version = "0.10.5+libjxl-0.11.0"
dependencies = [
"byteorder",
"criterion",
@@ -450,14 +450,14 @@ dependencies = [
[[package]]
name = "jpegxl-src"
-version = "0.10.5"
+version = "0.11.0"
dependencies = [
"cmake",
]
[[package]]
name = "jpegxl-sys"
-version = "0.10.4+libjxl-0.10.3"
+version = "0.11.0+libjxl-0.11.0"
dependencies = [
"image",
"jpegxl-src",
diff --git a/jpegxl-rs/Cargo.toml b/jpegxl-rs/Cargo.toml
index 9e8cc0b..fd3afe8 100644
--- a/jpegxl-rs/Cargo.toml
+++ b/jpegxl-rs/Cargo.toml
@@ -8,7 +8,7 @@ license = "GPL-3.0-or-later"
name = "jpegxl-rs"
readme = "README.md"
repository = "https://github.com/inflation/jpegxl-rs"
-version = "0.10.4+libjxl-0.10.3"
+version = "0.10.5+libjxl-0.11.0"
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -35,7 +35,7 @@ half = "2.4.0"
byteorder = "1.5.0"
[dependencies.jpegxl-sys]
-version = "0.10.3"
+version = "0.11.0"
path = "../jpegxl-sys"
default-features = false
diff --git a/jpegxl-rs/src/common.rs b/jpegxl-rs/src/common.rs
index 1580243..d557fb6 100644
--- a/jpegxl-rs/src/common.rs
+++ b/jpegxl-rs/src/common.rs
@@ -20,10 +20,10 @@ along with jpegxl-rs. If not, see .
use byteorder::{ByteOrder, NativeEndian, BE, LE};
use half::f16;
-use jpegxl_sys::types::{JxlDataType, JxlPixelFormat};
+use jpegxl_sys::common::types::{JxlDataType, JxlPixelFormat};
/// Endianness of the pixels
-pub type Endianness = jpegxl_sys::types::JxlEndianness;
+pub type Endianness = jpegxl_sys::common::types::JxlEndianness;
mod private {
pub trait Sealed {}
diff --git a/jpegxl-rs/src/decode.rs b/jpegxl-rs/src/decode.rs
index 631b5ec..856a54f 100644
--- a/jpegxl-rs/src/decode.rs
+++ b/jpegxl-rs/src/decode.rs
@@ -21,16 +21,16 @@ use std::{mem::MaybeUninit, ptr::null};
#[allow(clippy::wildcard_imports)]
use jpegxl_sys::{
- codestream_header::{JxlBasicInfo, JxlOrientation},
+ common::types::{JxlDataType, JxlPixelFormat},
decode::*,
- types::{JxlDataType, JxlPixelFormat},
+ metadata::codestream_header::{JxlBasicInfo, JxlOrientation},
};
use crate::{
common::{Endianness, PixelType},
errors::{check_dec_status, DecodeError},
memory::MemoryManager,
- parallel::JxlParallelRunner,
+ parallel::ParallelRunner,
utils::check_valid_signature,
};
@@ -87,7 +87,7 @@ impl Default for PixelFormat {
pub struct JxlDecoder<'pr, 'mm> {
/// Opaque pointer to the underlying decoder
#[builder(setter(skip))]
- dec: *mut jpegxl_sys::decode::JxlDecoder,
+ ptr: *mut jpegxl_sys::decode::JxlDecoder,
/// Override desired pixel format
pub pixel_format: Option,
@@ -150,7 +150,7 @@ pub struct JxlDecoder<'pr, 'mm> {
pub init_jpeg_buffer: usize,
/// Set parallel runner
- pub parallel_runner: Option<&'pr dyn JxlParallelRunner>,
+ pub parallel_runner: Option<&'pr dyn ParallelRunner>,
/// Set memory manager
pub memory_manager: Option<&'mm dyn MemoryManager>,
@@ -161,7 +161,7 @@ impl<'pr, 'mm> JxlDecoderBuilder<'pr, 'mm> {
///
/// # Errors
/// Return [`DecodeError::CannotCreateDecoder`] if it fails to create the decoder.
- pub fn build(&self) -> Result, DecodeError> {
+ pub fn build(&mut self) -> Result, DecodeError> {
let mm = self.memory_manager.flatten();
let dec = unsafe {
mm.map_or_else(
@@ -175,7 +175,7 @@ impl<'pr, 'mm> JxlDecoderBuilder<'pr, 'mm> {
}
Ok(JxlDecoder {
- dec,
+ ptr: dec,
pixel_format: self.pixel_format.flatten(),
skip_reorientation: self.skip_reorientation.flatten(),
unpremul_alpha: self.unpremul_alpha.flatten(),
@@ -217,14 +217,14 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
let next_in = data.as_ptr();
let avail_in = std::mem::size_of_val(data) as _;
- check_dec_status(unsafe { JxlDecoderSetInput(self.dec, next_in, avail_in) })?;
- unsafe { JxlDecoderCloseInput(self.dec) };
+ check_dec_status(unsafe { JxlDecoderSetInput(self.ptr, next_in, avail_in) })?;
+ unsafe { JxlDecoderCloseInput(self.ptr) };
let mut status;
loop {
use JxlDecoderStatus as s;
- status = unsafe { JxlDecoderProcessInput(self.dec) };
+ status = unsafe { JxlDecoderProcessInput(self.ptr) };
match status {
s::NeedMoreInput | s::Error => return Err(DecodeError::GenericError),
@@ -232,7 +232,7 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
// Get the basic info
s::BasicInfo => {
check_dec_status(unsafe {
- JxlDecoderGetBasicInfo(self.dec, basic_info.as_mut_ptr())
+ JxlDecoderGetBasicInfo(self.ptr, basic_info.as_mut_ptr())
})?;
if let Some(pr) = self.parallel_runner {
@@ -246,26 +246,26 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
}
// Get JPEG reconstruction buffer
- s::JpegReconstruction => {
+ s::JPEGReconstruction => {
// Safety: JpegReconstruction is only called when reconstruct_jpeg_buffer
// is not None
let buf = unsafe { reconstruct_jpeg_buffer.as_mut().unwrap_unchecked() };
buf.resize(self.init_jpeg_buffer, 0);
check_dec_status(unsafe {
- JxlDecoderSetJPEGBuffer(self.dec, buf.as_mut_ptr(), buf.len())
+ JxlDecoderSetJPEGBuffer(self.ptr, buf.as_mut_ptr(), buf.len())
})?;
}
// JPEG buffer need more space
- s::JpegNeedMoreOutput => {
+ s::JPEGNeedMoreOutput => {
// Safety: JpegNeedMoreOutput is only called when reconstruct_jpeg_buffer
// is not None
let buf = unsafe { reconstruct_jpeg_buffer.as_mut().unwrap_unchecked() };
- let need_to_write = unsafe { JxlDecoderReleaseJPEGBuffer(self.dec) };
+ let need_to_write = unsafe { JxlDecoderReleaseJPEGBuffer(self.ptr) };
buf.resize(buf.len() + need_to_write, 0);
check_dec_status(unsafe {
- JxlDecoderSetJPEGBuffer(self.dec, buf.as_mut_ptr(), buf.len())
+ JxlDecoderSetJPEGBuffer(self.ptr, buf.as_mut_ptr(), buf.len())
})?;
}
@@ -277,13 +277,13 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
s::FullImage => continue,
s::Success => {
if let Some(buf) = reconstruct_jpeg_buffer.as_mut() {
- let remaining = unsafe { JxlDecoderReleaseJPEGBuffer(self.dec) };
+ let remaining = unsafe { JxlDecoderReleaseJPEGBuffer(self.ptr) };
buf.truncate(buf.len() - remaining);
buf.shrink_to_fit();
}
- unsafe { JxlDecoderReset(self.dec) };
+ unsafe { JxlDecoderReset(self.ptr) };
let info = unsafe { basic_info.assume_init() };
return Ok(Metadata {
@@ -304,6 +304,7 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
s::PreviewImage => todo!(),
s::Frame => todo!(),
s::Box => todo!(),
+ s::BoxComplete => todo!(),
s::FrameProgression => todo!(),
}
}
@@ -312,39 +313,39 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
fn setup_decoder(&self, icc: bool, reconstruct_jpeg: bool) -> Result<(), DecodeError> {
if let Some(runner) = self.parallel_runner {
check_dec_status(unsafe {
- JxlDecoderSetParallelRunner(self.dec, runner.runner(), runner.as_opaque_ptr())
+ JxlDecoderSetParallelRunner(self.ptr, runner.runner(), runner.as_opaque_ptr())
})?;
}
let events = {
- use JxlDecoderStatus::{BasicInfo, ColorEncoding, FullImage, JpegReconstruction};
+ use JxlDecoderStatus::{BasicInfo, ColorEncoding, FullImage, JPEGReconstruction};
let mut events = BasicInfo as i32 | FullImage as i32;
if icc {
events |= ColorEncoding as i32;
}
if reconstruct_jpeg {
- events |= JpegReconstruction as i32;
+ events |= JPEGReconstruction as i32;
}
events
};
- check_dec_status(unsafe { JxlDecoderSubscribeEvents(self.dec, events) })?;
+ check_dec_status(unsafe { JxlDecoderSubscribeEvents(self.ptr, events) })?;
if let Some(val) = self.skip_reorientation {
- check_dec_status(unsafe { JxlDecoderSetKeepOrientation(self.dec, val.into()) })?;
+ check_dec_status(unsafe { JxlDecoderSetKeepOrientation(self.ptr, val.into()) })?;
}
if let Some(val) = self.unpremul_alpha {
- check_dec_status(unsafe { JxlDecoderSetUnpremultiplyAlpha(self.dec, val.into()) })?;
+ check_dec_status(unsafe { JxlDecoderSetUnpremultiplyAlpha(self.ptr, val.into()) })?;
}
if let Some(val) = self.render_spotcolors {
- check_dec_status(unsafe { JxlDecoderSetRenderSpotcolors(self.dec, val.into()) })?;
+ check_dec_status(unsafe { JxlDecoderSetRenderSpotcolors(self.ptr, val.into()) })?;
}
if let Some(val) = self.coalescing {
- check_dec_status(unsafe { JxlDecoderSetCoalescing(self.dec, val.into()) })?;
+ check_dec_status(unsafe { JxlDecoderSetCoalescing(self.ptr, val.into()) })?;
}
if let Some(val) = self.desired_intensity_target {
- check_dec_status(unsafe { JxlDecoderSetDesiredIntensityTarget(self.dec, val) })?;
+ check_dec_status(unsafe { JxlDecoderSetDesiredIntensityTarget(self.ptr, val) })?;
}
Ok(())
@@ -353,13 +354,13 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
fn get_icc_profile(&self, icc_profile: &mut Vec) -> Result<(), DecodeError> {
let mut icc_size = 0;
check_dec_status(unsafe {
- JxlDecoderGetICCProfileSize(self.dec, JxlColorProfileTarget::Data, &mut icc_size)
+ JxlDecoderGetICCProfileSize(self.ptr, JxlColorProfileTarget::Data, &mut icc_size)
})?;
icc_profile.resize(icc_size, 0);
check_dec_status(unsafe {
JxlDecoderGetColorAsICCProfile(
- self.dec,
+ self.ptr,
JxlColorProfileTarget::Data,
icc_profile.as_mut_ptr(),
icc_size,
@@ -401,12 +402,12 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
let mut size = 0;
check_dec_status(unsafe {
- JxlDecoderImageOutBufferSize(self.dec, &pixel_format, &mut size)
+ JxlDecoderImageOutBufferSize(self.ptr, &pixel_format, &mut size)
})?;
pixels.resize(size, 0);
check_dec_status(unsafe {
- JxlDecoderSetImageOutBuffer(self.dec, &pixel_format, pixels.as_mut_ptr().cast(), size)
+ JxlDecoderSetImageOutBuffer(self.ptr, &pixel_format, pixels.as_mut_ptr().cast(), size)
})?;
unsafe { *format = pixel_format };
@@ -496,7 +497,7 @@ impl<'pr, 'mm> JxlDecoder<'pr, 'mm> {
impl<'prl, 'mm> Drop for JxlDecoder<'prl, 'mm> {
fn drop(&mut self) {
- unsafe { JxlDecoderDestroy(self.dec) };
+ unsafe { JxlDecoderDestroy(self.ptr) };
}
}
diff --git a/jpegxl-rs/src/decode/result.rs b/jpegxl-rs/src/decode/result.rs
index 408f536..f1bf329 100644
--- a/jpegxl-rs/src/decode/result.rs
+++ b/jpegxl-rs/src/decode/result.rs
@@ -16,7 +16,7 @@ along with jpegxl-rs. If not, see .
*/
use half::f16;
-use jpegxl_sys::types::{JxlDataType, JxlPixelFormat};
+use jpegxl_sys::common::types::{JxlDataType, JxlPixelFormat};
use super::Orientation;
use crate::common::PixelType;
diff --git a/jpegxl-rs/src/encode.rs b/jpegxl-rs/src/encode.rs
index 28bba33..c140e58 100644
--- a/jpegxl-rs/src/encode.rs
+++ b/jpegxl-rs/src/encode.rs
@@ -20,10 +20,10 @@ along with jpegxl-rs. If not, see .
use std::{marker::PhantomData, mem::MaybeUninit, ops::Deref, ptr::null};
#[allow(clippy::wildcard_imports)]
-use jpegxl_sys::encode::*;
+use jpegxl_sys::encoder::encode::*;
use crate::{
- common::PixelType, errors::EncodeError, memory::MemoryManager, parallel::JxlParallelRunner,
+ common::PixelType, errors::EncodeError, memory::MemoryManager, parallel::ParallelRunner,
};
mod options;
@@ -62,7 +62,7 @@ impl Deref for EncoderResult {
pub struct JxlEncoder<'prl, 'mm> {
/// Opaque pointer to the underlying encoder
#[builder(setter(skip))]
- enc: *mut jpegxl_sys::encode::JxlEncoder,
+ enc: *mut jpegxl_sys::encoder::encode::JxlEncoder,
/// Opaque pointer to the encoder options
#[builder(setter(skip))]
options_ptr: *mut JxlEncoderFrameSettings,
@@ -121,7 +121,7 @@ pub struct JxlEncoder<'prl, 'mm> {
/// Set parallel runner
///
/// Default: `None`, indicating single thread execution
- pub parallel_runner: Option<&'prl dyn JxlParallelRunner>,
+ pub parallel_runner: Option<&'prl dyn ParallelRunner>,
/// Whether box is used in encoder
use_box: bool,
@@ -211,7 +211,7 @@ impl JxlEncoder<'_, '_> {
self.check_enc_status(unsafe {
JxlEncoderFrameSettingsSetOption(
self.options_ptr,
- FrameSetting::Effort,
+ JxlEncoderFrameSettingId::Effort,
self.speed as _,
)
})?;
@@ -221,7 +221,7 @@ impl JxlEncoder<'_, '_> {
self.check_enc_status(unsafe {
JxlEncoderFrameSettingsSetOption(
self.options_ptr,
- FrameSetting::DecodingSpeed,
+ JxlEncoderFrameSettingId::DecodingSpeed,
self.decoding_speed,
)
})?;
@@ -365,7 +365,7 @@ impl<'prl, 'mm> JxlEncoder<'prl, 'mm> {
/// Return [`EncodeError`] if it fails to set frame option
pub fn set_frame_option(
&mut self,
- option: FrameSetting,
+ option: JxlEncoderFrameSettingId,
value: i64,
) -> Result<(), EncodeError> {
self.check_enc_status(unsafe {
diff --git a/jpegxl-rs/src/encode/frame.rs b/jpegxl-rs/src/encode/frame.rs
index 9f3b912..44e1ad4 100644
--- a/jpegxl-rs/src/encode/frame.rs
+++ b/jpegxl-rs/src/encode/frame.rs
@@ -1,6 +1,6 @@
use std::marker::PhantomData;
-use jpegxl_sys::types::{JxlEndianness, JxlPixelFormat};
+use jpegxl_sys::common::types::{JxlEndianness, JxlPixelFormat};
use crate::{common::PixelType, EncodeError};
diff --git a/jpegxl-rs/src/encode/metadata.rs b/jpegxl-rs/src/encode/metadata.rs
index 2a8bfe4..c3f528e 100644
--- a/jpegxl-rs/src/encode/metadata.rs
+++ b/jpegxl-rs/src/encode/metadata.rs
@@ -1,4 +1,4 @@
-use jpegxl_sys::types::JxlBoxType;
+use jpegxl_sys::common::types::JxlBoxType;
/// Metadata box
pub enum Metadata<'d> {
diff --git a/jpegxl-rs/src/encode/options.rs b/jpegxl-rs/src/encode/options.rs
index 5bac696..5123c2b 100644
--- a/jpegxl-rs/src/encode/options.rs
+++ b/jpegxl-rs/src/encode/options.rs
@@ -1,6 +1,6 @@
use std::mem::MaybeUninit;
-use jpegxl_sys::{color_encoding::JxlColorEncoding, encode as api};
+use jpegxl_sys::{color::color_encoding::JxlColorEncoding, encoder::encode as api};
/// Encoding speed
#[derive(Debug, Clone, Copy)]
diff --git a/jpegxl-rs/src/errors.rs b/jpegxl-rs/src/errors.rs
index 94306f9..cba59a8 100644
--- a/jpegxl-rs/src/errors.rs
+++ b/jpegxl-rs/src/errors.rs
@@ -19,7 +19,7 @@ along with jpegxl-rs. If not, see .
use thiserror::Error;
-use jpegxl_sys::{decode::JxlDecoderStatus, encode::JxlEncoderError};
+use jpegxl_sys::{decode::JxlDecoderStatus, encoder::encode::JxlEncoderError};
/// Errors derived from [`JxlDecoderStatus`]
#[derive(Error, Debug)]
@@ -28,7 +28,10 @@ pub enum DecodeError {
#[error("Cannot create a decoder")]
CannotCreateDecoder,
/// Unknown Error
- #[error("Generic Error")]
+ #[error(
+ "Generic Error. Please build `libjxl` from source (using `vendored` feature)
+ in debug mode to get more information. Check `stderr` for any internal error messages."
+ )]
GenericError,
/// Invalid input
#[error("The input does not contain a valid codestream or container")]
@@ -36,6 +39,9 @@ pub enum DecodeError {
/// Unsupported Pixel bit width
#[error("Unsupported Pixel bit width: {0}")]
UnsupportedBitWidth(u32),
+ /// Internal error, usually invalid usages of the `libjxl` library
+ #[error("Internal error, please file an issus: {0}")]
+ InternalError(&'static str),
/// Unknown status
#[error("Unknown status: `{0:?}`")]
UnknownStatus(JxlDecoderStatus),
@@ -49,7 +55,10 @@ pub enum EncodeError {
#[error("Cannot create an encoder")]
CannotCreateEncoder,
/// Generic Error
- #[error("Generic Error")]
+ #[error(
+ "Generic Error. Please build `libjxl` from source (using `vendored` feature)
+ in debug mode to get more information. Check `stderr` for any internal error messages."
+ )]
GenericError,
/// Not Supported
#[error("Encoder does not support it (yet)")]
@@ -66,7 +75,8 @@ pub enum EncodeError {
/// Input is invalid (e.g. corrupt JPEG file or ICC profile)
#[error("Input is invalid")]
BadInput,
- /// The encoder API is used in an incorrect way. In this case, a debug build of libjxl should output a specific error message
+ /// The encoder API is used in an incorrect way. In this case,
+ /// a debug build of libjxl should output a specific error message
#[error("The encoder API is used in an incorrect way")]
ApiUsage,
/// Unknown status
diff --git a/jpegxl-rs/src/image.rs b/jpegxl-rs/src/image.rs
index 0e2f43b..a11c01f 100644
--- a/jpegxl-rs/src/image.rs
+++ b/jpegxl-rs/src/image.rs
@@ -20,7 +20,7 @@
use std::mem::MaybeUninit;
use image::{DynamicImage, ImageBuffer};
-use jpegxl_sys::types::{JxlDataType, JxlPixelFormat};
+use jpegxl_sys::common::types::{JxlDataType, JxlPixelFormat};
use crate::{
common::PixelType,
diff --git a/jpegxl-rs/src/memory.rs b/jpegxl-rs/src/memory.rs
index 619d1cc..e442599 100644
--- a/jpegxl-rs/src/memory.rs
+++ b/jpegxl-rs/src/memory.rs
@@ -17,31 +17,24 @@
//! Memory manager interface
-use std::ffi::c_void;
-
-use jpegxl_sys::memory_manager::JxlMemoryManager;
-
-/// Allocating function type
-pub type AllocFn = unsafe extern "C-unwind" fn(opaque: *mut c_void, size: usize) -> *mut c_void;
-/// Deallocating function type
-pub type FreeFn = unsafe extern "C-unwind" fn(opaque: *mut c_void, address: *mut c_void);
+use jpegxl_sys::common::memory_manager::{JpegxlAllocFunc, JpegxlFreeFunc, JxlMemoryManager};
/// General trait for a memory manager
#[allow(clippy::module_name_repetitions)]
pub trait MemoryManager {
/// Return a custom allocating function
- fn alloc(&self) -> AllocFn;
+ fn alloc(&self) -> JpegxlAllocFunc;
/// Return a custom deallocating function
- fn free(&self) -> FreeFn;
+ fn free(&self) -> JpegxlFreeFunc;
/// Helper conversion function for C API
#[must_use]
fn manager(&self) -> JxlMemoryManager {
JxlMemoryManager {
opaque: (self as *const Self).cast_mut().cast(),
- alloc: self.alloc(),
- free: self.free(),
+ alloc: Some(self.alloc()),
+ free: Some(self.free()),
}
}
}
@@ -49,65 +42,43 @@ pub trait MemoryManager {
#[cfg(test)]
pub(crate) mod tests {
use std::{
+ ffi::c_void,
ptr::null_mut,
sync::atomic::{AtomicUsize, Ordering},
};
+ use testresult::TestResult;
+
use crate::{decoder_builder, encoder_builder};
use super::*;
-
- pub struct NoManager {}
-
- impl MemoryManager for NoManager {
- fn alloc(&self) -> AllocFn {
- #[cfg_attr(coverage_nightly, coverage(off))]
- unsafe extern "C-unwind" fn alloc(_opaque: *mut c_void, _size: usize) -> *mut c_void {
- null_mut()
- }
-
- alloc
- }
-
- fn free(&self) -> FreeFn {
- #[cfg_attr(coverage_nightly, coverage(off))]
- unsafe extern "C-unwind" fn free(_opaque: *mut c_void, _address: *mut c_void) {
- debug_assert!(false, "Should not be called");
- }
-
- free
- }
- }
-
/// Example implementation of [`MemoryManager`] of a fixed size allocator
- pub struct BumpManager {
- arena: Box<[u8; N]>,
+ pub struct BumpManager {
+ arena: Vec,
footer: AtomicUsize,
}
- impl Default for BumpManager {
- fn default() -> Self {
+ impl BumpManager {
+ pub(crate) fn new(n: usize) -> Self {
Self {
- arena: Box::new([0_u8; N]),
+ arena: vec![0; n],
footer: AtomicUsize::new(0),
}
}
}
- impl MemoryManager for BumpManager {
- fn alloc(&self) -> AllocFn {
+ impl MemoryManager for BumpManager {
+ fn alloc(&self) -> JpegxlAllocFunc {
#[cfg_attr(coverage_nightly, coverage(off))]
- unsafe extern "C-unwind" fn alloc(
- opaque: *mut c_void,
- size: usize,
- ) -> *mut c_void {
- let mm = &mut *opaque.cast::>();
+ unsafe extern "C-unwind" fn alloc(opaque: *mut c_void, size: usize) -> *mut c_void {
+ let mm = &mut *opaque.cast::();
let footer = mm.footer.load(Ordering::Acquire);
let mut new = footer + size;
loop {
- if new > N {
+ if new > mm.arena.len() {
+ println!("Out of memory");
break null_mut();
} else if let Err(s) = mm.footer.compare_exchange_weak(
footer,
@@ -123,10 +94,10 @@ pub(crate) mod tests {
}
}
- alloc::
+ alloc
}
- fn free(&self) -> FreeFn {
+ fn free(&self) -> JpegxlFreeFunc {
#[cfg_attr(coverage_nightly, coverage(off))]
unsafe extern "C-unwind" fn free(_opaque: *mut c_void, _address: *mut c_void) {}
@@ -136,7 +107,7 @@ pub(crate) mod tests {
pub struct PanicManager {}
impl MemoryManager for PanicManager {
- fn alloc(&self) -> AllocFn {
+ fn alloc(&self) -> JpegxlAllocFunc {
#[cfg_attr(coverage_nightly, coverage(off))]
unsafe extern "C-unwind" fn alloc(_opaque: *mut c_void, _size: usize) -> *mut c_void {
panic!("Stack unwind test")
@@ -145,7 +116,7 @@ pub(crate) mod tests {
alloc
}
- fn free(&self) -> FreeFn {
+ fn free(&self) -> JpegxlFreeFunc {
#[cfg_attr(coverage_nightly, coverage(off))]
unsafe extern "C-unwind" fn free(_opaque: *mut c_void, _address: *mut c_void) {
debug_assert!(false, "Should not be called");
@@ -156,20 +127,21 @@ pub(crate) mod tests {
}
#[test]
- fn test_mm() {
- let mm = NoManager {};
- assert!(decoder_builder().memory_manager(&mm).build().is_err());
- assert!(encoder_builder().memory_manager(&mm).build().is_err());
-
- let mm = BumpManager::<{ 1024 * 10 }>::default();
- assert!(decoder_builder().memory_manager(&mm).build().is_ok());
- assert!(encoder_builder().memory_manager(&mm).build().is_ok());
+ fn test_mm() -> TestResult {
+ let mm = BumpManager::new(1024 * 1024 * 50);
+ let dec = decoder_builder().memory_manager(&mm).build()?;
+ let (meta, img) = dec.decode_with::(crate::tests::SAMPLE_JXL)?;
+
+ let mut enc = encoder_builder().memory_manager(&mm).build()?;
+ let _ = enc.encode::(&img, meta.width, meta.height)?;
+
+ Ok(())
}
#[test]
#[should_panic = "Stack unwind test"]
fn test_unwind() {
let mm = PanicManager {};
- let _ = decoder_builder().memory_manager(&mm).build();
+ let _ = decoder_builder().memory_manager(&mm).build().unwrap();
}
}
diff --git a/jpegxl-rs/src/parallel.rs b/jpegxl-rs/src/parallel.rs
index e9b6e4f..95ec229 100644
--- a/jpegxl-rs/src/parallel.rs
+++ b/jpegxl-rs/src/parallel.rs
@@ -34,50 +34,19 @@ use std::ffi::c_void;
pub mod resizable_runner;
pub mod threads_runner;
-/// Parallel runner return code
-pub use jpegxl_sys::parallel_runner::JxlParallelRetCode;
+use jpegxl_sys::threads::parallel_runner::JxlParallelRunner;
-use crate::decode::BasicInfo;
-/// Parallel runner initialization callback type
-pub type InitFn = unsafe extern "C-unwind" fn(*mut c_void, usize) -> i32;
-/// Parallel runner data processing callback type
-pub type RunFn = unsafe extern "C-unwind" fn(*mut c_void, u32, usize);
+pub use jpegxl_sys::threads::parallel_runner::{
+ JxlParallelRetCode, JxlParallelRunFunction, JxlParallelRunInit,
+};
-/// FFI runner function.
-///
-/// A parallel runner implementation can be
-/// provided by a JPEG XL caller to allow running computations in multiple
-/// threads. This function must call the initialization function `init_func` in the
-/// same thread that called it and then call the passed `run_func` once for every
-/// number in the range [`start_range`, `end_range`) (including `start_range`ge but not
-/// including `end_range`) possibly from different multiple threads in parallel.
-///
-/// The `JxlParallelRunner` function does not need to be re-entrant. This means
-/// that the same `JxlParallelRunner` function with the same `runner_opaque`
-/// provided parameter will not be called from the library from either `init_func` or
-/// `run_func` in the same decoder or encoder instance. However, a single decoding
-/// or encoding instance may call the provided `JxlParallelRunner` multiple
-/// times for different parts of the decoding or encoding process.
-///
-/// # Returns
-/// - `0`: if the @p init call succeeded (returned 0) and no other error
-/// occurred in the runner code.
-/// - `JXL_PARALLEL_RET_RUNNER_ERROR` if an error occurred in the runner
-/// code, for example, setting up the threads.
-/// - Return the return value of `init_func` if non-zero.
-pub type RunnerFn = unsafe extern "C-unwind" fn(
- runner_opaque: *mut c_void,
- jpegxl_opaque: *mut c_void,
- init_func: InitFn,
- run_func: RunFn,
- start_range: u32,
- end_range: u32,
-) -> JxlParallelRetCode;
+use crate::decode::BasicInfo;
/// JPEG XL Parallel Runner
-pub trait JxlParallelRunner {
- /// Get a [`RunnerFn`] for the parallel runner.
- fn runner(&self) -> RunnerFn;
+#[allow(clippy::module_name_repetitions)]
+pub trait ParallelRunner {
+ /// Get a [`JxlParallelRunner`] for the parallel runner.
+ fn runner(&self) -> JxlParallelRunner;
/// Get an opaque pointer to the runner.
fn as_opaque_ptr(&self) -> *mut c_void;
diff --git a/jpegxl-rs/src/parallel/resizable_runner.rs b/jpegxl-rs/src/parallel/resizable_runner.rs
index 3a8caf3..d059e40 100644
--- a/jpegxl-rs/src/parallel/resizable_runner.rs
+++ b/jpegxl-rs/src/parallel/resizable_runner.rs
@@ -21,10 +21,9 @@ along with jpegxl-rs. If not, see .
use std::{ffi::c_void, ptr::null_mut};
-#[allow(clippy::wildcard_imports)]
-use jpegxl_sys::resizable_parallel_runner::*;
+use jpegxl_sys::threads::resizable_parallel_runner as api;
-use super::{JxlParallelRunner, RunnerFn};
+use super::{JxlParallelRunner, ParallelRunner};
use crate::{decode::BasicInfo, memory::MemoryManager};
@@ -37,36 +36,41 @@ pub struct ResizableRunner<'mm> {
impl<'mm> ResizableRunner<'mm> {
/// Construct with number of threads
#[must_use]
- pub fn new(memory_manager: Option<&'mm dyn MemoryManager>) -> Self {
+ pub fn new(memory_manager: Option<&'mm dyn MemoryManager>) -> Option {
let mm = memory_manager.map(MemoryManager::manager);
- let runner_ptr =
- unsafe { JxlResizableParallelRunnerCreate(mm.as_ref().map_or(null_mut(), |mm| mm)) };
-
- Self {
- runner_ptr,
- _memory_manager: memory_manager,
+ let runner_ptr = unsafe {
+ api::JxlResizableParallelRunnerCreate(mm.as_ref().map_or(null_mut(), |mm| mm))
+ };
+
+ if runner_ptr.is_null() {
+ None
+ } else {
+ Some(Self {
+ runner_ptr,
+ _memory_manager: memory_manager,
+ })
}
}
/// Set number of threads depending on the size of the image
pub fn set_num_threads(&self, width: u64, height: u64) {
- let num = unsafe { JxlResizableParallelRunnerSuggestThreads(width, height) };
- unsafe { JxlResizableParallelRunnerSetThreads(self.runner_ptr, num as usize) };
+ let num = unsafe { api::JxlResizableParallelRunnerSuggestThreads(width, height) };
+ unsafe { api::JxlResizableParallelRunnerSetThreads(self.runner_ptr, num as usize) };
}
}
impl Default for ResizableRunner<'_> {
fn default() -> Self {
Self {
- runner_ptr: unsafe { JxlResizableParallelRunnerCreate(std::ptr::null()) },
+ runner_ptr: unsafe { api::JxlResizableParallelRunnerCreate(std::ptr::null()) },
_memory_manager: None,
}
}
}
-impl JxlParallelRunner for ResizableRunner<'_> {
- fn runner(&self) -> RunnerFn {
- JxlResizableParallelRunner
+impl ParallelRunner for ResizableRunner<'_> {
+ fn runner(&self) -> JxlParallelRunner {
+ api::JxlResizableParallelRunner
}
fn as_opaque_ptr(&self) -> *mut c_void {
@@ -80,30 +84,22 @@ impl JxlParallelRunner for ResizableRunner<'_> {
impl Drop for ResizableRunner<'_> {
fn drop(&mut self) {
- unsafe { JxlResizableParallelRunnerDestroy(self.runner_ptr) };
+ unsafe { api::JxlResizableParallelRunnerDestroy(self.runner_ptr) };
}
}
#[cfg(test)]
mod tests {
- use testresult::TestResult;
- use crate::{decoder_builder, memory::tests::BumpManager};
+ use crate::memory::tests::BumpManager;
use super::*;
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
- fn test_construction() -> TestResult {
- let memory_manager = BumpManager::<{ 1024 * 5 }>::default();
+ fn test_construction() {
+ let memory_manager = BumpManager::new(1024);
let parallel_runner = ResizableRunner::new(Some(&memory_manager));
-
- let decoder = decoder_builder()
- .memory_manager(&memory_manager)
- .parallel_runner(¶llel_runner)
- .build()?;
- decoder.decode(crate::tests::SAMPLE_JXL)?;
-
- Ok(())
+ assert!(parallel_runner.is_some());
}
}
diff --git a/jpegxl-rs/src/parallel/threads_runner.rs b/jpegxl-rs/src/parallel/threads_runner.rs
index a299c01..7ec0704 100644
--- a/jpegxl-rs/src/parallel/threads_runner.rs
+++ b/jpegxl-rs/src/parallel/threads_runner.rs
@@ -20,9 +20,9 @@ along with jpegxl-rs. If not, see .
use std::{ffi::c_void, ptr::null_mut};
#[allow(clippy::wildcard_imports)]
-use jpegxl_sys::thread_parallel_runner::*;
+use jpegxl_sys::threads::thread_parallel_runner::*;
-use super::{JxlParallelRunner, RunnerFn};
+use super::{JxlParallelRunner, ParallelRunner};
use crate::memory::MemoryManager;
@@ -72,8 +72,8 @@ impl Default for ThreadsRunner<'_> {
}
}
-impl JxlParallelRunner for ThreadsRunner<'_> {
- fn runner(&self) -> RunnerFn {
+impl ParallelRunner for ThreadsRunner<'_> {
+ fn runner(&self) -> JxlParallelRunner {
JxlThreadParallelRunner
}
@@ -90,17 +90,13 @@ impl Drop for ThreadsRunner<'_> {
#[cfg(test)]
mod tests {
- use crate::memory::tests::{BumpManager, NoManager};
+ use crate::memory::tests::BumpManager;
use super::*;
#[test]
fn test_construction() {
- let memory_manager = NoManager {};
- let parallel_runner = ThreadsRunner::new(Some(&memory_manager), None);
- assert!(parallel_runner.is_none());
-
- let memory_manager = BumpManager::<1024>::default();
+ let memory_manager = BumpManager::new(1024);
let parallel_runner = ThreadsRunner::new(Some(&memory_manager), Some(10));
assert!(parallel_runner.is_some());
}
diff --git a/jpegxl-rs/src/tests/encode.rs b/jpegxl-rs/src/tests/encode.rs
index 58c62ec..a32e1b7 100644
--- a/jpegxl-rs/src/tests/encode.rs
+++ b/jpegxl-rs/src/tests/encode.rs
@@ -211,7 +211,10 @@ fn gray() -> TestResult {
)?;
_ = decoder.decode(&result)?;
- encoder.set_frame_option(jpegxl_sys::encode::FrameSetting::BrotliEffort, 1)?;
+ encoder.set_frame_option(
+ jpegxl_sys::encoder::encode::JxlEncoderFrameSettingId::BrotliEffort,
+ 1,
+ )?;
Ok(())
}
diff --git a/jpegxl-src/Cargo.toml b/jpegxl-src/Cargo.toml
index 06e6dd8..2627f6c 100644
--- a/jpegxl-src/Cargo.toml
+++ b/jpegxl-src/Cargo.toml
@@ -6,7 +6,7 @@ license = "BSD-3-Clause"
name = "jpegxl-src"
readme = "README.md"
repository = "https://github.com/inflation/jpegxl-rs"
-version = "0.10.5"
+version = "0.11.0"
rust-version.workspace = true
exclude = [
"libjxl/third_party/libpng",
diff --git a/jpegxl-src/libjxl b/jpegxl-src/libjxl
index 4a3b22d..4df1e9e 160000
--- a/jpegxl-src/libjxl
+++ b/jpegxl-src/libjxl
@@ -1 +1 @@
-Subproject commit 4a3b22d2600f92d8706fb72d85d52bfee2acbd54
+Subproject commit 4df1e9eccdf86b8df4c0c7c08f529263906f9c4f
diff --git a/jpegxl-sys/Cargo.toml b/jpegxl-sys/Cargo.toml
index a06c510..746f208 100644
--- a/jpegxl-sys/Cargo.toml
+++ b/jpegxl-sys/Cargo.toml
@@ -9,7 +9,7 @@ links = "jxl"
name = "jpegxl-sys"
readme = "README.md"
repository = "https://github.com/inflation/jpegxl-rs"
-version = "0.10.4+libjxl-0.10.3"
+version = "0.11.0+libjxl-0.11.0"
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -21,6 +21,9 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] }
pedantic = "warn"
module_name_repetitions = "allow"
+[lints.rustdoc]
+broken_intra_doc_links = "deny"
+
[package.metadata.docs.rs]
features = ["docs"]
@@ -28,7 +31,7 @@ features = ["docs"]
pkg-config = "0.3.31"
[build-dependencies.jpegxl-src]
-version = "0.10.4"
+version = "0.11.0"
path = "../jpegxl-src"
optional = true
diff --git a/jpegxl-sys/src/codestream_header.rs b/jpegxl-sys/src/codestream_header.rs
deleted file mode 100644
index 29eeec3..0000000
--- a/jpegxl-sys/src/codestream_header.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-use crate::types::JxlBool;
-
-#[repr(C)]
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
-pub enum JxlOrientation {
- Identity = 1,
- FlipHorizontal = 2,
- Rotate180 = 3,
- FlipVertical = 4,
- Transpose = 5,
- Rotate90Cw = 6,
- AntiTranspose = 7,
- Rotate90Ccw = 8,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
-pub enum JxlExtraChannelType {
- Alpha,
- Depth,
- SpotColor,
- SelectionMask,
- Black,
- Cfa,
- Thermal,
- Reserved0,
- Reserved1,
- Reserved2,
- Reserved3,
- Reserved4,
- Reserved5,
- Reserved6,
- Reserved7,
- Unknown,
- Optional,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlPreviewHeader {
- pub xsize: u32,
- pub ysize: u32,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlAnimationHeader {
- pub tps_numerator: u32,
- pub tps_denominator: u32,
- pub num_loops: u32,
- pub have_timecodes: JxlBool,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlBasicInfo {
- pub have_container: JxlBool,
- pub xsize: u32,
- pub ysize: u32,
- pub bits_per_sample: u32,
- pub exponent_bits_per_sample: u32,
- pub intensity_target: f32,
- pub min_nits: f32,
- pub relative_to_max_display: JxlBool,
- pub linear_below: f32,
- pub uses_original_profile: JxlBool,
- pub have_preview: JxlBool,
- pub have_animation: JxlBool,
- pub orientation: JxlOrientation,
- pub num_color_channels: u32,
- pub num_extra_channels: u32,
- pub alpha_bits: u32,
- pub alpha_exponent_bits: u32,
- pub alpha_premultiplied: JxlBool,
- pub preview: JxlPreviewHeader,
- pub animation: JxlAnimationHeader,
- pub intrinsic_xsize: u32,
- pub intrinsic_ysize: u32,
- _padding: [u8; 100],
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlExtraChannelInfo {
- pub type_: JxlExtraChannelType,
- pub bits_per_sample: u32,
- pub exponent_bits_per_sample: u32,
- pub dim_shift: u32,
- pub name_length: u32,
- pub alpha_associated: JxlBool,
- pub spot_color: [f32; 4usize],
- pub cfa_channel: u32,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlHeaderExtensions {
- pub extensions: u64,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
-pub enum JxlBlendMode {
- Replace = 0,
- Add = 1,
- Blend = 2,
- MULADD = 3,
- MUL = 4,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlBlendInfo {
- pub blendmode: JxlBlendMode,
- pub source: u32,
- pub alpha: u32,
- pub clamp: JxlBool,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlLayerInfo {
- pub have_crop: JxlBool,
- pub crop_x0: i32,
- pub crop_y0: i32,
- pub xsize: u32,
- pub ysize: u32,
- pub blend_info: JxlBlendInfo,
- pub save_as_reference: u32,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlFrameHeader {
- pub duration: u32,
- pub timecode: u32,
- pub name_length: u32,
- pub is_last: JxlBool,
- pub layer_info: JxlLayerInfo,
-}
diff --git a/jpegxl-sys/src/color.rs b/jpegxl-sys/src/color.rs
new file mode 100644
index 0000000..edeafff
--- /dev/null
+++ b/jpegxl-sys/src/color.rs
@@ -0,0 +1,22 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! `jxl_color`: ICC profiles and color space conversions.
+
+pub mod cms;
+pub mod cms_interface;
+pub mod color_encoding;
diff --git a/jpegxl-sys/src/color/cms.rs b/jpegxl-sys/src/color/cms.rs
new file mode 100644
index 0000000..f7ee801
--- /dev/null
+++ b/jpegxl-sys/src/color/cms.rs
@@ -0,0 +1,24 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! ICC profiles and color space conversions.
+
+use super::cms_interface::JxlCmsInterface;
+
+extern "C" {
+ pub fn JxlGetDefaultCms() -> *const JxlCmsInterface;
+}
diff --git a/jpegxl-sys/src/cms.rs b/jpegxl-sys/src/color/cms_interface.rs
similarity index 83%
rename from jpegxl-sys/src/cms.rs
rename to jpegxl-sys/src/color/cms_interface.rs
index 0a967f5..36c4fbc 100644
--- a/jpegxl-sys/src/cms.rs
+++ b/jpegxl-sys/src/color/cms_interface.rs
@@ -15,13 +15,18 @@ You should have received a copy of the GNU General Public License
along with jpegxl-sys. If not, see .
*/
+//! Interface to allow the injection of different color management systems
+//! (CMSes, also called color management modules, or CMMs) in JPEG XL.
+//!
+//! A CMS is needed by the JPEG XL encoder and decoder to perform colorspace
+//! conversions. This defines an interface that can be implemented for different
+//! CMSes and then passed to the library.
+
use std::ffi::c_void;
-use crate::{color_encoding::JxlColorEncoding, types::JxlBool};
+use crate::common::types::JxlBool;
-extern "C" {
- pub fn JxlGetDefaultCms() -> *const JxlCmsInterface;
-}
+use super::color_encoding::JxlColorEncoding;
pub type JpegXlCmsSetFieldsFromIccFunc = extern "C" fn(
user_data: *mut c_void,
diff --git a/jpegxl-sys/src/color/color_encoding.rs b/jpegxl-sys/src/color/color_encoding.rs
new file mode 100644
index 0000000..2e18dde
--- /dev/null
+++ b/jpegxl-sys/src/color/color_encoding.rs
@@ -0,0 +1,159 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Color Encoding definitions used by JPEG XL.
+//! All CIE units are for the standard 1931 2 degree observer.
+
+#[cfg(doc)]
+use crate::metadata::codestream_header::JxlBasicInfo;
+
+/// Color space of the image data.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlColorSpace {
+ /// Tristimulus RGB
+ Rgb = 0,
+ /// Luminance based, the primaries in [`JxlColorEncoding`] must be ignored.
+ /// This value implies that [`JxlBasicInfo::num_color_channels`] is `1`, any
+ /// other value implies `num_color_channels` is `3`.
+ Gray,
+ /// XYB (opsin) color space
+ Xyb,
+ /// None of the other table entries describe the color space appropriately
+ Unknown,
+}
+
+/// Built-in white points for color encoding. When decoding, the numerical xy
+/// white point value can be read from the [`JxlColorEncoding::white_point`]
+/// field regardless of the enum value. When encoding, enum values except
+/// [`JxlWhitePoint::Custom`] override the numerical fields. Some enum values
+/// match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however
+/// the white point and RGB primaries are separate enums here.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlWhitePoint {
+ /// CIE Standard Illuminant D65: 0.3127, 0.3290
+ D65 = 1,
+ /// White point must be read from the [`JxlColorEncoding::white_point`] field,
+ /// or as ICC profile. This enum value is not an exact match of the
+ /// corresponding CICP value.
+ Custom = 2,
+ /// CIE Standard Illuminant E (equal-energy): 1/3, 1/3
+ E = 10,
+ /// DCI-P3 from SMPTE RP 431-2: 0.314, 0.351
+ Dci = 11,
+}
+
+/// Built-in primaries for color encoding. When decoding, the primaries can be
+/// read from the [`JxlColorEncoding::primaries_red_xy`], [`JxlColorEncoding::primaries_green_xy`],
+/// and [`JxlColorEncoding::primaries_blue_xy`] fields regardless of the enum value. When encoding,
+/// the enum values except [`JxlPrimaries::Custom`] override the numerical fields. Some enum values
+/// match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however the white point
+/// and RGB primaries are separate enums here.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlPrimaries {
+ /// The CIE xy values of the red, green and blue primaries are: 0.639998686,
+ /// 0.330010138; 0.300003784, 0.600003357; 0.150002046, 0.059997204
+ SRgb = 1,
+ /// Primaries must be read from the [`JxlColorEncoding::primaries_red_xy`],
+ /// [`JxlColorEncoding::primaries_green_xy`] and [`JxlColorEncoding::primaries_blue_xy`] fields,
+ /// or as ICC profile. This enum value is not an exact match of the corresponding CICP value.
+ Custom = 2,
+ /// As specified in Rec. ITU-R BT.2100-1
+ Rec2100 = 9,
+ /// As specified in SMPTE RP 431-2
+ P3 = 11,
+}
+
+/// Built-in transfer functions for color encoding. Enum values match a subset
+/// of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)) unless specified
+/// otherwise.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlTransferFunction {
+ /// As specified in ITU-R BT.709-6
+ BT709 = 1,
+ /// None of the other table entries describe the transfer function.
+ Unknown = 2,
+ /// The gamma exponent is 1
+ Linear = 8,
+ /// As specified in IEC 61966-2-1 sRGB
+ SRGB = 13,
+ /// As specified in SMPTE ST 2084
+ PQ = 16,
+ /// As specified in SMPTE ST 428-1
+ DCI = 17,
+ /// As specified in Rec. ITU-R BT.2100-1
+ HLG = 18,
+ /// Transfer function follows power law given by the gamma value in [`JxlColorEncoding`].
+ /// Not a CICP value.
+ Gamma = 65535,
+}
+
+/// Rendering intent for color encoding, as specified in ISO 15076-1:2010
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlRenderingIntent {
+ /// vendor-specific
+ Perceptual = 0,
+ /// media-relative
+ Relative,
+ /// vendor-specific
+ Saturation,
+ /// ICC-absolute
+ Absolute,
+}
+
+/// Color encoding of the image as structured information.
+#[repr(C)]
+#[derive(Clone, Debug)]
+pub struct JxlColorEncoding {
+ /// Color space of the image data.
+ pub color_space: JxlColorSpace,
+
+ /// Built-in white point. If this value is [`JxlWhitePoint::Custom`], must
+ /// use the numerical white point values from [`Self::white_point_xy`].
+ pub white_point: JxlWhitePoint,
+
+ /// Numerical whitepoint values in CIE xy space.
+ pub white_point_xy: [f64; 2],
+
+ /// Built-in RGB primaries. If this value is [`JxlPrimaries::Custom`], must
+ /// use the numerical primaries values below. This field and the custom values
+ /// below are unused and must be ignored if the color space is
+ /// [`JxlColorSpace::Gray`] or [`JxlColorSpace::Xyb`].
+ pub primaries: JxlPrimaries,
+
+ /// Numerical red primary values in CIE xy space.
+ pub primaries_red_xy: [f64; 2],
+
+ /// Numerical green primary values in CIE xy space.
+ pub primaries_green_xy: [f64; 2],
+
+ /// Numerical blue primary values in CIE xy space.
+ pub primaries_blue_xy: [f64; 2],
+
+ /// Transfer function if `have_gamma` is 0.
+ pub transfer_function: JxlTransferFunction,
+
+ /// Gamma value used when [`Self::transfer_function`] is [`JxlTransferFunction::Gamma`].
+ pub gamma: f64,
+
+ /// Rendering intent defined for the color profile.
+ pub rendering_intent: JxlRenderingIntent,
+}
diff --git a/jpegxl-sys/src/color_encoding.rs b/jpegxl-sys/src/color_encoding.rs
deleted file mode 100644
index 67cb005..0000000
--- a/jpegxl-sys/src/color_encoding.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlColorSpace {
- Rgb = 0,
- Gray,
- Xyb,
- Unknown,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlWhitePoint {
- D65 = 1,
- Custom = 2,
- E = 10,
- Dci = 11,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlPrimaries {
- SRgb = 1,
- Custom = 2,
- Rec2100 = 9,
- P3 = 11,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlTransferFunction {
- Rec709 = 1,
- Unknown = 2,
- Linear = 8,
- SRgb = 13,
- Pq = 16,
- Dci = 17,
- Hlg = 18,
- Gamma = 65535,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlRenderingIntent {
- Perceptual = 0,
- Relative,
- Saturation,
- Absolute,
-}
-
-#[repr(C)]
-#[derive(Clone, Debug)]
-pub struct JxlColorEncoding {
- pub color_space: JxlColorSpace,
- pub white_point: JxlWhitePoint,
- pub white_point_xy: [f64; 2usize],
- pub primaries: JxlPrimaries,
- pub primaries_red_xy: [f64; 2usize],
- pub primaries_green_xy: [f64; 2usize],
- pub primaries_blue_xy: [f64; 2usize],
- pub transfer_function: JxlTransferFunction,
- pub gamma: f64,
- pub rendering_intent: JxlRenderingIntent,
-}
diff --git a/jpegxl-sys/src/common.rs b/jpegxl-sys/src/common.rs
new file mode 100644
index 0000000..477d505
--- /dev/null
+++ b/jpegxl-sys/src/common.rs
@@ -0,0 +1,21 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! `jxl_common`: Common utilities for the JPEG XL library.
+
+pub mod memory_manager;
+pub mod types;
diff --git a/jpegxl-sys/src/common/memory_manager.rs b/jpegxl-sys/src/common/memory_manager.rs
new file mode 100644
index 0000000..139f825
--- /dev/null
+++ b/jpegxl-sys/src/common/memory_manager.rs
@@ -0,0 +1,64 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Abstraction functions used by JPEG XL to allocate memory.
+
+use std::ffi::c_void;
+
+/// Allocating function for a memory region of a given size.
+///
+/// Allocates a contiguous memory region of size `size` bytes. The returned
+/// memory may not be aligned to a specific size or initialized at all.
+///
+/// # Parameters
+/// - `opaque`: custom memory manager handle provided by the caller.
+/// - `size`: size in bytes of the requested memory region.
+///
+/// # Returns
+/// - `NULL` if the memory cannot be allocated.
+/// - Pointer to the memory otherwise.
+pub type JpegxlAllocFunc =
+ unsafe extern "C-unwind" fn(opaque: *mut c_void, size: usize) -> *mut c_void;
+
+/// Deallocating function pointer type.
+///
+/// This function **MUST** do nothing if `address` is `NULL`.
+///
+/// # Parameters
+/// - `opaque`: custom memory manager handle provided by the caller.
+/// - `address`: memory region pointer returned by [`JpegxlAllocFunc`], or `NULL`.
+pub type JpegxlFreeFunc = unsafe extern "C-unwind" fn(opaque: *mut c_void, address: *mut c_void);
+
+/// Memory Manager struct.
+/// These functions, when provided by the caller, will be used to handle memory
+/// allocations.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlMemoryManager {
+ /// The opaque pointer that will be passed as the first parameter to all the
+ /// functions in this struct.
+ pub opaque: *mut c_void,
+
+ /// Memory allocation function. This can be NULL if and only if also the
+ /// [`Self::free`] member in this class is NULL. All dynamic memory will be allocated
+ /// and freed with these functions if they are not NULL, otherwise with the
+ /// standard malloc/free.
+ pub alloc: Option,
+
+ /// Free function matching the [`Self::alloc`] member.
+ pub free: Option,
+}
diff --git a/jpegxl-sys/src/common/types.rs b/jpegxl-sys/src/common/types.rs
new file mode 100644
index 0000000..cb090bc
--- /dev/null
+++ b/jpegxl-sys/src/common/types.rs
@@ -0,0 +1,148 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Data types for the JPEG XL API, for both encoding and decoding.
+
+use std::ffi::c_char;
+
+#[cfg(doc)]
+use crate::metadata::codestream_header::JxlBasicInfo;
+
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum JxlBool {
+ True = 1,
+ False = 0,
+}
+
+impl From for JxlBool {
+ fn from(b: bool) -> Self {
+ if b {
+ JxlBool::True
+ } else {
+ JxlBool::False
+ }
+ }
+}
+
+/// Data type for the sample values per channel per pixel.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum JxlDataType {
+ /// Use 32-bit single-precision floating point values, with range 0.0-1.0
+ /// (within gamut, may go outside this range for wide color gamut). Floating
+ /// point output, either [`JxlDataType::Float`] or [`JxlDataType::Float16`], is recommended
+ /// for HDR and wide gamut images when color profile conversion is required.
+ Float = 0,
+
+ /// Use type `u8`. May clip wide color gamut data.
+ Uint8 = 2,
+
+ /// Use type `u16`. May clip wide color gamut data.
+ Uint16 = 3,
+
+ /// Use 16-bit IEEE 754 half-precision floating point values.
+ Float16 = 5,
+}
+
+/// Ordering of multi-byte data.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum JxlEndianness {
+ /// Use the endianness of the system, either little endian or big endian,
+ /// without forcing either specific endianness. Do not use if pixel data
+ /// should be exported to a well defined format.
+ Native = 0,
+ /// Force little endian
+ Little = 1,
+ /// Force big endian
+ Big = 2,
+}
+
+/// Data type for the sample values per channel per pixel for the output buffer
+/// for pixels. This is not necessarily the same as the data type encoded in the
+/// codestream. The channels are interleaved per pixel. The pixels are
+/// organized row by row, left to right, top to bottom.
+/// TODO: support different channel orders if needed (RGB, BGR, ...)
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct JxlPixelFormat {
+ /// Amount of channels available in a pixel buffer.
+ /// 1: single-channel data, e.g. grayscale or a single extra channel
+ /// 2: single-channel + alpha
+ /// 3: trichromatic, e.g. RGB
+ /// 4: trichromatic + alpha
+ /// TODO: this needs finetuning. It is not yet defined how the user
+ /// chooses output color space. CMYK+alpha needs 5 channels.
+ pub num_channels: u32,
+
+ /// Data type of each channel.
+ pub data_type: JxlDataType,
+
+ /// Whether multi-byte data types are represented in big endian or little
+ /// endian format. This applies to [`JxlDataType::Uint16`] and [`JxlDataType::Float`].
+ pub endianness: JxlEndianness,
+
+ /// Align scanlines to a multiple of align bytes, or 0 to require no
+ /// alignment at all (which has the same effect as value 1)
+ pub align: usize,
+}
+
+/// Settings for the interpretation of UINT input and output buffers.
+/// (buffers using a FLOAT data type are not affected by this)
+#[repr(i32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum JxlBitDepthType {
+ /// This is the default setting, where the encoder expects the input pixels
+ /// to use the full range of the pixel format data type (e.g. for UINT16, the
+ /// input range is 0 .. 65535 and the value 65535 is mapped to 1.0 when
+ /// converting to float), and the decoder uses the full range to output
+ /// pixels. If the bit depth in the basic info is different from this, the
+ /// encoder expects the values to be rescaled accordingly (e.g. multiplied by
+ /// 65535/4095 for a 12-bit image using UINT16 input data type).
+ FromPixelFormat = 0,
+
+ /// If this setting is selected, the encoder expects the input pixels to be
+ /// in the range defined by the [`JxlBasicInfo::bits_per_sample`] value (e.g.
+ /// for 12-bit images using UINT16 input data types, the allowed range is
+ /// 0 .. 4095 and the value 4095 is mapped to 1.0 when converting to float),
+ /// and the decoder outputs pixels in this range.
+ FromCodestream = 1,
+
+ /// This setting can only be used in the decoder to select a custom range for
+ /// pixel output.
+ Custom = 2,
+}
+
+/// Data type for describing the interpretation of the input and output buffers
+/// in terms of the range of allowed input and output pixel values.
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct JxlBitDepth {
+ /// Bit depth setting, see comment on [`JxlBitDepthType`]
+ pub r#type: JxlBitDepthType,
+
+ /// Custom bits per sample
+ pub bits_per_sample: u32,
+
+ /// Custom exponent bits per sample
+ pub exponent_bits_per_sample: u32,
+}
+
+/// Data type holding the 4-character type name of an ISOBMFF box.
+#[repr(transparent)]
+pub struct JxlBoxType(pub [c_char; 4]);
diff --git a/jpegxl-sys/src/decode.rs b/jpegxl-sys/src/decode.rs
index 8627671..31d031c 100644
--- a/jpegxl-sys/src/decode.rs
+++ b/jpegxl-sys/src/decode.rs
@@ -15,67 +15,270 @@ You should have received a copy of the GNU General Public License
along with jpegxl-sys. If not, see .
*/
+//! Decoding API for JPEG XL.
+
use std::{
ffi::c_void,
os::raw::{c_char, c_int},
};
use crate::{
- cms::JxlCmsInterface,
- codestream_header::{JxlBasicInfo, JxlBlendInfo, JxlExtraChannelInfo, JxlFrameHeader},
- color_encoding::JxlColorEncoding,
- memory_manager::JxlMemoryManager,
- parallel_runner::JxlParallelRunner,
- types::{JxlBitDepth, JxlBool, JxlBoxType, JxlPixelFormat},
+ color::{cms_interface::JxlCmsInterface, color_encoding::JxlColorEncoding},
+ common::memory_manager::JxlMemoryManager,
+ common::types::{JxlBitDepth, JxlBool, JxlBoxType, JxlPixelFormat},
+ metadata::codestream_header::{
+ JxlBasicInfo, JxlBlendInfo, JxlExtraChannelInfo, JxlFrameHeader,
+ },
+ threads::parallel_runner::JxlParallelRunner,
+};
+#[cfg(doc)]
+use crate::{
+ common::types::JxlBitDepthType,
+ metadata::codestream_header::{JxlOrientation, JxlPreviewHeader},
};
+/// The result of [`JxlSignatureCheck`].
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum JxlSignature {
+ /// Not enough bytes were passed to determine if a valid signature was found.
NotEnoughBytes = 0,
+ /// No valid JPEG XL header was found.
Invalid = 1,
+ /// A valid JPEG XL codestream signature was found, that is a JPEG XL image
+ /// without container.
Codestream = 2,
+ /// A valid container signature was found, that is a JPEG XL image embedded
+ /// in a box format container.
Container = 3,
}
-// Opaque type
+/// Opaque structure that holds the JPEG XL decoder.
+///
+/// Allocated and initialized with [`JxlDecoderCreate`].
+/// Cleaned up and deallocated with [`JxlDecoderDestroy`].
#[repr(C)]
pub struct JxlDecoder {
_unused: [u8; 0],
}
+/// Return value for [`JxlDecoderProcessInput`].
+/// The values from [`JxlDecoderStatus::BasicInfo`] onwards are optional informative
+/// events that can be subscribed to, they are never returned if they
+/// have not been registered with [`JxlDecoderSubscribeEvents`].
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum JxlDecoderStatus {
+ /// Function call finished successfully, or decoding is finished and there is
+ /// nothing more to be done.
+ ///
+ /// Note that [`JxlDecoderProcessInput`] will return [`JxlDecoderStatus::Success`] if
+ /// all events that were registered with [`JxlDecoderSubscribeEvents`] were
+ /// processed, even before the end of the JPEG XL codestream.
+ ///
+ /// In this case, the return value [`JxlDecoderReleaseInput`] will be the same
+ /// as it was at the last signaled event. E.g. if [`JxlDecoderStatus::FullImage`] was
+ /// subscribed to, then all bytes from the end of the JPEG XL codestream
+ /// (including possible boxes needed for jpeg reconstruction) will be returned
+ /// as unprocessed.
Success = 0,
+
+ /// An error occurred, for example invalid input file or out of memory.
+ /// TODO: add function to get error information from decoder.
Error = 1,
+
+ /// The decoder needs more input bytes to continue. Before the next [`JxlDecoderProcessInput`]
+ /// call, more input data must be set, by calling [`JxlDecoderReleaseInput`] (if input was set previously)
+ /// and then calling [`JxlDecoderSetInput`]. [`JxlDecoderReleaseInput`] returns how many bytes
+ /// are not yet processed, before a next call to [`JxlDecoderProcessInput`]
+ /// all unprocessed bytes must be provided again (the address need not match,
+ /// but the contents must), and more bytes must be concatenated after the
+ /// unprocessed bytes.
+ /// In most cases, [`JxlDecoderReleaseInput`] will return no unprocessed bytes
+ /// at this event, the only exceptions are if the previously set input ended
+ /// within (a) the raw codestream signature, (b) the signature box, (c) a box
+ /// header, or (d) the first 4 bytes of a `brob`, `ftyp`, or `jxlp` box. In any
+ /// of these cases the number of unprocessed bytes is less than 20.
NeedMoreInput = 2,
+
+ /// The decoder is able to decode a preview image and requests setting a
+ /// preview output buffer using [`JxlDecoderSetPreviewOutBuffer`]. This occurs
+ /// if [`JxlDecoderStatus::PreviewImage`] is requested and it is possible to decode a
+ /// preview image from the codestream and the preview out buffer was not yet
+ /// set. There is maximum one preview image in a codestream.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the frame header (including `ToC`) of the preview frame as
+ /// unprocessed.
NeedPreviewOutBuffer = 3,
+
+ /// The decoder requests an output buffer to store the full resolution image,
+ /// which can be set with [`JxlDecoderSetImageOutBuffer`] or with [`JxlDecoderSetImageOutCallback`].
+ /// This event re-occurs for new frames if there are multiple animation frames and requires setting an output again.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the frame header (including `ToC`) as unprocessed.
NeedImageOutBuffer = 5,
- JpegNeedMoreOutput = 6,
+
+ /// The JPEG reconstruction buffer is too small for reconstructed JPEG
+ /// codestream to fit. [`JxlDecoderSetJPEGBuffer`] must be called again to
+ /// make room for remaining bytes. This event may occur multiple times
+ /// after [`JxlDecoderStatus::JPEGReconstruction`].
+ JPEGNeedMoreOutput = 6,
+
+ /// The box contents output buffer is too small. [`JxlDecoderSetBoxBuffer`]
+ /// must be called again to make room for remaining bytes. This event may occur
+ /// multiple times after [`JxlDecoderStatus::Box`].
BoxNeedMoreOutput = 7,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: Basic information such as image dimensions and
+ /// extra channels. This event occurs max once per image.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the basic info as unprocessed (including the last byte of basic info
+ /// if it did not end on a byte boundary).
BasicInfo = 0x40,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: Color encoding or ICC profile from the
+ /// codestream header. This event occurs max once per image and always later
+ /// than [`JxlDecoderStatus::BasicInfo`] and earlier than any pixel data.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the image header (which is the start of the first frame) as
+ /// unprocessed.
ColorEncoding = 0x100,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: Preview image, a small frame, decoded. This
+ /// event can only happen if the image has a preview frame encoded. This event
+ /// occurs max once for the codestream and always later than [`JxlDecoderStatus::ColorEncoding`]
+ /// and before [`JxlDecoderStatus::Frame`]. In this case, [`JxlDecoderReleaseInput`] will return all bytes
+ /// from the end of the preview frame as unprocessed.
PreviewImage = 0x200,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: Beginning of a frame. [`JxlDecoderGetFrameHeader`] can be
+ /// used at this point.
+ ///
+ /// ## Note:
+ ///
+ /// a JPEG XL image can have internal frames that are not intended to be
+ /// displayed (e.g. used for compositing a final frame), but this only returns
+ /// displayed frames, unless [`JxlDecoderSetCoalescing`] was set to [`JxlBool::False`]:
+ /// in that case, the individual layers are returned, without blending.
+ /// Note that even when coalescing is disabled, only frames of type `kRegularFrame` are returned;
+ /// frames of type `kReferenceOnly` and `kLfFrame` are always for internal purposes only and cannot be accessed.
+ /// A displayed frame either has an animation duration or is the only or last
+ /// frame in the image. This event occurs max once per displayed frame, always
+ /// later than [`JxlDecoderStatus::ColorEncoding`], and always earlier than any pixel
+ /// data. While JPEG XL supports encoding a single frame as the composition of
+ /// multiple internal sub-frames also called frames, this event is not
+ /// indicated for the internal frames. In this case, [`JxlDecoderReleaseInput`] will return all bytes
+ /// from the end of the frame header (including `ToC`) as unprocessed.
Frame = 0x400,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: full frame (or layer, in case coalescing is
+ /// disabled) is decoded. [`JxlDecoderSetImageOutBuffer`] must be used after
+ /// getting the basic image information to be able to get the image pixels, if
+ /// not this return status only indicates we're past this point in the
+ /// codestream. This event occurs max once per frame.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the frame (or if [`JxlDecoderStatus::JPEGReconstruction`] is subscribed to,
+ /// from the end of the last box that is needed for jpeg reconstruction) as
+ /// unprocessed.
FullImage = 0x1000,
- JpegReconstruction = 0x2000,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: JPEG reconstruction data decoded.
+ /// [`JxlDecoderSetJPEGBuffer`] may be used to set a JPEG reconstruction buffer
+ /// after getting the JPEG reconstruction data. If a JPEG reconstruction buffer
+ /// is set a byte stream identical to the JPEG codestream used to encode the
+ /// image will be written to the JPEG reconstruction buffer instead of pixels
+ /// to the image out buffer. This event occurs max once per image and always
+ /// before [`JxlDecoderStatus::FullImage`].
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the `jbrd` box as unprocessed.
+ JPEGReconstruction = 0x2000,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: The header of a box of the container format
+ /// (BMFF) is decoded. The following API functions related to boxes can be used
+ /// after this event:
+ /// - [`JxlDecoderSetBoxBuffer`] and [`JxlDecoderReleaseBoxBuffer`]: set and release a buffer to get the box
+ /// data.
+ /// - [`JxlDecoderGetBoxType`] get the 4-character box typename.
+ /// - [`JxlDecoderGetBoxSizeRaw`] get the size of the box as it appears in
+ /// the container file, not decompressed.
+ /// - [`JxlDecoderSetDecompressBoxes`] to configure whether to get the box
+ /// data decompressed, or possibly compressed.
+ ///
+ /// Boxes can be compressed. This is so when their box type is
+ /// "brob". In that case, they have an underlying decompressed box
+ /// type and decompressed data. [`JxlDecoderSetDecompressBoxes`] allows
+ /// configuring which data to get. Decompressing requires
+ /// Brotli. [`JxlDecoderGetBoxType`] has a flag to get the compressed box
+ /// type, which can be "brob", or the decompressed box type. If a box
+ /// is not compressed (its compressed type is not "brob"), then
+ /// the output decompressed box type and data is independent of what
+ /// setting is configured.
+ ///
+ /// The buffer set with [`JxlDecoderSetBoxBuffer`] must be set again for each
+ /// next box to be obtained, or can be left unset to skip outputting this box.
+ /// The output buffer contains the full box data when the
+ /// [`JxlDecoderStatus::BoxComplete`] (if subscribed to) or subsequent [`JxlDecoderStatus::Success`]
+ /// or subsequent [`JxlDecoderStatus::Box`] event occurs. [`JxlDecoderStatus::Box`] occurs for all boxes,
+ /// including non-metadata boxes such as the signature box or codestream boxes.
+ /// To check whether the box is a metadata type for respectively EXIF, XMP or
+ /// JUMBF, use [`JxlDecoderGetBoxType`] and check for types "Exif", "xml " and
+ /// "jumb" respectively.
+ ///
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// start of the box header as unprocessed.
Box = 0x4000,
+
+ /// Informative event by [`JxlDecoderProcessInput`]: a progressive step in decoding the frame is
+ /// reached. When calling [`JxlDecoderFlushImage`] at this point, the flushed
+ /// image will correspond exactly to this point in decoding, and not yet
+ /// contain partial results (such as partially more fine detail) of a next
+ /// step. By default, this event will trigger maximum once per frame, when a
+ /// 8x8th resolution (DC) image is ready (the image data is still returned at
+ /// full resolution, giving upscaled DC). Use [`JxlDecoderSetProgressiveDetail`] to configure more fine-grainedness.
+ /// The event is not guaranteed to trigger, not all images have progressive steps
+ /// or DC encoded.
+ /// In this case, [`JxlDecoderReleaseInput`] will return all bytes from the
+ /// end of the section that was needed to produce this progressive event as
+ /// unprocessed.
FrameProgression = 0x8000,
+
+ /// The box being decoded is now complete. This is only emitted if a buffer
+ /// was set for the box.
+ BoxComplete = 0x10000,
}
+/// Types of progressive detail.
+/// Setting a progressive detail with value N implies all progressive details
+/// with smaller or equal value. Currently only the following level of
+/// progressive detail is implemented:
+/// - [`JxlProgressiveDetail::DC`] (which implies [`JxlProgressiveDetail::Frames`])
+/// - [`JxlProgressiveDetail::LastPasses`] (which implies [`JxlProgressiveDetail::DC`]
+/// and [`JxlProgressiveDetail::Frames`])
+/// - [`JxlProgressiveDetail::Passes`] (which implies [`JxlProgressiveDetail::LastPasses`],
+/// [`JxlProgressiveDetail::DC`] and [`JxlProgressiveDetail::Frames`])
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum JxlProgressiveDetail {
+ /// After completed kRegularFrames
Frames = 0,
+ /// After completed DC (1:8)
DC = 1,
+ /// After completed AC passes that are the last pass for their resolution target.
LastPasses = 2,
+ /// After completed AC passes that are not the last pass for their resolution target.
Passes = 3,
+ /// During DC frame when lower resolutions are completed (1:32, 1:16)
DCProgressive = 4,
+ /// After completed groups
DCGroups = 5,
+ /// After completed groups
Groups = 6,
}
+/// Defines which color profile to get: the profile from the codestream
+/// metadata header, which represents the color profile of the original image,
+/// or the color profile from the pixel data produced by the decoder. Both are
+/// the same if the [`JxlBasicInfo`] has `uses_original_profile` set.
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum JxlColorProfileTarget {
@@ -83,6 +286,20 @@ pub enum JxlColorProfileTarget {
Data = 1,
}
+/// Function type for [`JxlDecoderSetImageOutCallback`].
+///
+/// The callback may be called simultaneously by different threads when using a
+/// threaded parallel runner, on different pixels.
+///
+/// # Parameters
+/// - `opaque`: optional user data, as given to [`JxlDecoderSetImageOutCallback`].
+/// - `x`: horizontal position of leftmost pixel of the pixel data.
+/// - `y`: vertical position of the pixel data.
+/// - `num_pixels`: amount of pixels included in the pixel data, horizontally.
+/// This is not the same as xsize of the full image, it may be smaller.
+/// - `pixels`: pixel data as a horizontal stripe, in the format passed to
+/// [`JxlDecoderSetImageOutCallback`]. The memory is not owned by the user, and
+/// is only valid during the time the callback is running.
pub type JxlImageOutCallback = extern "C" fn(
opaque: *mut c_void,
x: usize,
@@ -91,12 +308,40 @@ pub type JxlImageOutCallback = extern "C" fn(
pixels: *const c_void,
);
+/// Initialization callback for [`JxlDecoderSetMultithreadedImageOutCallback`].
+///
+/// # Parameters
+/// - `init_opaque`: optional user data, as given to
+/// [`JxlDecoderSetMultithreadedImageOutCallback`].
+/// - `num_threads`: maximum number of threads that will call the [`run`](JxlImageOutRunCallback)
+/// callback concurrently.
+/// - `num_pixels_per_thread`: maximum number of pixels that will be passed in
+/// one call to [`run`](JxlImageOutRunCallback).
+///
+/// # Returns
+/// - a pointer to data that will be passed to the [`run`](JxlImageOutRunCallback) callback, or
+/// `NULL` if initialization failed.
pub type JxlImageOutInitCallback = extern "C" fn(
init_opaque: *mut c_void,
num_threads: usize,
num_pixels_per_thread: usize,
) -> *mut c_void;
+/// Worker callback for [`JxlDecoderSetMultithreadedImageOutCallback`]
+///
+/// # Parameters
+/// - `run_opaque`: user data returned by the [`init`](JxlImageOutInitCallback) callback.
+/// - `thread_id`: number in `[0, num_threads)` identifying the thread of the
+/// current invocation of the callback.
+/// - `x`: horizontal position of the first (leftmost) pixel of the pixel data.
+/// - `y`: vertical position of the pixel data.
+/// - `num_pixels`: number of pixels in the pixel data. May be less than the
+/// full `xsize` of the image, and will be at most equal to the `num_pixels_per_thread`
+/// that was passed to [`init`](JxlImageOutInitCallback).
+/// - `pixels`: pixel data as a horizontal stripe, in the format passed to
+/// [`JxlDecoderSetMultithreadedImageOutCallback`]. The data pointed to
+/// remains owned by the caller and is only guaranteed to outlive the current
+/// callback invocation.
pub type JxlImageOutRunCallback = extern "C" fn(
run_opaque: *mut c_void,
thread_id: usize,
@@ -106,72 +351,429 @@ pub type JxlImageOutRunCallback = extern "C" fn(
pixels: *const c_void,
);
+///
+/// Destruction callback for [`JxlDecoderSetMultithreadedImageOutCallback`],
+/// called after all invocations of the [`run`](JxlImageOutCallback) callback to perform any
+/// appropriate clean-up of the `run_opaque` data returned by [`init`](JxlImageOutInitCallback).
+///
+/// # Parameters
+/// - `run_opaque`: user data returned by the [`init`](JxlImageOutInitCallback) callback.
pub type JxlImageOutDestroyCallback = extern "C" fn(run_opaque: *mut c_void);
extern "C" {
+ /// Decoder library version.
+ ///
+ /// # Returns
+ /// The decoder library version as an integer:
+ /// `MAJOR_VERSION * 1000000 + MINOR_VERSION * 1000 + PATCH_VERSION`. For example,
+ /// version 1.2.3 would return 1002003.
pub fn JxlDecoderVersion() -> u32;
+
+ /// JPEG XL signature identification.
+ ///
+ /// Checks if the passed buffer contains a valid JPEG XL signature. The passed `buf` of size
+ /// `size` doesn't need to be a full image, only the beginning of the file.
+ ///
+ /// # Returns
+ /// A flag indicating if a JPEG XL signature was found and what type.
+ /// - [`JxlSignature::NotEnoughBytes`] if not enough bytes were passed to
+ /// determine if a valid signature is there.
+ /// - [`JxlSignature::Invalid`] if no valid signature found for JPEG XL decoding.
+ /// - [`JxlSignature::Codestream`] if a valid JPEG XL codestream signature was
+ /// found.
+ /// - [`JxlSignature::Container`] if a valid JPEG XL container signature was found.
pub fn JxlSignatureCheck(buf: *const u8, len: usize) -> JxlSignature;
+
+ /// Creates an instance of [`JxlDecoder`] and initializes it.
+ ///
+ /// `memory_manager` will be used for all the library dynamic allocations made
+ /// from this instance. The parameter may be `NULL`, in which case the default
+ /// allocator will be used. See [`crate::common::memory_manager`] for details.
+ ///
+ /// # Parameters
+ /// - `memory_manager`: custom allocator function. It may be `NULL`. The memory
+ /// manager will be copied internally.
+ ///
+ /// # Returns
+ /// - `NULL` if the instance cannot be allocated or initialized.
+ /// - Pointer to initialized [`JxlDecoder`] otherwise.
pub fn JxlDecoderCreate(memory_manager: *const JxlMemoryManager) -> *mut JxlDecoder;
+
+ /// Re-initializes a [`JxlDecoder`] instance, so it can be re-used for decoding
+ /// another image. All state and settings are reset as if the object was
+ /// newly created with [`JxlDecoderCreate`], but the memory manager is kept.
+ ///
+ /// # Parameters
+ /// - `dec`: instance to be re-initialized.
pub fn JxlDecoderReset(dec: *mut JxlDecoder);
+
+ /// Deinitializes and frees [`JxlDecoder`] instance.
+ ///
+ /// # Parameters
+ /// - `dec`: instance to be cleaned up and deallocated.
pub fn JxlDecoderDestroy(dec: *mut JxlDecoder);
+
+ /// Rewinds decoder to the beginning. The same input must be given again from
+ /// the beginning of the file and the decoder will emit events from the beginning
+ /// again. When rewinding (as opposed to [`JxlDecoderReset`]), the decoder can
+ /// keep state about the image, which it can use to skip to a requested frame
+ /// more efficiently with [`JxlDecoderSkipFrames`]. Settings such as parallel
+ /// runner or subscribed events are kept. After rewind, [`JxlDecoderSubscribeEvents`]
+ /// can be used again, and it is feasible to leave out events that were already
+ /// handled before, such as [`JxlDecoderStatus::BasicInfo`] and [`JxlDecoderStatus::ColorEncoding`],
+ /// since they will provide the same information as before.
+ /// The difference to [`JxlDecoderReset`] is that some state is kept, namely
+ /// settings set by a call to
+ /// - [`JxlDecoderSetCoalescing`],
+ /// - [`JxlDecoderSetDesiredIntensityTarget`],
+ /// - [`JxlDecoderSetDecompressBoxes`],
+ /// - [`JxlDecoderSetKeepOrientation`],
+ /// - [`JxlDecoderSetUnpremultiplyAlpha`],
+ /// - [`JxlDecoderSetParallelRunner`],
+ /// - [`JxlDecoderSetRenderSpotcolors`], and
+ /// - [`JxlDecoderSubscribeEvents`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
pub fn JxlDecoderRewind(dec: *mut JxlDecoder);
+
+ /// Makes the decoder skip the next `amount` frames. It still needs to process
+ /// the input, but will not output the frame events. It can be more efficient
+ /// when skipping frames, and even more so when using this after [`JxlDecoderRewind`].
+ /// If the decoder is already processing a frame (could have emitted [`JxlDecoderStatus::Frame`]
+ /// but not yet [`JxlDecoderStatus::FullImage`]), it starts skipping from the next frame.
+ /// If the amount is larger than the amount of frames remaining in the image, all remaining
+ /// frames are skipped. Calling this function multiple times adds the amount to skip to the
+ /// already existing amount.
+ ///
+ /// A frame here is defined as a frame that without skipping emits events such
+ /// as [`JxlDecoderStatus::Frame`] and [`JxlDecoderStatus::FullImage`], frames that are internal
+ /// to the file format but are not rendered as part of an animation, or are not
+ /// the final still frame of a still image, are not counted.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `amount`: the amount of frames to skip
pub fn JxlDecoderSkipFrames(dec: *mut JxlDecoder, amount: usize);
+ /// Skips processing the current frame. Can be called after frame processing
+ /// already started, signaled by a [`JxlDecoderStatus::NeedImageOutBuffer`] event,
+ /// but before the corresponding [`JxlDecoderStatus::FullImage`] event. The next signaled
+ /// event will be another [`JxlDecoderStatus::Frame`], or [`JxlDecoderStatus::Success`] if there
+ /// are no more frames. If pixel data is required from the already processed part
+ /// of the frame, [`JxlDecoderFlushImage`] must be called before this.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if there is a frame to skip, and
+ /// - [`JxlDecoderStatus::Error`] if the function was not called during frame processing.
pub fn JxlDecoderSkipCurrentFrame(dec: *mut JxlDecoder) -> JxlDecoderStatus;
+ /// Set the parallel runner for multithreading. May only be set before starting
+ /// decoding.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `parallel_runner`: function pointer to runner for multithreading. It may
+ /// be `NULL` to use the default, single-threaded, runner. A multithreaded
+ /// runner should be set to reach fast performance.
+ /// - `parallel_runner_opaque`: opaque pointer for `parallel_runner`.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the runner was set, [`JxlDecoderStatus::Error`]
+ /// otherwise (the previous runner remains set).
pub fn JxlDecoderSetParallelRunner(
dec: *mut JxlDecoder,
parallel_runner: JxlParallelRunner,
parallel_runner_opaque: *mut c_void,
) -> JxlDecoderStatus;
+ /// Returns a hint indicating how many more bytes the decoder is expected to
+ /// need to make [`JxlDecoderGetBasicInfo`] available after the next
+ /// [`JxlDecoderProcessInput`] call. This is a suggested large enough value for
+ /// the amount of bytes to provide in the next [`JxlDecoderSetInput`] call, but
+ /// it is not guaranteed to be an upper bound nor a lower bound. This number does
+ /// not include bytes that have already been released from the input. Can be used
+ /// before the first [`JxlDecoderProcessInput`] call, and is correct the first
+ /// time in most cases. If not, [`JxlDecoderSizeHintBasicInfo`] can be called
+ /// again to get an updated hint.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - the size hint in bytes if the basic info is not yet fully decoded.
+ /// - 0 when the basic info is already available.
pub fn JxlDecoderSizeHintBasicInfo(dec: *const JxlDecoder) -> usize;
+ /// Select for which informative events, i.e. [`JxlDecoderStatus::BasicInfo`], etc., the
+ /// decoder should return with a status. It is not required to subscribe to any
+ /// events, data can still be requested from the decoder as soon as it is available.
+ /// By default, the decoder is subscribed to no events (`events_wanted == 0`), and
+ /// the decoder will then only return when it cannot continue because it needs
+ /// more input data or more output buffer. This function may only be called
+ /// before using [`JxlDecoderProcessInput`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `events_wanted`: bitfield of desired events.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if no error, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSubscribeEvents(
dec: *mut JxlDecoder,
events_wanted: c_int,
) -> JxlDecoderStatus;
+ /// Enables or disables preserving of as-in-bitstream pixeldata
+ /// orientation. Some images are encoded with an Orientation tag
+ /// indicating that the decoder must perform a rotation and/or
+ /// mirroring to the encoded image data.
+ ///
+ /// - If `skip_reorientation` is [`JxlBool::False`] (the default): the decoder
+ /// will apply the transformation from the orientation setting, hence
+ /// rendering the image according to its specified intent. When
+ /// producing a [`JxlBasicInfo`], the decoder will always set the
+ /// orientation field to [`JxlOrientation::Identity`] (matching the returned
+ /// pixel data) and also align xsize and ysize so that they correspond
+ /// to the width and the height of the returned pixel data.
+ /// - If `skip_reorientation` is [`JxlBool::True`]: the decoder will skip
+ /// applying the transformation from the orientation setting, returning
+ /// the image in the as-in-bitstream pixeldata orientation.
+ /// This may be faster to decode since the decoder doesn't have to apply the
+ /// transformation, but can cause wrong display of the image if the
+ /// orientation tag is not correctly taken into account by the user.
+ ///
+ /// By default, this option is disabled, and the returned pixel data is
+ /// re-oriented according to the image's Orientation setting.
+ ///
+ /// This function must be called at the beginning, before decoding is performed.
+ ///
+ /// See [`JxlBasicInfo`] for the orientation field, and [`JxlOrientation`] for the
+ /// possible values.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `skip_reorientation`: [`JxlBool::True`] to enable, [`JxlBool::False`] to disable.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if no error, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetKeepOrientation(
dec: *mut JxlDecoder,
keep_orientation: JxlBool,
) -> JxlDecoderStatus;
+ /// Enables or disables preserving of associated alpha channels. If
+ /// `unpremul_alpha` is set to [`JxlBool::False`] then for associated alpha channel,
+ /// the pixel data is returned with premultiplied colors. If it is set to [`JxlBool::True`],
+ /// the colors will be unpremultiplied based on the alpha channel. This
+ /// function has no effect if the image does not have an associated alpha
+ /// channel.
+ ///
+ /// By default, this option is disabled, and the returned pixel data is "as is".
+ ///
+ /// This function must be called at the beginning, before decoding is performed.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `unpremul_alpha`: [`JxlBool::True`] to enable, [`JxlBool::False`] to disable.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if no error, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetUnpremultiplyAlpha(
dec: *mut JxlDecoder,
unpremul_alpha: JxlBool,
) -> JxlDecoderStatus;
+ /// Enables or disables rendering spot colors. By default, spot colors
+ /// are rendered, which is OK for viewing the decoded image. If `render_spotcolors`
+ /// is [`JxlBool::False`], then spot colors are not rendered, and have to be
+ /// retrieved separately using [`JxlDecoderSetExtraChannelBuffer`]. This is
+ /// useful for e.g. printing applications.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `render_spotcolors`: [`JxlBool::True`] to enable (default), [`JxlBool::False`] to disable.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if no error, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetRenderSpotcolors(
dec: *mut JxlDecoder,
render_spotcolors: JxlBool,
) -> JxlDecoderStatus;
+ /// Enables or disables coalescing of zero-duration frames. By default, frames
+ /// are returned with coalescing enabled, i.e. all frames have the image
+ /// dimensions, and are blended if needed. When coalescing is disabled, frames
+ /// can have arbitrary dimensions, a non-zero crop offset, and blending is not
+ /// performed. For display, coalescing is recommended. For loading a multi-layer
+ /// still image as separate layers (as opposed to the merged image), coalescing
+ /// has to be disabled.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `coalescing`: [`JxlBool::True`] to enable coalescing (default), [`JxlBool::False`] to
+ /// disable it.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if no error, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetCoalescing(dec: *mut JxlDecoder, coalescing: JxlBool) -> JxlDecoderStatus;
+ /// Decodes JPEG XL file using the available bytes. Requires input has been
+ /// set with [`JxlDecoderSetInput`]. After [`JxlDecoderProcessInput`], input
+ /// can optionally be released with [`JxlDecoderReleaseInput`] and then set
+ /// again to next bytes in the stream. [`JxlDecoderReleaseInput`] returns how
+ /// many bytes are not yet processed, before a next call to [`JxlDecoderProcessInput`]
+ /// all unprocessed bytes must be provided again (the address need not match, but the contents must),
+ /// and more bytes may be concatenated after the unprocessed bytes.
+ ///
+ /// The returned status indicates whether the decoder needs more input bytes, or
+ /// more output buffer for a certain type of output data. No matter what the
+ /// returned status is (other than [`JxlDecoderStatus::Error`]), new information,
+ /// such as [`JxlDecoderGetBasicInfo`], may have become available after this call.
+ /// When the return value is not [`JxlDecoderStatus::Error`] or [`JxlDecoderStatus::Success`], the
+ /// decoding requires more [`JxlDecoderProcessInput`] calls to continue.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] when decoding finished and all events handled.
+ /// If you still have more unprocessed input data anyway, then you can still
+ /// continue by using [`JxlDecoderSetInput`] and calling [`JxlDecoderProcessInput`] again,
+ /// similar to handling [`JxlDecoderStatus::NeedMoreInput`]. [`JxlDecoderStatus::Success`] can occur instead of
+ /// [`JxlDecoderStatus::NeedMoreInput`] when, for example, the input data ended right at
+ /// the boundary of a box of the container format, all essential codestream
+ /// boxes were already decoded, but extra metadata boxes are still present in
+ /// the next data. [`JxlDecoderProcessInput`] cannot return success if all
+ /// codestream boxes have not been seen yet.
+ /// - [`JxlDecoderStatus::Error`] when decoding failed, e.g. invalid codestream.
+ /// - [`JxlDecoderStatus::NeedMoreInput`] when more input data is necessary.
+ /// - [`JxlDecoderStatus::BasicInfo`] when basic info such as image dimensions is
+ /// available and this informative event is subscribed to.
+ /// - [`JxlDecoderStatus::ColorEncoding`] when color profile information is
+ /// available and this informative event is subscribed to.
+ /// - [`JxlDecoderStatus::PreviewImage`] when preview pixel information is
+ /// available and output in the preview buffer.
+ /// - [`JxlDecoderStatus::FullImage`] when all pixel information at highest detail
+ /// is available and has been output in the pixel buffer.
pub fn JxlDecoderProcessInput(dec: *mut JxlDecoder) -> JxlDecoderStatus;
+ /// Sets input data for [`JxlDecoderProcessInput`]. The data is owned by the
+ /// caller and may be used by the decoder until [`JxlDecoderReleaseInput`] is
+ /// called or the decoder is destroyed or reset, so it must be kept alive until then.
+ /// Cannot be called if [`JxlDecoderSetInput`] was already called and [`JxlDecoderReleaseInput`]
+ /// was not yet called, and cannot be called after [`JxlDecoderCloseInput`] indicating the end
+ /// of input was called.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `data`: pointer to next bytes to read from
+ /// - `size`: amount of bytes available starting from data
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if input was already set without releasing or [`JxlDecoderCloseInput`]
+ /// was already called
+ /// - [`JxlDecoderStatus::Success`] otherwise
pub fn JxlDecoderSetInput(
dec: *mut JxlDecoder,
data: *const u8,
size: usize,
) -> JxlDecoderStatus;
+ /// Releases input which was provided with [`JxlDecoderSetInput`]. Between
+ /// [`JxlDecoderProcessInput`] and [`JxlDecoderReleaseInput`], the user may not
+ /// alter the data in the buffer. Calling [`JxlDecoderReleaseInput`] is required
+ /// whenever any input is already set and new input needs to be added with
+ /// [`JxlDecoderSetInput`], but is not required before [`JxlDecoderDestroy`] or
+ /// [`JxlDecoderReset`]. Calling [`JxlDecoderReleaseInput`] when no input is set
+ /// is not an error and returns `0`.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// The amount of bytes the decoder has not yet processed that are still
+ /// remaining in the data set by [`JxlDecoderSetInput`], or `0` if no input is
+ /// set or [`JxlDecoderReleaseInput`] was already called. For a next call to
+ /// [`JxlDecoderProcessInput`], the buffer must start with these unprocessed
+ /// bytes. From this value it is possible to infer the position of certain JPEG
+ /// XL codestream elements (e.g. end of headers, frame start/end). See the
+ /// documentation of individual values of [`JxlDecoderStatus`] for more
+ /// information.
pub fn JxlDecoderReleaseInput(dec: *mut JxlDecoder) -> usize;
+ /// Marks the input as finished, indicates that no more [`JxlDecoderSetInput`]
+ /// will be called. This function allows the decoder to determine correctly if it
+ /// should return success, need more input or error in certain cases. For
+ /// backwards compatibility with a previous version of the API, using this
+ /// function is optional when not using the [`JxlDecoderStatus::Box`] event (the decoder
+ /// is able to determine the end of the image frames without marking the end),
+ /// but using this function is required when using [`JxlDecoderStatus::Box`] for getting
+ /// metadata box contents. This function does not replace [`JxlDecoderReleaseInput`],
+ /// that function should still be called if its return value is needed.
+ ///
+ /// [`JxlDecoderCloseInput`] should be called as soon as all known input bytes
+ /// are set (e.g. at the beginning when not streaming but setting all input
+ /// at once), before the final [`JxlDecoderProcessInput`] calls.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
pub fn JxlDecoderCloseInput(dec: *mut JxlDecoder);
+ /// Outputs the basic image information, such as image dimensions, bit depth and
+ /// all other [`JxlBasicInfo`] fields, if available.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `info`: struct to copy the information into, or `NULL` to only check
+ /// whether the information is available through the return value.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case of other error conditions.
pub fn JxlDecoderGetBasicInfo(
dec: *const JxlDecoder,
info: *mut JxlBasicInfo,
) -> JxlDecoderStatus;
+ /// Outputs information for extra channel at the given index. The index must be
+ /// smaller than `num_extra_channels` in the associated [`JxlBasicInfo`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `index`: index of the extra channel to query.
+ /// - `info`: struct to copy the information into, or `NULL` to only check
+ /// whether the information is available through the return value.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case of other error conditions.
pub fn JxlDecoderGetExtraChannelInfo(
dec: *const JxlDecoder,
index: usize,
info: *mut JxlExtraChannelInfo,
) -> JxlDecoderStatus;
+ /// Outputs name for extra channel at the given index in UTF-8. The index must be
+ /// smaller than `num_extra_channels` in the associated [`JxlBasicInfo`]. The
+ /// buffer for name must have at least `name_length + 1` bytes allocated, gotten
+ /// from the associated [`JxlExtraChannelInfo`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `index`: index of the extra channel to query.
+ /// - `name`: buffer to copy the name into
+ /// - `size`: size of the name buffer in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case of other error conditions.
pub fn JxlDecoderGetExtraChannelName(
dec: *const JxlDecoder,
index: usize,
@@ -179,18 +781,106 @@ extern "C" {
size: usize,
) -> JxlDecoderStatus;
+ /// Outputs the color profile as JPEG XL encoded structured data, if available.
+ /// This is an alternative to an ICC Profile, which can represent a more limited
+ /// amount of color spaces, but represents them exactly through enum values.
+ ///
+ /// It is often possible to use [`JxlDecoderGetColorAsICCProfile`] as an
+ /// alternative anyway. The following scenarios are possible:
+ /// - The JPEG XL image has an attached ICC Profile, in that case, the encoded
+ /// structured data is not available and this function will return an error
+ /// status. [`JxlDecoderGetColorAsICCProfile`] should be called instead.
+ /// - The JPEG XL image has an encoded structured color profile, and it
+ /// represents an RGB or grayscale color space. This function will return it.
+ /// You can still use [`JxlDecoderGetColorAsICCProfile`] as well as an
+ /// alternative if desired, though depending on which RGB color space is
+ /// represented, the ICC profile may be a close approximation. It is also not
+ /// always feasible to deduce from an ICC profile which named color space it
+ /// exactly represents, if any, as it can represent any arbitrary space.
+ /// HDR color spaces such as those using PQ and HLG are also potentially
+ /// problematic, in that: while ICC profiles can encode a transfer function
+ /// that happens to approximate those of PQ and HLG (HLG for only one given
+ /// system gamma at a time, and necessitating a 3D LUT if gamma is to be
+ /// different from `1`), they cannot (before ICCv4.4) semantically signal that
+ /// this is the color space that they represent. Therefore, they will
+ /// typically not actually be interpreted as representing an HDR color space.
+ /// This is especially detrimental to PQ which will then be interpreted as if
+ /// the maximum signal value represented SDR white instead of 10000 cd/m^2,
+ /// meaning that the image will be displayed two orders of magnitude (5-7 EV)
+ /// too dim.
+ /// - The JPEG XL image has an encoded structured color profile, and it
+ /// indicates an unknown or xyb color space. In that case, [`JxlDecoderGetColorAsICCProfile`]
+ /// is not available.
+ ///
+ /// When rendering an image on a system where ICC-based color management is used,
+ /// [`JxlDecoderGetColorAsICCProfile`] should generally be used first as it will
+ /// return a ready-to-use profile (with the aforementioned caveat about HDR).
+ /// When knowledge about the nominal color space is desired if available, [`JxlDecoderGetColorAsEncodedProfile`]
+ /// should be used first.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `target`: whether to get the original color profile from the metadata
+ /// or the color profile of the decoded pixels.
+ /// - `color_encoding`: struct to copy the information into, or `NULL` to only
+ /// check whether the information is available through the return value.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the data is available and returned
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case the encoded structured color profile does not exist in the
+ /// codestream.
pub fn JxlDecoderGetColorAsEncodedProfile(
dec: *const JxlDecoder,
target: JxlColorProfileTarget,
color_encoding: *mut JxlColorEncoding,
) -> JxlDecoderStatus;
+ /// Outputs the size in bytes of the ICC profile returned by [`JxlDecoderGetColorAsICCProfile`], if available,
+ /// or indicates there is none available. In most cases, the image will have an ICC profile available, but
+ /// if it does not, [`JxlDecoderGetColorAsEncodedProfile`] must be used instead.
+ ///
+ /// See [`JxlDecoderGetColorAsEncodedProfile`] for more information. The ICC
+ /// profile is either the exact ICC profile attached to the codestream metadata,
+ /// or a close approximation generated from JPEG XL encoded structured data,
+ /// depending on what is encoded in the codestream.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `target`: whether to get the original color profile from the metadata
+ /// or the color profile of the decoded pixels.
+ /// - `size`: variable to output the size into, or `NULL` to only check the
+ /// return status.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the ICC profile is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if the decoder has not yet received enough
+ /// input data to determine whether an ICC profile is available or what its
+ /// size is
+ /// - [`JxlDecoderStatus::Error`] in case the ICC profile is not available and
+ /// cannot be generated.
pub fn JxlDecoderGetICCProfileSize(
dec: *const JxlDecoder,
target: JxlColorProfileTarget,
size: *mut usize,
) -> JxlDecoderStatus;
+ /// Outputs ICC profile if available. The profile is only available if
+ /// [`JxlDecoderGetICCProfileSize`] returns success. The output buffer must have
+ /// at least as many bytes as given by [`JxlDecoderGetICCProfileSize`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `target`: whether to get the original color profile from the metadata
+ /// or the color profile of the decoded pixels.
+ /// - `icc_profile`: buffer to copy the ICC profile into
+ /// - `size`: size of the `icc_profile` buffer in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`]: if the profile was successfully returned
+ /// - [`JxlDecoderStatus::NeedMoreInput`]: if not yet available
+ /// - [`JxlDecoderStatus::Error`]: if the profile doesn't exist or the output size is not
+ /// large enough.
pub fn JxlDecoderGetColorAsICCProfile(
dec: *const JxlDecoder,
target: JxlColorProfileTarget,
@@ -198,16 +888,83 @@ extern "C" {
size: usize,
) -> JxlDecoderStatus;
+ /// Sets the desired output color profile of the decoded image by calling
+ /// [`JxlDecoderSetOutputColorProfile`], passing on `color_encoding` and
+ /// setting `icc_data` to `NULL`. See [`JxlDecoderSetOutputColorProfile`] for
+ /// details.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `color_encoding`: the default color encoding to set
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the preference was set successfully, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetPreferredColorProfile(
dec: *mut JxlDecoder,
color_encoding: *const JxlColorEncoding,
) -> JxlDecoderStatus;
+ /// Requests that the decoder perform tone mapping to the peak display luminance
+ /// passed as `desired_intensity_target`, if appropriate.
+ ///
+ /// # Note
+ /// This is provided for convenience and the exact tone mapping that is
+ /// performed is not meant to be considered authoritative in any way. It may
+ /// change from version to version.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `desired_intensity_target`: the intended target peak luminance
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the preference was set successfully, [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetDesiredIntensityTarget(
dec: *mut JxlDecoder,
desired_intensity_target: f32,
) -> JxlDecoderStatus;
+ /// Sets the desired output color profile of the decoded image either from a
+ /// color encoding or an ICC profile. Valid calls of this function have either
+ /// `color_encoding` or `icc_data` set to `NULL` and `icc_size` must be `0` if and
+ /// only if `icc_data` is `NULL`.
+ ///
+ /// Depending on whether a color management system (CMS) has been set the
+ /// behavior is as follows:
+ ///
+ /// If a color management system (CMS) has been set with [`JxlDecoderSetCms`],
+ /// and the CMS supports output to the desired color encoding or ICC profile,
+ /// then it will provide the output in that color encoding or ICC profile. If the
+ /// desired color encoding or the ICC is not supported, then an error will be
+ /// returned.
+ ///
+ /// If no CMS has been set with [`JxlDecoderSetCms`], there are two cases:
+ ///
+ /// 1. Calling this function with a color encoding will convert XYB images to
+ /// the desired color encoding. In this case, if the requested color encoding has
+ /// a narrower gamut, or the white points differ, then the resulting image can
+ /// have significant color distortion. Non-XYB images will not be converted to
+ /// the desired color space.
+ ///
+ /// 2. Calling this function with an ICC profile will result in an error.
+ ///
+ /// If called with an ICC profile (after a call to [`JxlDecoderSetCms`]), the
+ /// ICC profile has to be a valid RGB or grayscale color profile.
+ ///
+ /// Can only be set after the [`JxlDecoderStatus::ColorEncoding`] event occurred and
+ /// before any other event occurred, and should be used before getting
+ /// [`JxlColorProfileTarget::Data`].
+ ///
+ /// This function must not be called before [`JxlDecoderSetCms`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `color_encoding`: the output color encoding
+ /// - `icc_data`: bytes of the icc profile
+ /// - `icc_size`: size of the icc profile in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the color profile was set successfully,
+ /// [`JxlDecoderStatus::Error`] otherwise.
pub fn JxlDecoderSetOutputColorProfile(
dec: *mut JxlDecoder,
color_encoding: *const JxlColorEncoding,
@@ -215,14 +972,51 @@ extern "C" {
icc_size: usize,
) -> JxlDecoderStatus;
+ /// Sets the color management system (CMS) that will be used for color
+ /// conversion (if applicable) during decoding. May only be set before starting
+ /// decoding and must not be called after [`JxlDecoderSetOutputColorProfile`].
+ ///
+ /// See [`JxlDecoderSetOutputColorProfile`] for how color conversions are done
+ /// depending on whether or not a CMS has been set with [`JxlDecoderSetCms`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object.
+ /// - `cms`: structure representing a CMS implementation. See [`JxlCmsInterface`] for more details.
pub fn JxlDecoderSetCms(dec: *mut JxlDecoder, cms: JxlCmsInterface) -> JxlDecoderStatus;
+ /// Returns the minimum size in bytes of the preview image output pixel buffer
+ /// for the given format. This is the buffer for [`JxlDecoderSetPreviewOutBuffer`].
+ /// Requires the preview header information is available in the decoder.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of pixels
+ /// - `size`: output value, buffer size in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success
+ /// - [`JxlDecoderStatus::Error`] on error, such as information not available yet.
pub fn JxlDecoderPreviewOutBufferSize(
dec: *const JxlDecoder,
format: *const JxlPixelFormat,
size: *mut usize,
) -> JxlDecoderStatus;
+ /// Sets the buffer to write the low-resolution preview image
+ /// to. The size of the buffer must be at least as large as given by [`JxlDecoderPreviewOutBufferSize`].
+ /// The buffer follows the format described by [`JxlPixelFormat`]. The preview image dimensions are given by the
+ /// [`JxlPreviewHeader`]. The buffer is owned by the caller.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of pixels. Object owned by user and its contents are
+ /// copied internally.
+ /// - `buffer`: buffer type to output the pixel data to
+ /// - `size`: size of buffer in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// size too small.
pub fn JxlDecoderSetPreviewOutBuffer(
dec: *mut JxlDecoder,
format: *const JxlPixelFormat,
@@ -230,29 +1024,102 @@ extern "C" {
size: usize,
) -> JxlDecoderStatus;
+ /// Outputs the information from the frame, such as duration when `have_animation`.
+ /// This function can be called when [`JxlDecoderStatus::Frame`] occurred for the current
+ /// frame, even when `have_animation` in the [`JxlBasicInfo`] is [`JxlBool::False`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `header`: struct to copy the information into, or `NULL` to only check
+ /// whether the information is available through the return value.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case of other error conditions.
pub fn JxlDecoderGetFrameHeader(
dec: *const JxlDecoder,
header: *mut JxlFrameHeader,
) -> JxlDecoderStatus;
+ /// Outputs name for the current frame. The buffer for name must have at least
+ /// `name_length + 1` bytes allocated, gotten from the associated [`JxlFrameHeader`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `name`: buffer to copy the name into
+ /// - `size`: size of the name buffer in bytes, including zero termination
+ /// character, so this must be at least [`JxlFrameHeader::name_length`] + 1.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::NeedMoreInput`] if not yet available
+ /// - [`JxlDecoderStatus::Error`] in case of other error conditions.
pub fn JxlDecoderGetFrameName(
dec: *const JxlDecoder,
name: *mut c_char,
size: usize,
) -> JxlDecoderStatus;
+ /// Outputs the blend information for the current frame for a specific extra
+ /// channel. This function can be called once the [`JxlDecoderStatus::Frame`] event occurred
+ /// for the current frame, even if the `have_animation` field in the [`JxlBasicInfo`] is [`JxlBool::False`].
+ /// This information is only useful if coalescing is disabled; otherwise the decoder will have performed
+ /// blending already.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `index`: the index of the extra channel
+ /// - `blend_info`: struct to copy the information into
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success
+ /// - [`JxlDecoderStatus::Error`] on error
pub fn JxlDecoderGetExtraChannelBlendInfo(
dec: *const JxlDecoder,
index: usize,
blend_info: *mut JxlBlendInfo,
);
+ /// Returns the minimum size in bytes of the image output pixel buffer for the
+ /// given format. This is the buffer for [`JxlDecoderSetImageOutBuffer`].
+ /// Requires that the basic image information is available in the decoder in the
+ /// case of coalescing enabled (default). In case coalescing is disabled, this
+ /// can only be called after the [`JxlDecoderStatus::Frame`] event occurs. In that case,
+ /// it will return the size required to store the possibly cropped frame (which
+ /// can be larger or smaller than the image dimensions).
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels.
+ /// - `size`: output value, buffer size in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// information not available yet.
pub fn JxlDecoderImageOutBufferSize(
dec: *const JxlDecoder,
format: *const JxlPixelFormat,
size: *mut usize,
) -> JxlDecoderStatus;
+ /// Sets the buffer to write the full resolution image to. This can be set when
+ /// the [`JxlDecoderStatus::Frame`] event occurs, must be set when the
+ /// [`JxlDecoderStatus::NeedImageOutBuffer`] event occurs, and applies only for the
+ /// current frame. The size of the buffer must be at least as large as given
+ /// by [`JxlDecoderImageOutBufferSize`]. The buffer follows the format described
+ /// by [`JxlPixelFormat`]. The buffer is owned by the caller.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels. Object owned by user and its contents
+ /// are copied internally.
+ /// - `buffer`: buffer type to output the pixel data to
+ /// - `size`: size of buffer in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// size too small.
pub fn JxlDecoderSetImageOutBuffer(
dec: *mut JxlDecoder,
format: *const JxlPixelFormat,
@@ -260,6 +1127,48 @@ extern "C" {
size: usize,
) -> JxlDecoderStatus;
+ /// Sets pixel output callback. This is an alternative to [`JxlDecoderSetImageOutBuffer`].
+ /// This can be set when the [`JxlDecoderStatus::Frame`] event occurs, must be set when the
+ /// [`JxlDecoderStatus::NeedImageOutBuffer`] event occurs, and applies only for the current frame.
+ /// Only one of [`JxlDecoderSetImageOutBuffer`] or [`JxlDecoderSetImageOutCallback`] may be used
+ /// for the same frame, not both at the same time.
+ ///
+ /// The callback will be called multiple times, to receive the image
+ /// data in small chunks. The callback receives a horizontal stripe of pixel
+ /// data, `1` pixel high, xsize pixels wide, called a scanline. The xsize here is
+ /// not the same as the full image width, the scanline may be a partial section,
+ /// and xsize may differ between calls. The user can then process and/or copy the
+ /// partial scanline to an image buffer. The callback may be called
+ /// simultaneously by different threads when using a threaded parallel runner, on
+ /// different pixels.
+ ///
+ /// If [`JxlDecoderFlushImage`] is not used, then each pixel will be visited
+ /// exactly once by the different callback calls, during processing with one or
+ /// more [`JxlDecoderProcessInput`] calls. These pixels are decoded to full
+ /// detail, they are not part of a lower resolution or lower quality progressive
+ /// pass, but the final pass.
+ ///
+ /// If [`JxlDecoderFlushImage`] is used, then in addition each pixel will be
+ /// visited zero or one times during the blocking [`JxlDecoderFlushImage`] call.
+ /// Pixels visited as a result of [`JxlDecoderFlushImage`] may represent a lower
+ /// resolution or lower quality intermediate progressive pass of the image. Any
+ /// visited pixel will be of a quality at least as good or better than previous
+ /// visits of this pixel. A pixel may be visited zero times if it cannot be
+ /// decoded yet or if it was already decoded to full precision (this behavior is
+ /// not guaranteed).
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels. Object owned by user; its contents are
+ /// copied internally.
+ /// - `callback`: the callback function receiving partial scanlines of pixel
+ /// data.
+ /// - `opaque`: optional user data, which will be passed on to the callback,
+ /// may be `NULL`.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such
+ /// as [`JxlDecoderSetImageOutBuffer`] already set.
pub fn JxlDecoderSetImageOutCallback(
dec: *mut JxlDecoder,
format: *const JxlPixelFormat,
@@ -267,6 +1176,27 @@ extern "C" {
opaque: *mut c_void,
) -> JxlDecoderStatus;
+ /// Similar to [`JxlDecoderSetImageOutCallback`] except that the callback is
+ /// allowed an initialization phase during which it is informed of how many
+ /// threads will call it concurrently, and those calls are further informed of
+ /// which thread they are occurring in.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels. Object owned by user; its contents are
+ /// copied internally.
+ /// - `init_callback`: initialization callback.
+ /// - `run_callback`: the callback function receiving partial scanlines of
+ /// pixel data.
+ /// - `destroy_callback`: clean-up callback invoked after all calls to `run_callback`.
+ /// May be `NULL` if no clean-up is necessary.
+ /// - `init_opaque`: optional user data passed to `init_callback`, may be `NULL`
+ /// (unlike the return value from `init_callback` which may only be `NULL` if
+ /// initialization failed).
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such
+ /// as [`JxlDecoderSetImageOutBuffer`] having already been called.
pub fn JxlDecoderSetMultithreadedImageOutCallback(
dec: *mut JxlDecoder,
format: *const JxlPixelFormat,
@@ -276,6 +1206,21 @@ extern "C" {
init_opaque: *mut c_void,
) -> JxlDecoderStatus;
+ /// Returns the minimum size in bytes of an extra channel pixel buffer for the
+ /// given format. This is the buffer for [`JxlDecoderSetExtraChannelBuffer`].
+ /// Requires the basic image information is available in the decoder.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels. The `num_channels` value is ignored and is
+ /// always treated to be `1`.
+ /// - `size`: output value, buffer size in bytes
+ /// - `index`: which extra channel to get, matching the index used in [`JxlDecoderGetExtraChannelInfo`].
+ /// Must be smaller than `num_extra_channels` in the associated [`JxlBasicInfo`].
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success
+ /// - [`JxlDecoderStatus::Error`] on error, such as information not available yet or invalid index.
pub fn JxlDecoderExtraChannelBufferSize(
dec: *const JxlDecoder,
format: *const JxlPixelFormat,
@@ -283,6 +1228,33 @@ extern "C" {
index: u32,
) -> JxlDecoderStatus;
+ /// Sets the buffer to write an extra channel to. This can be set when
+ /// the [`JxlDecoderStatus::Frame`] or [`JxlDecoderStatus::NeedImageOutBuffer`] event occurs,
+ /// and applies only for the current frame. The size of the buffer must be at
+ /// least as large as given by [`JxlDecoderExtraChannelBufferSize`]. The buffer
+ /// follows the format described by [`JxlPixelFormat`], but where `num_channels`
+ /// is `1`. The buffer is owned by the caller. The amount of extra channels is
+ /// given by the `num_extra_channels` field in the associated [`JxlBasicInfo`],
+ /// and the information of individual extra channels can be queried with [`JxlDecoderGetExtraChannelInfo`].
+ /// To get multiple extra channels, this function must be called multiple times, once for each wanted index.
+ /// Not all images have extra channels. The alpha channel is an extra channel and can be gotten
+ /// as part of the color channels when using an RGBA pixel buffer with [`JxlDecoderSetImageOutBuffer`],
+ /// but additionally also can be gotten separately as extra channel. The color channels themselves cannot be gotten
+ /// this way.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `format`: format of the pixels. Object owned by user and its contents
+ /// are copied internally. The `num_channels` value is ignored and is always
+ /// treated to be `1`.
+ /// - `buffer`: buffer type to output the pixel data to
+ /// - `size`: size of buffer in bytes
+ /// - `index`: which extra channel to get, matching the index used in [`JxlDecoderGetExtraChannelInfo`].
+ /// Must be smaller than `num_extra_channels` in the associated [`JxlBasicInfo`].
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// size too small or invalid index.
pub fn JxlDecoderSetExtraChannelBuffer(
dec: *mut JxlDecoder,
format: *const JxlPixelFormat,
@@ -291,46 +1263,268 @@ extern "C" {
index: u32,
) -> JxlDecoderStatus;
+ /// Sets output buffer for reconstructed JPEG codestream.
+ ///
+ /// The data is owned by the caller and may be used by the decoder until [`JxlDecoderReleaseJPEGBuffer`]
+ /// is called or the decoder is destroyed or reset so must be kept alive until then.
+ ///
+ /// If a JPEG buffer was set before and released with [`JxlDecoderReleaseJPEGBuffer`],
+ /// bytes that the decoder has already output should not be included,
+ /// only the remaining bytes output must be set.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `data`: pointer to next bytes to write to
+ /// - `size`: amount of bytes available starting from data
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if output buffer was already set and [`JxlDecoderReleaseJPEGBuffer`]
+ /// was not called on it, [`JxlDecoderStatus::Success`] otherwise
pub fn JxlDecoderSetJPEGBuffer(
dec: *mut JxlDecoder,
data: *mut u8,
size: usize,
) -> JxlDecoderStatus;
+ /// Releases buffer which was provided with [`JxlDecoderSetJPEGBuffer`].
+ ///
+ /// Calling [`JxlDecoderReleaseJPEGBuffer`] is required whenever
+ /// a buffer is already set and a new buffer needs to be added with [`JxlDecoderSetJPEGBuffer`],
+ /// but is not required before [`JxlDecoderDestroy`] or [`JxlDecoderReset`].
+ ///
+ /// Calling [`JxlDecoderReleaseJPEGBuffer`] when no buffer is set is
+ /// not an error and returns `0`.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - The amount of bytes the decoder has not yet written to of the data
+ /// set by [`JxlDecoderSetJPEGBuffer`], or `0` if no buffer is set or
+ /// [`JxlDecoderReleaseJPEGBuffer`] was already called.
pub fn JxlDecoderReleaseJPEGBuffer(dec: *mut JxlDecoder) -> usize;
+ /// Sets output buffer for box output codestream.
+ ///
+ /// The data is owned by the caller and may be used by the decoder until [`JxlDecoderReleaseBoxBuffer`]
+ /// is called or the decoder is destroyed or reset so must be kept alive until then.
+ ///
+ /// If for the current box a box buffer was set before and released with [`JxlDecoderReleaseBoxBuffer`],
+ /// bytes that the decoder has already output should not be included, only the remaining bytes output must be set.
+ ///
+ /// The [`JxlDecoderReleaseBoxBuffer`] must be used at the next [`JxlDecoderStatus::Box`] event or final
+ /// [`JxlDecoderStatus::Success`] event to compute the size of the output box bytes.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `data`: pointer to next bytes to write to
+ /// - `size`: amount of bytes available starting from data
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if output buffer was already set and [`JxlDecoderReleaseBoxBuffer`]
+ /// was not called on it, [`JxlDecoderStatus::Success`] otherwise
pub fn JxlDecoderSetBoxBuffer(
dec: *mut JxlDecoder,
data: *mut u8,
size: usize,
) -> JxlDecoderStatus;
+ /// Releases buffer which was provided with [`JxlDecoderSetBoxBuffer`].
+ ///
+ /// Calling [`JxlDecoderReleaseBoxBuffer`] is required whenever a buffer is already set and
+ /// a new buffer needs to be added with [`JxlDecoderSetBoxBuffer`], but is not required before
+ /// [`JxlDecoderDestroy`] or [`JxlDecoderReset`].
+ ///
+ /// Calling [`JxlDecoderReleaseBoxBuffer`] when no buffer is set is not an error and returns `0`.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - The amount of bytes the decoder has not yet written to of the data set by [`JxlDecoderSetBoxBuffer`],
+ /// or `0` if no buffer is set or [`JxlDecoderReleaseBoxBuffer`] was already called.,
pub fn JxlDecoderReleaseBoxBuffer(dec: *mut JxlDecoder) -> usize;
+ /// Configures whether to get boxes in raw mode or in decompressed mode. In raw
+ /// mode, boxes are output as their bytes appear in the container file, which may
+ /// be decompressed, or compressed if their type is "brob". In decompressed mode,
+ /// "brob" boxes are decompressed with Brotli before outputting them. The size of
+ /// the decompressed stream is not known before the decompression has already
+ /// finished.
+ ///
+ /// The default mode is raw. This setting can only be changed before decoding, or
+ /// directly after a [`JxlDecoderStatus::Box`] event, and is remembered until the decoder
+ /// is reset or destroyed.
+ ///
+ /// Enabling decompressed mode requires Brotli support from the library.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `decompress`: [`JxlBool::True`] to transparently decompress, [`JxlBool::False`]
+ /// to get boxes in raw mode.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if decompressed mode is set and Brotli is not
+ /// available, [`JxlDecoderStatus::Success`] otherwise.
pub fn JxlDecoderSetDecompressBoxes(
dec: *mut JxlDecoder,
decompress: JxlBool,
) -> JxlDecoderStatus;
+ /// Outputs the type of the current box, after a [`JxlDecoderStatus::Box`] event occurred,
+ /// as `4` characters without null termination character. In case of a compressed
+ /// "brob" box, this will return "brob" if the decompressed argument is
+ /// [`JxlBool::False`], or the underlying box type if the decompressed argument is
+ /// [`JxlBool::True`].
+ ///
+ /// The following box types are currently described in ISO/IEC 18181-2:
+ /// - "Exif": a box with EXIF metadata. Starts with a 4-byte tiff header offset
+ /// (big-endian `uint32`) that indicates the start of the actual EXIF data
+ /// (which starts with a tiff header). Usually the offset will be zero and the
+ /// EXIF data starts immediately after the offset field. The Exif orientation
+ /// should be ignored by applications; the JPEG XL codestream orientation
+ /// takes precedence and libjxl will by default apply the correct orientation
+ /// automatically (see [`JxlDecoderSetKeepOrientation`]).
+ /// - "xml ": a box with XML data, in particular XMP metadata.
+ /// - "jumb": a JUMBF superbox (JPEG Universal Metadata Box Format, ISO/IEC
+ /// 19566-5).
+ /// - "JXL ": mandatory signature box, must come first, `12` bytes long
+ /// including the box header
+ /// - "ftyp": a second mandatory signature box, must come second, `20` bytes
+ /// long including the box header
+ /// - "jxll": a JXL level box. This indicates if the codestream is level `5` or
+ /// level `10` compatible. If not present, it is level `5`. Level `10` allows
+ /// more features such as very high image resolution and bit-depths above `16`
+ /// bits per channel. Added automatically by the encoder when
+ /// [`crate::encoder::encode::JxlEncoderSetCodestreamLevel`] is used
+ /// - "jxlc": a box with the image codestream, in case the codestream is not
+ /// split across multiple boxes. The codestream contains the JPEG XL image
+ /// itself, including the basic info such as image dimensions, ICC color
+ /// profile, and all the pixel data of all the image frames.
+ /// - "jxlp": a codestream box in case it is split across multiple boxes.
+ /// The contents are the same as in case of a jxlc box, when concatenated.
+ /// - "brob": a Brotli-compressed box, which otherwise represents an existing
+ /// type of box such as Exif or "xml ". When [`JxlDecoderSetDecompressBoxes`]
+ /// is set to [`JxlBool::True`], these boxes will be transparently decompressed by the
+ /// decoder.
+ /// - "jxli": frame index box, can list the keyframes in case of a JPEG XL
+ /// animation allowing the decoder to jump to individual frames more
+ /// efficiently.
+ /// - "jbrd": JPEG reconstruction box, contains the information required to
+ /// byte-for-byte losslessly reconstruct a JPEG-1 image. The JPEG DCT
+ /// coefficients (pixel content) themselves as well as the ICC profile are
+ /// encoded in the JXL codestream (jxlc or jxlp) itself. EXIF, XMP and JUMBF
+ /// metadata is encoded in the corresponding boxes. The jbrd box itself
+ /// contains information such as the remaining app markers of the JPEG-1 file
+ /// and everything else required to fit the information together into the
+ /// exact original JPEG file.
+ ///
+ /// Other application-specific boxes can exist. Their typename should not begin
+ /// with "jxl" or "JXL" or conflict with other existing typenames.
+ ///
+ /// The signature, jxl* and jbrd boxes are processed by the decoder and would
+ /// typically be ignored by applications. The typical way to use this function is
+ /// to check if an encountered box contains metadata that the application is
+ /// interested in (e.g. EXIF or XMP metadata), in order to conditionally set a
+ /// box buffer.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `type`: buffer to copy the type into
+ /// - `decompressed`: which box type to get: [`JxlBool::False`] to get the raw box type,
+ /// which can be `"brob"`, [`JxlBool::True`] to get the underlying box type.
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if the value is available
+ /// - [`JxlDecoderStatus::Error`] if not, for example the JPEG XL file does not use the container format.
pub fn JxlDecoderGetBoxType(
dec: *mut JxlDecoder,
box_type: &mut JxlBoxType,
decompressed: JxlBool,
) -> JxlDecoderStatus;
+ /// Returns the size of a box as it appears in the container file, after the
+ /// [`JxlDecoderStatus::Box`] event. This includes all the box headers.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `size`: raw size of the box in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if no box size is available, [`JxlDecoderStatus::Success`] otherwise.
pub fn JxlDecoderGetBoxSizeRaw(dec: *mut JxlDecoder, size: *mut u64) -> JxlDecoderStatus;
+ /// Returns the size of the contents of a box, after the [`JxlDecoderStatus::Box`] event.
+ /// This does not include any of the headers of the box. For compressed "brob" boxes,
+ /// this is the size of the compressed content. Even when [`JxlDecoderSetDecompressBoxes`] is enabled,
+ /// the return value of function does not change, and the decompressed size is not known before it
+ /// has already been decompressed and output.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `size`: size of the payload of the box in bytes
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Error`] if no box size is available, [`JxlDecoderStatus::Success`]
+ /// otherwise.
pub fn JxlDecoderGetBoxSizeContents(dec: *mut JxlDecoder, size: *mut u64) -> JxlDecoderStatus;
+ /// Configures at which progressive steps in frame decoding the [`JxlDecoderStatus::FrameProgression`] event occurs.
+ /// The default value for the level of detail if this function is never called is [`JxlProgressiveDetail::DC`].
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `detail`: at which level of detail to trigger [`JxlDecoderStatus::FrameProgression`]
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// an invalid value for the progressive detail.
pub fn JxlDecoderSetProgressiveDetail(
dec: *mut JxlDecoder,
detail: JxlProgressiveDetail,
) -> JxlDecoderStatus;
+ /// Returns the intended downsampling ratio for the progressive frame produced
+ /// by [`JxlDecoderFlushImage`] after the latest [`JxlDecoderStatus::FrameProgression`] event.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// The intended downsampling ratio, can be `1`, `2`, `4` or `8`.
pub fn JxlDecoderGetIntendedDownsamplingRatio(dec: *const JxlDecoder) -> usize;
+ /// Outputs progressive step towards the decoded image so far when only partial
+ /// input was received. If the flush was successful, the buffer set with [`JxlDecoderSetImageOutBuffer`]
+ /// will contain partial image data.
+ ///
+ /// Can be called when [`JxlDecoderProcessInput`] returns [`JxlDecoderStatus::NeedMoreInput`], after the
+ /// [`JxlDecoderStatus::Frame`] event already occurred and before the [`JxlDecoderStatus::FullImage`] event
+ /// occurred for a frame.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] if image data was flushed to the output buffer,
+ /// - [`JxlDecoderStatus::Error`] when no flush was done, e.g., if not enough image data was available yet
+ /// even for flush, or no output buffer was set yet. This error is not fatal, it only indicates no flushed
+ /// image is available right now. Regular decoding can still be performed.
pub fn JxlDecoderFlushImage(dec: *mut JxlDecoder) -> JxlDecoderStatus;
+ /// Sets the bit depth of the output buffer or callback.
+ ///
+ /// Can be called after [`JxlDecoderSetImageOutBuffer`] or
+ /// [`JxlDecoderSetImageOutCallback`]. For float pixel data types, only the default
+ /// [`JxlBitDepthType::FromPixelFormat`] setting is supported.
+ ///
+ /// # Parameters
+ /// - `dec`: decoder object
+ /// - `bit_depth`: the bit depth setting of the pixel output
+ ///
+ /// # Returns
+ /// - [`JxlDecoderStatus::Success`] on success, [`JxlDecoderStatus::Error`] on error, such as
+ /// incompatible custom bit depth and pixel data type.
pub fn JxlDecoderSetImageOutBitDepth(
dec: *mut JxlDecoder,
bit_depth: *const JxlBitDepth,
diff --git a/jpegxl-sys/src/encode.rs b/jpegxl-sys/src/encode.rs
deleted file mode 100644
index 76415ee..0000000
--- a/jpegxl-sys/src/encode.rs
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
-This file is part of jpegxl-sys.
-
-jpegxl-sys is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-jpegxl-sys is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with jpegxl-sys. If not, see .
-*/
-
-use std::ffi::{c_char, c_void};
-
-use crate::{
- cms::JxlCmsInterface,
- codestream_header::{
- JxlBasicInfo, JxlBlendInfo, JxlExtraChannelInfo, JxlExtraChannelType, JxlFrameHeader,
- },
- color_encoding::JxlColorEncoding,
- memory_manager::JxlMemoryManager,
- parallel_runner::JxlParallelRunner,
- stats::JxlEncoderStats,
- types::{JxlBitDepth, JxlBool, JxlBoxType, JxlPixelFormat},
-};
-
-// Opaque type
-#[repr(C)]
-pub struct JxlEncoder {
- _unused: [u8; 0],
-}
-
-#[repr(C)]
-pub struct JxlEncoderFrameSettings {
- _unused: [u8; 0],
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlEncoderStatus {
- Success = 0,
- Error = 1,
- NeedMoreOutput = 2,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlEncoderError {
- OK = 0,
- Generic = 1,
- OutOfMemory = 2,
- Jbrd = 3, //JPEG bitstream reconstruction data could not be represented
- BadInput = 4,
- NotSupported = 0x80,
- ApiUsage = 0x81,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum FrameSetting {
- Effort = 0,
- DecodingSpeed = 1,
- Resampling = 2,
- ExtraChannelResampling = 3,
- AlreadyDownsampled = 4,
- PhotonNoise = 5,
- Noise = 6,
- Dots = 7,
- Patches = 8,
- Epf = 9,
- Gaborish = 10,
- Modular = 11,
- KeepInvisible = 12,
- GroupOrder = 13,
- GroupOrderCenterX = 14,
- GroupOrderCenterY = 15,
- Responsive = 16,
- ProgressiveAc = 17,
- QprogressiveAc = 18,
- ProgressiveDc = 19,
- ChannelColorsGlobalPercent = 20,
- ChannelColorsGroupPercent = 21,
- PaletteColors = 22,
- LossyPalette = 23,
- ColorTransform = 24,
- ModularColorSpace = 25,
- ModularGroupSize = 26,
- ModularPredictor = 27,
- ModularMaTreeLearningPercent = 28,
- ModularNbPrevChannels = 29,
- JpegReconCfl = 30,
- IndexBox = 31,
- BrotliEffort = 32,
- JpegCompressBoxes = 33,
- Buffering = 34,
- JpegKeepExif = 35,
- JpegKeepXmp = 36,
- JpegKeepJumbf = 37,
- UseFullImageHeuristics = 38,
- FillEnum = 65535,
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlEncoderOutputProcessor {
- opaque: *mut c_void,
- get_buffer: extern "C" fn(opaque: *mut c_void, size: *mut usize) -> *mut c_void,
- release_buffer: extern "C" fn(opaque: *mut c_void, written_bytes: usize),
- seek: Option,
- set_finalized_position: extern "C" fn(opaque: *mut c_void, finalized_position: u64),
-}
-
-/**
- * This struct provides callback functions to pass pixel data in a streaming
- * manner instead of requiring the entire frame data in memory at once.
- */
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub struct JxlChunkedFrameInputSource {
- opaque: *mut c_void,
-
- get_color_channels_pixel_format:
- extern "C" fn(opaque: *mut c_void, pixel_format: *mut JxlPixelFormat),
-
- get_color_channels_data: extern "C" fn(
- opaque: *mut c_void,
- xpos: usize,
- ypos: usize,
- xsize: usize,
- ysize: usize,
- row_offset: *mut usize,
- ) -> *const c_void,
-
- get_extra_channel_pixel_format:
- extern "C" fn(opaque: *mut c_void, ec_index: usize, pixel_format: *mut JxlPixelFormat),
-
- get_extra_channel_data_at: extern "C" fn(
- opaque: *mut c_void,
- ec_index: usize,
- xpos: usize,
- ypos: usize,
- xsize: usize,
- ysize: usize,
- row_offset: *mut usize,
- ) -> *const c_void,
- release_buffer: extern "C" fn(opaque: *mut c_void, buf: *const c_void),
-}
-
-pub type JxlDebugImageCallback = extern "C" fn(
- opaque: *mut c_void,
- label: *const c_char,
- xsize: usize,
- ysize: usize,
- color: *const JxlColorEncoding,
- pixels: *const u16,
-);
-
-extern "C" {
- pub fn JxlEncoderVersion() -> u32;
-
- pub fn JxlEncoderCreate(memory_manager: *const JxlMemoryManager) -> *mut JxlEncoder;
-
- pub fn JxlEncoderReset(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderDestroy(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderSetCms(enc: *mut JxlEncoder, cms: JxlCmsInterface);
-
- pub fn JxlEncoderSetParallelRunner(
- enc: *mut JxlEncoder,
- parallel_runner: JxlParallelRunner,
- parallel_runner_opaque: *mut c_void,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderGetError(enc: *mut JxlEncoder) -> JxlEncoderError;
-
- pub fn JxlEncoderProcessOutput(
- enc: *mut JxlEncoder,
- next_out: *mut *mut u8,
- avail_out: *mut usize,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetFrameHeader(
- frame_settings: *mut JxlEncoderFrameSettings,
- frame_header: *const JxlFrameHeader,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetExtraChannelBlendInfo(
- frame_settings: *mut JxlEncoderFrameSettings,
- index: usize,
- blend_info: *const JxlBlendInfo,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetFrameName(
- frame_settings: *mut JxlEncoderFrameSettings,
- frame_name: *const u8,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetFrameBitDepth(
- frame_settings: *mut JxlEncoderFrameSettings,
- bit_depth: *const JxlBitDepth,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderAddJPEGFrame(
- options: *const JxlEncoderFrameSettings,
- buffer: *const u8,
- size: usize,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderAddImageFrame(
- options: *const JxlEncoderFrameSettings,
- pixel_format: *const JxlPixelFormat,
- buffer: *const c_void,
- size: usize,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetOutputProcessor(
- enc: *mut JxlEncoder,
- output_processor: JxlEncoderOutputProcessor,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderFlushInput(enc: *mut JxlEncoder) -> JxlEncoderStatus;
-
- pub fn JxlEncoderAddChunkedFrame(
- frame_settings: *const JxlEncoderFrameSettings,
- is_last_frame: JxlBool,
- chunked_frame_input: JxlChunkedFrameInputSource,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetExtraChannelBuffer(
- frame_settings: *const JxlEncoderFrameSettings,
- pixel_format: *const JxlPixelFormat,
- buffer: *const c_void,
- size: usize,
- index: u32,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderAddBox(
- enc: *mut JxlEncoder,
- box_type: *const JxlBoxType,
- contents: *const u8,
- size: usize,
- compress_box: JxlBool,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderUseBoxes(enc: *mut JxlEncoder) -> JxlEncoderStatus;
-
- pub fn JxlEncoderCloseBoxes(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderCloseFrames(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderCloseInput(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderSetColorEncoding(
- enc: *mut JxlEncoder,
- color: *const JxlColorEncoding,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetICCProfile(
- enc: *mut JxlEncoder,
- icc_profile: *const u8,
- size: usize,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderInitBasicInfo(info: *mut JxlBasicInfo);
-
- pub fn JxlEncoderInitFrameHeader(frame_header: *mut JxlFrameHeader);
-
- pub fn JxlEncoderInitBlendInfo(blend_info: *mut JxlBlendInfo);
-
- pub fn JxlEncoderSetBasicInfo(
- enc: *mut JxlEncoder,
- info: *const JxlBasicInfo,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetUpsamplingMode(
- enc: *mut JxlEncoder,
- factor: i64,
- mode: i64,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderInitExtraChannelInfo(
- channel_type: JxlExtraChannelType,
- info: *mut JxlExtraChannelInfo,
- );
-
- pub fn JxlEncoderSetExtraChannelInfo(
- enc: *mut JxlEncoder,
- index: usize,
- info: *const JxlExtraChannelInfo,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetExtraChannelName(
- enc: *mut JxlEncoder,
- index: usize,
- name: *const u8,
- size: usize,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderFrameSettingsSetOption(
- frame_settings: *mut JxlEncoderFrameSettings,
- option: FrameSetting,
- value: i64,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderFrameSettingsSetFloatOption(
- frame_settings: *mut JxlEncoderFrameSettings,
- option: FrameSetting,
- value: f32,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderUseContainer(enc: *mut JxlEncoder, use_container: bool) -> JxlEncoderStatus;
-
- pub fn JxlEncoderStoreJPEGMetadata(
- enc: *mut JxlEncoder,
- store_jpeg_metadata: bool,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetCodestreamLevel(enc: *mut JxlEncoder, level: i32) -> JxlEncoderStatus;
-
- pub fn JxlEncoderGetRequiredCodestreamLevel(enc: *mut JxlEncoder) -> i32;
-
- pub fn JxlEncoderSetFrameLossless(
- frame_settings: *mut JxlEncoderFrameSettings,
- lossless: bool,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetFrameDistance(
- options: *mut JxlEncoderFrameSettings,
- distance: f32,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderSetExtraChannelDistance(
- frame_settings: *mut JxlEncoderFrameSettings,
- index: usize,
- distance: f32,
- ) -> JxlEncoderStatus;
-
- pub fn JxlEncoderDistanceFromQuality(quality: f32) -> f32;
-
- pub fn JxlEncoderFrameSettingsCreate(
- enc: *mut JxlEncoder,
- source: *const JxlEncoderFrameSettings,
- ) -> *mut JxlEncoderFrameSettings;
-
- pub fn JxlColorEncodingSetToSRGB(color_encoding: *mut JxlColorEncoding, is_gray: bool);
-
- pub fn JxlColorEncodingSetToLinearSRGB(color_encoding: *mut JxlColorEncoding, is_gray: bool);
-
- pub fn JxlEncoderAllowExpertOptions(enc: *mut JxlEncoder);
-
- pub fn JxlEncoderSetDebugImageCallback(
- frame_settings: *mut JxlEncoderFrameSettings,
- callback: JxlDebugImageCallback,
- opaque: *mut c_void,
- );
-
- pub fn JxlEncoderCollectStats(
- frame_settings: *mut JxlEncoderFrameSettings,
- stats: *mut JxlEncoderStats,
- );
-}
diff --git a/jpegxl-sys/src/encoder.rs b/jpegxl-sys/src/encoder.rs
new file mode 100644
index 0000000..514d86f
--- /dev/null
+++ b/jpegxl-sys/src/encoder.rs
@@ -0,0 +1,21 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! `jxl_encoder`: JPEG XL encoder.
+
+pub mod encode;
+pub mod stats;
diff --git a/jpegxl-sys/src/encoder/encode.rs b/jpegxl-sys/src/encoder/encode.rs
new file mode 100644
index 0000000..e1d24a7
--- /dev/null
+++ b/jpegxl-sys/src/encoder/encode.rs
@@ -0,0 +1,1598 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Encoding API for JPEG XL.
+
+use std::ffi::{c_char, c_void};
+
+use super::stats::JxlEncoderStats;
+use crate::{
+ color::{cms_interface::JxlCmsInterface, color_encoding::JxlColorEncoding},
+ common::memory_manager::JxlMemoryManager,
+ common::types::{JxlBitDepth, JxlBool, JxlBoxType, JxlPixelFormat},
+ metadata::codestream_header::{
+ JxlBasicInfo, JxlBlendInfo, JxlExtraChannelInfo, JxlExtraChannelType, JxlFrameHeader,
+ },
+ threads::parallel_runner::JxlParallelRunner,
+};
+
+#[cfg(doc)]
+use crate::common::{
+ encoder::stats::JxlEncoderStatsCreate,
+ types::{JxlBitDepthType, JxlDataType},
+};
+
+/// Opaque structure that holds the JPEG XL encoder.
+///
+/// Allocated and initialized with [`JxlEncoderCreate`].
+/// Cleaned up and deallocated with [`JxlEncoderDestroy`].
+#[repr(C)]
+pub struct JxlEncoder {
+ _unused: [u8; 0],
+}
+
+/// Settings and metadata for a single image frame. This includes encoder options
+/// for a frame such as compression quality and speed.
+///
+/// Allocated and initialized with [`JxlEncoderFrameSettingsCreate`].
+/// Cleaned up and deallocated when the encoder is destroyed with
+/// [`JxlEncoderDestroy`].
+#[repr(C)]
+pub struct JxlEncoderFrameSettings {
+ _unused: [u8; 0],
+}
+
+/// Return value for multiple encoder functions.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlEncoderStatus {
+ /// Function call finished successfully, or encoding is finished and there is
+ /// nothing more to be done
+ Success = 0,
+ /// An error occurred, for example out of memory.
+ Error = 1,
+ /// The encoder needs more output buffer to continue encoding.
+ NeedMoreOutput = 2,
+}
+
+/// Error conditions:
+/// API usage errors have the 0x80 bit set to 1
+/// Other errors have the 0x80 bit set to 0
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlEncoderError {
+ /// No error
+ OK = 0,
+
+ /// Generic encoder error due to unspecified cause
+ Generic = 1,
+
+ /// Out of memory. TODO: not really used
+ OutOfMemory = 2,
+
+ /// JPEG bitstream reconstruction data could not be represented (e.g. too much tail data)
+ Jbrd = 3,
+
+ /// Input is invalid (e.g. corrupt JPEG file or ICC profile)
+ BadInput = 4,
+
+ /// The encoder doesn't (yet) support this. Either no version of libjxl
+ /// supports this, and the API is used incorrectly, or the libjxl version
+ /// should have been checked before trying to do this.
+ NotSupported = 0x80,
+
+ /// The encoder API is used in an incorrect way.
+ /// In this case, a debug build of libjxl should output a specific error
+ /// message. (if not, please open an issue about it)
+ ApiUsage = 0x81,
+}
+
+/// Id of encoder options for a frame. This includes options such as setting
+/// encoding effort/speed or overriding the use of certain coding tools, for this
+/// frame. This does not include non-frame related encoder options such as for
+/// boxes.
+#[repr(C)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum JxlEncoderFrameSettingId {
+ /// Sets encoder effort/speed level without affecting decoding speed. Valid
+ /// values are, from faster to slower speed: 1:lightning 2:thunder 3:falcon
+ /// 4:cheetah 5:hare 6:wombat 7:squirrel 8:kitten 9:tortoise 10:glacier.
+ /// Default: squirrel (7).
+ Effort = 0,
+
+ /// Sets the decoding speed tier for the provided options. Minimum is 0
+ /// (slowest to decode, best quality/density), and maximum is 4 (fastest to
+ /// decode, at the cost of some quality/density). Default is 0.
+ DecodingSpeed = 1,
+
+ /// Sets resampling option. If enabled, the image is downsampled before
+ /// compression, and upsampled to original size in the decoder. Integer option,
+ /// use -1 for the default behavior (resampling only applied for low quality),
+ /// 1 for no downsampling (1x1), 2 for 2x2 downsampling, 4 for 4x4
+ /// downsampling, 8 for 8x8 downsampling.
+ Resampling = 2,
+
+ /// Similar to [`Self::Resampling`], but for extra channels.
+ /// Integer option, use -1 for the default behavior (depends on encoder
+ /// implementation), 1 for no downsampling (1x1), 2 for 2x2 downsampling, 4 for
+ /// 4x4 downsampling, 8 for 8x8 downsampling.
+ ExtraChannelResampling = 3,
+
+ /// Indicates the frame added with [`JxlEncoderAddImageFrame`] is already
+ /// downsampled by the downsampling factor set with [`Self::Resampling`]. The input frame
+ /// must then be given in the downsampled resolution, not the full image resolution.
+ /// The downsampled resolution is given by `ceil(xsize / resampling)`, `ceil(ysize / resampling)`
+ /// with `xsize` and `ysize` the dimensions given in the basic info, and `resampling`
+ /// the factor set with [`Self::Resampling`].
+ /// Use 0 to disable, 1 to enable. Default value is 0.
+ AlreadyDownsampled = 4,
+
+ /// Adds noise to the image emulating photographic film noise, the higher the
+ /// given number, the grainier the image will be. As an example, a value of 100
+ /// gives low noise whereas a value of 3200 gives a lot of noise. The default
+ /// value is 0.
+ PhotonNoise = 5,
+
+ /// Enables adaptive noise generation. This setting is not recommended for
+ /// use, please use [`Self::PhotonNoise`] instead.
+ /// Use -1 for the default (encoder chooses), 0 to disable, 1 to enable.
+ Noise = 6,
+
+ /// Enables or disables dots generation. Use -1 for the default (encoder
+ /// chooses), 0 to disable, 1 to enable.
+ Dots = 7,
+
+ /// Enables or disables patches generation. Use -1 for the default (encoder
+ /// chooses), 0 to disable, 1 to enable.
+ Patches = 8,
+
+ /// Edge preserving filter level, -1 to 3. Use -1 for the default (encoder
+ /// chooses), 0 to 3 to set a strength.
+ Epf = 9,
+
+ /// Enables or disables the gaborish filter. Use -1 for the default (encoder
+ /// chooses), 0 to disable, 1 to enable.
+ Gaborish = 10,
+
+ /// Enables modular encoding. Use -1 for default (encoder
+ /// chooses), 0 to enforce `VarDCT` mode (e.g. for photographic images), 1 to
+ /// enforce modular mode (e.g. for lossless images).
+ Modular = 11,
+
+ /// Enables or disables preserving color of invisible pixels. Use -1 for the
+ /// default (1 if lossless, 0 if lossy), 0 to disable, 1 to enable.
+ KeepInvisible = 12,
+
+ /// Determines the order in which 256x256 regions are stored in the codestream
+ /// for progressive rendering. Use -1 for the encoder
+ /// default, 0 for scanline order, 1 for center-first order.
+ GroupOrder = 13,
+
+ /// Determines the horizontal position of center for the center-first group
+ /// order. Use -1 to automatically use the middle of the image, 0..xsize to
+ /// specifically set it.
+ GroupOrderCenterX = 14,
+
+ /// Determines the center for the center-first group order. Use -1 to
+ /// automatically use the middle of the image, 0..ysize to specifically set it.
+ GroupOrderCenterY = 15,
+
+ /// Enables or disables progressive encoding for modular mode. Use -1 for the
+ /// encoder default, 0 to disable, 1 to enable.
+ Responsive = 16,
+
+ /// Set the progressive mode for the AC coefficients of `VarDCT`, using spectral
+ /// progression from the DCT coefficients. Use -1 for the encoder default, 0 to
+ /// disable, 1 to enable.
+ ProgressiveAc = 17,
+
+ /// Set the progressive mode for the AC coefficients of `VarDCT`, using
+ /// quantization of the least significant bits. Use -1 for the encoder default,
+ /// 0 to disable, 1 to enable.
+ QprogressiveAc = 18,
+
+ /// Set the progressive mode using lower-resolution DC images for `VarDCT`. Use
+ /// -1 for the encoder default, 0 to disable, 1 to have an extra 64x64 lower
+ /// resolution pass, 2 to have a 512x512 and 64x64 lower resolution pass.
+ ProgressiveDc = 19,
+
+ /// Use Global channel palette if the amount of colors is smaller than this
+ /// percentage of range. Use 0-100 to set an explicit percentage, -1 to use the
+ /// encoder default. Used for modular encoding.
+ ChannelColorsGlobalPercent = 20,
+
+ /// Use Local (per-group) channel palette if the amount of colors is smaller
+ /// than this percentage of range. Use 0-100 to set an explicit percentage, -1
+ /// to use the encoder default. Used for modular encoding.
+ ChannelColorsGroupPercent = 21,
+
+ /// Use color palette if amount of colors is smaller than or equal to this
+ /// amount, or -1 to use the encoder default. Used for modular encoding.
+ PaletteColors = 22,
+
+ /// Enables or disables delta palette. Use -1 for the default (encoder
+ /// chooses), 0 to disable, 1 to enable. Used in modular mode.
+ LossyPalette = 23,
+
+ /// Color transform for internal encoding: -1 = default, 0=XYB, 1=none (RGB),
+ /// 2=YCbCr. The XYB setting performs the forward XYB transform. None and
+ /// YCbCr both perform no transform, but YCbCr is used to indicate that the
+ /// encoded data losslessly represents YCbCr values.
+ ColorTransform = 24,
+
+ /// Reversible color transform for modular encoding: -1=default, 0-41=RCT
+ /// index, e.g. index 0 = none, index 6 = `YCoCg`.
+ /// If this option is set to a non-default value, the RCT will be globally
+ /// applied to the whole frame.
+ /// The default behavior is to try several RCTs locally per modular group,
+ /// depending on the speed and distance setting.
+ ModularColorSpace = 25,
+
+ /// Group size for modular encoding: -1=default, 0=128, 1=256, 2=512, 3=1024.
+ ModularGroupSize = 26,
+
+ /// Predictor for modular encoding. -1 = default, 0=zero, 1=left, 2=top,
+ /// 3=avg0, 4=select, 5=gradient, 6=weighted, 7=topright, 8=topleft,
+ /// 9=leftleft, 10=avg1, 11=avg2, 12=avg3, 13=toptop predictive average 14=mix
+ /// 5 and 6, 15=mix everything.
+ ModularPredictor = 27,
+
+ /// Fraction of pixels used to learn MA trees as a percentage. -1 = default,
+ /// 0 = no MA and fast decode, 50 = default value, 100 = all, values above
+ /// 100 are also permitted. Higher values use more encoder memory.
+ ModularMaTreeLearningPercent = 28,
+
+ /// Number of extra (previous-channel) MA tree properties to use. -1 =
+ /// default, 0-11 = valid values. Recommended values are in the range 0 to 3,
+ /// or 0 to amount of channels minus 1 (including all extra channels, and
+ /// excluding color channels when using `VarDCT` mode). Higher value gives slower
+ /// encoding and slower decoding.
+ ModularNbPrevChannels = 29,
+
+ /// Enable or disable CFL (chroma-from-luma) for lossless JPEG recompression.
+ /// -1 = default, 0 = disable CFL, 1 = enable CFL.
+ JpegReconCfl = 30,
+
+ /// Prepare the frame for indexing in the frame index box.
+ /// 0 = ignore this frame (same as not setting a value),
+ /// 1 = index this frame within the Frame Index Box.
+ /// If any frames are indexed, the first frame needs to
+ /// be indexed, too. If the first frame is not indexed, and
+ /// a later frame is attempted to be indexed, [`JxlEncoderStatus::Error`] will occur.
+ /// If non-keyframes, i.e., frames with cropping, blending or patches are
+ /// attempted to be indexed, [`JxlEncoderStatus::Error`] will occur.
+ IndexBox = 31,
+
+ /// Sets brotli encode effort for use in JPEG recompression and
+ /// compressed metadata boxes (brob). Can be -1 (default) or 0 (fastest) to 11
+ /// (slowest). Default is based on the general encode effort in case of JPEG
+ /// recompression, and 4 for brob boxes.
+ BrotliEffort = 32,
+
+ /// Enables or disables brotli compression of metadata boxes derived from
+ /// a JPEG frame when using [`JxlEncoderAddJPEGFrame`]. This has no effect on
+ /// boxes added using [`JxlEncoderAddBox`]. -1 = default, 0 = disable
+ /// compression, 1 = enable compression.
+ JpegCompressBoxes = 33,
+
+ /// Control what kind of buffering is used, when using chunked image frames.
+ /// -1 = default (let the encoder decide)
+ /// 0 = buffers everything, basically the same as non-streamed code path
+ /// (mainly for testing)
+ /// 1 = buffers everything for images that are smaller than 2048 x 2048, and
+ /// uses streaming input and output for larger images
+ /// 2 = uses streaming input and output for all images that are larger than
+ /// one group, i.e. 256 x 256 pixels by default
+ /// 3 = currently same as 2
+ ///
+ /// When using streaming input and output the encoder minimizes memory usage at
+ /// the cost of compression density. Also note that images produced with
+ /// streaming mode might not be progressively decodeable.
+ Buffering = 34,
+
+ /// Keep or discard Exif metadata boxes derived from a JPEG frame when using
+ /// [`JxlEncoderAddJPEGFrame`]. This has no effect on boxes added using
+ /// [`JxlEncoderAddBox`]. When [`JxlEncoderStoreJPEGMetadata`] is set to 1,
+ /// this option cannot be set to 0. Even when Exif metadata is discarded, the
+ /// orientation will still be applied. 0 = discard Exif metadata, 1 = keep Exif
+ /// metadata (default).
+ JpegKeepExif = 35,
+
+ /// Keep or discard XMP metadata boxes derived from a JPEG frame when using
+ /// [`JxlEncoderAddJPEGFrame`]. This has no effect on boxes added using
+ /// [`JxlEncoderAddBox`]. When [`JxlEncoderStoreJPEGMetadata`] is set to 1,
+ /// this option cannot be set to 0. 0 = discard XMP metadata, 1 = keep XMP
+ /// metadata (default).
+ JpegKeepXmp = 36,
+
+ /// Keep or discard JUMBF metadata boxes derived from a JPEG frame when using
+ /// [`JxlEncoderAddJPEGFrame`]. This has no effect on boxes added using
+ /// [`JxlEncoderAddBox`]. 0 = discard JUMBF metadata, 1 = keep JUMBF metadata
+ /// (default).
+ JpegKeepJumbf = 37,
+
+ /// If this mode is disabled, the encoder will not make any image quality
+ /// decisions that are computed based on the full image, but stored only once
+ /// (e.g. the X quant multiplier in the frame header). Used mainly for testing
+ /// equivalence of streaming and non-streaming code.
+ /// 0 = disabled, 1 = enabled (default)
+ UseFullImageHeuristics = 38,
+
+ /// Disable perceptual optimizations. 0 = optimizations enabled (default), 1 =
+ /// optimizations disabled.
+ DisablePerceptualHeuristics = 39,
+
+ /// Enum value not to be used as an option. This value is added to force the
+ /// C compiler to have the enum to take a known size.
+ FillEnum = 65535,
+}
+
+/// The [`JxlEncoderOutputProcessor`] structure provides an interface for the
+/// encoder's output processing. Users of the library, who want to do streaming
+/// encoding, should implement the required callbacks for buffering, writing,
+/// seeking (if supported), and setting a finalized position during the encoding
+/// process.
+///
+/// At a high level, the processor can be in one of two states:
+/// - With an active buffer: This indicates that a buffer has been acquired using
+/// `get_buffer` and encoded data can be written to it.
+/// - Without an active buffer: In this state, no data can be written. A new
+/// buffer must be acquired after releasing any previously active buffer.
+///
+/// The library will not acquire more than one buffer at a given time.
+///
+/// The state of the processor includes `position` and `finalized position`,
+/// which have the following meaning.
+///
+/// - position: Represents the current position, in bytes, within the output
+/// stream where the encoded data will be written next. This position moves
+/// forward with each `release_buffer` call as data is written, and can also be
+/// adjusted through the optional seek callback, if provided. At this position
+/// the next write will occur.
+///
+/// - finalized position: A position in the output stream that ensures all bytes
+/// before this point are finalized and won't be changed by later writes.
+///
+/// All fields but `seek` are required, `seek` is optional and can be `None`.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlEncoderOutputProcessor {
+ /// An opaque pointer that the client can use to store custom data.
+ /// This data will be passed to the associated callback functions.
+ opaque: *mut c_void,
+ /// Acquires a buffer at the current position into which the library will write
+ /// the output data.
+ ///
+ /// If the `size` argument points to 0 and the returned value is NULL, this
+ /// will be interpreted as asking the output writing to stop. In such a case,
+ /// the library will return an error. The client is expected to set the size of
+ /// the returned buffer based on the suggested `size` when this function is
+ /// called.
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `size`: Points to a suggested buffer size when called; must be set to
+ /// the size of the returned buffer once the function returns.
+ ///
+ /// # Returns
+ /// A pointer to the acquired buffer or NULL to indicate a stop
+ /// condition.
+ get_buffer: extern "C-unwind" fn(opaque: *mut c_void, size: *mut usize) -> *mut c_void,
+ /// Notifies the user of library that the current buffer's data has been
+ /// written and can be released. This function should advance the current
+ /// osition of the buffer by `written_bytes` number of bytes.
+ ///
+ /// # Parameters
+ /// - `opaque`: user supplied parameters to the callback
+ /// - `written_bytes`: the number of bytes written to the buffer.
+ release_buffer: extern "C-unwind" fn(opaque: *mut c_void, written_bytes: usize),
+ /// Seeks to a specific position in the output. This function is optional and
+ /// can be set to `None` if the output doesn't support seeking. Can only be done
+ /// when there is no buffer. Cannot be used to seek before the finalized
+ /// position.
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `position`: The position to seek to, in bytes.
+ seek: Option,
+ /// Sets a finalized position on the output data, at a specific position.
+ /// Seeking will never request a position before the finalized position.
+ ///
+ /// Will only be called if there is no active buffer.
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `finalized_position`: The position, in bytes, where the finalized
+ /// position should be set.
+ set_finalized_position: extern "C-unwind" fn(opaque: *mut c_void, finalized_position: u64),
+}
+
+/// This struct provides callback functions to pass pixel data in a streaming
+/// manner instead of requiring the entire frame data in memory at once.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlChunkedFrameInputSource {
+ /// A pointer to any user-defined data or state. This can be used to pass
+ /// information to the callback functions.
+ opaque: *mut c_void,
+
+ /// Get the pixel format that color channel data will be provided in.
+ /// When called, `pixel_format` points to a suggested pixel format; if
+ /// color channel data can be given in this pixel format, processing might
+ /// be more efficient.
+ ///
+ /// This function will be called exactly once, before any call to
+ /// [`Self::get_color_channels_data`].
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `pixel_format`: Format for pixels.
+ get_color_channels_pixel_format:
+ extern "C-unwind" fn(opaque: *mut c_void, pixel_format: *mut JxlPixelFormat),
+
+ /// Callback to retrieve a rectangle of color channel data at a specific
+ /// location. It is guaranteed that `xpos` and `ypos` are multiples of 8. `xsize`,
+ /// `ysize` will be multiples of 8, unless the resulting rectangle would be out
+ /// of image bounds. Moreover, `xsize` and `ysize` will be at most 2048. The
+ /// returned data will be assumed to be in the format returned by the
+ /// (preceding) call to [`Self::get_color_channels_pixel_format`], except the `align`
+ /// parameter of the pixel format will be ignored. Instead, the `i`-th row will
+ /// be assumed to start at position `return_value + i * *row_offset`, with the
+ /// value of `*row_offset` decided by the callee.
+ ///
+ /// Note that multiple calls to `get_color_channel_data_at` may happen before a
+ /// call to [`Self::release_buffer`].
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `xpos`: Horizontal position for the data.
+ /// - `ypos`: Vertical position for the data.
+ /// - `xsize`: Horizontal size of the requested rectangle of data.
+ /// - `ysize`: Vertical size of the requested rectangle of data.
+ /// - `row_offset`: Pointer to the byte offset between consecutive rows of
+ /// the retrieved pixel data.
+ ///
+ /// # Returns
+ /// Pointer to the retrieved pixel data.
+ get_color_channels_data_at: extern "C-unwind" fn(
+ opaque: *mut c_void,
+ xpos: usize,
+ ypos: usize,
+ xsize: usize,
+ ysize: usize,
+ row_offset: *mut usize,
+ ) -> *const c_void,
+
+ /// Get the pixel format that extra channel data will be provided in.
+ /// When called, `pixel_format` points to a suggested pixel format; if
+ /// extra channel data can be given in this pixel format, processing might
+ /// be more efficient.
+ ///
+ /// This function will be called exactly once per index, before any call to
+ /// [`Self::get_extra_channel_data_at`] with that given index.
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `ec_index`: Zero-indexed index of the extra channel.
+ /// - `pixel_format`: Format for extra channel data.
+ get_extra_channel_pixel_format: extern "C-unwind" fn(
+ opaque: *mut c_void,
+ ec_index: usize,
+ pixel_format: *mut JxlPixelFormat,
+ ),
+
+ /// Callback to retrieve a rectangle of extra channel `ec_index` data at a
+ /// specific location. It is guaranteed that `xpos` and `ypos` are multiples of
+ /// 8. `xsize`, `ysize` will be multiples of 8, unless the resulting rectangle
+ /// would be out of image bounds. Moreover, `xsize` and `ysize` will be at most
+ /// 2048. The returned data will be assumed to be in the format returned by the
+ /// (preceding) call to [`Self::get_extra_channel_pixel_format`] with the
+ /// corresponding extra channel index `ec_index`, except the `align` parameter
+ /// of the pixel format will be ignored. Instead, the `i`-th row will be
+ /// assumed to start at position `return_value + i * *row_offset`, with the
+ /// value of `*row_offset` decided by the callee.
+ ///
+ /// Note that multiple calls to `get_extra_channel_data_at` may happen before a
+ /// call to [`Self::release_buffer`].
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `xpos`: Horizontal position for the data.
+ /// - `ypos`: Vertical position for the data.
+ /// - `xsize`: Horizontal size of the requested rectangle of data.
+ /// - `ysize`: Vertical size of the requested rectangle of data.
+ /// - `row_offset`: Pointer to the byte offset between consecutive rows of
+ /// the retrieved pixel data.
+ ///
+ /// # Returns
+ /// Pointer to the retrieved pixel data.
+ get_extra_channel_data_at: extern "C-unwind" fn(
+ opaque: *mut c_void,
+ ec_index: usize,
+ xpos: usize,
+ ypos: usize,
+ xsize: usize,
+ ysize: usize,
+ row_offset: *mut usize,
+ ) -> *const c_void,
+
+ /// Releases the buffer `buf` (obtained through a call to
+ /// [`Self::get_color_channels_data_at`] or [`Self::get_extra_channel_data_at`]). This function
+ /// will be called exactly once per call to [`Self::get_color_channels_data_at`] or
+ /// [`Self::get_extra_channel_data_at`].
+ ///
+ /// # Parameters
+ /// - `opaque`: User supplied parameters to the callback.
+ /// - `buf`: Pointer returned by [`Self::get_color_channels_data_at`] or
+ /// [`Self::get_extra_channel_data_at`].
+ release_buffer: extern "C-unwind" fn(opaque: *mut c_void, buf: *const c_void),
+}
+
+/// Function type for [`JxlEncoderSetDebugImageCallback`].
+///
+/// The callback may be called simultaneously by different threads when using a
+/// threaded parallel runner, on different debug images.
+///
+/// # Parameters
+/// - `opaque`: Optional user data, as given to [`JxlEncoderSetDebugImageCallback`].
+/// - `label`: Label of debug image, can be used in filenames.
+/// - `xsize`: Width of debug image.
+/// - `ysize`: Height of debug image.
+/// - `color`: Color encoding of debug image.
+/// - `pixels`: Pixel data of debug image as big-endian 16-bit unsigned samples.
+/// The memory is not owned by the user, and is only valid during the time the
+/// callback is running.
+pub type JxlDebugImageCallback = extern "C-unwind" fn(
+ opaque: *mut c_void,
+ label: *const c_char,
+ xsize: usize,
+ ysize: usize,
+ color: *const JxlColorEncoding,
+ pixels: *const u16,
+);
+
+extern "C" {
+ /// Encoder library version.
+ ///
+ /// # Returns
+ /// The encoder library version as an integer:
+ /// `MAJOR_VERSION * 1000000 + MINOR_VERSION * 1000 + PATCH_VERSION`.
+ /// For example, version 1.2.3 would return 1002003.
+ pub fn JxlEncoderVersion() -> u32;
+
+ /// Creates an instance of `JxlEncoder` and initializes it.
+ ///
+ /// # Parameters
+ /// - `memory_manager`: Custom allocator function. It may be `NULL`. The memory
+ /// manager will be copied internally. If `NULL`, the default allocator will be used.
+ /// See [`crate::common::memory_manager`] for details.
+ ///
+ /// # Returns
+ /// - `NULL` if the instance cannot be allocated or initialized.
+ /// - Pointer to initialized [`JxlEncoder`] otherwise.
+ pub fn JxlEncoderCreate(memory_manager: *const JxlMemoryManager) -> *mut JxlEncoder;
+
+ /// Re-initializes a [`JxlEncoder`] instance, so it can be re-used for encoding
+ /// another image. All state and settings are reset as if the object was
+ /// newly created with [`JxlEncoderCreate`], but the memory manager is kept.
+ ///
+ /// # Parameters
+ /// - `enc`: Instance to be re-initialized.
+ pub fn JxlEncoderReset(enc: *mut JxlEncoder);
+
+ /// Deinitializes and frees a [`JxlEncoder`] instance.
+ ///
+ /// # Parameters
+ /// - `enc`: Instance to be cleaned up and deallocated.
+ pub fn JxlEncoderDestroy(enc: *mut JxlEncoder);
+
+ /// Sets the color management system (CMS) that will be used for color conversion
+ /// (if applicable) during encoding. May only be set before starting encoding. If
+ /// left unset, the default CMS implementation will be used.
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ /// - `cms`: Structure representing a CMS implementation. See [`JxlCmsInterface`] for more details.
+ pub fn JxlEncoderSetCms(enc: *mut JxlEncoder, cms: JxlCmsInterface);
+
+ /// Set the parallel runner for multithreading. May only be set before starting
+ /// encoding.
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ /// - `parallel_runner`: Function pointer to runner for multithreading. It may
+ /// be `NULL` to use the default, single-threaded, runner. A multithreaded
+ /// runner should be set to reach fast performance.
+ /// - `parallel_runner_opaque`: Opaque pointer for `parallel_runner`.
+ ///
+ /// # Returns
+ /// - `JxlEncoderStatus::Success` if the runner was set.
+ /// - `JxlEncoderStatus::Error` otherwise (the previous runner remains set).
+ pub fn JxlEncoderSetParallelRunner(
+ enc: *mut JxlEncoder,
+ parallel_runner: JxlParallelRunner,
+ parallel_runner_opaque: *mut c_void,
+ ) -> JxlEncoderStatus;
+
+ /// Get the (last) error code in case [`JxlEncoderStatus::Error`] was returned.
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ ///
+ /// # Returns
+ /// The [`JxlEncoderError`] that caused the (last) [`JxlEncoderStatus::Error`] to be returned.
+ pub fn JxlEncoderGetError(enc: *mut JxlEncoder) -> JxlEncoderError;
+
+ /// Encodes a JPEG XL file using the available bytes. `*avail_out` indicates how
+ /// many output bytes are available, and `*next_out` points to the input bytes.
+ /// `*avail_out` will be decremented by the amount of bytes that have been
+ /// processed by the encoder and `*next_out` will be incremented by the same
+ /// amount, so `*next_out` will now point at the amount of `*avail_out` unprocessed
+ /// bytes.
+ ///
+ /// The returned status indicates whether the encoder needs more output bytes.
+ /// When the return value is not [`JxlEncoderStatus::Error`] or [`JxlEncoderStatus::Success`], the
+ /// encoding requires more [`JxlEncoderProcessOutput`] calls to continue.
+ ///
+ /// The caller must guarantee that `*avail_out >= 32` when calling
+ /// [`JxlEncoderProcessOutput`]; otherwise, [`JxlEncoderStatus::NeedMoreOutput`] will
+ /// be returned. It is guaranteed that, if `*avail_out >= 32`, at least one byte of
+ /// output will be written.
+ ///
+ /// This encodes the frames and/or boxes added so far. If the last frame or last
+ /// box has been added, [`JxlEncoderCloseInput`], [`JxlEncoderCloseFrames`]
+ /// and/or [`JxlEncoderCloseBoxes`] must be called before the next
+ /// [`JxlEncoderProcessOutput`] call, or the codestream won't be encoded
+ /// correctly.
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ /// - `next_out`: Pointer to next bytes to write to.
+ /// - `avail_out`: Amount of bytes available starting from `*next_out`.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] when encoding finished and all events handled.
+ /// - [`JxlEncoderStatus::Error`] when encoding failed, e.g. invalid input.
+ /// - [`JxlEncoderStatus::NeedMoreOutput`] more output buffer is necessary.
+ pub fn JxlEncoderProcessOutput(
+ enc: *mut JxlEncoder,
+ next_out: *mut *mut u8,
+ avail_out: *mut usize,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the frame information for this frame to the encoder. This includes
+ /// animation information such as frame duration to store in the frame header.
+ /// The frame header fields represent the frame as passed to the encoder, but not
+ /// necessarily the exact values as they will be encoded file format: the encoder
+ /// could change crop and blending options of a frame for more efficient encoding
+ /// or introduce additional internal frames. Animation duration and time code
+ /// information is not altered since those are immutable metadata of the frame.
+ ///
+ /// It is not required to use this function, however if `have_animation` is set
+ /// to true in the basic info, then this function should be used to set the
+ /// time duration of this individual frame. By default individual frames have a
+ /// time duration of 0, making them form a composite still. See [`JxlFrameHeader`]
+ /// for more information.
+ ///
+ /// This information is stored in the [`JxlEncoderFrameSettings`] and so is used
+ /// for any frame encoded with these [`JxlEncoderFrameSettings`]. It is ok to
+ /// change between [`JxlEncoderAddImageFrame`] calls, each added image frame
+ /// will have the frame header that was set in the options at the time of calling
+ /// [`JxlEncoderAddImageFrame`].
+ ///
+ /// The `is_last` and `name_length` fields of the [`JxlFrameHeader`] are ignored,
+ /// use [`JxlEncoderCloseFrames`] to indicate last frame, and [`JxlEncoderSetFrameName`]
+ /// to indicate the name and its length instead.
+ /// Calling this function will clear any name that was previously set with [`JxlEncoderSetFrameName`].
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `frame_header`: frame header data to set. Object owned by the caller and
+ /// does not need to be kept in memory, its information is copied internally.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success
+ /// - [`JxlEncoderStatus::Error`] on error
+ pub fn JxlEncoderSetFrameHeader(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ frame_header: *const JxlFrameHeader,
+ ) -> JxlEncoderStatus;
+
+ /// Sets blend info of an extra channel. The blend info of extra channels is set
+ /// separately from that of the color channels, the color channels are set with
+ /// [`JxlEncoderSetFrameHeader`].
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `index`: index of the extra channel to use.
+ /// - `blend_info`: blend info to set for the extra channel.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetExtraChannelBlendInfo(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ index: usize,
+ blend_info: *const JxlBlendInfo,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the name of the animation frame. This function is optional, frames are
+ /// not required to have a name. This setting is a part of the frame header, and
+ /// the same principles as for [`JxlEncoderSetFrameHeader`] apply. The
+ /// `name_length` field of [`JxlFrameHeader`] is ignored by the encoder, this
+ /// function determines the name length instead as the length in bytes of the C
+ /// string.
+ ///
+ /// The maximum possible name length is 1071 bytes (excluding terminating null
+ /// character).
+ ///
+ /// Calling [`JxlEncoderSetFrameHeader`] clears any name that was
+ /// previously set.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `frame_name`: name of the next frame to be encoded, as a UTF-8 encoded C
+ /// string (zero terminated). Owned by the caller, and copied internally.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success
+ /// - [`JxlEncoderStatus::Error`] on error
+ pub fn JxlEncoderSetFrameName(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ frame_name: *const u8,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the bit depth of the input buffer.
+ ///
+ /// For float pixel formats, only the default [`JxlBitDepthType::FromPixelFormat`]
+ /// setting is allowed, while for unsigned pixel formats,
+ /// [`JxlBitDepthType::FromCodestream`] setting is also allowed. See the comment
+ /// on [`JxlEncoderAddImageFrame`] for the effects of the bit depth setting.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: Set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `bit_depth`: The bit depth setting of the pixel input.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetFrameBitDepth(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ bit_depth: *const JxlBitDepth,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the buffer to read JPEG encoded bytes from for the next frame to encode.
+ ///
+ /// If [`JxlEncoderSetBasicInfo`] has not yet been called, calling
+ /// [`JxlEncoderAddJPEGFrame`] will implicitly call it with the parameters of
+ /// the added JPEG frame.
+ ///
+ /// If [`JxlEncoderSetColorEncoding`] or [`JxlEncoderSetICCProfile`] has not
+ /// yet been called, calling [`JxlEncoderAddJPEGFrame`] will implicitly call it
+ /// with the parameters of the added JPEG frame.
+ ///
+ /// If the encoder is set to store JPEG reconstruction metadata using [`JxlEncoderStoreJPEGMetadata`]
+ /// and a single JPEG frame is added, it will be possible to losslessly reconstruct the JPEG codestream.
+ ///
+ /// If this is the last frame, [`JxlEncoderCloseInput`] or [`JxlEncoderCloseFrames`] must be called before the next
+ /// [`JxlEncoderProcessOutput`] call.
+ ///
+ /// Note, this can only be used to add JPEG frames for lossless compression. To
+ /// encode with lossy compression, the JPEG must be decoded manually and a pixel
+ /// buffer added using [`JxlEncoderAddImageFrame`].
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `buffer`: bytes to read JPEG from. Owned by the caller and its contents
+ /// are copied internally.
+ /// - `size`: size of buffer in bytes.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success
+ /// - [`JxlEncoderStatus::Error`] on error
+ pub fn JxlEncoderAddJPEGFrame(
+ options: *const JxlEncoderFrameSettings,
+ buffer: *const u8,
+ size: usize,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the buffer to read pixels from for the next image to encode. Must call
+ /// [`JxlEncoderSetBasicInfo`] before [`JxlEncoderAddImageFrame`].
+ ///
+ /// Currently only some data types for pixel formats are supported:
+ /// - [`JxlDataType::Uint8`], with range 0..255
+ /// - [`JxlDataType::Uint16`], with range 0..65535
+ /// - [`JxlDataType::Float16`], with nominal range 0..1
+ /// - [`JxlDataType::Float`], with nominal range 0..1
+ ///
+ /// Note: the sample data type in `pixel_format` is allowed to be different from
+ /// what is described in the [`JxlBasicInfo`]. The type in `pixel_format`,
+ /// together with an optional [`JxlBitDepth`] parameter set by [`JxlEncoderSetFrameBitDepth`]
+ /// describes the format of the uncompressed pixel buffer. The `bits_per_sample` and `exponent_bits_per_sample`
+ /// in the [`JxlBasicInfo`] describes what will actually be encoded in the JPEG XL
+ /// codestream. For example, to encode a 12-bit image, you would set
+ /// `bits_per_sample` to 12, while the input frame buffer can be in the following
+ /// formats:
+ /// - if pixel format is in [`JxlDataType::Uint16`] with default bit depth setting
+ /// (i.e. [`JxlBitDepthType::FromPixelFormat`]), input sample values are
+ /// rescaled to 16-bit, i.e. multiplied by 65535/4095;
+ /// - if pixel format is in [`JxlDataType::Uint16`] with [`JxlBitDepthType::FromCodestream`] bit depth setting,
+ /// input sample values are provided unscaled;
+ /// - if pixel format is in [`JxlDataType::Float`], input sample values are
+ /// rescaled to 0..1, i.e. multiplied by 1.0/4095.0. While it is allowed, it is
+ /// obviously not recommended to use a `pixel_format` with lower precision than
+ /// what is specified in the [`JxlBasicInfo`].
+ ///
+ /// We support interleaved channels as described by the [`JxlPixelFormat`]:
+ /// - single-channel data, e.g. grayscale
+ /// - single-channel + alpha
+ /// - trichromatic, e.g. RGB
+ /// - trichromatic + alpha
+ ///
+ /// Extra channels not handled here need to be set by [`JxlEncoderSetExtraChannelBuffer`].
+ /// If the image has alpha, and alpha is not passed here, it will implicitly be
+ /// set to all-opaque (an alpha value of 1.0 everywhere).
+ ///
+ /// The pixels are assumed to be encoded in the original profile that is set with
+ /// [`JxlEncoderSetColorEncoding`] or [`JxlEncoderSetICCProfile`]. If none of
+ /// these functions were used, the pixels are assumed to be nonlinear sRGB for
+ /// integer data types ([`JxlDataType::Uint8`], [`JxlDataType::Uint16`]), and linear
+ /// sRGB for floating point data types ([`JxlDataType::Float16`], [`JxlDataType::Float`]).
+ ///
+ /// Sample values in floating-point pixel formats are allowed to be outside the
+ /// nominal range, e.g. to represent out-of-sRGB-gamut colors in the
+ /// `uses_original_profile=false` case. They are however not allowed to be NaN or
+ /// +-infinity.
+ ///
+ /// If this is the last frame, [`JxlEncoderCloseInput`] or [`JxlEncoderCloseFrames`] must be called before the next
+ /// [`JxlEncoderProcessOutput`] call.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `pixel_format`: format for pixels. Object owned by the caller and its
+ /// contents are copied internally.
+ /// - `buffer`: buffer type to input the pixel data from. Owned by the caller
+ /// and its contents are copied internally.
+ /// - `size`: size of buffer in bytes. This size should match what is implied
+ /// by the frame dimensions and the pixel format.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success
+ /// - [`JxlEncoderStatus::Error`] on error
+ pub fn JxlEncoderAddImageFrame(
+ options: *const JxlEncoderFrameSettings,
+ pixel_format: *const JxlPixelFormat,
+ buffer: *const c_void,
+ size: usize,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the output processor for the encoder. This processor determines how the
+ /// encoder will handle buffering, writing, seeking (if supported), and
+ /// setting a finalized position during the encoding process.
+ ///
+ /// This should not be used when using [`JxlEncoderProcessOutput`].
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ /// - `output_processor`: The struct containing the callbacks for managing
+ /// output.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetOutputProcessor(
+ enc: *mut JxlEncoder,
+ output_processor: JxlEncoderOutputProcessor,
+ ) -> JxlEncoderStatus;
+
+ /// Flushes any buffered input in the encoder, ensuring that all available input
+ /// data has been processed and written to the output.
+ ///
+ /// This function can only be used after [`JxlEncoderSetOutputProcessor`].
+ /// Before making the last call to [`JxlEncoderFlushInput`], users should call
+ /// [`JxlEncoderCloseInput`] to signal the end of input data.
+ ///
+ /// This should not be used when using [`JxlEncoderProcessOutput`].
+ ///
+ /// # Parameters
+ /// - `enc`: Encoder object.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderFlushInput(enc: *mut JxlEncoder) -> JxlEncoderStatus;
+
+ /// Adds a frame to the encoder using a chunked input source.
+ ///
+ /// This function gives a way to encode a frame by providing pixel data in a
+ /// chunked or streaming manner, which can be especially useful when dealing with
+ /// large images that may not fit entirely in memory or when trying to optimize
+ /// memory usage. The input data is provided through callbacks defined in the
+ /// [`JxlChunkedFrameInputSource`] struct. Once the frame data has been
+ /// completely retrieved, this function will flush the input and close it if it
+ /// is the last frame.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: Set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `is_last_frame`: Indicates if this is the last frame.
+ /// - `chunked_frame_input`: Struct providing callback methods for retrieving
+ /// pixel data in chunks.
+ ///
+ /// # Returns
+ /// Returns a status indicating the success or failure of adding the
+ /// frame.
+ pub fn JxlEncoderAddChunkedFrame(
+ frame_settings: *const JxlEncoderFrameSettings,
+ is_last_frame: JxlBool,
+ chunked_frame_input: JxlChunkedFrameInputSource,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the buffer to read pixels from for an extra channel at a given index.
+ /// The index must be smaller than the `num_extra_channels` in the associated
+ /// [`JxlBasicInfo`]. Must call [`JxlEncoderSetExtraChannelInfo`] before
+ /// [`JxlEncoderSetExtraChannelBuffer`].
+ ///
+ /// TODO: mention what data types in pixel formats are supported.
+ ///
+ /// It is required to call this function for every extra channel, except for the
+ /// alpha channel if that was already set through [`JxlEncoderAddImageFrame`].
+ ///
+ /// # Parameters
+ /// - `frame_settings`: Set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `pixel_format`: Format for pixels. Object owned by the caller and its
+ /// contents are copied internally. The `num_channels` value is ignored, since the
+ /// number of channels for an extra channel is always assumed to be one.
+ /// - `buffer`: Buffer type to input the pixel data from. Owned by the caller
+ /// and its contents are copied internally.
+ /// - `size`: Size of buffer in bytes. This size should match what is implied
+ /// by the frame dimensions and the pixel format.
+ /// - `index`: Index of the extra channel to use.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetExtraChannelBuffer(
+ frame_settings: *const JxlEncoderFrameSettings,
+ pixel_format: *const JxlPixelFormat,
+ buffer: *const c_void,
+ size: usize,
+ index: u32,
+ ) -> JxlEncoderStatus;
+
+ /// Adds a metadata box to the file format. [`JxlEncoderProcessOutput`] must be
+ /// used to effectively write the box to the output. [`JxlEncoderUseBoxes`] must
+ /// be enabled before using this function.
+ ///
+ /// Boxes allow inserting application-specific data and metadata (Exif, XML/XMP,
+ /// JUMBF and user defined boxes).
+ ///
+ /// The box format follows ISO BMFF and shares features and box types with other
+ /// image and video formats, including the Exif, XML and JUMBF boxes. The box
+ /// format for JPEG XL is specified in ISO/IEC 18181-2.
+ ///
+ /// Boxes in general don't contain other boxes inside, except a JUMBF superbox.
+ /// Boxes follow each other sequentially and are byte-aligned. If the container
+ /// format is used, the JXL stream consists of concatenated boxes.
+ /// It is also possible to use a direct codestream without boxes, but in that
+ /// case metadata cannot be added.
+ ///
+ /// Each box generally has the following byte structure in the file:
+ /// - 4 bytes: box size including box header (Big endian. If set to 0, an
+ /// 8-byte 64-bit size follows instead).
+ /// - 4 bytes: type, e.g. "JXL " for the signature box, "jxlc" for a codestream
+ /// box.
+ /// - N bytes: box contents.
+ ///
+ /// Only the box contents are provided to the contents argument of this function,
+ /// the encoder encodes the size header itself. Most boxes are written
+ /// automatically by the encoder as needed ("JXL ", "ftyp", "jxll", "jxlc",
+ /// "jxlp", "jxli", "jbrd"), and this function only needs to be called to add
+ /// optional metadata when encoding from pixels (using [`JxlEncoderAddImageFrame`]).
+ /// When recompressing JPEG files (using [`JxlEncoderAddJPEGFrame`]),
+ /// if the input JPEG contains EXIF, XMP or JUMBF
+ /// metadata, the corresponding boxes are already added automatically.
+ ///
+ /// Box types are given by 4 characters. The following boxes can be added with
+ /// this function:
+ /// - "Exif": a box with EXIF metadata, can be added by libjxl users, or is
+ /// automatically added when needed for JPEG reconstruction. The contents of
+ /// this box must be prepended by a 4-byte tiff header offset, which may
+ /// be 4 zero bytes in case the tiff header follows immediately.
+ /// The EXIF metadata must be in sync with what is encoded in the JPEG XL
+ /// codestream, specifically the image orientation. While this is not
+ /// recommended in practice, in case of conflicting metadata, the JPEG XL
+ /// codestream takes precedence.
+ /// - "xml ": a box with XML data, in particular XMP metadata, can be added by
+ /// libjxl users, or is automatically added when needed for JPEG reconstruction
+ /// - "jumb": a JUMBF superbox, which can contain boxes with different types of
+ /// metadata inside. This box type can be added by the encoder transparently,
+ /// and other libraries to create and handle JUMBF content exist.
+ /// - Application-specific boxes. Their typename should not begin with "jxl" or
+ /// "JXL" or conflict with other existing typenames, and they should be
+ /// registered with MP4RA (mp4ra.org).
+ ///
+ /// These boxes can be stored uncompressed or Brotli-compressed (using a "brob"
+ /// box), depending on the `compress_box` parameter.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `box_type`: the box type, e.g. "Exif" for EXIF metadata, "xml " for XMP or
+ /// IPTC metadata, "jumb" for JUMBF metadata.
+ /// - `contents`: the full contents of the box, for example EXIF
+ /// data. ISO BMFF box header must not be included, only the contents. Owned by
+ /// the caller and its contents are copied internally.
+ /// - `size`: size of the box contents.
+ /// - `compress_box`: Whether to compress this box as a "brob" box. Requires
+ /// Brotli support.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error, such as
+ /// when using this function without [`JxlEncoderUseContainer`], or adding a box
+ /// type that would result in an invalid file format.
+ pub fn JxlEncoderAddBox(
+ enc: *mut JxlEncoder,
+ box_type: *const JxlBoxType,
+ contents: *const u8,
+ size: usize,
+ compress_box: JxlBool,
+ ) -> JxlEncoderStatus;
+
+ /// Indicates the intention to add metadata boxes. This allows [`JxlEncoderAddBox`] to be used.
+ /// When using this function, then it is required to use [`JxlEncoderCloseBoxes`] at the end.
+ ///
+ /// By default the encoder assumes no metadata boxes will be added.
+ ///
+ /// This setting can only be set at the beginning, before encoding starts.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ pub fn JxlEncoderUseBoxes(enc: *mut JxlEncoder) -> JxlEncoderStatus;
+
+ /// Declares that no further boxes will be added with [`JxlEncoderAddBox`].
+ /// This function must be called after the last box is added so the encoder knows
+ /// the stream will be finished. It is not necessary to use this function if
+ /// [`JxlEncoderUseBoxes`] is not used. Further frames may still be added.
+ ///
+ /// Must be called between [`JxlEncoderAddBox`] of the last box
+ /// and the next call to [`JxlEncoderProcessOutput`], or [`JxlEncoderProcessOutput`]
+ /// won't output the last box correctly.
+ ///
+ /// NOTE: if you don't need to close frames and boxes at separate times, you can
+ /// use [`JxlEncoderCloseInput`] instead to close both at once.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ pub fn JxlEncoderCloseBoxes(enc: *mut JxlEncoder);
+
+ /// Declares that no frames will be added and [`JxlEncoderAddImageFrame`] and
+ /// [`JxlEncoderAddJPEGFrame`] won't be called anymore. Further metadata boxes
+ /// may still be added. This function or [`JxlEncoderCloseInput`] must be called
+ /// after adding the last frame and the next call to
+ /// [`JxlEncoderProcessOutput`], or the frame won't be properly marked as last.
+ ///
+ /// NOTE: if you don't need to close frames and boxes at separate times, you can
+ /// use [`JxlEncoderCloseInput`] instead to close both at once.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ pub fn JxlEncoderCloseFrames(enc: *mut JxlEncoder);
+
+ /// Closes any input to the encoder, equivalent to calling [`JxlEncoderCloseFrames`]
+ /// as well as calling [`JxlEncoderCloseBoxes`] if needed. No further input of any kind
+ /// may be given to the encoder, but further [`JxlEncoderProcessOutput`] calls should be
+ /// done to create the final output.
+ ///
+ /// The requirements of both [`JxlEncoderCloseFrames`] and [`JxlEncoderCloseBoxes`] apply
+ /// to this function. Either this function or the other two must be called after the final
+ /// frame and/or box, and the next [`JxlEncoderProcessOutput`] call, or the codestream won't
+ /// be encoded correctly.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ pub fn JxlEncoderCloseInput(enc: *mut JxlEncoder);
+
+ /// Sets the original color encoding of the image encoded by this encoder. This
+ /// is an alternative to [`JxlEncoderSetICCProfile`] and only one of these two
+ /// must be used. This one sets the color encoding as a [`JxlColorEncoding`],
+ /// while the other sets it as ICC binary data. Must be called after
+ /// [`JxlEncoderSetBasicInfo`].
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `color`: color encoding. Object owned by the caller and its contents are
+ /// copied internally.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetColorEncoding(
+ enc: *mut JxlEncoder,
+ color: *const JxlColorEncoding,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the original color encoding of the image encoded by this encoder as an
+ /// ICC color profile. This is an alternative to [`JxlEncoderSetColorEncoding`]
+ /// and only one of these two must be used. This one sets the color encoding as
+ /// ICC binary data, while the other defines it as a [`JxlColorEncoding`]. Must
+ /// be called after [`JxlEncoderSetBasicInfo`].
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `icc_profile`: bytes of the original ICC profile
+ /// - `size`: size of the `icc_profile` buffer in bytes
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetICCProfile(
+ enc: *mut JxlEncoder,
+ icc_profile: *const u8,
+ size: usize,
+ ) -> JxlEncoderStatus;
+
+ /// Initializes a [`JxlBasicInfo`] struct to default values.
+ /// For forwards-compatibility, this function has to be called before values
+ /// are assigned to the struct fields.
+ /// The default values correspond to an 8-bit RGB image, no alpha or any
+ /// other extra channels.
+ ///
+ /// # Parameters
+ /// - `info`: global image metadata. Object owned by the caller.
+ pub fn JxlEncoderInitBasicInfo(info: *mut JxlBasicInfo);
+
+ /// Initializes a [`JxlFrameHeader`] struct to default values.
+ /// For forwards-compatibility, this function has to be called before values
+ /// are assigned to the struct fields.
+ /// The default values correspond to a frame with no animation duration and the
+ /// 'replace' blend mode. After using this function, animation duration must
+ /// be set, and for composite still, blend settings must be set.
+ ///
+ /// # Parameters
+ /// - `frame_header`: frame metadata. Object owned by the caller.
+ pub fn JxlEncoderInitFrameHeader(frame_header: *mut JxlFrameHeader);
+
+ /// Initializes a [`JxlBlendInfo`] struct to default values.
+ /// For forwards-compatibility, this function has to be called before values
+ /// are assigned to the struct fields.
+ ///
+ /// # Parameters
+ /// - `blend_info`: blending info. Object owned by the caller.
+ pub fn JxlEncoderInitBlendInfo(blend_info: *mut JxlBlendInfo);
+
+ /// Sets the global metadata of the image encoded by this encoder.
+ ///
+ /// If the [`JxlBasicInfo`] contains information of extra channels beyond an
+ /// alpha channel, then [`JxlEncoderSetExtraChannelInfo`] must be called between
+ /// [`JxlEncoderSetBasicInfo`] and [`JxlEncoderAddImageFrame`]. In order to
+ /// indicate extra channels, the value of `info.num_extra_channels` should be set
+ /// to the number of extra channels, also counting the alpha channel if present.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `info`: global image metadata. Object owned by the caller and its
+ /// contents are copied internally.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetBasicInfo(
+ enc: *mut JxlEncoder,
+ info: *const JxlBasicInfo,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the upsampling method the decoder will use in case there are frames
+ /// with [`JxlEncoderFrameSettingsSetOption`] set. This is useful in combination
+ /// with the [`JxlEncoderFrameSettingsSetOption`] option, to control
+ /// the type of upsampling that will be used.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `factor`: upsampling factor to configure (1, 2, 4 or 8; for 1 this
+ /// function has no effect at all)
+ /// - `mode`: upsampling mode to use for this upsampling:
+ /// - `-1`: default (good for photographic images, no signaling overhead)
+ /// - `0`: nearest neighbor (good for pixel art)
+ /// - `1`: 'pixel dots' (same as NN for 2x, diamond-shaped 'pixel dots' for 4x/8x)
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful,
+ /// - [`JxlEncoderStatus::Error`] otherwise
+ pub fn JxlEncoderSetUpsamplingMode(
+ enc: *mut JxlEncoder,
+ factor: i64,
+ mode: i64,
+ ) -> JxlEncoderStatus;
+
+ /// Initializes a [`JxlExtraChannelInfo`] struct to default values.
+ /// For forwards-compatibility, this function has to be called before values
+ /// are assigned to the struct fields.
+ /// The default values correspond to an 8-bit channel of the provided type.
+ ///
+ /// # Parameters
+ /// - `channel_type`: type of the extra channel.
+ /// - `info`: global extra channel metadata. Object owned by the caller and its
+ /// contents are copied internally.
+ pub fn JxlEncoderInitExtraChannelInfo(
+ channel_type: JxlExtraChannelType,
+ info: *mut JxlExtraChannelInfo,
+ );
+
+ /// Sets information for the extra channel at the given index. The index
+ /// must be smaller than `num_extra_channels` in the associated [`JxlBasicInfo`].
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `index`: index of the extra channel to set.
+ /// - `info`: global extra channel metadata. Object owned by the caller and its
+ /// contents are copied internally.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetExtraChannelInfo(
+ enc: *mut JxlEncoder,
+ index: usize,
+ info: *const JxlExtraChannelInfo,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the name for the extra channel at the given index in UTF-8. The index
+ /// must be smaller than the `num_extra_channels` in the associated [`JxlBasicInfo`].
+ ///
+ /// TODO: remove size parameter for consistency with [`JxlEncoderSetFrameName`]
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `index`: index of the extra channel to set.
+ /// - `name`: buffer with the name of the extra channel.
+ /// - `size`: size of the name buffer in bytes, not counting the terminating
+ /// character.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] on success.
+ /// - [`JxlEncoderStatus::Error`] on error.
+ pub fn JxlEncoderSetExtraChannelName(
+ enc: *mut JxlEncoder,
+ index: usize,
+ name: *const u8,
+ size: usize,
+ ) -> JxlEncoderStatus;
+
+ /// Sets a frame-specific option of integer type to the encoder options.
+ /// The [`FrameSetting`] argument determines which option is set.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `option`: ID of the option to set.
+ /// - `value`: Integer value to set for this option.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] in case of an error, such as invalid or unknown option id, or
+ /// invalid integer value for the given option. If an error is returned, the
+ /// state of the [`JxlEncoderFrameSettings`] object is still valid and is the same as before
+ /// this function was called.
+ pub fn JxlEncoderFrameSettingsSetOption(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ option: JxlEncoderFrameSettingId,
+ value: i64,
+ ) -> JxlEncoderStatus;
+
+ /// Sets a frame-specific option of float type to the encoder options.
+ /// The [`FrameSetting`] argument determines which option is set.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `option`: ID of the option to set.
+ /// - `value`: Float value to set for this option.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] in case of an error, such as invalid or unknown option id, or
+ /// invalid float value for the given option. If an error is returned, the
+ /// state of the [`JxlEncoderFrameSettings`] object is still valid and is the same as before
+ /// this function was called.
+ pub fn JxlEncoderFrameSettingsSetFloatOption(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ option: JxlEncoderFrameSettingId,
+ value: f32,
+ ) -> JxlEncoderStatus;
+
+ /// Forces the encoder to use the box-based container format (BMFF) even
+ /// when not necessary.
+ ///
+ /// When using [`JxlEncoderUseBoxes`], [`JxlEncoderStoreJPEGMetadata`] or
+ /// [`JxlEncoderSetCodestreamLevel`] with level 10, the encoder will automatically
+ /// also use the container format, it is not necessary to use
+ /// [`JxlEncoderUseContainer`] for those use cases.
+ ///
+ /// By default this setting is disabled.
+ ///
+ /// This setting can only be set at the beginning, before encoding starts.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `use_container`: true if the encoder should always output the JPEG XL
+ /// container format, false to only output it when necessary.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderUseContainer(enc: *mut JxlEncoder, use_container: bool) -> JxlEncoderStatus;
+
+ /// Configure the encoder to store JPEG reconstruction metadata in the JPEG XL
+ /// container.
+ ///
+ /// If this is set to true and a single JPEG frame is added, it will be
+ /// possible to losslessly reconstruct the JPEG codestream.
+ ///
+ /// This setting can only be set at the beginning, before encoding starts.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `store_jpeg_metadata`: true if the encoder should store JPEG metadata.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderStoreJPEGMetadata(
+ enc: *mut JxlEncoder,
+ store_jpeg_metadata: bool,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the feature level of the JPEG XL codestream. Valid values are 5 and
+ /// 10, or -1 (to choose automatically). Using the minimum required level, or
+ /// level 5 in most cases, is recommended for compatibility with all decoders.
+ ///
+ /// Level 5: for end-user image delivery, this level is the most widely
+ /// supported level by image decoders and the recommended level to use unless a
+ /// level 10 feature is absolutely necessary. Supports a maximum resolution
+ /// 268435456 pixels total with a maximum width or height of 262144 pixels,
+ /// maximum 16-bit color channel depth, maximum 120 frames per second for
+ /// animation, maximum ICC color profile size of 4 MiB, it allows all color
+ /// models and extra channel types except CMYK and the [`JxlExtraChannelType::Black`]
+ /// extra channel, and a maximum of 4 extra channels in addition to the 3 color
+ /// channels. It also sets boundaries to certain internally used coding tools.
+ ///
+ /// Level 10: this level removes or increases the bounds of most of the level
+ /// 5 limitations, allows CMYK color and up to 32 bits per color channel, but
+ /// may be less widely supported.
+ ///
+ /// The default value is -1. This means the encoder will automatically choose
+ /// between level 5 and level 10 based on what information is inside the [`JxlBasicInfo`]
+ /// structure. Do note that some level 10 features, particularly those used by animated
+ /// JPEG XL codestreams, might require level 10, even though the [`JxlBasicInfo`] only
+ /// suggests level 5. In this case, the level must be explicitly set to 10, otherwise
+ /// the encoder will return an error. The encoder will restrict internal encoding choices
+ /// to those compatible with the level setting.
+ ///
+ /// This setting can only be set at the beginning, before encoding starts.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `level`: the level value to set, must be -1, 5, or 10.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful.
+ /// - [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetCodestreamLevel(enc: *mut JxlEncoder, level: i32) -> JxlEncoderStatus;
+
+ /// Returns the codestream level required to support the currently configured
+ /// settings and basic info. This function can only be used at the beginning,
+ /// before encoding starts, but after setting basic info.
+ ///
+ /// This does not support per-frame settings, only global configuration, such as
+ /// the image dimensions, that are known at the time of writing the header of
+ /// the JPEG XL file.
+ ///
+ /// If this returns 5, nothing needs to be done and the codestream can be
+ /// compatible with any decoder. If this returns 10, [`JxlEncoderSetCodestreamLevel`]
+ /// has to be used to set the codestream level to 10, or the encoder can be configured
+ /// differently to allow using the more compatible level 5.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ ///
+ /// # Returns
+ /// - `-1`: if no level can support the configuration (e.g. image dimensions
+ /// larger than even level 10 supports),
+ /// - `5`: if level 5 is supported,
+ /// - `10`: if setting the codestream level to 10 is required.
+ pub fn JxlEncoderGetRequiredCodestreamLevel(enc: *mut JxlEncoder) -> i32;
+
+ /// Enables lossless encoding.
+ ///
+ /// This is not an option like the others on itself, but rather while enabled it
+ /// overrides a set of existing options (such as distance, modular mode and
+ /// color transform) that enables bit-for-bit lossless encoding.
+ ///
+ /// When disabled, those options are not overridden, but since those options
+ /// could still have been manually set to a combination that operates losslessly,
+ /// using this function with lossless set to [`JxlBool::False`] does not
+ /// guarantee lossy encoding, though the default set of options is lossy.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `lossless`: whether to override options for lossless mode
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful, [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetFrameLossless(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ lossless: bool,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the distance level for lossy compression: target max butteraugli
+ /// distance, lower = higher quality. Range: 0 .. 25.
+ /// 0.0 = mathematically lossless (however, use [`JxlEncoderSetFrameLossless`]
+ /// instead to use true lossless, as setting distance to 0 alone is not the only
+ /// requirement). 1.0 = visually lossless. Recommended range: 0.5 .. 3.0. Default
+ /// value: 1.0.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `distance`: the distance value to set.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful, [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetFrameDistance(
+ options: *mut JxlEncoderFrameSettings,
+ distance: f32,
+ ) -> JxlEncoderStatus;
+
+ /// Sets the distance level for lossy compression of extra channels.
+ /// The distance is as in [`JxlEncoderSetFrameDistance`] (lower = higher
+ /// quality). If not set, or if set to the special value -1, the distance that
+ /// was set with [`JxlEncoderSetFrameDistance`] will be used.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `index`: index of the extra channel to set a distance value for.
+ /// - `distance`: the distance value to set.
+ ///
+ /// # Returns
+ /// - [`JxlEncoderStatus::Success`] if the operation was successful, [`JxlEncoderStatus::Error`] otherwise.
+ pub fn JxlEncoderSetExtraChannelDistance(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ index: usize,
+ distance: f32,
+ ) -> JxlEncoderStatus;
+
+ /// Maps JPEG-style quality factor to distance.
+ ///
+ /// This function takes in input a JPEG-style quality factor `quality` and
+ /// produces as output a `distance` value suitable to be used with
+ /// [`JxlEncoderSetFrameDistance`] and [`JxlEncoderSetExtraChannelDistance`].
+ ///
+ /// The `distance` value influences the level of compression, with lower values
+ /// indicating higher quality:
+ /// - 0.0 implies lossless compression (however, note that calling
+ /// [`JxlEncoderSetFrameLossless`] is required).
+ /// - 1.0 represents a visually lossy compression, which is also the default
+ /// setting.
+ ///
+ /// The `quality` parameter, ranging up to 100, is inversely related to
+ /// `distance`:
+ /// - A `quality` of 100.0 maps to a `distance` of 0.0 (lossless).
+ /// - A `quality` of 90.0 corresponds to a `distance` of 1.0.
+ ///
+ /// Recommended Range:
+ /// - `distance`: 0.5 to 3.0.
+ /// - corresponding `quality`: approximately 96 to 68.
+ ///
+ /// Allowed Range:
+ /// - `distance`: 0.0 to 25.0.
+ /// - corresponding `quality`: 100.0 to 0.0.
+ ///
+ /// Note: the `quality` parameter has no consistent psychovisual meaning
+ /// across different codecs and libraries. Using the mapping defined by
+ /// [`JxlEncoderDistanceFromQuality`] will result in a visual quality roughly
+ /// equivalent to what would be obtained with `libjpeg-turbo` with the same
+ /// `quality` parameter, but that is by no means guaranteed; do not assume that
+ /// the same quality value will result in similar file sizes and image quality
+ /// across different codecs.
+ pub fn JxlEncoderDistanceFromQuality(quality: f32) -> f32;
+
+ /// Create a new set of encoder options, with all values initially copied from
+ /// the `source` options, or set to default if `source` is `NULL`.
+ ///
+ /// The returned pointer is an opaque struct tied to the encoder and it will be
+ /// deallocated by the encoder when [`JxlEncoderDestroy`] is called. For
+ /// functions taking both a [`JxlEncoder`] and a [`JxlEncoderFrameSettings`],
+ /// only [`JxlEncoderFrameSettings`] created with this function for the same
+ /// encoder instance can be used.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ /// - `source`: source options to copy initial values from, or `NULL` to get
+ /// defaults initialized to defaults.
+ ///
+ /// # Returns
+ /// The opaque struct pointer identifying a new set of encoder options.
+ pub fn JxlEncoderFrameSettingsCreate(
+ enc: *mut JxlEncoder,
+ source: *const JxlEncoderFrameSettings,
+ ) -> *mut JxlEncoderFrameSettings;
+
+ /// Sets a color encoding to be sRGB.
+ ///
+ /// # Parameters
+ /// - `color_encoding`: color encoding instance.
+ /// - `is_gray`: whether the color encoding should be gray scale or color.
+ pub fn JxlColorEncodingSetToSRGB(color_encoding: *mut JxlColorEncoding, is_gray: bool);
+
+ /// Sets a color encoding to be linear sRGB.
+ ///
+ /// # Parameters
+ /// - `color_encoding`: [color encoding instance](JxlColorEncoding).
+ /// - `is_gray`: whether the color encoding should be gray scale or color.
+ pub fn JxlColorEncodingSetToLinearSRGB(color_encoding: *mut JxlColorEncoding, is_gray: bool);
+
+ /// Enables usage of expert options.
+ ///
+ /// At the moment, the only expert option is setting an effort value of 11,
+ /// which gives the best compression for pixel-lossless modes but is very slow.
+ ///
+ /// # Parameters
+ /// - `enc`: encoder object.
+ pub fn JxlEncoderAllowExpertOptions(enc: *mut JxlEncoder);
+
+ /// Sets the given debug image callback that will be used by the encoder to
+ /// output various debug images during encoding.
+ ///
+ /// This only has any effect if the encoder was compiled with the appropriate
+ /// debug build flags.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `callback`: used to return the debug image.
+ /// - `opaque`: user supplied parameter to the image callback.
+ pub fn JxlEncoderSetDebugImageCallback(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ callback: JxlDebugImageCallback,
+ opaque: *mut c_void,
+ );
+
+ /// Sets the given stats object for gathering various statistics during encoding.
+ ///
+ /// This only has any effect if the encoder was compiled with the appropriate
+ /// debug build flags.
+ ///
+ /// # Parameters
+ /// - `frame_settings`: set of options and metadata for this frame. Also
+ /// includes reference to the encoder object.
+ /// - `stats`: object that can be used to query the gathered stats (created
+ /// by [`JxlEncoderStatsCreate`])
+ pub fn JxlEncoderCollectStats(
+ frame_settings: *mut JxlEncoderFrameSettings,
+ stats: *mut JxlEncoderStats,
+ );
+}
diff --git a/jpegxl-sys/src/encoder/stats.rs b/jpegxl-sys/src/encoder/stats.rs
new file mode 100644
index 0000000..4ee94dc
--- /dev/null
+++ b/jpegxl-sys/src/encoder/stats.rs
@@ -0,0 +1,96 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! API to collect various statistics from JXL encoder.
+
+#[cfg(doc)]
+use crate::encoder::encode::JxlEncoderCollectStats;
+
+/// Opaque structure that holds the encoder statistics.
+///
+/// Allocated and initialized with [`JxlEncoderStatsCreate`].
+/// Cleaned up and deallocated with [`JxlEncoderStatsDestroy`].
+#[repr(C)]
+pub struct JxlEncoderStats {
+ _unused: [u8; 0],
+}
+
+extern "C" {
+ /// Creates an instance of [`JxlEncoderStats`] and initializes it.
+ ///
+ /// # Returns
+ /// A pointer to the initialized [`JxlEncoderStats`] instance.
+ pub fn JxlEncoderStatsCreate() -> *mut JxlEncoderStats;
+
+ /// Deinitializes and frees [`JxlEncoderStats`] instance.
+ ///
+ /// # Parameters
+ /// - `stats`: Instance to be cleaned up and deallocated. No-op if `stats` is
+ /// a null pointer.
+ pub fn JxlEncoderStatsDestroy(stats: *mut JxlEncoderStats);
+
+ /// Returns the value of the statistics corresponding to the given key.
+ ///
+ /// # Parameters
+ /// - `stats`: Object that was passed to the encoder with a
+ /// [`JxlEncoderCollectStats`] function.
+ /// - `key`: The particular statistics to query.
+ ///
+ /// # Returns
+ /// The value of the statistics.
+ pub fn JxlEncoderStatsGet(stats: *const JxlEncoderStats, key: JxlEncoderStatsKey) -> usize;
+
+ /** Updates the values of the given stats object with that of an other.
+ *
+ * @param stats object whose values will be updated (usually added together)
+ * @param other stats object whose values will be merged with stats
+ */
+ pub fn JxlEncoderStatsMerge(stats: *mut JxlEncoderStats, other: *const JxlEncoderStats);
+}
+
+/// Data type for querying [`JxlEncoderStats`] object
+#[repr(C)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum JxlEncoderStatsKey {
+ HeaderBits,
+ TocBits,
+ DictionaryBits,
+ SplinesBits,
+ NoiseBits,
+ QuantBits,
+ ModularTreeBits,
+ ModularGlobalBits,
+ DcBits,
+ ModularDcGroupBits,
+ ControlFieldsBits,
+ CoefOrderBits,
+ AcHistogramBits,
+ AcBits,
+ ModularAcGroupBits,
+ NumSmallBlocks,
+ NumDct4x8Blocks,
+ NumAfvBlocks,
+ NumDct8Blocks,
+ NumDct8x32Blocks,
+ NumDct16Blocks,
+ NumDct16x32Blocks,
+ NumDct32Blocks,
+ NumDct32x64Blocks,
+ NumDct64Blocks,
+ NumButteraugliIters,
+ NumStats,
+}
diff --git a/jpegxl-sys/src/lib.rs b/jpegxl-sys/src/lib.rs
index febe373..edba90c 100644
--- a/jpegxl-sys/src/lib.rs
+++ b/jpegxl-sys/src/lib.rs
@@ -17,29 +17,24 @@ along with jpegxl-sys. If not, see .
#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
-pub mod cms;
-pub mod codestream_header;
-pub mod color_encoding;
pub mod decode;
-pub mod encode;
-pub mod memory_manager;
-pub mod parallel_runner;
-pub mod stats;
-pub mod types;
-pub mod resizable_parallel_runner;
-pub mod thread_parallel_runner;
+pub mod color;
+pub mod common;
+pub mod encoder;
+pub mod metadata;
+pub mod threads;
#[cfg(test)]
mod test {
use crate::{
+ common::types::*,
decode::*,
- encode::*,
- thread_parallel_runner::{
+ encoder::encode::*,
+ threads::thread_parallel_runner::{
JxlThreadParallelRunner, JxlThreadParallelRunnerCreate,
JxlThreadParallelRunnerDefaultNumWorkerThreads, JxlThreadParallelRunnerDestroy,
},
- types::*,
};
use std::{mem::MaybeUninit, ptr};
@@ -81,8 +76,8 @@ mod test {
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_bindings_version() {
unsafe {
- assert_eq!(JxlDecoderVersion(), 10003);
- assert_eq!(JxlEncoderVersion(), 10003);
+ assert_eq!(JxlDecoderVersion(), 11000);
+ assert_eq!(JxlEncoderVersion(), 11000);
}
}
@@ -215,7 +210,7 @@ mod test {
BasicInfo, Error, FullImage, NeedImageOutBuffer, NeedMoreInput, Success,
};
- use crate::resizable_parallel_runner::{
+ use crate::threads::resizable_parallel_runner::{
JxlResizableParallelRunner, JxlResizableParallelRunnerCreate,
JxlResizableParallelRunnerDestroy, JxlResizableParallelRunnerSetThreads,
JxlResizableParallelRunnerSuggestThreads,
diff --git a/jpegxl-sys/src/memory_manager.rs b/jpegxl-sys/src/memory_manager.rs
deleted file mode 100644
index dbf7da5..0000000
--- a/jpegxl-sys/src/memory_manager.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use std::ffi::c_void;
-
-pub type JpegxlAllocFunc =
- unsafe extern "C-unwind" fn(opaque: *mut c_void, size: usize) -> *mut c_void;
-pub type JpegxlFreeFunc = unsafe extern "C-unwind" fn(opaque: *mut c_void, address: *mut c_void);
-
-#[repr(C)]
-#[derive(Clone, Debug)]
-pub struct JxlMemoryManager {
- pub opaque: *mut c_void,
- pub alloc: JpegxlAllocFunc,
- pub free: JpegxlFreeFunc,
-}
diff --git a/jpegxl-sys/src/metadata.rs b/jpegxl-sys/src/metadata.rs
new file mode 100644
index 0000000..057597e
--- /dev/null
+++ b/jpegxl-sys/src/metadata.rs
@@ -0,0 +1,22 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! `jxl_metadata`: JPEG XL metadata structures.
+
+pub mod codestream_header;
+pub mod compressed_icc;
+pub mod gain_map;
diff --git a/jpegxl-sys/src/metadata/codestream_header.rs b/jpegxl-sys/src/metadata/codestream_header.rs
new file mode 100644
index 0000000..9219b95
--- /dev/null
+++ b/jpegxl-sys/src/metadata/codestream_header.rs
@@ -0,0 +1,388 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Definitions of structs and enums for the metadata from the JPEG XL
+//! codestream headers (signature, metadata, preview dimensions, ...), excluding
+//! color encoding which is in [`crate::color::color_encoding`].
+
+use crate::common::types::JxlBool;
+
+#[cfg(doc)]
+use crate::{
+ color::color_encoding::{JxlColorEncoding, JxlColorSpace},
+ decode::{
+ JxlColorProfileTarget, JxlDecoderGetExtraChannelBlendInfo, JxlDecoderGetExtraChannelInfo,
+ },
+ encoder::encode::{JxlEncoderCloseFrames, JxlEncoderSetFrameName},
+};
+
+/// Image orientation metadata.
+///
+/// Values 1..8 match the EXIF definitions.
+/// The name indicates the operation to perform to transform from the encoded
+/// image to the display image.
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub enum JxlOrientation {
+ Identity = 1,
+ FlipHorizontal = 2,
+ Rotate180 = 3,
+ FlipVertical = 4,
+ Transpose = 5,
+ Rotate90Cw = 6,
+ AntiTranspose = 7,
+ Rotate90Ccw = 8,
+}
+
+/// Given type of an extra channel.
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub enum JxlExtraChannelType {
+ Alpha,
+ Depth,
+ SpotColor,
+ SelectionMask,
+ Black,
+ Cfa,
+ Thermal,
+ Reserved0,
+ Reserved1,
+ Reserved2,
+ Reserved3,
+ Reserved4,
+ Reserved5,
+ Reserved6,
+ Reserved7,
+ Unknown,
+ Optional,
+}
+
+/// The codestream preview header
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlPreviewHeader {
+ /// Preview width in pixels
+ pub xsize: u32,
+ /// Preview height in pixels
+ pub ysize: u32,
+}
+
+/// The codestream animation header, optionally present in the beginning of
+/// the codestream, and if it is it applies to all animation frames, unlike
+/// [`JxlFrameHeader`] which applies to an individual frame.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlAnimationHeader {
+ /// Numerator of ticks per second of a single animation frame time unit
+ pub tps_numerator: u32,
+
+ /// Denominator of ticks per second of a single animation frame time unit
+ pub tps_denominator: u32,
+
+ /// Amount of animation loops, or 0 to repeat infinitely
+ pub num_loops: u32,
+
+ /// Whether animation time codes are present at animation frames in the
+ /// codestream
+ pub have_timecodes: JxlBool,
+}
+
+/// Basic image information. This information is available from the file
+/// signature and first part of the codestream header.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlBasicInfo {
+ /// Whether the codestream is embedded in the container format. If true,
+ /// metadata information and extensions may be available in addition to the
+ /// codestream.
+ pub have_container: JxlBool,
+
+ /// Width of the image in pixels, before applying orientation.
+ pub xsize: u32,
+
+ /// Height of the image in pixels, before applying orientation.
+ pub ysize: u32,
+
+ /// Original image color channel bit depth.
+ pub bits_per_sample: u32,
+
+ /// Original image color channel floating point exponent bits, or 0 if they
+ /// are unsigned integer. For example, if the original data is half-precision
+ /// (binary16) floating point, `bits_per_sample` is 16 and
+ /// `exponent_bits_per_sample` is 5, and so on for other floating point
+ /// precisions.
+ pub exponent_bits_per_sample: u32,
+
+ /// Upper bound on the intensity level present in the image in nits. For
+ /// unsigned integer pixel encodings, this is the brightness of the largest
+ /// representable value. The image does not necessarily contain a pixel
+ /// actually this bright. An encoder is allowed to set 255 for SDR images
+ /// without computing a histogram.
+ /// Leaving this set to its default of 0 lets libjxl choose a sensible default
+ /// value based on the color encoding.
+ pub intensity_target: f32,
+
+ /// Lower bound on the intensity level present in the image. This may be
+ /// loose, i.e. lower than the actual darkest pixel. When tone mapping, a
+ /// decoder will map `[min_nits, intensity_target]` to the display range.
+ pub min_nits: f32,
+
+ /// See the description of [`Self::linear_below`].
+ pub relative_to_max_display: JxlBool,
+
+ /// The tone mapping will leave unchanged (linear mapping) any pixels whose
+ /// brightness is strictly below this. The interpretation depends on
+ /// `relative_to_max_display`. If true, this is a ratio \[0, 1\] of the maximum
+ /// display brightness \[nits\], otherwise an absolute brightness \[nits\].
+ pub linear_below: f32,
+
+ /// Whether the data in the codestream is encoded in the original color
+ /// profile that is attached to the codestream metadata header, or is
+ /// encoded in an internally supported absolute color space (which the decoder
+ /// can always convert to linear or non-linear sRGB or to XYB). If the original
+ /// profile is used, the decoder outputs pixel data in the color space matching
+ /// that profile, but doesn't convert it to any other color space. If the
+ /// original profile is not used, the decoder only outputs the data as sRGB
+ /// (linear if outputting to floating point, nonlinear with standard sRGB
+ /// transfer function if outputting to unsigned integers) but will not convert
+ /// it to to the original color profile. The decoder also does not convert to
+ /// the target display color profile. To convert the pixel data produced by
+ /// the decoder to the original color profile, one of the `JxlDecoderGetColor*`
+ /// functions needs to be called with
+ /// [`JxlColorProfileTarget::Data`] to get the color profile of the decoder
+ /// output, and then an external CMS can be used for conversion. Note that for
+ /// lossy compression, this should be set to false for most use cases, and if
+ /// needed, the image should be converted to the original color profile after
+ /// decoding, as described above.
+ pub uses_original_profile: JxlBool,
+
+ /// Indicates a preview image exists near the beginning of the codestream.
+ /// The preview itself or its dimensions are not included in the basic info.
+ pub have_preview: JxlBool,
+
+ /// Indicates animation frames exist in the codestream. The animation
+ /// information is not included in the basic info.
+ pub have_animation: JxlBool,
+
+ /// Image orientation, value 1-8 matching the values used by JEITA CP-3451C
+ /// (Exif version 2.3).
+ pub orientation: JxlOrientation,
+
+ /// Number of color channels encoded in the image, this is either 1 for
+ /// grayscale data, or 3 for colored data. This count does not include
+ /// the alpha channel or other extra channels. To check presence of an alpha
+ /// channel, such as in the case of RGBA color, check `alpha_bits != 0`.
+ /// If and only if this is `1`, the [`JxlColorSpace`] in the [`JxlColorEncoding`] is
+ /// [`JxlColorSpace::Gray`].
+ pub num_color_channels: u32,
+
+ /// Number of additional image channels. This includes the main alpha channel,
+ /// but can also include additional channels such as depth, additional alpha
+ /// channels, spot colors, and so on. Information about the extra channels
+ /// can be queried with [`JxlDecoderGetExtraChannelInfo`]. The main alpha
+ /// channel, if it exists, also has its information available in the
+ /// `alpha_bits`, `alpha_exponent_bits` and `alpha_premultiplied` fields in this
+ /// [`JxlBasicInfo`].
+ pub num_extra_channels: u32,
+
+ /// Bit depth of the encoded alpha channel, or 0 if there is no alpha channel.
+ /// If present, matches the `alpha_bits` value of the [`JxlExtraChannelInfo`]
+ /// associated with this alpha channel.
+ pub alpha_bits: u32,
+
+ /// Alpha channel floating point exponent bits, or 0 if they are unsigned. If
+ /// present, matches the `alpha_bits` value of the [`JxlExtraChannelInfo`] associated
+ /// with this alpha channel. integer.
+ pub alpha_exponent_bits: u32,
+
+ /// Whether the alpha channel is premultiplied. Only used if there is a main
+ /// alpha channel. Matches the `alpha_premultiplied` value of the
+ /// [`JxlExtraChannelInfo`] associated with this alpha channel.
+ pub alpha_premultiplied: JxlBool,
+
+ /// Dimensions of encoded preview image, only used if `have_preview` is
+ /// [`JxlBool::True`].
+ pub preview: JxlPreviewHeader,
+
+ /// Animation header with global animation properties for all frames, only
+ /// used if `have_animation` is [`JxlBool::True`].
+ pub animation: JxlAnimationHeader,
+
+ /// Intrinsic width of the image.
+ /// The intrinsic size can be different from the actual size in pixels
+ /// (as given by xsize and ysize) and it denotes the recommended dimensions
+ /// for displaying the image, i.e. applications are advised to resample the
+ /// decoded image to the intrinsic dimensions.
+ pub intrinsic_xsize: u32,
+
+ /// Intrinsic height of the image.
+ /// The intrinsic size can be different from the actual size in pixels
+ /// (as given by xsize and ysize) and it denotes the recommended dimensions
+ /// for displaying the image, i.e. applications are advised to resample the
+ /// decoded image to the intrinsic dimensions.
+ pub intrinsic_ysize: u32,
+
+ /// Padding for forwards-compatibility, in case more fields are exposed
+ /// in a future version of the library.
+ _padding: [u8; 100],
+}
+
+/// Information for a single extra channel.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlExtraChannelInfo {
+ /// Given type of an extra channel.
+ pub r#type: JxlExtraChannelType,
+
+ /// Total bits per sample for this channel.
+ pub bits_per_sample: u32,
+
+ /// Floating point exponent bits per channel, or 0 if they are unsigned
+ /// integer.
+ pub exponent_bits_per_sample: u32,
+
+ /// The exponent the channel is downsampled by on each axis.
+ /// TODO(lode): expand this comment to match the JPEG XL specification,
+ /// specify how to upscale, how to round the size computation, and to which
+ /// extra channels this field applies.
+ pub dim_shift: u32,
+
+ /// Length of the extra channel name in bytes, or 0 if no name.
+ /// Excludes null termination character.
+ pub name_length: u32,
+
+ /// Whether alpha channel uses premultiplied alpha. Only applicable if
+ /// type is [`JxlExtraChannelType::Alpha`].
+ pub alpha_premultiplied: JxlBool,
+
+ /// Spot color of the current spot channel in linear RGBA. Only applicable if
+ /// type is [`JxlExtraChannelType::SpotColor`].
+ pub spot_color: [f32; 4],
+
+ /// Only applicable if type is [`JxlExtraChannelType::Cfa`].
+ /// TODO(lode): add comment about the meaning of this field.
+ pub cfa_channel: u32,
+}
+/// Extensions in the codestream header.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlHeaderExtensions {
+ /// Extension bits.
+ pub extensions: u64,
+}
+/// Frame blend modes.
+/// When decoding, if coalescing is enabled (default), this can be ignored.
+#[repr(C)]
+#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
+pub enum JxlBlendMode {
+ Replace = 0,
+ Add = 1,
+ Blend = 2,
+ MULADD = 3,
+ MUL = 4,
+}
+
+/// The information about blending the color channels or a single extra channel.
+/// When decoding, if coalescing is enabled (default), this can be ignored and
+/// the blend mode is considered to be [`JxlBlendMode::Replace`].
+/// When encoding, these settings apply to the pixel data given to the encoder.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlBlendInfo {
+ /// Blend mode.
+ pub blendmode: JxlBlendMode,
+ /// Reference frame ID to use as the 'bottom' layer (0-3).
+ pub source: u32,
+ /// Which extra channel to use as the 'alpha' channel for blend modes
+ /// [`JxlBlendMode::Blend`] and [`JxlBlendMode::MULADD`].
+ pub alpha: u32,
+ /// Clamp values to \[0,1\] for the purpose of blending.
+ pub clamp: JxlBool,
+}
+
+/// The information about layers.
+/// When decoding, if coalescing is enabled (default), this can be ignored.
+/// When encoding, these settings apply to the pixel data given to the encoder,
+/// the encoder could choose an internal representation that differs.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlLayerInfo {
+ /// Whether cropping is applied for this frame. When decoding, if false,
+ /// [`Self::crop_x0`] and [`Self::crop_y0`] are set to zero, and [`Self::xsize`] and [`Self::ysize`] to the main
+ /// image dimensions. When encoding and this is false, those fields are
+ /// ignored. When decoding, if coalescing is enabled (default), this is always
+ /// false, regardless of the internal encoding in the JPEG XL codestream.
+ pub have_crop: JxlBool,
+
+ /// Horizontal offset of the frame (can be negative).
+ pub crop_x0: i32,
+
+ /// Vertical offset of the frame (can be negative).
+ pub crop_y0: i32,
+
+ /// Width of the frame (number of columns).
+ pub xsize: u32,
+
+ /// Height of the frame (number of rows).
+ pub ysize: u32,
+
+ /// The blending info for the color channels. Blending info for extra channels
+ /// has to be retrieved separately using [`JxlDecoderGetExtraChannelBlendInfo`].
+ pub blend_info: JxlBlendInfo,
+
+ /// After blending, save the frame as reference frame with this ID (0-3).
+ /// Special case: if the frame duration is nonzero, ID 0 means "will not be
+ /// referenced in the future". This value is not used for the last frame.
+ /// When encoding, ID 3 is reserved to frames that are generated internally by
+ /// the encoder, and should not be used by applications.
+ pub save_as_reference: u32,
+}
+
+///The header of one displayed frame or non-coalesced layer.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlFrameHeader {
+ /// How long to wait after rendering in ticks. The duration in seconds of a
+ /// tick is given by [`JxlAnimationHeader::tps_numerator`] and [`JxlAnimationHeader::tps_denominator`] in
+ /// [`JxlAnimationHeader`].
+ pub duration: u32,
+
+ /// SMPTE timecode of the current frame in form 0xHHMMSSFF, or 0. The bits are
+ /// interpreted from most-significant to least-significant as hour, minute,
+ /// second, and frame. If timecode is nonzero, it is strictly larger than that
+ /// of a previous frame with nonzero duration. These values are only available
+ /// if `have_timecodes` in [`JxlAnimationHeader`] is [`JxlBool::True`].
+ /// This value is only used if `have_timecodes` in [`JxlAnimationHeader`] is
+ /// [`JxlBool::True`].
+ pub timecode: u32,
+
+ /// Length of the frame name in bytes, or 0 if no name.
+ /// Excludes null termination character. This value is set by the decoder.
+ /// For the encoder, this value is ignored and [`JxlEncoderSetFrameName`] is
+ /// used instead to set the name and the length.
+ pub name_length: u32,
+
+ /** Indicates this is the last animation frame. This value is set by the
+ * decoder to indicate no further frames follow. For the encoder, it is not
+ * required to set this value and it is ignored, [`JxlEncoderCloseFrames`] is
+ * used to indicate the last frame to the encoder instead.
+ */
+ pub is_last: JxlBool,
+ /** Information about the layer in case of no coalescing.
+ */
+ pub layer_info: JxlLayerInfo,
+}
diff --git a/jpegxl-sys/src/metadata/compressed_icc.rs b/jpegxl-sys/src/metadata/compressed_icc.rs
new file mode 100644
index 0000000..aaa4cb9
--- /dev/null
+++ b/jpegxl-sys/src/metadata/compressed_icc.rs
@@ -0,0 +1,73 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Utility functions to compress and decompress ICC streams.
+
+use crate::common::{memory_manager, types::JxlBool};
+
+extern "C" {
+ /// Allocates a buffer using the memory manager, fills it with a compressed
+ /// representation of an ICC profile, returns the result through `output_buffer`
+ /// and indicates its size through `output_size`.
+ ///
+ /// The result must be freed using the memory manager once it is not of any more
+ /// use.
+ ///
+ /// # Parameters
+ ///
+ /// - `memory_manager`: Pointer to a `JxlMemoryManager`.
+ /// - `icc`: Pointer to a buffer containing the uncompressed ICC profile.
+ /// - `icc_size`: Size of the buffer containing the ICC profile.
+ /// - `compressed_icc`: Will be set to a pointer to the buffer containing the result.
+ /// - `compressed_icc_size`: Will be set to the size of the buffer containing the result.
+ ///
+ /// # Returns
+ ///
+ /// Whether compressing the profile was successful.
+ pub fn JxlICCProfileEncode(
+ memory_manager: *const memory_manager::JxlMemoryManager,
+ icc: *const u8,
+ icc_size: usize,
+ compressed_icc: *mut *mut u8,
+ compressed_icc_size: *mut usize,
+ ) -> JxlBool;
+
+ /// Allocates a buffer using the memory manager, fills it with the decompressed
+ /// version of the ICC profile in `compressed_icc`, returns the result through
+ /// `icc` and indicates its size through `icc_size`.
+ ///
+ /// The result must be freed using the memory manager once it is no longer needed.
+ ///
+ /// # Parameters
+ ///
+ /// - `memory_manager`: Pointer to a `JxlMemoryManager`.
+ /// - `compressed_icc`: Pointer to a buffer containing the compressed ICC profile.
+ /// - `compressed_icc_size`: Size of the buffer containing the compressed ICC profile.
+ /// - `icc`: Will be set to a pointer to the buffer containing the result.
+ /// - `icc_size`: Will be set to the size of the buffer containing the result.
+ ///
+ /// # Returns
+ ///
+ /// Whether decompressing the profile was successful.
+ pub fn JxlICCProfileDecode(
+ memory_manager: *const memory_manager::JxlMemoryManager,
+ compressed_icc: *const u8,
+ compressed_icc_size: usize,
+ icc: *mut *mut u8,
+ icc_size: *mut usize,
+ ) -> JxlBool;
+}
diff --git a/jpegxl-sys/src/metadata/gain_map.rs b/jpegxl-sys/src/metadata/gain_map.rs
new file mode 100644
index 0000000..df728f0
--- /dev/null
+++ b/jpegxl-sys/src/metadata/gain_map.rs
@@ -0,0 +1,134 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Utility functions to manipulate jhgm (gain map) boxes.
+
+use crate::{color::color_encoding::JxlColorEncoding, common::types::JxlBool};
+
+/// Gain map bundle
+///
+/// This structure is used to serialize gain map data to and from an input
+/// buffer. It holds pointers to sections within the buffer, and different parts
+/// of the gain map data such as metadata, ICC profile data, and the gain map
+/// itself.
+///
+/// The pointers in this structure do not take ownership of the memory they point
+/// to. Instead, they reference specific locations within the provided buffer. It
+/// is the caller's responsibility to ensure that the buffer remains valid and is
+/// not deallocated as long as these pointers are in use. The structure should be
+/// considered as providing a view into the buffer, not as an owner of the data.
+#[repr(C)]
+#[derive(Debug, Clone)]
+pub struct JxlGainMapBundle {
+ /// Version number of the gain map bundle.
+ pub jhgm_version: u8,
+ /// Size of the gain map metadata in bytes.
+ pub gain_map_metadata_size: u16,
+ /// Pointer to the gain map metadata, which is a binary
+ /// blob following ISO 21496-1. This pointer references data within the input
+ /// buffer.
+ pub gain_map_metadata: *const u8,
+ /// Indicates whether a color encoding is present.
+ pub has_color_encoding: JxlBool,
+ /// If `has_color_encoding` is true, this field contains the
+ /// uncompressed color encoding data.
+ pub color_encoding: JxlColorEncoding,
+ /// Size of the alternative ICC profile in bytes (compressed
+ /// size).
+ pub alt_icc_size: u32,
+ /// Pointer to the compressed ICC profile. This pointer references
+ /// data within the input buffer.
+ pub alt_icc: *const u8,
+ /// Size of the gain map in bytes.
+ pub gain_map_size: u32,
+ /// Pointer to the gain map data, which is a JPEG XL naked
+ /// codestream. This pointer references data within the input buffer.
+ pub gain_map: *const u8,
+}
+
+extern "C" {
+ /// Calculates the total size required to serialize the gain map bundle into a
+ /// binary buffer. This function accounts for all the necessary space to
+ /// serialize fields such as gain map metadata, color encoding, compressed ICC
+ /// profile data, and the gain map itself.
+ ///
+ /// # Parameters
+ /// - `map_bundle`: A reference to the [`JxlGainMapBundle`] containing all
+ /// necessary data to compute the size.
+ /// - `bundle_size`: A mutable reference to a `usize` where the size in bytes
+ /// required to serialize the bundle will be stored.
+ ///
+ /// # Returns
+ /// - A boolean indicating whether setting the size was successful.
+ pub fn JxlGainMapGetBundleSize(
+ map_bundle: *const JxlGainMapBundle,
+ bundle_size: *mut usize,
+ ) -> JxlBool;
+
+ /// Serializes the gain map bundle into a preallocated buffer. The function
+ /// ensures that all parts of the bundle such as metadata, color encoding,
+ /// compressed ICC profile, and the gain map are correctly encoded into the
+ /// buffer. First call [`JxlGainMapGetBundleSize`] to get the size needed for
+ /// the buffer.
+ ///
+ /// # Parameters
+ /// - `map_bundle`: A pointer to the [`JxlGainMapBundle`] to serialize.
+ /// - `output_buffer`: A pointer to the buffer where the serialized data
+ /// will be written.
+ /// - `output_buffer_size`: The size of the output buffer in bytes. Must be
+ /// large enough to hold the entire serialized data.
+ /// - `bytes_written`: A mutable reference to a `usize` where the number of bytes
+ /// written to the output buffer will be stored.
+ ///
+ /// # Returns
+ /// - A boolean indicating whether writing the bundle was successful.
+ pub fn JxlGainMapWriteBundle(
+ map_bundle: *const JxlGainMapBundle,
+ output_buffer: *mut u8,
+ output_buffer_size: usize,
+ bytes_written: *mut usize,
+ ) -> JxlBool;
+
+ /// Deserializes a gain map bundle from a provided buffer and populates a
+ /// [`JxlGainMapBundle`] structure with the data extracted. This function assumes
+ /// the buffer contains a valid serialized gain map bundle. After successful
+ /// execution, the [`JxlGainMapBundle`] structure will reference three different
+ /// sections within the buffer:
+ /// - `gain_map_metadata`
+ /// - `alt_icc`
+ /// - `gain_map`
+ ///
+ /// These sections will be accompanied by their respective sizes. Users must
+ /// ensure that the buffer remains valid as long as these pointers are in use.
+ ///
+ /// # Parameters
+ /// - `map_bundle`: Pointer to a preallocated [`JxlGainMapBundle`] where
+ /// the deserialized data will be stored.
+ /// - `input_buffer`: Pointer to the buffer containing the serialized gain
+ /// map bundle data.
+ /// - `input_buffer_size`: The size of the input buffer in bytes.
+ /// - `bytes_read`: The number of bytes read from the input buffer.
+ ///
+ /// # Returns
+ /// - A boolean indicating whether reading the bundle was successful.
+ pub fn JxlGainMapReadBundle(
+ map_bundle: *mut JxlGainMapBundle,
+ input_buffer: *const u8,
+ input_buffer_size: usize,
+ bytes_read: *mut usize,
+ ) -> JxlBool;
+}
diff --git a/jpegxl-sys/src/parallel_runner.rs b/jpegxl-sys/src/parallel_runner.rs
deleted file mode 100644
index e461a30..0000000
--- a/jpegxl-sys/src/parallel_runner.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::ffi::c_void;
-
-pub type JxlParallelRetCode = i32;
-
-pub type JxlParallelRunInit = unsafe extern "C-unwind" fn(
- jpegxl_opaque: *mut c_void,
- num_threads: usize,
-) -> JxlParallelRetCode;
-
-pub type JxlParallelRunFunction =
- unsafe extern "C-unwind" fn(jpegxl_opaque: *mut c_void, value: u32, thread_id: usize);
-
-pub type JxlParallelRunner = unsafe extern "C-unwind" fn(
- runner_opaque: *mut c_void,
- jpegxl_opaque: *mut c_void,
- init: JxlParallelRunInit,
- func: JxlParallelRunFunction,
- start_range: u32,
- end_range: u32,
-) -> JxlParallelRetCode;
diff --git a/jpegxl-sys/src/resizable_parallel_runner.rs b/jpegxl-sys/src/resizable_parallel_runner.rs
deleted file mode 100644
index b2d5749..0000000
--- a/jpegxl-sys/src/resizable_parallel_runner.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-This file is part of jpegxl-sys.
-
-jpegxl-sys is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-jpegxl-sys is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with jpegxl-sys. If not, see .
-*/
-
-use std::ffi::c_void;
-
-use crate::{
- memory_manager::JxlMemoryManager,
- parallel_runner::{JxlParallelRetCode, JxlParallelRunFunction, JxlParallelRunInit},
-};
-
-extern "C-unwind" {
- pub fn JxlResizableParallelRunner(
- runner_opaque: *mut c_void,
- jpegxl_opaque: *mut c_void,
- init: JxlParallelRunInit,
- func: JxlParallelRunFunction,
- start_range: u32,
- end_range: u32,
- ) -> JxlParallelRetCode;
-
- pub fn JxlResizableParallelRunnerCreate(memory_manager: *const JxlMemoryManager)
- -> *mut c_void;
-
- pub fn JxlResizableParallelRunnerSetThreads(runner_opaque: *mut c_void, num_threads: usize);
-
- pub fn JxlResizableParallelRunnerSuggestThreads(xsize: u64, ysize: u64) -> u32;
-
- pub fn JxlResizableParallelRunnerDestroy(runner_opaque: *mut c_void);
-
- pub fn JxlThreadParallelRunnerDefaultNumWorkerThreads() -> usize;
-}
diff --git a/jpegxl-sys/src/stats.rs b/jpegxl-sys/src/stats.rs
deleted file mode 100644
index 15ca650..0000000
--- a/jpegxl-sys/src/stats.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-#[repr(C)]
-pub struct JxlEncoderStats {
- _unused: [u8; 0],
-}
-
-extern "C" {
- pub fn JxlEncoderStatsCreate() -> *mut JxlEncoderStats;
- pub fn JxlEncoderStatsDestroy(stats: *mut JxlEncoderStats);
- pub fn JxlEncoderStatsGet(stats: *const JxlEncoderStats, key: JxlEncoderStatsKey) -> usize;
- pub fn JxlEncoderStatsMerge(stats: *mut JxlEncoderStats, other: *const JxlEncoderStats);
-}
-
-#[repr(C)]
-#[derive(Debug, Clone)]
-pub enum JxlEncoderStatsKey {
- HeaderBits,
- TocBits,
- DictionaryBits,
- SplinesBits,
- NoiseBits,
- QuantBits,
- ModularTreeBits,
- ModularGlobalBits,
- DcBits,
- ModularDcGroupBits,
- ControlFieldsBits,
- CoefOrderBits,
- AcHistogramBits,
- AcBits,
- ModularAcGroupBits,
- NumSmallBlocks,
- NumDct4x8Blocks,
- NumAfvBlocks,
- NumDct8Blocks,
- NumDct8x32Blocks,
- NumDct16Blocks,
- NumDct16x32Blocks,
- NumDct32Blocks,
- NumDct32x64Blocks,
- NumDct64Blocks,
- NumButteraugliIters,
- NumStats,
-}
diff --git a/jpegxl-sys/src/thread_parallel_runner.rs b/jpegxl-sys/src/thread_parallel_runner.rs
deleted file mode 100644
index 1439697..0000000
--- a/jpegxl-sys/src/thread_parallel_runner.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-This file is part of jpegxl-sys.
-
-jpegxl-sys is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-jpegxl-sys is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with jpegxl-sys. If not, see .
-*/
-
-use std::ffi::c_void;
-
-use crate::{
- memory_manager::JxlMemoryManager,
- parallel_runner::{JxlParallelRetCode, JxlParallelRunFunction, JxlParallelRunInit},
-};
-
-extern "C-unwind" {
- pub fn JxlThreadParallelRunner(
- runner_opaque: *mut c_void,
- jpegxl_opaque: *mut c_void,
- init: JxlParallelRunInit,
- func: JxlParallelRunFunction,
- start_range: u32,
- end_range: u32,
- ) -> JxlParallelRetCode;
-
- pub fn JxlThreadParallelRunnerCreate(
- memory_manager: *const JxlMemoryManager,
- num_worker_threads: usize,
- ) -> *mut c_void;
-
- pub fn JxlThreadParallelRunnerDestroy(runner_opaque: *mut c_void);
-
- pub fn JxlThreadParallelRunnerDefaultNumWorkerThreads() -> usize;
-}
diff --git a/jpegxl-sys/src/threads.rs b/jpegxl-sys/src/threads.rs
new file mode 100644
index 0000000..3c248f5
--- /dev/null
+++ b/jpegxl-sys/src/threads.rs
@@ -0,0 +1,22 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! `libjxl_threads`: Parallel processing support for JPEG XL.
+
+pub mod parallel_runner;
+pub mod resizable_parallel_runner;
+pub mod thread_parallel_runner;
diff --git a/jpegxl-sys/src/threads/parallel_runner.rs b/jpegxl-sys/src/threads/parallel_runner.rs
new file mode 100644
index 0000000..2cd5208
--- /dev/null
+++ b/jpegxl-sys/src/threads/parallel_runner.rs
@@ -0,0 +1,122 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! API for running data operations in parallel in a multi-threaded environment.
+//! This module allows the JPEG XL caller to define their own way of creating and
+//! assigning threads.
+//!
+//! The [`JxlParallelRunner`] function type defines a parallel data processing
+//! runner that may be implemented by the caller to allow the library to process
+//! in multiple threads. The multi-threaded processing in this library only
+//! requires to run the same function over each number of a range, possibly
+//! running each call in a different thread. The JPEG XL caller is responsible
+//! for implementing this logic using the thread APIs available in their system.
+//! For convenience, a C++ implementation based on `std::thread` is provided in
+//! [`super::thread_parallel_runner`] (part of the `jpegxl_threads` library).
+//!
+//! Thread pools usually store small numbers of heterogeneous tasks in a queue.
+//! When tasks are identical or differ only by an integer input parameter, it is
+//! much faster to store just one function of an integer parameter and call it
+//! for each value. Conventional vector-of-tasks can be run in parallel using a
+//! lambda function adapter that simply calls `task_funcs[task]`.
+//!
+//! If no multi-threading is desired, a `NULL` value of [`JxlParallelRunner`]
+//! will use an internal implementation without multi-threading.
+
+use std::ffi::{c_int, c_void};
+
+/// Return code used in the `JxlParallel*` functions as return value. A value
+/// of [`JXL_PARALLEL_RET_SUCCESS`] means success and any other value means error.
+/// The special value [`JXL_PARALLEL_RET_RUNNER_ERROR`] can be used by the runner
+/// to indicate any other error.
+pub type JxlParallelRetCode = c_int;
+
+/// Code returned by the [`JxlParallelRunInit`] function to indicate success.
+pub const JXL_PARALLEL_RET_SUCCESS: JxlParallelRetCode = 0;
+
+/// Code returned by the [`JxlParallelRunInit`] function to indicate a general error.
+pub const JXL_PARALLEL_RET_RUNNER_ERROR: JxlParallelRetCode = -1;
+
+/// Parallel run initialization callback. See [`JxlParallelRunner`] for details.
+///
+/// This function MUST be called by the [`JxlParallelRunner`] only once, on the
+/// same thread that called [`JxlParallelRunner`], before any parallel
+/// execution. The purpose of this call is to provide the maximum number of
+/// threads that the [`JxlParallelRunner`] will use, which can be used by JPEG XL
+/// to allocate per-thread storage if needed.
+///
+/// # Parameters
+/// - `jpegxl_opaque`: the `jpegxl_opaque` handle provided to
+/// [`JxlParallelRunner`] must be passed here.
+/// - `num_threads`: the maximum number of threads. This value must be
+/// positive.
+///
+/// # Returns
+/// - `0` if the initialization process was successful.
+/// - An error code if there was an error, which should be returned by
+/// [`JxlParallelRunner`].
+pub type JxlParallelRunInit = unsafe extern "C-unwind" fn(
+ jpegxl_opaque: *mut c_void,
+ num_threads: usize,
+) -> JxlParallelRetCode;
+
+/// Parallel run data processing callback. See [`JxlParallelRunner`] for
+/// details.
+///
+/// This function MUST be called once for every number in the range `[start_range,
+/// end_range)` (including `start_range` but not including `end_range`) passing this
+/// number as the `value`. Calls for different values may be executed from
+/// different threads in parallel.
+///
+/// # Parameters
+/// - `jpegxl_opaque`: the `jpegxl_opaque` handle provided to
+/// [`JxlParallelRunner`] must be passed here.
+/// - `value`: the number in the range `[start_range, end_range)` of the call.
+/// - `thread_id`: the thread number where this function is being called from.
+/// This must be lower than the `num_threads` value passed to
+/// [`JxlParallelRunInit`].
+pub type JxlParallelRunFunction =
+ unsafe extern "C-unwind" fn(jpegxl_opaque: *mut c_void, value: u32, thread_id: usize);
+
+/// [`JxlParallelRunner`] function type. A parallel runner implementation can be
+/// provided by a JPEG XL caller to allow running computations in multiple
+/// threads. This function must call the initialization function [`init`](JxlParallelRunInit) in the
+/// same thread that called it and then call the passed [`func`](JxlParallelRunFunction) once for every
+/// number in the range `[start_range, end_range)` (including `start_range` but not
+/// including `end_range`) possibly from different multiple threads in parallel.
+///
+/// The [`JxlParallelRunner`] function does not need to be re-entrant. This
+/// means that the same [`JxlParallelRunner`] function with the same
+/// `runner_opaque` provided parameter will not be called from the library from
+/// either [`init`](JxlParallelRunInit) or [`func`](JxlParallelRunFunction) in the same decoder or encoder instance.
+/// However, a single decoding or encoding instance may call the provided [`JxlParallelRunner`] multiple
+/// times for different parts of the decoding or encoding process.
+///
+/// # Returns
+/// - `0`: if the [`init`](JxlParallelRunInit) call succeeded (returned `0`) and no other error
+/// occurred in the runner code.
+/// - [`JXL_PARALLEL_RET_RUNNER_ERROR`]: if an error occurred in the runner
+/// code, for example, setting up the threads.
+/// - The return value of [`init()`](JxlParallelRunInit) if non-zero.
+pub type JxlParallelRunner = unsafe extern "C-unwind" fn(
+ runner_opaque: *mut c_void,
+ jpegxl_opaque: *mut c_void,
+ init: JxlParallelRunInit,
+ func: JxlParallelRunFunction,
+ start_range: u32,
+ end_range: u32,
+) -> JxlParallelRetCode;
diff --git a/jpegxl-sys/src/threads/resizable_parallel_runner.rs b/jpegxl-sys/src/threads/resizable_parallel_runner.rs
new file mode 100644
index 0000000..4b57ad2
--- /dev/null
+++ b/jpegxl-sys/src/threads/resizable_parallel_runner.rs
@@ -0,0 +1,68 @@
+/*!
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Implementation using `std::thread` of a resizeable [`JxlParallelRunner`].
+
+//! Implementation of [`JxlParallelRunner`] than can be used to enable
+//! multithreading when using the JPEG XL library. This uses `std::thread`
+//! internally and related synchronization functions. The number of threads
+//! created can be changed after creation of the thread pool; the threads
+//! (including the main thread) are re-used for every
+//! `ResizableParallelRunner::Runner` call. Only one concurrent
+//! [`JxlResizableParallelRunner`] call per instance is allowed at a time.
+//!
+//! This is a scalable, lower-overhead thread pool runner, especially suitable
+//! for data-parallel computations in the fork-join model, where clients need to
+//! know when all tasks have completed.
+//!
+//! Compared to the implementation in [`super::thread_parallel_runner`], this
+//! implementation is tuned for execution on lower-powered systems, including
+//! for example ARM CPUs with big.LITTLE computation models.
+
+use std::ffi::c_void;
+
+#[cfg(doc)]
+use super::parallel_runner::JxlParallelRunner;
+use super::parallel_runner::{JxlParallelRetCode, JxlParallelRunFunction, JxlParallelRunInit};
+use crate::common::memory_manager::JxlMemoryManager;
+
+extern "C-unwind" {
+ /// Parallel runner internally using `std::thread`. Use as [`JxlParallelRunner`].
+ pub fn JxlResizableParallelRunner(
+ runner_opaque: *mut c_void,
+ jpegxl_opaque: *mut c_void,
+ init: JxlParallelRunInit,
+ func: JxlParallelRunFunction,
+ start_range: u32,
+ end_range: u32,
+ ) -> JxlParallelRetCode;
+
+ /// Creates the runner for [`JxlResizableParallelRunner`]. Use as the opaque
+ /// runner. The runner will execute tasks on the calling thread until
+ /// [`JxlResizableParallelRunnerSetThreads`] is called.
+ pub fn JxlResizableParallelRunnerCreate(memory_manager: *const JxlMemoryManager)
+ -> *mut c_void;
+
+ /// Changes the number of threads for [`JxlResizableParallelRunner`].
+ pub fn JxlResizableParallelRunnerSetThreads(runner_opaque: *mut c_void, num_threads: usize);
+
+ /// Suggests a number of threads to use for an image of given size.
+ pub fn JxlResizableParallelRunnerSuggestThreads(xsize: u64, ysize: u64) -> u32;
+
+ /// Destroys the runner created by [`JxlResizableParallelRunnerCreate`].
+ pub fn JxlResizableParallelRunnerDestroy(runner_opaque: *mut c_void);
+}
diff --git a/jpegxl-sys/src/threads/thread_parallel_runner.rs b/jpegxl-sys/src/threads/thread_parallel_runner.rs
new file mode 100644
index 0000000..dadff93
--- /dev/null
+++ b/jpegxl-sys/src/threads/thread_parallel_runner.rs
@@ -0,0 +1,66 @@
+/*
+This file is part of jpegxl-sys.
+
+jpegxl-sys is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+jpegxl-sys is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with jpegxl-sys. If not, see .
+*/
+
+//! Implementation using `std::thread` of a [`JxlParallelRunner`].
+
+//! Implementation of [`JxlParallelRunner`] that can be used to enable
+//! multithreading when using the JPEG XL library. This uses `std::thread`
+//! internally and related synchronization functions. The number of threads
+//! created is fixed at construction time and the threads are re-used for every
+//! `ThreadParallelRunner::Runner` call. Only one concurrent
+//! `JxlThreadParallelRunner` call per instance is allowed at a time.
+//!
+//! This is a scalable, lower-overhead thread pool runner, especially suitable
+//! for data-parallel computations in the fork-join model, where clients need to
+//! know when all tasks have completed.
+//!
+//! This thread pool can efficiently load-balance millions of tasks using an
+//! atomic counter, thus avoiding per-task virtual or system calls. With 48
+//! hyperthreads and 1M tasks that add to an atomic counter, overall runtime is
+//! 10-20x higher when using `std::async`, and ~200x for a queue-based thread
+//! pool.
+
+use std::ffi::c_void;
+
+#[cfg(doc)]
+use super::parallel_runner::JxlParallelRunner;
+use super::parallel_runner::{JxlParallelRetCode, JxlParallelRunFunction, JxlParallelRunInit};
+use crate::common::memory_manager::JxlMemoryManager;
+
+extern "C-unwind" {
+ /// Parallel runner internally using `std::thread`. Use as [`JxlParallelRunner`].
+ pub fn JxlThreadParallelRunner(
+ runner_opaque: *mut c_void,
+ jpegxl_opaque: *mut c_void,
+ init: JxlParallelRunInit,
+ func: JxlParallelRunFunction,
+ start_range: u32,
+ end_range: u32,
+ ) -> JxlParallelRetCode;
+
+ /// Creates the runner for [`JxlThreadParallelRunner`]. Use as the opaque runner.
+ pub fn JxlThreadParallelRunnerCreate(
+ memory_manager: *const JxlMemoryManager,
+ num_worker_threads: usize,
+ ) -> *mut c_void;
+
+ /// Destroys the runner created by [`JxlThreadParallelRunnerCreate`].
+ pub fn JxlThreadParallelRunnerDestroy(runner_opaque: *mut c_void);
+
+ /// Returns a default `num_worker_threads` value for [`JxlThreadParallelRunnerCreate`].
+ pub fn JxlThreadParallelRunnerDefaultNumWorkerThreads() -> usize;
+}
diff --git a/jpegxl-sys/src/types.rs b/jpegxl-sys/src/types.rs
deleted file mode 100644
index 32dbfdd..0000000
--- a/jpegxl-sys/src/types.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-This file is part of jpegxl-sys.
-
-jpegxl-sys is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-jpegxl-sys is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with jpegxl-sys. If not, see .
-*/
-
-use std::ffi::c_char;
-
-#[repr(i32)]
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum JxlBool {
- True = 1,
- False = 0,
-}
-
-impl From for JxlBool {
- fn from(b: bool) -> Self {
- if b {
- JxlBool::True
- } else {
- JxlBool::False
- }
- }
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlDataType {
- Float = 0,
- Uint8 = 2,
- Uint16 = 3,
- Float16 = 5,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlEndianness {
- Native = 0,
- Little,
- Big,
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct JxlPixelFormat {
- pub num_channels: u32,
- pub data_type: JxlDataType,
- pub endianness: JxlEndianness,
- pub align: usize,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum JxlBitDepthType {
- BitDepthFromPixelFormat = 0,
- BitDepthFromCodestream = 1,
- BitDepthCustom = 2,
-}
-
-#[repr(C)]
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
-pub struct JxlBitDepth {
- type_: JxlBitDepthType,
- bits_per_sample: u32,
- exponent_bits_per_sample: u32,
-}
-
-#[repr(transparent)]
-pub struct JxlBoxType(pub [c_char; 4]);