diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index edde7dc89..532d20e00 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -305,37 +305,74 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write8Bit(Stream stream, ImageFrame image) where TPixel : struct, IPixel { + bool isGray8 = typeof(TPixel) == typeof(Gray8); using (IMemoryOwner colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(ColorPaletteSize8Bit, AllocationOptions.Clean)) - using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { Span colorPalette = colorPaletteBuffer.GetSpan(); - int idx = 0; - var color = default(Rgba32); - ReadOnlySpan paletteSpan = quantized.Palette.Span; - - // TODO: Use bulk conversion here for better perf - foreach (TPixel quantizedColor in paletteSpan) + if (isGray8) { - quantizedColor.ToRgba32(ref color); - colorPalette[idx] = color.B; - colorPalette[idx + 1] = color.G; - colorPalette[idx + 2] = color.R; - - // Padding byte, always 0 - colorPalette[idx + 3] = 0; - idx += 4; - } + for (byte i = 0; i <= 255; i++) + { + int idx = i * 4; + colorPalette[idx] = i; + colorPalette[idx + 1] = i; + colorPalette[idx + 2] = i; - stream.Write(colorPalette); + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + } - for (int y = image.Height - 1; y >= 0; y--) - { - ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); - stream.Write(pixelSpan); + stream.Write(colorPalette); - for (int i = 0; i < this.padding; i++) + using (IMemoryOwner rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean)) + { + Span outputPixelRow = rowSpanBuffer.GetSpan(); + for (int y = image.Height - 1; y >= 0; y--) + { + Span inputPixelRow = image.GetPixelRowSpan(y); + PixelOperations.Instance.ToGray8Bytes(this.configuration, inputPixelRow, outputPixelRow, image.Width); + stream.Write(outputPixelRow); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } + } + } + } + else + { + using (IQuantizedFrame quantized = this.quantizer.CreateFrameQuantizer(this.configuration, 256).QuantizeFrame(image)) { - stream.WriteByte(0); + ReadOnlySpan quantizedColors = quantized.Palette.Span; + var color = default(Rgba32); + + // TODO: Use bulk conversion here for better perf + int idx = 0; + foreach (TPixel quantizedColor in quantizedColors) + { + quantizedColor.ToRgba32(ref color); + colorPalette[idx] = color.B; + colorPalette[idx + 1] = color.G; + colorPalette[idx + 2] = color.R; + + // Padding byte, always 0 + colorPalette[idx + 3] = 0; + idx += 4; + } + + stream.Write(colorPalette); + + for (int y = image.Height - 1; y >= 0; y--) + { + ReadOnlySpan pixelSpan = quantized.GetRowSpan(y); + stream.Write(pixelSpan); + + for (int i = 0; i < this.padding; i++) + { + stream.WriteByte(0); + } + } } } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index dd76e9443..162d3f30b 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -169,8 +169,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp TestBmpEncoderCore( provider, bitsPerPixel, - supportTransparency: false, - ImageComparer.TolerantPercentage(0.01f)); + supportTransparency: false); [Theory] [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] @@ -179,8 +178,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp TestBmpEncoderCore( provider, bitsPerPixel, - supportTransparency: true, - ImageComparer.TolerantPercentage(0.01f)); + supportTransparency: true); [Theory] [WithFile(TestImages.Png.GrayAlpha2BitInterlaced, PixelTypes.Rgba32, BmpBitsPerPixel.Pixel32)]