The binary PGM and PPM formats store 16-bit samples most significant
byte first. The decoder and encoder read and wrote them in native
little-endian order, so every wide sample was byte swapped. This
corrects the swizzled colors reported for 16-bit PPM images.
- Reverse the sample byte order in BinaryDecoder and BinaryEncoder.
- Fix integer division in the max pixel value upscale factor.
- Add exact-value, reference-decoder, upscale, and round-trip tests.
- Add a 16-bit PPM test image and its Magick-anchored reference PNG.
- Document the binary decoder and encoder in full.
Tightened icon frame bounds validation to treat `ImageOffset == available` as invalid, preventing non-empty resources from starting at the exclusive end of the icon stream. Added a regression test that mutates an ICO directory entry to this boundary value and verifies both `Decode` and `Identify` throw `InvalidImageContentException` with the expected message.
Fixes EXIF serialization when `ExifLong8Array` downgrades to `ExifDataType.Long` but still stores values as `ulong`. `ExifWriter.WriteValue` now handles `ulong` inputs in the `Long` branch by writing 32-bit values, and a BigTIFF metadata test verifies mixed in-range values are written correctly as two little-endian `uint`s.
Update TIFF metadata creation to build ImageMetadata after IFD tag processing and copy root-frame EXIF/ICC/IPTC/XMP profiles to image scope via deep clones. This keeps image-level metadata in sync for downstream single-frame encoders while preserving independent mutability between frame and image metadata. Tests now cover preserved ICC handling and verify image-level profile presence, equality, and non-shared instances for EXIF/XMP/IPTC, including ignore-metadata behavior.
Handle CgBI chunks consistently when they appear after IHDR by routing both identify/decode paths through a new `ReadCgbiChunk()` method that immediately validates already-read headers. This prevents invalid CgBI images from bypassing compatibility checks when chunk order is unusual. Added PNG tests that reorder the first two chunks to confirm incompatible CgBI headers now throw in both identify and decode flows. Also renames `ZlibInflateStream` to `ZlibInflateReader` and updates EXR/PNG/TIFF call sites for clearer intent.
Introduce explicit associated/unassociated pixel conversion APIs across `IPixel` and `PixelOperations`, and rework associated-alpha operations to use representation-aware bulk hooks. Update pixel implementations, converters, blenders, and generated code to consistently apply `Premultiply`/`UnPremultiply` semantics, plus SIMD-backed conversion paths for half and signed formats.
Fix codec and processing behavior where alpha handling was incorrect or lossy (notably TIFF/EXR decode/encode, convolution/resize/filter/normalization/dithering paths), and add targeted tests for these cases. Expand AOT compiler roots (including EXR and additional pixel/processor coverage), add a new public API test project for pixel-operations extensibility, and add broad alpha-representation and quantization regression coverage.
Refactors `Color` to track both exposed and stored alpha representations, adds `ToScaledVector4(PixelAlphaRepresentation)`, and adjusts pixel conversion paths so associated formats preserve canonical values without unnecessary unpremultiply/reassociate loss. This also updates equality/hash behavior to compare canonical scaled values.
SIMD helpers are split into `MultiplyAddEstimate` vs `FusedMultiplyAdd`, with byte-to-float normalization updated to match scalar rounding exactly across vector widths. JPEG converters, resize kernels, and Porter-Duff/associated-alpha blending paths were updated to use the appropriate helper for either fast estimate or strict fused rounding semantics. Tests were expanded substantially (including exhaustive component/alpha cases and fused-order checks), incidental test cleanup was applied, benchmark comment snapshots were refreshed, and one black/white reference output image was updated.
- Change >= to > for correct MaxFrames boundary
- Skip fdAT chunk data when hitting maxFrames in Identify to maintain stream alignment
- Add tests for Identify and Load with MaxFrames
The Identify method had two bugs when processing fdAT (FrameData) chunks:
1. A spurious Skip(4) before SkipChunkDataAndCrc caused the stream to
be misaligned by 4 bytes, since chunk.Length already includes the
4-byte sequence number.
2. Unlike Decode, which consumes all fdAT chunks for a frame in one shot
via ReadScanlines + ReadNextFrameDataChunk, Identify processed them
individually, calling InitializeFrameMetadata for each chunk and
inflating the frame count.
The fix removes the extra Skip(4) and adds SkipRemainingFrameDataChunks
to consume all continuation fdAT chunks for a frame, mirroring how
ReadNextFrameDataChunk works during decoding.