diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index ef3ca24ee..2226a1ec9 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.Os22ShortSize)
+ {
+ // 16 bytes
+ this.infoHeader = BmpInfoHeader.ParseOs22Short(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 4dd63a962..5177bc325 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 Os22ShortSize = 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 ParseOs22Short(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));
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
index 5f2de9f51..98c3c194d 100644
--- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
@@ -89,18 +89,17 @@ namespace SixLabors.ImageSharp.Tests
}
[Theory]
- [MemberData(nameof(RatioFiles))]
- public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit)
+ [WithFile(Os2v2Short, PixelTypes.Rgba32)]
+ public void BmpDecoder_CanDecode_Os2v2XShortHeader(TestImageProvider provider)
+ where TPixel : struct, IPixel
{
- var testFile = TestFile.Create(imagePath);
- using (var stream = new MemoryStream(testFile.Bytes, false))
+ using (Image image = provider.GetImage(new BmpDecoder()))
{
- 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);
+ image.DebugSave(provider, "png");
+
+ // TODO: Neither System.Drawing not MagickReferenceDecoder
+ // can correctly decode this file.
+ // image.CompareToOriginal(provider);
}
}
}
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 1144a3f7c..8e226d337 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
= {
diff --git a/tests/Images/Input/Bmp/pal8os2v2-16.bmp b/tests/Images/Input/Bmp/pal8os2v2-16.bmp
new file mode 100644
index 000000000..95a1d2345
Binary files /dev/null and b/tests/Images/Input/Bmp/pal8os2v2-16.bmp differ