From 02ba124667906c9ec81070373ee016d3076ba32b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 12:27:56 +1100 Subject: [PATCH 1/7] Use ref --- src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 44311e080..d58a960b5 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -179,9 +179,8 @@ namespace SixLabors.ImageSharp.Quantizers float b = Volume(this.colorCube[k], this.vmb) / weight; float a = Volume(this.colorCube[k], this.vma) / weight; - var color = default(TPixel); + ref TPixel color = ref this.palette[k]; color.PackFromVector4(new Vector4(r, g, b, a) / 255F); - this.palette[k] = color; } } } From b219fda083b0ba0537e65e572e22f178e284c0f8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 14:00:29 +1100 Subject: [PATCH 2/7] Fix quantized output --- .../Quantizers/WuQuantizer{TPixel}.cs | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index d58a960b5..639786406 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -196,19 +196,21 @@ namespace SixLabors.ImageSharp.Quantizers var rgba = default(Rgba32); pixel.ToRgba32(ref rgba); - int r = rgba.R >> 2; // 8 - IndexBits - int g = rgba.G >> 2; - int b = rgba.B >> 2; - int a = rgba.A >> 5; // 8 - IndexAlphaBits - - int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); - - this.vwt[ind]++; - this.vmr[ind] += r; - this.vmg[ind] += g; - this.vmb[ind] += b; - this.vma[ind] += a; - this.m2[ind] += (r * r) + (g * g) + (b * b) + (a * a); + int r = rgba.R >> (8 - IndexBits); + int g = rgba.G >> (8 - IndexBits); + int b = rgba.B >> (8 - IndexBits); + int a = rgba.A >> (8 - IndexAlphaBits); + + int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); + + this.vwt[index]++; + this.vmr[index] += rgba.R; + this.vmg[index] += rgba.G; + this.vmb[index] += rgba.B; + this.vma[index] += rgba.A; + + var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A); + this.m2[index] += Vector4.Dot(vector, vector); } /// @@ -617,14 +619,12 @@ namespace SixLabors.ImageSharp.Quantizers float halfA = baseA + Top(cube, direction, i, this.vma); float halfW = baseW + Top(cube, direction, i, this.vwt); - float temp; - if (MathF.Abs(halfW) < Constants.Epsilon) { continue; } - temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; + float temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; halfR = wholeR - halfR; halfG = wholeG - halfG; From a7ffeffcec5c1f410bb787f9b5dfd3ffecf73990 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 14:22:23 +1100 Subject: [PATCH 3/7] Minor optimization --- src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 639786406..629bc1431 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -174,13 +174,13 @@ namespace SixLabors.ImageSharp.Quantizers if (MathF.Abs(weight) > Constants.Epsilon) { - float r = Volume(this.colorCube[k], this.vmr) / weight; - float g = Volume(this.colorCube[k], this.vmg) / weight; - float b = Volume(this.colorCube[k], this.vmb) / weight; - float a = Volume(this.colorCube[k], this.vma) / weight; + float r = Volume(this.colorCube[k], this.vmr); + float g = Volume(this.colorCube[k], this.vmg); + float b = Volume(this.colorCube[k], this.vmb); + float a = Volume(this.colorCube[k], this.vma); ref TPixel color = ref this.palette[k]; - color.PackFromVector4(new Vector4(r, g, b, a) / 255F); + color.PackFromVector4(new Vector4(r, g, b, a) / weight / 255F); } } } From 31b4a6420d43b5f06ce31d124bf26c335ce2ade2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 14:35:51 +1100 Subject: [PATCH 4/7] Use struct for Box --- src/ImageSharp/Quantizers/Box.cs | 5 +- .../Quantizers/WuQuantizer{TPixel}.cs | 93 +++++++++---------- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/ImageSharp/Quantizers/Box.cs b/src/ImageSharp/Quantizers/Box.cs index 4a1e17753..cd1936b65 100644 --- a/src/ImageSharp/Quantizers/Box.cs +++ b/src/ImageSharp/Quantizers/Box.cs @@ -5,9 +5,8 @@ namespace SixLabors.ImageSharp.Quantizers { /// /// Represents a box color cube. - /// TODO: This should be a struct for performance /// - internal sealed class Box + internal struct Box { /// /// Gets or sets the min red value, exclusive. @@ -54,4 +53,4 @@ namespace SixLabors.ImageSharp.Quantizers /// public int Volume { get; set; } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 629bc1431..11d9bd5db 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -168,16 +168,16 @@ namespace SixLabors.ImageSharp.Quantizers this.palette = new TPixel[this.colors]; for (int k = 0; k < this.colors; k++) { - this.Mark(this.colorCube[k], (byte)k); + this.Mark(ref this.colorCube[k], (byte)k); - float weight = Volume(this.colorCube[k], this.vwt); + float weight = Volume(ref this.colorCube[k], this.vwt); if (MathF.Abs(weight) > Constants.Epsilon) { - float r = Volume(this.colorCube[k], this.vmr); - float g = Volume(this.colorCube[k], this.vmg); - float b = Volume(this.colorCube[k], this.vmb); - float a = Volume(this.colorCube[k], this.vma); + float r = Volume(ref this.colorCube[k], this.vmr); + float g = Volume(ref this.colorCube[k], this.vmg); + float b = Volume(ref this.colorCube[k], this.vmb); + float a = Volume(ref this.colorCube[k], this.vma); ref TPixel color = ref this.palette[k]; color.PackFromVector4(new Vector4(r, g, b, a) / weight / 255F); @@ -302,7 +302,7 @@ namespace SixLabors.ImageSharp.Quantizers /// The cube. /// The moment. /// The result. - private static float Volume(Box cube, long[] moment) + private static float Volume(ref Box cube, long[] moment) { return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] @@ -329,7 +329,7 @@ namespace SixLabors.ImageSharp.Quantizers /// The direction. /// The moment. /// The result. - private static long Bottom(Box cube, int direction, long[] moment) + private static long Bottom(ref Box cube, int direction, long[] moment) { switch (direction) { @@ -390,7 +390,7 @@ namespace SixLabors.ImageSharp.Quantizers /// The position. /// The moment. /// The result. - private static long Top(Box cube, int direction, int position, long[] moment) + private static long Top(ref Box cube, int direction, int position, long[] moment) { switch (direction) { @@ -554,12 +554,12 @@ namespace SixLabors.ImageSharp.Quantizers /// /// The cube. /// The . - private float Variance(Box cube) + private float Variance(ref Box cube) { - float dr = Volume(cube, this.vmr); - float dg = Volume(cube, this.vmg); - float db = Volume(cube, this.vmb); - float da = Volume(cube, this.vma); + float dr = Volume(ref cube, this.vmr); + float dg = Volume(ref cube, this.vmg); + float db = Volume(ref cube, this.vmb); + float da = Volume(ref cube, this.vma); float xx = this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] @@ -579,7 +579,8 @@ namespace SixLabors.ImageSharp.Quantizers - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt)); + // TODO: Vector.Dot + return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(ref cube, this.vwt)); } /// @@ -600,24 +601,24 @@ namespace SixLabors.ImageSharp.Quantizers /// The whole alpha. /// The whole weight. /// The . - private float Maximize(Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW) + private float Maximize(ref Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW) { - long baseR = Bottom(cube, direction, this.vmr); - long baseG = Bottom(cube, direction, this.vmg); - long baseB = Bottom(cube, direction, this.vmb); - long baseA = Bottom(cube, direction, this.vma); - long baseW = Bottom(cube, direction, this.vwt); + long baseR = Bottom(ref cube, direction, this.vmr); + long baseG = Bottom(ref cube, direction, this.vmg); + long baseB = Bottom(ref cube, direction, this.vmb); + long baseA = Bottom(ref cube, direction, this.vma); + long baseW = Bottom(ref cube, direction, this.vwt); float max = 0F; cut = -1; for (int i = first; i < last; i++) { - float halfR = baseR + Top(cube, direction, i, this.vmr); - float halfG = baseG + Top(cube, direction, i, this.vmg); - float halfB = baseB + Top(cube, direction, i, this.vmb); - float halfA = baseA + Top(cube, direction, i, this.vma); - float halfW = baseW + Top(cube, direction, i, this.vwt); + float halfR = baseR + Top(ref cube, direction, i, this.vmr); + float halfG = baseG + Top(ref cube, direction, i, this.vmg); + float halfB = baseB + Top(ref cube, direction, i, this.vmb); + float halfA = baseA + Top(ref cube, direction, i, this.vma); + float halfW = baseW + Top(ref cube, direction, i, this.vwt); if (MathF.Abs(halfW) < Constants.Epsilon) { @@ -655,18 +656,18 @@ namespace SixLabors.ImageSharp.Quantizers /// The first set. /// The second set. /// Returns a value indicating whether the box has been split. - private bool Cut(Box set1, Box set2) + private bool Cut(ref Box set1, ref Box set2) { - float wholeR = Volume(set1, this.vmr); - float wholeG = Volume(set1, this.vmg); - float wholeB = Volume(set1, this.vmb); - float wholeA = Volume(set1, this.vma); - float wholeW = Volume(set1, this.vwt); + float wholeR = Volume(ref set1, this.vmr); + float wholeG = Volume(ref set1, this.vmg); + float wholeB = Volume(ref set1, this.vmb); + float wholeA = Volume(ref set1, this.vma); + float wholeW = Volume(ref set1, this.vwt); - float maxr = this.Maximize(set1, 0, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxg = this.Maximize(set1, 1, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxb = this.Maximize(set1, 2, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxa = this.Maximize(set1, 3, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxr = this.Maximize(ref set1, 0, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxg = this.Maximize(ref set1, 1, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxb = this.Maximize(ref set1, 2, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxa = this.Maximize(ref set1, 3, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); int dir; @@ -743,7 +744,7 @@ namespace SixLabors.ImageSharp.Quantizers /// /// The cube. /// A label. - private void Mark(Box cube, byte label) + private void Mark(ref Box cube, byte label) { for (int r = cube.R0 + 1; r <= cube.R1; r++) { @@ -768,23 +769,19 @@ namespace SixLabors.ImageSharp.Quantizers this.colorCube = new Box[this.colors]; float[] vv = new float[this.colors]; - for (int i = 0; i < this.colors; i++) - { - this.colorCube[i] = new Box(); - } - - this.colorCube[0].R0 = this.colorCube[0].G0 = this.colorCube[0].B0 = this.colorCube[0].A0 = 0; - this.colorCube[0].R1 = this.colorCube[0].G1 = this.colorCube[0].B1 = IndexCount - 1; - this.colorCube[0].A1 = IndexAlphaCount - 1; + ref var cube = ref this.colorCube[0]; + cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0; + cube.R1 = cube.G1 = cube.B1 = IndexCount - 1; + cube.A1 = IndexAlphaCount - 1; int next = 0; for (int i = 1; i < this.colors; i++) { - if (this.Cut(this.colorCube[next], this.colorCube[i])) + if (this.Cut(ref this.colorCube[next], ref this.colorCube[i])) { - vv[next] = this.colorCube[next].Volume > 1 ? this.Variance(this.colorCube[next]) : 0F; - vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(this.colorCube[i]) : 0F; + vv[next] = this.colorCube[next].Volume > 1 ? this.Variance(ref this.colorCube[next]) : 0F; + vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(ref this.colorCube[i]) : 0F; } else { From 5f734e18b8991488a933012365e79cfc90190e27 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 14:59:14 +1100 Subject: [PATCH 5/7] Use Vector4.Dot where we can --- .../Quantizers/WuQuantizer{TPixel}.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 11d9bd5db..ba1a3c165 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -579,8 +579,8 @@ namespace SixLabors.ImageSharp.Quantizers - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; - // TODO: Vector.Dot - return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(ref cube, this.vwt)); + var vector = new Vector4(dr, dg, db, da); + return xx - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt)); } /// @@ -625,12 +625,9 @@ namespace SixLabors.ImageSharp.Quantizers continue; } - float temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; + var vector = new Vector4(halfR, halfG, halfB, halfA); + float temp = Vector4.Dot(vector, vector) / halfW; - halfR = wholeR - halfR; - halfG = wholeG - halfG; - halfB = wholeB - halfB; - halfA = wholeA - halfA; halfW = wholeW - halfW; if (MathF.Abs(halfW) < Constants.Epsilon) @@ -638,7 +635,14 @@ namespace SixLabors.ImageSharp.Quantizers continue; } - temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW; + halfR = wholeR - halfR; + halfG = wholeG - halfG; + halfB = wholeB - halfB; + halfA = wholeA - halfA; + + vector = new Vector4(halfR, halfG, halfB, halfA); + + temp += Vector4.Dot(vector, vector) / halfW; if (temp > max) { From 4876a0087fb8e3b672b5a5f0b3089cf21ea0062c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 15:31:58 +1100 Subject: [PATCH 6/7] Use same ordering as original code Makes debugging a lot easier --- .../Quantizers/WuQuantizer{TPixel}.cs | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index ba1a3c165..740902168 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -334,7 +334,7 @@ namespace SixLabors.ImageSharp.Quantizers switch (direction) { // Red - case 0: + case 3: return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] @@ -345,7 +345,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Green - case 1: + case 2: return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] @@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Blue - case 2: + case 1: return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] @@ -367,7 +367,7 @@ namespace SixLabors.ImageSharp.Quantizers + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Alpha - case 3: + case 0: return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] @@ -395,7 +395,7 @@ namespace SixLabors.ImageSharp.Quantizers switch (direction) { // Red - case 0: + case 3: return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] - moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)] - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] @@ -406,7 +406,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; // Green - case 1: + case 2: return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] - moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)] - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] @@ -417,7 +417,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; // Blue - case 2: + case 1: return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] @@ -428,7 +428,7 @@ namespace SixLabors.ImageSharp.Quantizers - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; // Alpha - case 3: + case 0: return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] @@ -668,16 +668,16 @@ namespace SixLabors.ImageSharp.Quantizers float wholeA = Volume(ref set1, this.vma); float wholeW = Volume(ref set1, this.vwt); - float maxr = this.Maximize(ref set1, 0, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxg = this.Maximize(ref set1, 1, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxb = this.Maximize(ref set1, 2, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); - float maxa = this.Maximize(ref set1, 3, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW); + float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW); int dir; if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa)) { - dir = 0; + dir = 3; if (cutr < 0) { @@ -686,15 +686,15 @@ namespace SixLabors.ImageSharp.Quantizers } else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa)) { - dir = 1; + dir = 2; } else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa)) { - dir = 2; + dir = 1; } else { - dir = 3; + dir = 0; } set2.R1 = set1.R1; @@ -705,7 +705,7 @@ namespace SixLabors.ImageSharp.Quantizers switch (dir) { // Red - case 0: + case 3: set2.R0 = set1.R1 = cutr; set2.G0 = set1.G0; set2.B0 = set1.B0; @@ -713,7 +713,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Green - case 1: + case 2: set2.G0 = set1.G1 = cutg; set2.R0 = set1.R0; set2.B0 = set1.B0; @@ -721,7 +721,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Blue - case 2: + case 1: set2.B0 = set1.B1 = cutb; set2.R0 = set1.R0; set2.G0 = set1.G0; @@ -729,7 +729,7 @@ namespace SixLabors.ImageSharp.Quantizers break; // Alpha - case 3: + case 0: set2.A0 = set1.A1 = cuta; set2.R0 = set1.R0; set2.G0 = set1.G0; From bf7c0163bb3079cb386cfab11387fadd59231d3c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 7 Dec 2017 15:50:37 +1100 Subject: [PATCH 7/7] A little more ref --- src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 740902168..cb9eb9b0e 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -782,10 +782,12 @@ namespace SixLabors.ImageSharp.Quantizers for (int i = 1; i < this.colors; i++) { - if (this.Cut(ref this.colorCube[next], ref this.colorCube[i])) + ref var nextCube = ref this.colorCube[next]; + ref var currentCube = ref this.colorCube[i]; + if (this.Cut(ref nextCube, ref currentCube)) { - vv[next] = this.colorCube[next].Volume > 1 ? this.Variance(ref this.colorCube[next]) : 0F; - vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(ref this.colorCube[i]) : 0F; + vv[next] = nextCube.Volume > 1 ? this.Variance(ref nextCube) : 0F; + vv[i] = currentCube.Volume > 1 ? this.Variance(ref currentCube) : 0F; } else { @@ -805,7 +807,7 @@ namespace SixLabors.ImageSharp.Quantizers } } - if (temp <= 0.0) + if (temp <= 0F) { this.colors = i + 1; break;