From f533726aef66f38e3b3703ee51279473f01d5ab4 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 27 Jul 2020 11:08:54 +0100 Subject: [PATCH] Remove last of pointer code and add benchmarks --- .../Formats/Jpeg/Components/Block8x8F.cs | 10 +++--- .../Formats/Jpeg/JpegEncoderCore.cs | 33 +++++++++---------- .../Codecs/Jpeg/EncodeJpeg.cs | 19 ++++++++++- .../Formats/Jpg/Block8x8FTests.cs | 2 +- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 26d3e0dbb3..b7835d6706 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -376,16 +376,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Source block /// Destination block /// The quantization table - /// Pointer to elements of + /// The 8x8 Unzig block. public static unsafe void Quantize( ref Block8x8F block, ref Block8x8F dest, ref Block8x8F qt, - byte* unzigPtr) + ref ZigZag unZig) { for (int zig = 0; zig < Size; zig++) { - dest[zig] = block[unzigPtr[zig]]; + dest[zig] = block[unZig[zig]]; } DivideRoundAll(ref dest, ref qt); @@ -396,12 +396,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// The destination block. /// The source block. - public static unsafe void Scale16X16To8X8(ref Block8x8F destination, Block8x8F* source) + public static unsafe void Scale16X16To8X8(ref Block8x8F destination, ReadOnlySpan source) { for (int i = 0; i < 4; i++) { int dstOff = ((i & 2) << 4) | ((i & 1) << 2); - float* iSource = (float*)(source + i); + Block8x8F iSource = source[i]; for (int y = 0; y < 4; y++) { diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 08ffd53343..26e804b923 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -431,7 +431,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackLuminanceQuantTable, - unzig.Data); + ref unzig); prevDCCb = this.WriteBlock( QuantIndex.Chrominance, prevDCCb, @@ -439,7 +439,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - unzig.Data); + ref unzig); prevDCCr = this.WriteBlock( QuantIndex.Chrominance, prevDCCr, @@ -447,7 +447,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - unzig.Data); + ref unzig); } } } @@ -512,7 +512,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// Temporal block to be used as FDCT Destination /// Temporal block 2 /// Quantization table - /// The 8x8 Unzig block pointer + /// The 8x8 Unzig block. /// /// The /// @@ -523,11 +523,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref Block8x8F tempDest1, ref Block8x8F tempDest2, ref Block8x8F quant, - byte* unzigPtr) + ref ZigZag unZig) { FastFloatingPointDCT.TransformFDCT(ref src, ref tempDest1, ref tempDest2); - Block8x8F.Quantize(ref tempDest1, ref tempDest2, ref quant, unzigPtr); + Block8x8F.Quantize(ref tempDest1, ref tempDest2, ref quant, ref unZig); int dc = (int)tempDest2[0]; @@ -974,11 +974,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) Block8x8F b = default; - - BlockQuad cb = default; - BlockQuad cr = default; - var cbPtr = (Block8x8F*)cb.Data; - var crPtr = (Block8x8F*)cr.Data; + Span cb = stackalloc Block8x8F[4]; + Span cr = stackalloc Block8x8F[4]; Block8x8F temp1 = default; Block8x8F temp2 = default; @@ -1009,8 +1006,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg pixelConverter.Convert(frame, x + xOff, y + yOff, currentRows); - cbPtr[i] = pixelConverter.Cb; - crPtr[i] = pixelConverter.Cr; + cb[i] = pixelConverter.Cb; + cr[i] = pixelConverter.Cr; prevDCY = this.WriteBlock( QuantIndex.Luminance, @@ -1019,10 +1016,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackLuminanceQuantTable, - unzig.Data); + ref unzig); } - Block8x8F.Scale16X16To8X8(ref b, cbPtr); + Block8x8F.Scale16X16To8X8(ref b, cb); prevDCCb = this.WriteBlock( QuantIndex.Chrominance, prevDCCb, @@ -1030,9 +1027,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - unzig.Data); + ref unzig); - Block8x8F.Scale16X16To8X8(ref b, crPtr); + Block8x8F.Scale16X16To8X8(ref b, cr); prevDCCr = this.WriteBlock( QuantIndex.Chrominance, prevDCCr, @@ -1040,7 +1037,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - unzig.Data); + ref unzig); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs index 0a1fe977f8..b5be18189e 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs @@ -10,6 +10,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg using System.Drawing; using System.Drawing.Imaging; using System.IO; + using SixLabors.ImageSharp.Tests; using CoreImage = SixLabors.ImageSharp.Image; public class EncodeJpeg : BenchmarkBase @@ -24,7 +25,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { if (this.bmpStream == null) { - this.bmpStream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp"); + const string TestImage = TestImages.Bmp.Car; + this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); this.bmpCore = CoreImage.Load(this.bmpStream); this.bmpStream.Position = 0; this.bmpDrawing = Image.FromStream(this.bmpStream); @@ -58,3 +60,18 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg } } } + +/* +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.959 (1909/November2018Update/19H2) +Intel Core i7-8650U CPU 1.90GHz(Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +.NET Core SDK = 3.1.302 + + [Host] : .NET Core 3.1.6 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.31603), X64 RyuJIT + DefaultJob : .NET Core 3.1.6 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.31603), X64 RyuJIT + + +| Method | Mean | Error | StdDev | Median | Ratio | RatioSD | +|---------------------- |---------:|----------:|----------:|---------:|------:|--------:| +| 'System.Drawing Jpeg' | 4.473 ms | 0.0847 ms | 0.2012 ms | 4.408 ms | 1.00 | 0.00 | +| 'ImageSharp Jpeg' | 5.409 ms | 0.0379 ms | 0.0316 ms | 5.412 ms | 1.19 | 0.05 | +*/ diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 4c7277e5bc..722521f98d 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -282,7 +282,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var actualResults = default(Block8x8F); - Block8x8F.Quantize(ref block, ref actualResults, ref qt, unzig.Data); + Block8x8F.Quantize(ref block, ref actualResults, ref qt, ref unzig); for (int i = 0; i < Block8x8F.Size; i++) {