Summary
Parsing a TIFF that omits the SamplesPerPixel tag (277) panics with samples_per_pixel not found instead of applying the spec default.
The TIFF 6.0 specification defines a default value of 1 for SamplesPerPixel (tag 277 reference). Many single-channel grayscale TIFFs omit the tag entirely — notably the PerkinElmer/Phenix microscopy images in the Cell Painting Gallery open dataset.
Where
src/ifd.rs:
let samples_per_pixel = samples_per_pixel.expect("samples_per_pixel not found");
Because this is an .expect() inside the async IFD parse, it surfaces (via virtual_tiff/pyo3-async-runtimes) as an uncatchable Rust panic:
thread 'tokio-rt-worker' panicked at .../async-tiff/src/ifd.rs:375:51:
samples_per_pixel not found
Reproduce
Any TIFF lacking tag 277 triggers it. A public example (single-channel 16-bit LZW grayscale, no SamplesPerPixel tag):
s3://cellpainting-gallery/cpg0000-jump-pilot/source_4/images/2020_11_04_CPJUMP1/images/BR00116991__2020-11-05T19_51_35-Measurement1/Images/r01c01f01p01-ch1sk1fk1fl1.tiff
(publicly readable with --no-sign-request).
Confirmed absent via tifffile:
import tifffile
p = tifffile.TiffFile("r01c01f01p01-ch1sk1fk1fl1.tiff").pages[0]
assert 277 not in [t.code for t in p.tags] # SamplesPerPixel omitted
Suggested fix
Fall back to the spec default of 1:
let samples_per_pixel = samples_per_pixel.unwrap_or(1);
The existing PlanarConfiguration logic just below already handles the samples_per_pixel == 1 case, so this is a self-contained change. Happy to open a PR (with a minimal regression fixture).
Summary
Parsing a TIFF that omits the
SamplesPerPixeltag (277) panics withsamples_per_pixel not foundinstead of applying the spec default.The TIFF 6.0 specification defines a default value of 1 for
SamplesPerPixel(tag 277 reference). Many single-channel grayscale TIFFs omit the tag entirely — notably the PerkinElmer/Phenix microscopy images in the Cell Painting Gallery open dataset.Where
src/ifd.rs:Because this is an
.expect()inside the async IFD parse, it surfaces (viavirtual_tiff/pyo3-async-runtimes) as an uncatchable Rust panic:Reproduce
Any TIFF lacking tag 277 triggers it. A public example (single-channel 16-bit LZW grayscale, no
SamplesPerPixeltag):(publicly readable with
--no-sign-request).Confirmed absent via
tifffile:Suggested fix
Fall back to the spec default of 1:
The existing
PlanarConfigurationlogic just below already handles thesamples_per_pixel == 1case, so this is a self-contained change. Happy to open a PR (with a minimal regression fixture).