diff --git a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
index 0029a6b68d..618999c87d 100644
--- a/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpBitsPerPixel.cs
@@ -6,16 +6,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// Enumerates the available bits per pixel for bitmap.
///
- public enum BmpBitsPerPixel
+ public enum BmpBitsPerPixel : short
{
///
/// 24 bits per pixel. Each pixel consists of 3 bytes.
///
- Pixel24 = 3,
+ Pixel24 = 24,
///
/// 32 bits per pixel. Each pixel consists of 4 bytes.
///
- Pixel32 = 4
+ Pixel32 = 32
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 385c79896e..3bb44f1d06 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -536,6 +536,17 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.metaData = meta;
+ short bitsPerPixel = this.infoHeader.BitsPerPixel;
+ var bmpMetaData = new BmpMetaData();
+ this.metaData.AddOrUpdateFormatMetaData(BmpFormat.Instance, bmpMetaData);
+
+ // We can only encode at these bit rates so far.
+ if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24)
+ || bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32))
+ {
+ bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel;
+ }
+
// skip the remaining header because we can't read those parts
this.stream.Skip(skipAmount);
}
@@ -581,9 +592,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
if (this.infoHeader.ClrUsed == 0)
{
- if (this.infoHeader.BitsPerPixel == 1 ||
- this.infoHeader.BitsPerPixel == 4 ||
- this.infoHeader.BitsPerPixel == 8)
+ if (this.infoHeader.BitsPerPixel == 1
+ || this.infoHeader.BitsPerPixel == 4
+ || this.infoHeader.BitsPerPixel == 8)
{
colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
index 23b01ae9e8..b1a66accec 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// Gets or sets the number of bits per pixel.
///
- public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
+ public BmpBitsPerPixel? BitsPerPixel { get; set; }
///
public void Encode(Image image, Stream stream)
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index b49b8a8959..7a09a47f78 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -21,10 +21,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private int padding;
- private readonly BmpBitsPerPixel bitsPerPixel;
-
private readonly MemoryAllocator memoryAllocator;
+ private BmpBitsPerPixel? bitsPerPixel;
+
///
/// Initializes a new instance of the class.
///
@@ -48,10 +48,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
- // Cast to int will get the bytes per pixel
- short bpp = (short)(8 * (int)this.bitsPerPixel);
+ BmpMetaData bmpMetaData = image.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance);
+ this.bitsPerPixel = this.bitsPerPixel ?? bmpMetaData.BitsPerPixel;
+
+ short bpp = (short)this.bitsPerPixel;
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
- this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
+ this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F));
// Set Resolution.
ImageMetaData meta = image.MetaData;
@@ -145,10 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
}
}
- private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel)
- {
- return this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding);
- }
+ private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, this.padding);
///
/// Writes the 32bit color palette to the stream.
diff --git a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
index aa60f38662..3d678c13e1 100644
--- a/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpMetaData.cs
@@ -8,6 +8,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
public class BmpMetaData
{
- // TODO: Analyse what properties we would like to preserve.
+ ///
+ /// Gets or sets the number of bits per pixel.
+ ///
+ public BmpBitsPerPixel BitsPerPixel { get; set; } = BmpBitsPerPixel.Pixel24;
+
+ // TODO: Colors used once we support encoding palette bmps.
}
}
diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
index 56952f0356..f62504d08f 100644
--- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
@@ -12,6 +12,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
/// Gets the number of bits per pixel.
///
- BmpBitsPerPixel BitsPerPixel { get; }
+ BmpBitsPerPixel? BitsPerPixel { get; }
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
index d887d23ade..c75c656919 100644
--- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs
@@ -28,10 +28,14 @@ namespace SixLabors.ImageSharp.Tests
{ TestImages.Bmp.RLE, 2835, 2835, PixelResolutionUnit.PixelsPerMeter }
};
- public BmpEncoderTests(ITestOutputHelper output)
+ public static readonly TheoryData BmpBitsPerPixelFiles =
+ new TheoryData
{
- this.Output = output;
- }
+ { TestImages.Bmp.Car, BmpBitsPerPixel.Pixel24 },
+ { TestImages.Bmp.Bit32Rgb, BmpBitsPerPixel.Pixel32 }
+ };
+
+ public BmpEncoderTests(ITestOutputHelper output) => this.Output = output;
private ITestOutputHelper Output { get; }
@@ -61,13 +65,35 @@ namespace SixLabors.ImageSharp.Tests
}
[Theory]
- [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)]
- public void Encode_IsNotBoundToSinglePixelType(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel)
- where TPixel : struct, IPixel
+ [MemberData(nameof(BmpBitsPerPixelFiles))]
+ public void Encode_PreserveBitsPerPixel(string imagePath, BmpBitsPerPixel bmpBitsPerPixel)
{
- TestBmpEncoderCore(provider, bitsPerPixel);
+ var options = new BmpEncoder();
+
+ var testFile = TestFile.Create(imagePath);
+ using (Image input = testFile.CreateImage())
+ {
+ using (var memStream = new MemoryStream())
+ {
+ input.Save(memStream, options);
+
+ memStream.Position = 0;
+ using (var output = Image.Load(memStream))
+ {
+ BmpMetaData meta = output.MetaData.GetOrAddFormatMetaData(BmpFormat.Instance);
+
+ Assert.Equal(bmpBitsPerPixel, meta.BitsPerPixel);
+ }
+ }
+ }
}
+
+ [Theory]
+ [WithTestPatternImages(nameof(BitsPerPixel), 24, 24, PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24)]
+ public void Encode_IsNotBoundToSinglePixelType(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel)
+ where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel);
+
[Theory]
[WithTestPatternImages(nameof(BitsPerPixel), 48, 24, PixelTypes.Rgba32)]
[WithTestPatternImages(nameof(BitsPerPixel), 47, 8, PixelTypes.Rgba32)]
@@ -75,10 +101,7 @@ namespace SixLabors.ImageSharp.Tests
[WithSolidFilledImages(nameof(BitsPerPixel), 1, 1, 255, 100, 50, 255, PixelTypes.Rgba32)]
[WithTestPatternImages(nameof(BitsPerPixel), 7, 5, PixelTypes.Rgba32)]
public void Encode_WorksWithDifferentSizes(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel)
- where TPixel : struct, IPixel
- {
- TestBmpEncoderCore(provider, bitsPerPixel);
- }
+ where TPixel : struct, IPixel => TestBmpEncoderCore(provider, bitsPerPixel);
private static void TestBmpEncoderCore(TestImageProvider provider, BmpBitsPerPixel bitsPerPixel)
where TPixel : struct, IPixel
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index df015f7556..acfad042eb 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -178,6 +178,7 @@ namespace SixLabors.ImageSharp.Tests
public const string Bit8Inverted = "Bmp/test8-inverted.bmp";
public const string Bit16 = "Bmp/test16.bmp";
public const string Bit16Inverted = "Bmp/test16-inverted.bmp";
+ public const string Bit32Rgb = "Bmp/rgb32.bmp";
public static readonly string[] All
= {
diff --git a/tests/Images/Input/Bmp/rgb32.bmp b/tests/Images/Input/Bmp/rgb32.bmp
new file mode 100644
index 0000000000..5d57eaaea8
Binary files /dev/null and b/tests/Images/Input/Bmp/rgb32.bmp differ