Skip to content

Commit 6c3a9c9

Browse files
committed
Fixed corruption of true 3-byte Rgb24 input
1 parent 85fdaf0 commit 6c3a9c9

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,37 @@ public void CreateMultiFrameTiffStream_Empty_Sequence_Throws()
676676
act.Should().Throw<ArgumentException>();
677677
}
678678

679+
[FactWithAutomaticDisplayName]
680+
public void CreateMultiFrameTiff_Preserves_Rgb24_Pixels()
681+
{
682+
string jpgPath = GetRelativeFilePath("mountainclimbers.jpg");
683+
using var expected = SixLabors.ImageSharp.Image.Load<Rgb24>(jpgPath);
684+
685+
using var result = AnyBitmap.CreateMultiFrameTiff(new List<string> { jpgPath });
686+
687+
result.Width.Should().Be(expected.Width);
688+
result.Height.Should().Be(expected.Height);
689+
690+
var points = new[]
691+
{
692+
(1, 0),
693+
(expected.Width - 1, 0),
694+
(expected.Width / 3, expected.Height / 2),
695+
(expected.Width / 2, expected.Height / 3),
696+
(0, expected.Height - 1),
697+
(expected.Width - 1, expected.Height - 1)
698+
};
699+
700+
foreach (var (x, y) in points)
701+
{
702+
Rgb24 e = expected[x, y];
703+
var a = result.GetPixel(x, y);
704+
a.R.Should().Be(e.R, $"red channel at ({x},{y})");
705+
a.G.Should().Be(e.G, $"green channel at ({x},{y})");
706+
a.B.Should().Be(e.B, $"blue channel at ({x},{y})");
707+
}
708+
}
709+
679710
private static AnyBitmap CreateSolidBitmap(int width, int height, Rgb24 color, int dpi)
680711
{
681712
var image = new SixLabors.ImageSharp.Image<Rgb24>(width, height, color);

IronSoftware.Drawing/IronSoftware.Drawing.Common/AnyBitmap.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3409,7 +3409,15 @@ private static void InternalSaveAsMultiPageTiff(IEnumerable<Image> images, Strea
34093409
switch (image)
34103410
{
34113411
case Image<Rgb24> imageAsFormat:
3412-
imageAsFormat.CopyPixelDataTo(buffer);
3412+
{
3413+
// Rgb24 is 3 bytes/pixel, but the buffer/stride above and the
3414+
// TIFF tags below are 4 samples/pixel (RGBA). Copying the 3-bpp
3415+
// data directly would leave each row short by 'width' bytes,
3416+
// shifting every subsequent row and corrupting the page. Convert
3417+
// to Rgba32 so the bytes line up with the 4-bpp layout.
3418+
using var rgba = imageAsFormat.CloneAs<Rgba32>();
3419+
rgba.CopyPixelDataTo(buffer);
3420+
}
34133421
break;
34143422
case Image<Abgr32> imageAsFormat:
34153423
imageAsFormat.CopyPixelDataTo(buffer);
@@ -3418,7 +3426,13 @@ private static void InternalSaveAsMultiPageTiff(IEnumerable<Image> images, Strea
34183426
imageAsFormat.CopyPixelDataTo(buffer);
34193427
break;
34203428
case Image<Bgr24> imageAsFormat:
3421-
imageAsFormat.CopyPixelDataTo(buffer);
3429+
{
3430+
// Bgr24 is likewise 3 bytes/pixel; convert to Rgba32 for the
3431+
// same reason as Rgb24 above (this also yields the correct
3432+
// R,G,B sample order under PHOTOMETRIC.RGB).
3433+
using var rgba = imageAsFormat.CloneAs<Rgba32>();
3434+
rgba.CopyPixelDataTo(buffer);
3435+
}
34223436
break;
34233437
case Image<Bgra32> imageAsFormat:
34243438
imageAsFormat.CopyPixelDataTo(buffer);

0 commit comments

Comments
 (0)