Instead all methods with mutable self will initialize it on-demand.
There are only few methods that take `&self` and can not do that. For
those that have no error/option return we panic but both of these could
panic previously already. This should be fine by documentation alone. In
particular, the image size can be queried safely.
The bounds `Read + Seek` are not representational so we may remove them
from the struct itself. This also allows us to use more precise bounds
for direct access to the inner stream, especially were that does not
seek.
Groups operations according to their use case.
Funnel users towards the `IfdDecoder` instead. That type does not have
a generic over the underlying reader. It also works with a directory of
your own choosing. So the duplicates that should go are those directly
on the decoder.
Most of this is slightly gratuitous for now, we have no need internally,
but especially since the enums are non-exhaustive it will probably be
appreciated that you can interact with the buffer at a byte-level.
Additionally we make the extra promise that all sample types correspond
to some supported SampleType tag value. This prepares using the same
buffer for a runtime version of `Encoder::write_image`.
log16_to_y() uses f32::exp() which is not required to be correctly
rounded by IEEE 754. Apple libm on arm64 differs by 1 ULP from glibc
on x86_64, producing different CRC32 checksums for the decoded output.
Same issue as off_luv32.tif which was already demoted in commit 617dc6e.
A deterministic LUT-based approach could fix both in a follow-up.
Three 16x16 bilevel fax3 test images covering the key Group 3 variants:
- seq-1c-1b-fax3: basic G3, no fill bits, MSB-first fill order
- seq-1c-1b-fax3-fillbits: G3 with T4Options fill bits (byte-aligned EOLs)
- seq-1c-1b-fax3-lsb: G3 with FillOrder=2 (LSB-first)
All use MinIsWhite photometric with inverted sequential pattern, producing
the same decoded CRC32 hash (71f6a21a) as the uncompressed 1-bit images.
Cross-validated: libtiff writes the images, both libtiff and image-tiff
read them back and agree on the decoded data.
Fix two CI failures on i686 and powerpc:
1. chunk_col_stride overflow: RowsPerStrip = u32::MAX causes
data_row_bytes * chunk_height to exceed 32-bit usize. Clamp
the chunk height to the image height before computing stride
values, since a chunk never contributes more rows than the
image contains. Applied to both readout_for_size() and
set_row_stride().
2. off_luv32.tif hash mismatch: the LogLuv decoder produces
platform-dependent output (different hashes on x86_64, i686,
and powerpc), so demote to smoke test.
Add YCbCrUpsamplingReader that converts chroma-subsampled YCbCr block
data to full-resolution 3-bytes-per-pixel output. Each block of h×v
pixels stores h*v Y samples plus one shared Cb and Cr sample; the
reader expands these into per-pixel (Y, Cb, Cr) triples.
This enables decoding YCbCr TIFFs with any supported compression
method (uncompressed, LZW, Deflate, etc.), not just JPEG. Two more
libtiffpic test images now decode with verified hashes:
- dscf0013.tif (uncompressed YCbCr 2,1 subsampling)
- ycbcr-cat.tif (LZW-compressed YCbCr 2,2 subsampling)
The remaining two YCbCr test images (smallliz.tif, zackthecat.tif)
use Old JPEG compression (type 6) which is a separate unsupported
feature.
Add Group3Reader for decoding CCITT Group 3 (T.4) 1D compressed TIFF
images. The fax crate's Group3Decoder has a bug where new() verifies
but doesn't consume the initial EOL marker, causing its lookup tables
to destructively consume bits from the EOL code. We work around this
by using the crate's lower-level white::decode / black::decode
functions and handling EOL markers ourselves.
Also adds FillOrder tag (266) support: FillOrder=2 (LSB-to-MSB,
common in fax images) is handled by reversing bits in each byte
before decoding. This applies to both Group 3 and Group 4 readers.
Both libtiffpic fax test images (fax2d.tif, g3test.tif) now decode
correctly with verified CRC32 hashes.
Upgrade the libtiffpic test harness from decode-only smoke tests to
full output verification using CRC32 reference hashes. 50 of 61 images
now have hash-verified decoded output; the remaining 11 use unsupported
formats (YCbCr subsampling, Fax3, etc.) and remain as decode-only tests.
Uses read_image_to_buffer (the non-deprecated API) with ByteOrder::convert
for cross-platform LE normalization.
Remove the 13 individual depth tests from decode_images.rs — they tested
the same libtiffpic flower images that are now hash-verified here.
Address PR review feedback:
- Remove benches/decode.rs which referenced non-existent gen_bench_tiff.c
- Simplify compute_tiff_hash: replace 66-line match block with
as_buffer().as_bytes() + ByteOrder::convert for LE normalization
- Use TIFF Type repr(u16) as hash discriminant instead of ad-hoc u8
- Rename all 74 seq test images to match updated hashes
Measures decode throughput for 1024x1024 gray images at various bit
depths (3-24 bit). Requires pre-generated images in /tmp/bench-tiff/
(see stderr instructions for generation).
- compute_tiff_hash now panics on unhandled ColorType variants instead
of silently using a fallback discriminant
- print_seq_hashes correctly identifies existing 8-char hex hash suffix
vs non-hash filename segments
Move 74 seq-*.tiff test images to tests/images/seq/ and embed a CRC32
hash of the full decoded output (dimensions, color type, sample data)
as the last filename segment. Replace 75 individual test functions with
one generic verify_all_seq_images test that decodes each file and
validates its hash against the filename.
This catches byte-order, bit-alignment, stride, padding, and value
errors that sum-based tests would miss (e.g., swapped pixels preserve
the sum but change the hash). Adding new test images only requires
dropping a correctly-named file in seq/ — no test code changes needed.
Replace Python-generated test TIFFs with libtiff-generated ones to
eliminate circular validation. The C program (gen_seq_tiff.c) uses
libtiff's TIFFWriteScanline with MSB-first packed bit streams.
Cross-validated: tifffile independently confirms all 27 images match
the original Python-generated versions byte-for-byte. tiffinfo validates
all IFD structures. All 27 image-tiff decode tests pass unchanged.
Previously, sub-byte bit depths (1-7 bits per sample) were only
accepted for Gray and Multiband color types. This extends the
validation to accept all color types (RGB, RGBA, CMYK, CMYKA, YCbCr)
at sub-byte depths.
The data format is unchanged: sub-byte samples remain packed MSB-first
in the output buffer, exactly as for grayscale. Predictors are still
rejected for sub-byte data.
Tested via libtiffpic flower-rgb-contig-02/04 and flower-rgb-planar-02/04.
TIFF files can store samples at non-standard bit depths (e.g. 10, 12,
14, 24 bits) packed tightly in a continuous bit stream. Previously
these were rejected as unsupported color types.
This adds:
- MSB-first bit extraction from packed byte streams (unpack_bits,
extract_bits_msb) to expand N-bit samples to standard-width output
(9-16 bit → u16, 17-32 bit → u32)
- Output buffer sizing using the promoted sample width instead of the
packed bit depth (output_bits_per_sample field in ReadoutLayout)
- A new code path in expand_chunk that reads packed rows, unpacks to
standard-width samples, then applies predictor and color inversion
- Horizontal predictor support for extended depths
Tested with 12-bit grayscale and RGB images (existing test suite),
plus all libtiffpic depth test images (10/12/14/24-bit in gray, RGB
contig, and RGB planar configurations).