pub struct JxlDecoder;
impl JxlDecoder {
pub fn decode_tile(data: &[u8]) -> crate::error::RawResult<(usize, usize, usize, Vec<u16>)> {
use crate::error::{FormatError, RawError};
use jxl_oxide::JxlImage;
let image = JxlImage::builder()
.read(std::io::Cursor::new(data))
.map_err(|e| {
RawError::Format(FormatError::Decompression(format!(
"JXL decode error: {}",
e
)))
})?;
let width = image.width() as usize;
let height = image.height() as usize;
let render = image.render_frame(0).map_err(|e| {
RawError::Format(FormatError::Decompression(format!(
"JXL render error: {}",
e
)))
})?;
let fb = render.image_all_channels();
let channels = fb.channels();
let buf = fb.buf();
let output: Vec<u16> = buf
.iter()
.map(|&v| (v.clamp(0.0, 1.0) * 65535.0) as u16)
.collect();
Ok((width, height, channels, output))
}
pub fn decode_tile_with_depth(
data: &[u8],
target_bit_depth: u8,
) -> crate::error::RawResult<(usize, usize, usize, Vec<u16>)> {
use crate::error::{FormatError, RawError};
use jxl_oxide::JxlImage;
let image = JxlImage::builder()
.read(std::io::Cursor::new(data))
.map_err(|e| {
RawError::Format(FormatError::Decompression(format!(
"JXL decode error: {}",
e
)))
})?;
let width = image.width() as usize;
let height = image.height() as usize;
let render = image.render_frame(0).map_err(|e| {
RawError::Format(FormatError::Decompression(format!(
"JXL render error: {}",
e
)))
})?;
let fb = render.image_all_channels();
let channels = fb.channels();
let buf = fb.buf();
let max_value = (1u32 << target_bit_depth) - 1;
let output: Vec<u16> = buf
.iter()
.map(|&v| (v.clamp(0.0, 1.0) * max_value as f32) as u16)
.collect();
Ok((width, height, channels, output))
}
}
#[cfg(test)]
mod tests {
use super::JxlDecoder;
#[test]
fn test_jxl_decoder_invalid_data() {
let invalid_data = vec![0u8; 10];
let result = JxlDecoder::decode_tile(&invalid_data);
assert!(result.is_err());
}
}