Yalantis/uCrop · error · CImgIOException
load_jxl(): Does not support animated JPEG XL '%s'.
Error message
load_jxl(): Does not support animated JPEG XL '%s'.
What it means
load_jxl() only supports still images. If JxlBasicInfo.have_animation is non-zero, meaning the JXL file contains an animated sequence, the decoder is destroyed and this error is thrown. It is an explicit capability limitation, not a decode failure.
Source
Thrown at ucrop/src/main/jni/CImg.h:57193
JxlDecoderStatus status = JxlDecoderProcessInput(decoder);
if (status==JXL_DEC_SUCCESS || status==JXL_DEC_FULL_IMAGE) break;
else if (status==JXL_DEC_ERROR || status==JXL_DEC_NEED_MORE_INPUT) {
JxlDecoderDestroy(decoder);
throw CImgIOException(_cimg_instance
"load_jxl(): Failed to decode image '%s'.",
cimg_instance,
nfilename);
} else if (status==JXL_DEC_BASIC_INFO) {
if (JXL_DEC_SUCCESS!=JxlDecoderGetBasicInfo(decoder,&jxlInfo)) {
JxlDecoderDestroy(decoder);
throw CImgIOException(_cimg_instance
"load_jxl(): Failed to load image data '%s'.",
cimg_instance,
nfilename);
}
if (jxlInfo.have_animation!=0) {
JxlDecoderDestroy(decoder);
throw CImgIOException(_cimg_instance
"load_jxl(): Does not support animated JPEG XL '%s'.",
cimg_instance,
nfilename);
}
hasAlpha = jxlInfo.alpha_bits!=0;
nChannels = hasAlpha?jxlInfo.num_color_channels + 1:jxlInfo.num_color_channels;
isGray = jxlInfo.num_color_channels==1;
} else if (status==JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
std::size_t imgDataSize = 0;
format.num_channels = nChannels;
format.data_type = jxlInfo.bits_per_sample==16?JXL_TYPE_UINT16:JXL_TYPE_UINT8;
if (JXL_DEC_SUCCESS!=JxlDecoderImageOutBufferSize(decoder,&format,&imgDataSize)) {
JxlDecoderDestroy(decoder);
throw CImgIOException(_cimg_instance
"load_jxl(): Failed to decode image data '%s'.",
cimg_instance,
nfilename);
}View on GitHub (pinned to f788b534b4)
Solutions
- Detect animated JXL beforehand and handle separately (extract a frame or reject).
- Convert the animation to a still frame (first frame) with djxl/ffmpeg before loading.
- If animation support is needed, use libjxl directly or another codec path (e.g. load_gif/WebP for animation).
Example fix
// before
img.load_jxl(anim.jxl); // throws: animated
// after
// ffmpeg -i anim.jxl -frames:v 1 frame.png
img.load_png("frame.png"); Defensive patterns
Strategy: validation
Validate before calling
bool jxlIsAnimated(const char* path) {
// animation flag is only knowable via basic info; pre-screen with a probe decoder
std::FILE* f = std::fopen(path, "rb");
if (!f) return false;
// lightweight heuristic: inspect JXL container metadata or decode with libjxl directly
std::fclose(f);
return probeHaveAnimation(path); // wraps JxlDecoderGetBasicInfo
} Try / catch
try { img.load_jxl(path); } catch (CImgIOException& e) { if (strstr(e.what(), "animated")) useFirstFrameOnly(path); } Prevention
- Screen assets for animation flags during ingestion, not at load time
- Convert animated JXL to still frames or video pipeline separately
- Document that CImg load_jxl is stills-only for pipeline users
When it happens
Trigger: load_jxl(filename) is called on a JPEG XL file whose basic info reports have_animation != 0 (animated JXL, e.g. exported from an animation tool).
Common situations: Users converting GIF/APNG/WebM content to JXL and expecting CImg to read it; bulk-processing a folder that contains both still and animated .jxl assets.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- screenshot(): Screenshot feature is not supported when using
- load_jxl(): Failed to get file size '%s'.
- load_jxl(): Failed to configure decoder '%s'.
- load_jxl(): Failed to load image data '%s'.
- load_jxl(): Failed to decode image '%s'.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/0e2f14fcec052660.
Report an issue: GitHub.