Decode Jpeg into Rgb24 when pixel type not specified#1773
Decode Jpeg into Rgb24 when pixel type not specified#1773JimBobSquarePants merged 29 commits intomasterfrom
Conversation
| private bool Converted => this.pixelRowCounter >= this.pixelBuffer.Height; | ||
|
|
||
| public Buffer2D<TPixel> PixelBuffer | ||
| public Buffer2D<TPixel> GetPixelBuffer() |
There was a problem hiding this comment.
There is heavy lazy initialization, with side effects like CancellationToken firing. It's better to expose such stuff from a method than a property.
There was a problem hiding this comment.
I didn't like this property approach with a lot of lazy stuff behind from the start but couldn't come up with anything better. There's a lot of confusing bits of code here and there from my pr, I will work on decoder performance/refactoring next as I'm done with the encoder for now.
Codecov Report
@@ Coverage Diff @@
## master #1773 +/- ##
========================================
Coverage 84.49% 84.49%
========================================
Files 849 849
Lines 37412 37252 -160
Branches 4376 4385 +9
========================================
- Hits 31611 31477 -134
+ Misses 4947 4916 -31
- Partials 854 859 +5
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
|
A lot of reading here. Will try to review tomorrow night |
gfoidl
left a comment
There was a problem hiding this comment.
Just a quick look over the code, not detailed review.
...arp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs
Outdated
Show resolved
Hide resolved
| Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control); | ||
|
|
||
| int n = result.Length / 8; | ||
| int n = values.Component0.Length / 8; |
There was a problem hiding this comment.
| int n = values.Component0.Length / 8; | |
| int n = (int)((uint)values.Component0.Length / 8); |
So the JIT will emit a bit-hack division instead of the (signed) integer division by constant.
...ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs
Outdated
Show resolved
Hide resolved
...geSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs
Outdated
Show resolved
Hide resolved
|
|
||
| // Walking 8 elements at one step: | ||
| int n = result.Length / 8; | ||
| int n = values.Component0.Length / 8; |
There was a problem hiding this comment.
| int n = values.Component0.Length / 8; | |
| int n = (int)((uint)values.Component0.Length / 8); |
There was a problem hiding this comment.
I think this trick is only worth it when we are inside a tight loop or, or in a method that is expected to be called from a tight loop. In other cases I prefer readability.
There was a problem hiding this comment.
Or is it possible to achieve the same in a simpler way nint? I changed my code everywhere to nint n = values.Component0.Length / 8; because n is only used for the i < n comparison, and I like it better when the types match explicitly.
There was a problem hiding this comment.
We should go with readability, as you did now with nint. Codegen isn't ideal, but this pattern {array, span}.Length / ConstantOfPowerOfTwo is so common, that the JIT should be able to optimize this, so we don't need any hacks.
I'll have a look if there's a JIT-issue, otherwise create one.
Edit: filed dotnet/runtime#59922
| ref Vector<float> ggRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref gg); | ||
| ref Vector<float> bbRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref bb); | ||
|
|
||
| int n = values.Component0.Length / 8; |
There was a problem hiding this comment.
| int n = values.Component0.Length / 8; | |
| int n = (int)((uint)values.Component0.Length / 8); |
or maybe create a helper for this? The casts aren't very intuitive, but codegen is quite a difference.
There was a problem hiding this comment.
I'm not sure it's worth it, see #1773 (comment)
...Sharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs
Outdated
Show resolved
Hide resolved
| int n = values.Component0.Length / 8; | ||
| for (int i = 0; i < n; i++) |
There was a problem hiding this comment.
| int n = values.Component0.Length / 8; | |
| for (int i = 0; i < n; i++) | |
| int n = (int)((uint)values.Component0.Length / 8); | |
| for (nint i = 0; i < n; i++) |
Now I'll stop commenting on these -- otherwise it's too much noise generated by me 😉
...eSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs
Outdated
Show resolved
Hide resolved
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
Outdated
Show resolved
Hide resolved
…mageSharp into af/jpeg-pack-sandbox
Co-authored-by: Günther Foidl <gue@korporal.at>
…mageSharp into af/jpeg-pack-sandbox
Co-authored-by: Günther Foidl <gue@korporal.at>
Prerequisites
Description
Finish the plan defined in #1410:
PixelOperations.PackFromRgbPlanesinsteadImage<Rgb24>from non-generic DecodeResizeProcessor<T>: omit alpha premultiplication if the pixel type has no alpha channelFixes #1410, fixes #1121.
Performance
Did usual run of
LoadResizeSaveStressBenchmarkson 10 core desktop. The overall effect on speed is within noise range, but there might be some 1%-ish improvement. I assume the reason is that #1462's packing actually doesn't make big difference to the packing code introduced in #1411.But memory usage dropped significantly, which is the main goal here.
Before
After
/cc @br3aker @JimBobSquarePants @saucecontrol