Browse Source

Not using quantization for Grey8 images when encoding 8Bit Bitmaps

pull/909/head
Brian Popow 7 years ago
parent
commit
89d09ee994
  1. 83
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  2. 6
      tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs

83
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -305,37 +305,74 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private void Write8Bit<TPixel>(Stream stream, ImageFrame<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
bool isGray8 = typeof(TPixel) == typeof(Gray8);
using (IMemoryOwner<byte> colorPaletteBuffer = this.memoryAllocator.AllocateManagedByteBuffer(ColorPaletteSize8Bit, AllocationOptions.Clean))
using (IQuantizedFrame<TPixel> quantized = this.quantizer.CreateFrameQuantizer<TPixel>(this.configuration, 256).QuantizeFrame(image))
{
Span<byte> colorPalette = colorPaletteBuffer.GetSpan();
int idx = 0;
var color = default(Rgba32);
ReadOnlySpan<TPixel> 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<byte> pixelSpan = quantized.GetRowSpan(y);
stream.Write(pixelSpan);
stream.Write(colorPalette);
for (int i = 0; i < this.padding; i++)
using (IMemoryOwner<byte> rowSpanBuffer = this.memoryAllocator.AllocateManagedByteBuffer(image.Width, AllocationOptions.Clean))
{
Span<byte> outputPixelRow = rowSpanBuffer.GetSpan();
for (int y = image.Height - 1; y >= 0; y--)
{
Span<TPixel> inputPixelRow = image.GetPixelRowSpan(y);
PixelOperations<TPixel>.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<TPixel> quantized = this.quantizer.CreateFrameQuantizer<TPixel>(this.configuration, 256).QuantizeFrame(image))
{
stream.WriteByte(0);
ReadOnlySpan<TPixel> 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<byte> pixelSpan = quantized.GetRowSpan(y);
stream.Write(pixelSpan);
for (int i = 0; i < this.padding; i++)
{
stream.WriteByte(0);
}
}
}
}
}

6
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)]

Loading…
Cancel
Save