-
-
Notifications
You must be signed in to change notification settings - Fork 887
Description
Some analysis of the performance of the encoder based upon a breakdown of this benchmark indicates that encoding a large jpeg takes 80% of the entire processing time.
https://github.com/kleisauke/net-vips/tree/master/tests/NetVips.Benchmarks
This is due to the lack of hardware acceleration in our color conversion approach.
The current Jpeg encoder utilizes predefined tables to convert a span of Rgb24
pixels into separate Y Cb Cr Block8x8F
planes.
ImageSharp/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs
Lines 58 to 83 in f1a0fb6
public void Convert(ImageFrame<TPixel> frame, int x, int y, in RowOctet<TPixel> currentRows) | |
{ | |
this.pixelBlock.LoadAndStretchEdges(frame.PixelBuffer, x, y, currentRows); | |
Span<Rgb24> rgbSpan = this.rgbBlock.AsSpanUnsafe(); | |
PixelOperations<TPixel>.Instance.ToRgb24(frame.GetConfiguration(), this.pixelBlock.AsSpanUnsafe(), rgbSpan); | |
ref Block8x8F yBlock = ref this.Y; | |
ref Block8x8F cbBlock = ref this.Cb; | |
ref Block8x8F crBlock = ref this.Cr; | |
ref Rgb24 rgbStart = ref rgbSpan[0]; | |
for (int i = 0; i < 64; i++) | |
{ | |
ref Rgb24 c = ref Unsafe.Add(ref rgbStart, i); | |
this.colorTables.ConvertPixelInto( | |
c.R, | |
c.G, | |
c.B, | |
ref yBlock, | |
ref cbBlock, | |
ref crBlock, | |
i); | |
} | |
} |
While this is faster than naïve per-pixel floating point calculation it can be heavily optimized.
Short Term Goal
Add AVX2? acceleration directly to the converter to optimize conversion for .NET Core 3.1+. This should be a few hours work for someone with SIMD knowledge.
Long Term Goal
Establish an architecture similar to the Jpeg decoder ColorConverters allowing incremental addition accelerated converters for all platforms and color spaces.