InsightSoftwareConsortium / InsightSoftwareConsortium/ITK

TIFFImageIO writes EXTRASAMPLE_ASSOCALPHA for non-alpha extra samples (mislabels VECTOR channels)

Open
#6,650 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
1.7k
Forks
748
Avg merge
1d 1h
Merged PRs (30d)
64

Description

## Summary

`TIFFImageIO::InternalWrite()` tags the **first extra sample** of a multi-component write as `EXTRASAMPLE_ASSOCALPHA` (premultiplied alpha) unconditionally, regardless of whether the source image is actually gray+alpha / RGBA. For ITK `VECTOR`-typed data (the common case for 2- and 4-component scientific images — displacement fields, complex data, multi-channel measurements), this mislabels an independent data channel as premultiplied alpha. Standard TIFF readers may then premultiply or otherwise reinterpret that channel, changing display and breaking round-trips through non-ITK tools.

## Where

`Modules/IO/TIFF/src/itkTIFFImageIO.cxx`, `InternalWrite()`:

```cpp
sample_info[0] = EXTRASAMPLE_ASSOCALPHA; // first extra sample
for (uint16_t cc = 1; cc < extra_samples; ++cc)
sample_info[cc] = EXTRASAMPLE_UNSPECIFIED;
```

- **4+ components:** pre-existing behavior (present before #6636).
- **2 components:** newly reaches this path via #6636 (B83), which correctly stopped writing 2-component images as `PHOTOMETRIC_RGB` and now writes `PHOTOMETRIC_MINISBLACK` + 1 extra sample — but that extra sample inherits the `ASSOCALPHA` tag.

## Why it's a design decision (not a drive-by fix)

The IO layer generally cannot distinguish "gray+alpha / RGBA with genuine premultiplied alpha" from "N-channel vector" from `NumberOfComponents` alone. Options:

1. Default all non-color extra samples to `EXTRASAMPLE_UNSPECIFIED` (safe: no reader premultiplies; loses the ability to signal genuine alpha).
2. Use `GetPixelType()` (`RGBA` → `ASSOCALPHA`, `VECTOR`/others → `UNSPECIFIED`) to pick per-image.
3. Keep `ASSOCALPHA` (status quo) and document that ITK TIFF writes assume alpha semantics for the first extra sample.

Option 2 is the most correct but changes long-standing 4-component output, so it needs maintainer sign-off and a round-trip-compatibility check. This is out of scope for the #6636 bug-fix batch.

## Related

- PR #6636 (introduces the 2-component path; greptile flagged this as P2 there)
- Raised by @greptileai review on #6636

Contributor guide

Open the contributing guide

Research direction

Read Modules/IO/TIFF/src/itkTIFFImageIO.cxx, especially InternalWrite() and the EXTRASAMPLES block around lines 694–705. Check how GetPixelType() and the 2- and 4-component paths could distinguish RGBA from VECTOR data, then verify the chosen behavior with round-trip compatibility checks. Done means non-alpha vector channels are not labeled as premultiplied alpha while genuine alpha behavior is preserved or intentionally documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-vision
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.