Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,21 @@ public void FromTiffFile_MissingFile_ThrowsFileNotFound()
act.Should().Throw<FileNotFoundException>();
}

[TheoryWithAutomaticDisplayName]
[InlineData("example.tif")] // 24 bpp
[InlineData("test_dw_10.tif")] // 1 bpp, multi-page
[InlineData("multiframe.tiff")] // 16 bpp
public void FromTiffFile_BitsPerPixel_MatchesFromFile(string fileName)
{
string tiffPath = GetRelativeFilePath(fileName);

int expected = AnyBitmap.FromFile(tiffPath).BitsPerPixel;
int streamed = AnyBitmap.FromTiffFile(tiffPath).BitsPerPixel;

streamed.Should().Be(expected,
$"FromTiffFile should report the source color depth for '{fileName}', matching FromFile");
}

[FactWithAutomaticDisplayName]
public void Create_Multi_page_Tiff()
{
Expand Down
20 changes: 17 additions & 3 deletions IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,8 @@ public static AnyBitmap FromTiffFile(string file)
}

AnyBitmap bitmap = new();
bitmap.LoadLargeTiffFromFile(file);
// Preserve the source color depth so BitsPerPixel reports it, matching FromFile.
bitmap.LoadLargeTiffFromFile(file, preserveOriginalFormat: true);
return bitmap;
}

Expand Down Expand Up @@ -3270,7 +3271,7 @@ private void LoadImageFromFile(string file, bool preserveOriginalFormat)
if (IsTiffFile(file))
{
// Stream the TIFF page-by-page; never materialise the whole file.
LoadLargeTiffFromFile(file);
LoadLargeTiffFromFile(file, preserveOriginalFormat);
return;
}

Expand Down Expand Up @@ -3315,7 +3316,12 @@ private static bool IsTiffFile(string file)
/// time through the underlying <see cref="FileStream"/>, so the entire file
/// is never allocated as one array, enabling TIFF files larger than 2 GB.
/// </summary>
private void LoadLargeTiffFromFile(string file)
/// <param name="file">A fully qualified path to a TIFF file.</param>
/// <param name="preserveOriginalFormat">When <c>true</c>, report the source
/// color depth from <see cref="BitsPerPixel"/> (as <see cref="FromFile(string)"/>
/// does) instead of the decoded 32bpp value. The pixels are always decoded to
/// Rgba32 on this path regardless of the flag.</param>
private void LoadLargeTiffFromFile(string file, bool preserveOriginalFormat)
{
Tiff.SetErrorHandler(new DisableErrorHandler());

Expand All @@ -3331,6 +3337,7 @@ private void LoadLargeTiffFromFile(string file)

try
{
// ReadTiffFrames also populates _framesOriginalBitsPerPixel (per-frame source depth).
frames = ReadTiffFrames(tiff);
}
catch (DllNotFoundException e)
Expand All @@ -3345,6 +3352,13 @@ private void LoadLargeTiffFromFile(string file)
$"The TIFF file '{file}' was opened but contained no decodable image pages.");
}

if (preserveOriginalFormat)
{
_originalBitsPerPixel = _framesOriginalBitsPerPixel != null && _framesOriginalBitsPerPixel.Count > 0
? _framesOriginalBitsPerPixel[0]
: null;
}

// Hold the decoded pages directly. Binary is deliberately NOT set: the
// source file may be larger than a single byte[] can hold. The
// _streamedFromTiff flag tells the Binary getter to re-encode the pages as
Expand Down
7 changes: 3 additions & 4 deletions NuGet/IronSoftware.Drawing.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ For general support and technical inquiries, please email us at: support@ironsof
<summary>IronSoftware.System.Drawing is an open-source solution for .NET developers to replace System.Drawing.Common with a universal and flexible library.</summary>
<releaseNotes>
Features
- Added support for creating multi-page TIFFs while preserving per-page dimensions, orientation, and resolution
- Added support for loading TIFF and BigTIFF files larger than 2 GB using a streaming loader, enabling page-by-page decoding without loading the entire file into memory
Enhancements
- Added support for converting AnyBitmap images to 8, 24, or 32 bits per pixel
- AnyBitmap now preserves the original source color depth (BitsPerPixel) across derived operations, including frame extraction, cloning, rotation, redaction, and resizing
Bug Fixes
- Fixed an issue where AnyBitmap.BitsPerPixel reported incorrect color depths for TIFF images
- Fixed issues affecting multi-page TIFF generation, including incorrect resolution metadata and corrupted output for certain RGB image formats
- Fixed an issue where derived AnyBitmap operations incorrectly reported a decoded 32bpp color depth instead of the original source pixel depth
</releaseNotes>
<copyright>Copyright © Iron Software 2022-2026</copyright>
<tags>Images, Bitmap, SkiaSharp, SixLabors, BitMiracle, Maui, SVG, TIFF, TIF, GIF, JPEG, PNG, Color, Rectangle, Drawing, C#, VB.NET, ASPX, create, render, generate, standard, netstandard2.0, core, netcore</tags>
Expand Down
Loading