JXL documentation told us to ignore EXIF because orientation is
encoded in the stream itself.
ImageMagick was keeping the EXIF but not setting the stream.
Both should be kept and synchronized.
* setting plane count and bit depth
* setting image type to palette type to mirror setimagemonochrome's logic
* working version 1
* unit tests
* leave extra unit tests only
* improve code style
* rm magicktype header
* rm comment
* rm am makefile
* leave extra unit tests only
* put unit tests in right place!
* restore makefile.am from tests
* remove tests
* remove extra newlines to match style
* remove extra newlines to match style in if/elses
* remove palettetype setting
* use correct naming in if/else
* windows build fix
Co-authored-by: Dirk Lemstra <dirk@lemstra.org>
---------
Co-authored-by: Dirk Lemstra <dirk@lemstra.org>
Skip writing FRAM mode 4 disposal chunks in WriteOnePNGImage when
DEFI handles frame positioning. The extra FRAM chunks with delay=0
were conflicting with the FRAM mode 3 already set by WriteMNGImage,
causing incorrect playback speed.
* Fix JXL animated export transparent blending and offset frames
- Enforced alpha_trait normalization using TransparentAlphaChannel for missing alpha channels to prevent solid white backgrounds when converting sequences containing mixed transparencies.
- Removed strict geometry checks from JXLSameFrameType inside JXL encoder and moved buffer allocation natively into the sequential frame loop to accurately allocate dynamically varying dimensions.
- Populated JxlFrameHeader layer info parameters (have_crop, crop_x0, etc) to appropriately support animation sub-frames.
- Correctly parsed image->previous->dispose property to map ImageMagick's dispose rules straight into JXL's blendmode behaviors (JXL_BLEND_REPLACE vs JXL_BLEND_BLEND) safely on both color and alpha channels.
* Variable name frame makes more sense than next in this context
* Fix white areas in animated JXL exports by using OpaqueAlphaChannel instead of TransparentAlphaChannel
* Rename next variable to frame in JXLSameFrameType
* Fix AVIF/HEIC animation export error on sequences with mixed alpha bounds
- Normalizes alpha traits via TransparentAlphaChannel prior to heif frame processing, similar to JXL, fulfilling libheif's strict requirement to uniformly present either an alpha channel across every frame or entirely omit alpha tracking.
* Variable name frame makes more sense than next in this context
When writing APNG via ffmpeg in the VIDEO coder, ImageMagick bypasses the frame
duplication hack (by setting length_of_delay_loop = 1). As a result, exactly one
intermediate file is passed to ffmpeg for each original frame. Because ffmpeg
assumes 25 fps for image sequence inputs and no framerate was explicitly passed,
the output APNG was always forced to exactly 25 fps (40ms per frame), ignoring
the actual image delay.
This commit appends a precise setpts and -r override to the ffmpeg options
for APNG outputs, stretching or squeezing the input PTS perfectly to match
the requested time_per_frame and ensuring the correct APNG metadata is written.
* Add animated AVIF (image sequence) reading support via libheif sequence API
Use heif_sequences.h track API (libheif >= 1.19.0) to decode animated
AVIF files. When a HEIF container has an image sequence, frames are
decoded from the visual track with proper per-frame delay/timing
derived from the track timescale. Falls back to the existing top-level
images approach for non-animated files.
Key changes:
- Include heif_sequences.h for libheif >= 1.19.0
- Add ReadHEICSequenceFrames() using heif_track_decode_next_image()
- Detect sequences with heif_context_has_sequence() before falling
back to the primary image / top-level images path
- Set ticks_per_second from track timescale, delay from frame duration
- Properly propagate alpha trait and BackgroundDispose to all frames
* Add animated AVIF sequence writing support via libheif track API
When writing AVIF with multiple frames (adjoin mode), use the libheif
sequence track API (>= 1.19.0) to produce proper animated AVIF output
instead of encoding frames as separate top-level images.
Key changes:
- Add WriteHEICSequenceImage() that creates a visual sequence track
and encodes frames with heif_track_encode_sequence_image()
- Set track timescale from image->ticks_per_second and frame duration
from image->delay via heif_track_options_set_timescale() and
heif_image_set_duration()
- Set sequence-level timescale with heif_context_set_sequence_timescale()
to ensure proper duration computation in the output file
- Route multi-frame AVIF writes through the sequence writer in
WriteHEICImage(), falling back to the existing still-image path
for single frames and non-AVIF formats
- Supports quality, speed, chroma, and ICC profile options
* Some checks and cleanup
* Fix error handling logic in heic writer loops
When an error occurred in heif_image_create or heif_track_encode_sequence_image
during a multi-frame encode, the loop would break but 'status' was never set
to MagickFalse (it retained the initialized MagickTrue value). This caused the
encoder to proceed to write a potentially empty/corrupt file and incorrectly
report success.
This logic bug was present in the existing WriteHEICImage as well as the new
WriteHEICSequenceImage. Fixed both to properly assign IsHEIFSuccess to status
before breaking on error.
* Auto-coalesce images dynamically on encode for APNG/AVIF sequences
Since libheif requires every frame of a sequence encode to match the dimensions and placement expected by the track precisely, formats like GIF that use delta-frames (smaller dimensions + page offsets) caused the encoding loop to fail on the unequal frame sizes. We now detect this dynamically in WriteHEICImage and CoalesceImages if necessary to guarantee fully-baked frames before hitting WriteHEICSequenceImage.
* Update sequence API checks to require libheif >= 1.20.0
* Restore libheif >= 1.19.0 checks for security limits
JXL delivers fully coalesced frames where each frame is a complete
independent image. Without setting dispose, converting transparent
animated JXL to GIF/WebP/MNG causes frames to accumulate instead
of replacing, making previous frames bleed through transparent areas.
The video coder duplicates frames to simulate timing at a fixed
framerate for video formats. APNG supports per-frame delays natively
via fcTL chunks, so this duplication is unnecessary and causes the
output to have double (or more) the expected number of frames.