Skip to content

Default a missing TIFF BitsPerSample to one bit per sample - #3230

Merged
JimBobSquarePants merged 4 commits into
SixLabors:mainfrom
jafin:jf/tiff-default-bitspersample
Oct 27, 2026
Merged

JimBobSquarePants merged 4 commits into
SixLabors:mainfrom
jafin:jf/tiff-default-bitspersample

Conversation

@jafin

@jafin jafin commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

Use one bit per sample when a TIFF directory omits BitsPerSample. SamplesPerPixel also defaults to one. TIFF 6.0 defines these defaults on pages 29 and 39. Decode and Identify now report the correct bit depth for uncompressed and CCITT Group 4 bilevel files.

Keep file defaults separate from new metadata defaults. The shared eight-bit RGB default was initialized before its source field and therefore contained zero sample depths. Initialize that alias after the RGB field, and document the distinction on the metadata types.

A present but unusable BitsPerSample entry keeps its existing handling instead of inheriting a valid RGB default. When BitsPerSample is absent, reject SamplesPerPixel values outside the supported one-to-four range instead of silently changing the declared layout. This structural check remains fatal in every SegmentIntegrityHandling mode.

Testing

All new decoder inputs are stored files. Seven small TIFFs (3,396 bytes total) are derived from the existing basi3p02_fax4 fixture. Their active IFDs are sorted, with independently verified tag values. Pillow confirms exact source pixels for all three valid missing-tag files; Group 4 decoding uses libtiff.

Tests cover uncompressed and Group 4 data, both sample tags absent, unsupported sample counts, present invalid depth tags, and new image/frame metadata defaults. Decoder cases use the public Decode and Identify paths under all integrity modes. The runtime encoder setup and tag-rewriting helper were removed.

Six of the eight focused regressions fail on current main. All eight pass with the corrections. Release .NET 10: 869 TIFF-related and shared decoder tests passed.

No tolerances or reference images changed. The branch includes current main.

Fixes #3242.

TIFF 6.0 defines a default of one bit for each sample when the BitsPerSample entry is absent, and bilevel fax
and scanner files often omit it. The decoder assumed 8-bit RGB instead, so such files failed to decode or
reported the wrong bit depth. The default now uses one bit for each of the SamplesPerPixel samples.
Keep absent file tags separate from newly constructed RGB metadata. Initialize
the shared eight-bit RGB alias after the value it references. Preserve zero
sample depths for unusable present entries instead of inheriting RGB defaults.
Reject unsupported SamplesPerPixel counts when resolving an absent BitsPerSample
tag, so the four-channel representation cannot silently change the file layout.
Document the file defaults from TIFF 6.0 pages 29 and 39 at the parsing boundary.

Replace the PR's runtime TIFF encoding and tag rewriting with seven stored files
(3396 bytes), derived from the existing basi3p02_fax4 fixture. Verify sorted IFDs
and exact tag values independently; Pillow/libtiff confirms the valid missing-tag
variants retain the original pixels. Test Decode, Identify, frame metadata, and
all integrity modes through existing APIs. Remove the tag-rewriting helper.

Six of eight focused regressions fail on current main. All eight now pass.
Release .NET 10: 869 TIFF-related and shared decoder tests passed.
No tolerances or reference images changed.
@JimBobSquarePants
JimBobSquarePants merged commit 826512f into SixLabors:main Oct 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TIFF without a BitsPerSample entry fails to decode or reports 0 bits per pixel

2 participants