Skip to content

V3 TIFF : Allow additional and undefined extra samples #2942

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,22 @@ internal static class TiffDecoderOptionsParser
/// <returns>True, if the image uses tiles. Otherwise the images has strip's.</returns>
public static bool VerifyAndParse(this TiffDecoderCore options, ExifProfile exifProfile, TiffFrameMetadata frameMetadata)
{
IExifValue extraSamplesExifValue = exifProfile.GetValueInternal(ExifTag.ExtraSamples);
if (extraSamplesExifValue is not null)
if (exifProfile.TryGetValue(ExifTag.ExtraSamples, out IExifValue<ushort[]> samples))
{
short[] extraSamples = (short[])extraSamplesExifValue.GetValue();
if (extraSamples.Length != 1)
// We only support a single sample pertaining to alpha data.
// Other information is discarded.
TiffExtraSampleType sampleType = (TiffExtraSampleType)samples.Value[0];
if (sampleType is TiffExtraSampleType.CorelDrawUnassociatedAlphaData)
{
TiffThrowHelper.ThrowNotSupported("ExtraSamples is only supported with one extra sample for alpha data.");
// According to libtiff, this CorelDRAW-specific value indicates unassociated alpha.
// Patch required for compatibility with malformed CorelDRAW-generated TIFFs.
// https://libtiff.gitlab.io/libtiff/releases/v3.9.0beta.html
sampleType = TiffExtraSampleType.UnassociatedAlphaData;
}

TiffExtraSampleType extraSamplesType = (TiffExtraSampleType)extraSamples[0];
options.ExtraSamplesType = extraSamplesType;
if (extraSamplesType is not (TiffExtraSampleType.UnassociatedAlphaData or TiffExtraSampleType.AssociatedAlphaData))
if (sampleType is (TiffExtraSampleType.UnassociatedAlphaData or TiffExtraSampleType.AssociatedAlphaData))
{
TiffThrowHelper.ThrowNotSupported("Decoding Tiff images with ExtraSamples is not supported with UnspecifiedData.");
options.ExtraSamplesType = sampleType;
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/ImageSharp/Formats/Tiff/TiffExtraSampleType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,11 @@ internal enum TiffExtraSampleType
/// The extra data is unassociated alpha data is transparency information that logically exists independent of an image;
/// it is commonly called a soft matte.
/// </summary>
UnassociatedAlphaData = 2
UnassociatedAlphaData = 2,

/// <summary>
/// A CorelDRAW-specific value observed in damaged files, indicating unassociated alpha.
/// Not part of the official TIFF specification; patched in ImageSharp for compatibility.
/// </summary>
CorelDrawUnassociatedAlphaData = 999
}
5 changes: 5 additions & 0 deletions tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -772,4 +772,9 @@ public void TiffDecoder_Decode_Resize<TPixel>(TestImageProvider<TPixel> provider
testOutputDetails: details,
appendPixelTypeToFileName: false);
}

[Theory]
[WithFile(ExtraSamplesUnspecified, PixelTypes.Rgba32)]
public void TiffDecoder_CanDecode_ExtraSamplesUnspecified<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => TestTiffDecoder(provider);
}
1 change: 1 addition & 0 deletions tests/ImageSharp.Tests/TestImages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,7 @@ public static class Tiff
public const string Issues2587 = "Tiff/Issues/Issue2587.tiff";
public const string JpegCompressedGray0000539558 = "Tiff/Issues/JpegCompressedGray-0000539558.tiff";
public const string Tiled0000023664 = "Tiff/Issues/tiled-0000023664.tiff";
public const string ExtraSamplesUnspecified = "Tiff/Issues/ExtraSamplesUnspecified.tif";

public const string SmallRgbDeflate = "Tiff/rgb_small_deflate.tiff";
public const string SmallRgbLzw = "Tiff/rgb_small_lzw.tiff";
Expand Down
3 changes: 3 additions & 0 deletions tests/Images/Input/Tiff/Issues/ExtraSamplesUnspecified.tif
Git LFS file not shown
Loading