From 62aa36c4d07bfc80b250db734e138a39122d115c Mon Sep 17 00:00:00 2001 From: popow Date: Sat, 15 Dec 2018 16:18:55 +0100 Subject: [PATCH 1/5] added parsing of the OS22XBITMAPHEADER short variant (16 bytes) --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 5 ++++ src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 24 +++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index ef3ca24ee8..f6eb78ea9d 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -510,6 +510,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp // 12 bytes this.infoHeader = BmpInfoHeader.ParseCore(buffer); } + else if (headerSize == BmpInfoHeader.Os2Short) + { + // 16 bytes + this.infoHeader = BmpInfoHeader.ParseOs2Short(buffer); + } else if (headerSize >= BmpInfoHeader.Size) { // >= 40 bytes diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 4dd63a9626..a32f806a94 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -26,6 +26,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public const int CoreSize = 12; + /// + /// Defines the size of the short variant of the OS22XBITMAPHEADER data structure in the bitmap file. + /// + public const int Os2Short = 16; + /// /// Defines the size of the biggest supported header data structure in the bitmap file. /// @@ -143,7 +148,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Parses the BITMAPCOREHEADER consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes). /// - /// The data to parse, + /// The data to parse. /// Parsed header /// public static BmpInfoHeader ParseCore(ReadOnlySpan data) @@ -156,6 +161,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(10, 2))); } + /// + /// Parses a short variant of the OS22XBITMAPHEADER. It is identical to the BITMAPCOREHEADER, except that the width and height + /// are 4 bytes instead of 2. + /// + /// The data to parse. + /// Parsed header + /// + public static BmpInfoHeader ParseOs2Short(ReadOnlySpan data) + { + return new BmpInfoHeader( + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), + height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), + planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), + bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2))); + } + public unsafe void WriteTo(Span buffer) { ref BmpInfoHeader dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer)); From c0a0c6ec952d124d104926b17ae51b2a90b5ed7d Mon Sep 17 00:00:00 2001 From: popow Date: Sat, 15 Dec 2018 17:20:48 +0100 Subject: [PATCH 2/5] added unit test for decoding OS2 bitmap with 16 bytes header --- .../Formats/Bmp/BmpDecoderTests.cs | 30 ++++++++++++++----- tests/Images/Input/Bmp/pal8os2v2-16.bmp | 3 ++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 tests/Images/Input/Bmp/pal8os2v2-16.bmp diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 5f2de9f51e..dc858f9500 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -88,19 +88,33 @@ namespace SixLabors.ImageSharp.Tests } } - [Theory] - [MemberData(nameof(RatioFiles))] - public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) + [Fact] + public void DecodeOs22XShortHeader_VeryfyDimensions() { + string imagePath = @"Bmp/pal8os2v2-16.bmp"; var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { var decoder = new BmpDecoder(); - IImageInfo image = decoder.Identify(Configuration.Default, stream); - ImageMetaData meta = image.MetaData; - Assert.Equal(xResolution, meta.HorizontalResolution); - Assert.Equal(yResolution, meta.VerticalResolution); - Assert.Equal(resolutionUnit, meta.ResolutionUnits); + using (Image image = decoder.Decode(Configuration.Default, stream)) + { + Assert.Equal(127, image.Width); + Assert.Equal(64, image.Height); + } + } + } + + [Fact] + public void IdentifyOs22XShortHeader_VeryfyDimensions() + { + string imagePath = @"Bmp/pal8os2v2-16.bmp"; + var testFile = TestFile.Create(imagePath); + using (var stream = new MemoryStream(testFile.Bytes, false)) + { + IImageInfo imageInfo = Image.Identify(stream); + Assert.Equal(127, imageInfo.Width); + Assert.Equal(64, imageInfo.Height); + Assert.Equal(8, imageInfo.PixelType.BitsPerPixel); } } } diff --git a/tests/Images/Input/Bmp/pal8os2v2-16.bmp b/tests/Images/Input/Bmp/pal8os2v2-16.bmp new file mode 100644 index 0000000000..7cc99c56f7 --- /dev/null +++ b/tests/Images/Input/Bmp/pal8os2v2-16.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8085c60533095d9a756009f84c050d01605fc029a980a13d1bdabe943c50de5a +size 9246 From d446c0cb7dca13d312c7d7b25ca5d9077b81550d Mon Sep 17 00:00:00 2001 From: popow Date: Sun, 16 Dec 2018 21:36:29 +0100 Subject: [PATCH 3/5] Os2Short -> Os22ShortSize --- src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs | 4 ++-- src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index f6eb78ea9d..2226a1ec98 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -510,10 +510,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp // 12 bytes this.infoHeader = BmpInfoHeader.ParseCore(buffer); } - else if (headerSize == BmpInfoHeader.Os2Short) + else if (headerSize == BmpInfoHeader.Os22ShortSize) { // 16 bytes - this.infoHeader = BmpInfoHeader.ParseOs2Short(buffer); + this.infoHeader = BmpInfoHeader.ParseOs22Short(buffer); } else if (headerSize >= BmpInfoHeader.Size) { diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index a32f806a94..5177bc325c 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Defines the size of the short variant of the OS22XBITMAPHEADER data structure in the bitmap file. /// - public const int Os2Short = 16; + public const int Os22ShortSize = 16; /// /// Defines the size of the biggest supported header data structure in the bitmap file. @@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The data to parse. /// Parsed header /// - public static BmpInfoHeader ParseOs2Short(ReadOnlySpan data) + public static BmpInfoHeader ParseOs22Short(ReadOnlySpan data) { return new BmpInfoHeader( headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), From c4d80dbbf4258fa509922b420d1633fdf06fba72 Mon Sep 17 00:00:00 2001 From: popow Date: Tue, 18 Dec 2018 20:29:21 +0100 Subject: [PATCH 4/5] updated unit test to be in line with the other tests --- .../Formats/Bmp/BmpDecoderTests.cs | 33 +++++-------------- tests/ImageSharp.Tests/TestImages.cs | 1 + 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index dc858f9500..2d6a5474d6 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -11,6 +11,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests { using SixLabors.ImageSharp.MetaData; + using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using static TestImages.Bmp; public class BmpDecoderTests @@ -88,33 +89,15 @@ namespace SixLabors.ImageSharp.Tests } } - [Fact] - public void DecodeOs22XShortHeader_VeryfyDimensions() - { - string imagePath = @"Bmp/pal8os2v2-16.bmp"; - var testFile = TestFile.Create(imagePath); - using (var stream = new MemoryStream(testFile.Bytes, false)) - { - var decoder = new BmpDecoder(); - using (Image image = decoder.Decode(Configuration.Default, stream)) - { - Assert.Equal(127, image.Width); - Assert.Equal(64, image.Height); - } - } - } - - [Fact] - public void IdentifyOs22XShortHeader_VeryfyDimensions() + [Theory] + [WithFile(Os2v2Short, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_Os2v2XShortHeader(TestImageProvider provider) + where TPixel : struct, IPixel { - string imagePath = @"Bmp/pal8os2v2-16.bmp"; - var testFile = TestFile.Create(imagePath); - using (var stream = new MemoryStream(testFile.Bytes, false)) + using (Image image = provider.GetImage(new BmpDecoder())) { - IImageInfo imageInfo = Image.Identify(stream); - Assert.Equal(127, imageInfo.Width); - Assert.Equal(64, imageInfo.Height); - Assert.Equal(8, imageInfo.PixelType.BitsPerPixel); + image.DebugSave(provider, "png"); + image.CompareToOriginal(provider); } } } diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 1144a3f7c0..8e226d337d 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -201,6 +201,7 @@ namespace SixLabors.ImageSharp.Tests public const string Bit16 = "Bmp/test16.bmp"; public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; public const string Bit32Rgb = "Bmp/rgb32.bmp"; + public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public static readonly string[] All = { From f2a4c4bfd65174e897acb6ede01d0066566c3f55 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 20 Dec 2018 20:30:07 +1100 Subject: [PATCH 5/5] Disable comparison since the reference decoders cannpt decode the image. --- tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 2d6a5474d6..98c3c194df 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -11,7 +11,6 @@ using Xunit; namespace SixLabors.ImageSharp.Tests { using SixLabors.ImageSharp.MetaData; - using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using static TestImages.Bmp; public class BmpDecoderTests @@ -97,7 +96,10 @@ namespace SixLabors.ImageSharp.Tests using (Image image = provider.GetImage(new BmpDecoder())) { image.DebugSave(provider, "png"); - image.CompareToOriginal(provider); + + // TODO: Neither System.Drawing not MagickReferenceDecoder + // can correctly decode this file. + // image.CompareToOriginal(provider); } } }