Adds support for encoding 8-bit bitmaps#906
Conversation
Codecov Report
@@ Coverage Diff @@
## master #906 +/- ##
==========================================
- Coverage 89.55% 89.46% -0.09%
==========================================
Files 1031 1031
Lines 46115 46137 +22
Branches 3261 3264 +3
==========================================
- Hits 41297 41278 -19
- Misses 4108 4111 +3
- Partials 710 748 +38
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #906 +/- ##
==========================================
+ Coverage 89.6% 89.61% +0.01%
==========================================
Files 1060 1060
Lines 46542 46586 +44
Branches 3268 3272 +4
==========================================
+ Hits 41703 41750 +47
+ Misses 4128 4125 -3
Partials 711 711
Continue to review full report at Codecov.
|
|
@JimBobSquarePants: i have some trouble with unit tests failing for net472 and net462. I cannot not reproduce it locally. As far as i can tell, this matches the appveyor configuration which is failing. Do you have an idea how i can reproduce this issue? The tests work fine with net462 and net472 when i run them locally with: |
|
@brianpopow I think hardware-specific floating point inaccuracies are trolling us again. Which |
|
@antonfirsov |
|
@brianpopow for quantization, inconsistencies across platforms are acceptable. You just need to pass a tolerant comparer in |
|
|
||
| // We can only encode at these bit rates so far. | ||
| if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel16) | ||
| if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel8) |
There was a problem hiding this comment.
yes, 4 bit and 1 bit
antonfirsov
left a comment
There was a problem hiding this comment.
A few minor change requests and questions, otherwise looks very good!
| where TPixel : struct, IPixel<TPixel> | ||
| { | ||
| #if NETCOREAPP2_1 | ||
| Span<byte> colorPalette = stackalloc byte[ColorPaletteSize8Bit]; |
There was a problem hiding this comment.
1024 byte is too much for stackallock, we can remove this.
There was a problem hiding this comment.
What is the limit? I can never find an explicit instruction.
There was a problem hiding this comment.
I've read something in Joe Duffy's original material suggesting 128 bytes, based on their benchmarks.
There was a problem hiding this comment.
Ah ok. I use 257 bytes in the HuffmanTable but I'm gonna leave that as-is.
| #endif | ||
|
|
||
| var quantizer = new OctreeQuantizer(dither: true, maxColors: 256); | ||
| QuantizedFrame<TPixel> quantized = quantizer.CreateFrameQuantizer<TPixel>(this.configuration).QuantizeFrame(image); |
There was a problem hiding this comment.
FrameQuantizer<T> and QuantizedFrame<T> are IDisposable!
There was a problem hiding this comment.
Also:
IQuantizer should be configuratble by the user as an Encoder parameter, like we do it in PngEncoder!
| var color = default(Rgba32); | ||
| foreach (TPixel quantizedColor in quantized.Palette) | ||
| { | ||
| quantizedColor.ToRgba32(ref color); |
There was a problem hiding this comment.
Might be a stupid idea and lack of understanding, but:
What if we convert to Rgba32 first, and quantize in Rgba32 space?
There was a problem hiding this comment.
Yeah, in Octree we're working in the Rgba32 space then converting to/from so I see where you are coming from. However, by converting before quantization we end up allocating a new buffer to house the image. That's probably a lot more costly.
There was a problem hiding this comment.
Totally forgot that it will lead to another allocation, so let's keep it for now.
(An idea is starting to formulate in my mind, but of course it would break IQuantizer API again 😄.)
| #if NETCOREAPP2_1 | ||
| Span<byte> colorPalette = stackalloc byte[ColorPaletteSize8Bit]; | ||
| #else | ||
| byte[] colorPalette = new byte[ColorPaletteSize8Bit]; |
There was a problem hiding this comment.
I would suggest to use MemoryAllocator.AllocateManagedByteBuffer() for this size.
There was a problem hiding this comment.
We don't actually need the #ifdef anymore. It's supported in latest c# versions.
There was a problem hiding this comment.
I mean replacing GC array allocation.
|
|
||
| [Theory] | ||
| [WithFile(Bit8Gs, PixelTypes.Gray8, BmpBitsPerPixel.Pixel8)] | ||
| public void Encode_8BitGray_WithV3Header_Works<TPixel>(TestImageProvider<TPixel> provider, BmpBitsPerPixel bitsPerPixel) |
There was a problem hiding this comment.
I can't say enough times, how much I ❤️ this kind of extensive and explanatory test coverage! This is an important enabler for us to do optimizations and refactors.
For #907 stuff I'm literally spending days to add missing tests, so I can change the code safely.
There was a problem hiding this comment.
Thanks!
I'm merging, to resolve conflicts with #908.
|
@brianpopow I've been thinking on the quantizer inaccuracies. Do we really need execute the quantization when when |
|
@antonfirsov no you are right, when its Gray8, we do not actually need the quantization. I will change that. |
…coding Adds support for encoding 8-bit bitmaps

Prerequisites
Description
This PR add the support for encoding 8-Bit Bitmaps.