From 38a3201287d020c84d10a20d75cfc897701b0248 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 30 Nov 2016 17:46:11 +1100 Subject: [PATCH] Reduce memory usage in WuQuantizer --- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 9 ---- src/ImageSharp/Quantizers/Wu/WuQuantizer.cs | 45 ++++++++++---------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 2980782a6e..010bd635d4 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -523,15 +523,6 @@ namespace ImageSharp.Formats int alpha = bytes[3]; - // Premultiply the color. This helps prevent banding. - // TODO: Vector? - if (alpha < 255 && alpha > this.Threshold) - { - bytes[0] = (byte)(bytes[0] * alpha).Clamp(0, 255); - bytes[1] = (byte)(bytes[1] * alpha).Clamp(0, 255); - bytes[2] = (byte)(bytes[2] * alpha).Clamp(0, 255); - } - colorTable[offset] = bytes[0]; colorTable[offset + 1] = bytes[1]; colorTable[offset + 2] = bytes[2]; diff --git a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs index 8eabe38e62..2f3e89e99b 100644 --- a/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs +++ b/src/ImageSharp/Quantizers/Wu/WuQuantizer.cs @@ -6,7 +6,7 @@ namespace ImageSharp.Quantizers { using System; - using System.Collections.Generic; + using System.Buffers; using System.Numerics; using System.Threading.Tasks; @@ -24,10 +24,8 @@ namespace ImageSharp.Quantizers /// /// /// - /// Algorithm: Greedy orthogonal bipartition of RGB space for variance - /// minimization aided by inclusion-exclusion tricks. - /// For speed no nearest neighbor search is done. Slightly - /// better performance can be expected by more sophisticated + /// Algorithm: Greedy orthogonal bipartition of RGB space for variance minimization aided by inclusion-exclusion tricks. + /// For speed no nearest neighbor search is done. Slightly better performance can be expected by more sophisticated /// but more expensive versions. /// /// @@ -40,7 +38,7 @@ namespace ImageSharp.Quantizers /// /// The epsilon for comparing floating point numbers. /// - private const float Epsilon = 0.001f; + private const float Epsilon = 1e-5F; /// /// The index bits. @@ -325,17 +323,18 @@ namespace ImageSharp.Quantizers /// The pixel accessor. private void Build3DHistogram(PixelAccessor pixels) { + byte[] rgba = new byte[4]; for (int y = 0; y < pixels.Height; y++) { for (int x = 0; x < pixels.Width; x++) { // Colors are expected in r->g->b->a format - Color color = new Color(pixels[x, y].ToVector4()); + pixels[x, y].ToBytes(rgba, 0, ComponentOrder.XYZW); - byte r = color.R; - byte g = color.G; - byte b = color.B; - byte a = color.A; + byte r = rgba[0]; + byte g = rgba[1]; + byte b = rgba[2]; + byte a = rgba[3]; int inr = r >> (8 - IndexBits); int ing = g >> (8 - IndexBits); @@ -723,7 +722,7 @@ namespace ImageSharp.Quantizers /// The result. private QuantizedImage GenerateResult(PixelAccessor imagePixels, int colorCount, Box[] cube) { - List pallette = new List(); + TColor[] pallette = new TColor[colorCount]; byte[] pixels = new byte[imagePixels.Width * imagePixels.Height]; int width = imagePixels.Width; int height = imagePixels.Height; @@ -743,11 +742,7 @@ namespace ImageSharp.Quantizers TColor color = default(TColor); color.PackFromVector4(new Vector4(r, g, b, a) / 255F); - pallette.Add(color); - } - else - { - pallette.Add(default(TColor)); + pallette[k] = color; } } @@ -757,21 +752,25 @@ namespace ImageSharp.Quantizers Bootstrapper.Instance.ParallelOptions, y => { + byte[] rgba = ArrayPool.Shared.Rent(4); for (int x = 0; x < width; x++) { // Expected order r->g->b->a - Color color = new Color(imagePixels[x, y].ToVector4()); - int r = color.R >> (8 - IndexBits); - int g = color.G >> (8 - IndexBits); - int b = color.B >> (8 - IndexBits); - int a = color.A >> (8 - IndexAlphaBits); + imagePixels[x, y].ToBytes(rgba, 0, ComponentOrder.XYZW); + + int r = rgba[0] >> (8 - IndexBits); + int g = rgba[1] >> (8 - IndexBits); + int b = rgba[2] >> (8 - IndexBits); + int a = rgba[3] >> (8 - IndexAlphaBits); int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); pixels[(y * width) + x] = this.tag[ind]; } + + ArrayPool.Shared.Return(rgba); }); - return new QuantizedImage(width, height, pallette.ToArray(), pixels); + return new QuantizedImage(width, height, pallette, pixels); } } } \ No newline at end of file