Skip to content

Commit ffbc30f

Browse files
authored
Merge pull request #151 from iron-software/DW-39-support-large-tiff-streaming
DW-39: Support TIFF files larger than 2 GB via page-by-page streaming
2 parents d7c1983 + ec97898 commit ffbc30f

2 files changed

Lines changed: 323 additions & 23 deletions

File tree

IronSoftware.Drawing/IronSoftware.Drawing.Common.Tests/UnitTests/AnyBitmapFunctionality.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,75 @@ public void Try_UnLoad_Tiff_Image()
581581
Assert.Equal(2, anyBitmap.FrameCount);
582582
}
583583

584+
[FactWithAutomaticDisplayName]
585+
public void FromTiffFile_StreamsMultiPageTiff_MatchesFromFile()
586+
{
587+
string tiffPath = GetRelativeFilePath("IRON-274-39065.tif");
588+
589+
// Baseline: the standard in-memory loader.
590+
var expected = AnyBitmap.FromFile(tiffPath);
591+
592+
// Streaming loader: the path used automatically for TIFF files > ~2 GB.
593+
var streamed = AnyBitmap.FromTiffFile(tiffPath);
594+
595+
streamed.FrameCount.Should().Be(expected.FrameCount);
596+
597+
var expectedFrames = expected.GetAllFrames.ToList();
598+
var streamedFrames = streamed.GetAllFrames.ToList();
599+
streamedFrames.Count.Should().Be(expectedFrames.Count);
600+
for (int i = 0; i < expectedFrames.Count; i++)
601+
{
602+
streamedFrames[i].Width.Should().Be(expectedFrames[i].Width);
603+
streamedFrames[i].Height.Should().Be(expectedFrames[i].Height);
604+
}
605+
606+
// Content equivalence, not just dimensions: the decoded pixels of each
607+
// page must match the in-memory loader.
608+
for (int i = 0; i < expectedFrames.Count; i++)
609+
{
610+
expectedFrames[i].SaveAs($"expected-frame{i}.png");
611+
streamedFrames[i].SaveAs($"streamed-frame{i}.png");
612+
AssertImageAreEqual($"expected-frame{i}.png", $"streamed-frame{i}.png");
613+
}
614+
}
615+
616+
[FactWithAutomaticDisplayName]
617+
public void FromTiffFile_RawBytesAndFormat_ReportTiff()
618+
{
619+
string tiffPath = GetRelativeFilePath("IRON-274-39065.tif");
620+
621+
var streamed = AnyBitmap.FromTiffFile(tiffPath);
622+
623+
// The streamed bitmap keeps no original byte[]; the raw-byte accessors and
624+
// GetImageFormat must re-encode the pages as a multi-page TIFF (matching
625+
// FromFile) rather than reporting a single-page BMP.
626+
streamed.GetImageFormat().Should().Be(AnyBitmap.ImageFormat.Tiff);
627+
628+
byte[] bytes = streamed.GetBytes();
629+
var roundTrip = AnyBitmap.FromBytes(bytes);
630+
roundTrip.GetImageFormat().Should().Be(AnyBitmap.ImageFormat.Tiff);
631+
roundTrip.FrameCount.Should().Be(streamed.FrameCount);
632+
}
633+
634+
[FactWithAutomaticDisplayName]
635+
public void FromTiffFile_StreamsEveryPage_OfMultiPageTiff()
636+
{
637+
string tiffPath = GetRelativeFilePath("test_dw_10.tif");
638+
639+
var expected = AnyBitmap.FromFile(tiffPath);
640+
var streamed = AnyBitmap.FromTiffFile(tiffPath);
641+
642+
streamed.FrameCount.Should().Be(expected.FrameCount);
643+
streamed.FrameCount.Should().BeGreaterThan(1);
644+
}
645+
646+
[FactWithAutomaticDisplayName]
647+
public void FromTiffFile_MissingFile_ThrowsFileNotFound()
648+
{
649+
Action act = () => AnyBitmap.FromTiffFile(GetRelativeFilePath("does-not-exist-DW39.tiff"));
650+
act.Should().Throw<FileNotFoundException>();
651+
}
652+
584653
[FactWithAutomaticDisplayName]
585654
public void Create_Multi_page_Tiff()
586655
{

0 commit comments

Comments
 (0)