Browse Source

Merge branch 'master' into js/affine-transforms

af/merge-core
James Jackson-South 9 years ago
parent
commit
81baabfd15
  1. 2
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  2. 5
      src/ImageSharp/Quantizers/Box.cs
  3. 178
      src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs

2
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Memory
/// </summary> /// </summary>
/// <typeparam name="T">The element type</typeparam> /// <typeparam name="T">The element type</typeparam>
/// <param name="buffer">The <see cref="IBuffer2D{T}"/></param> /// <param name="buffer">The <see cref="IBuffer2D{T}"/></param>
/// <param name="rectangle">The rectangel subarea</param> /// <param name="rectangle">The rectangle subarea</param>
/// <returns>The <see cref="BufferArea{T}"/></returns> /// <returns>The <see cref="BufferArea{T}"/></returns>
public static BufferArea<T> GetArea<T>(this IBuffer2D<T> buffer, Rectangle rectangle) public static BufferArea<T> GetArea<T>(this IBuffer2D<T> buffer, Rectangle rectangle)
where T : struct => new BufferArea<T>(buffer, rectangle); where T : struct => new BufferArea<T>(buffer, rectangle);

5
src/ImageSharp/Quantizers/Box.cs

@ -5,9 +5,8 @@ namespace SixLabors.ImageSharp.Quantizers
{ {
/// <summary> /// <summary>
/// Represents a box color cube. /// Represents a box color cube.
/// TODO: This should be a struct for performance
/// </summary> /// </summary>
internal sealed class Box internal struct Box
{ {
/// <summary> /// <summary>
/// Gets or sets the min red value, exclusive. /// Gets or sets the min red value, exclusive.
@ -54,4 +53,4 @@ namespace SixLabors.ImageSharp.Quantizers
/// </summary> /// </summary>
public int Volume { get; set; } public int Volume { get; set; }
} }
} }

178
src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs

@ -168,20 +168,19 @@ namespace SixLabors.ImageSharp.Quantizers
this.palette = new TPixel[this.colors]; this.palette = new TPixel[this.colors];
for (int k = 0; k < this.colors; k++) 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) if (MathF.Abs(weight) > Constants.Epsilon)
{ {
float r = Volume(this.colorCube[k], this.vmr) / weight; float r = Volume(ref this.colorCube[k], this.vmr);
float g = Volume(this.colorCube[k], this.vmg) / weight; float g = Volume(ref this.colorCube[k], this.vmg);
float b = Volume(this.colorCube[k], this.vmb) / weight; float b = Volume(ref this.colorCube[k], this.vmb);
float a = Volume(this.colorCube[k], this.vma) / weight; float a = Volume(ref this.colorCube[k], this.vma);
var color = default(TPixel); 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);
this.palette[k] = color;
} }
} }
} }
@ -197,19 +196,21 @@ namespace SixLabors.ImageSharp.Quantizers
var rgba = default(Rgba32); var rgba = default(Rgba32);
pixel.ToRgba32(ref rgba); pixel.ToRgba32(ref rgba);
int r = rgba.R >> 2; // 8 - IndexBits int r = rgba.R >> (8 - IndexBits);
int g = rgba.G >> 2; int g = rgba.G >> (8 - IndexBits);
int b = rgba.B >> 2; int b = rgba.B >> (8 - IndexBits);
int a = rgba.A >> 5; // 8 - IndexAlphaBits int a = rgba.A >> (8 - IndexAlphaBits);
int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
int ind = 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;
this.vwt[ind]++; var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A);
this.vmr[ind] += r; this.m2[index] += Vector4.Dot(vector, vector);
this.vmg[ind] += g;
this.vmb[ind] += b;
this.vma[ind] += a;
this.m2[ind] += (r * r) + (g * g) + (b * b) + (a * a);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -301,7 +302,7 @@ namespace SixLabors.ImageSharp.Quantizers
/// <param name="cube">The cube.</param> /// <param name="cube">The cube.</param>
/// <param name="moment">The moment.</param> /// <param name="moment">The moment.</param>
/// <returns>The result.</returns> /// <returns>The result.</returns>
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)] return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)]
- moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)]
@ -328,12 +329,12 @@ namespace SixLabors.ImageSharp.Quantizers
/// <param name="direction">The direction.</param> /// <param name="direction">The direction.</param>
/// <param name="moment">The moment.</param> /// <param name="moment">The moment.</param>
/// <returns>The result.</returns> /// <returns>The result.</returns>
private static long Bottom(Box cube, int direction, long[] moment) private static long Bottom(ref Box cube, int direction, long[] moment)
{ {
switch (direction) switch (direction)
{ {
// Red // Red
case 0: case 3:
return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] 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.B1, cube.A0)]
+ moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)]
@ -344,7 +345,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Green // Green
case 1: case 2:
return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] 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.B1, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)]
@ -355,7 +356,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Blue // Blue
case 2: case 1:
return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] 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.G1, cube.B0, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)]
@ -366,7 +367,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Alpha // Alpha
case 3: case 0:
return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] 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.G1, cube.B0, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)]
@ -389,12 +390,12 @@ namespace SixLabors.ImageSharp.Quantizers
/// <param name="position">The position.</param> /// <param name="position">The position.</param>
/// <param name="moment">The moment.</param> /// <param name="moment">The moment.</param>
/// <returns>The result.</returns> /// <returns>The result.</returns>
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) switch (direction)
{ {
// Red // Red
case 0: case 3:
return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] 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.B1, cube.A0)]
- moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)]
@ -405,7 +406,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)];
// Green // Green
case 1: case 2:
return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] 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.B1, cube.A0)]
- moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)]
@ -416,7 +417,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)];
// Blue // Blue
case 2: case 1:
return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)]
- moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)]
- moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)]
@ -427,7 +428,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)];
// Alpha // Alpha
case 3: case 0:
return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)]
- moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)]
- moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)]
@ -553,12 +554,12 @@ namespace SixLabors.ImageSharp.Quantizers
/// </summary> /// </summary>
/// <param name="cube">The cube.</param> /// <param name="cube">The cube.</param>
/// <returns>The <see cref="float"/>.</returns> /// <returns>The <see cref="float"/>.</returns>
private float Variance(Box cube) private float Variance(ref Box cube)
{ {
float dr = Volume(cube, this.vmr); float dr = Volume(ref cube, this.vmr);
float dg = Volume(cube, this.vmg); float dg = Volume(ref cube, this.vmg);
float db = Volume(cube, this.vmb); float db = Volume(ref cube, this.vmb);
float da = Volume(cube, this.vma); float da = Volume(ref cube, this.vma);
float xx = float xx =
this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)]
@ -578,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.A1)]
+ this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + 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)); var vector = new Vector4(dr, dg, db, da);
return xx - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt));
} }
/// <summary> /// <summary>
@ -599,38 +601,33 @@ namespace SixLabors.ImageSharp.Quantizers
/// <param name="wholeA">The whole alpha.</param> /// <param name="wholeA">The whole alpha.</param>
/// <param name="wholeW">The whole weight.</param> /// <param name="wholeW">The whole weight.</param>
/// <returns>The <see cref="float"/>.</returns> /// <returns>The <see cref="float"/>.</returns>
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 baseR = Bottom(ref cube, direction, this.vmr);
long baseG = Bottom(cube, direction, this.vmg); long baseG = Bottom(ref cube, direction, this.vmg);
long baseB = Bottom(cube, direction, this.vmb); long baseB = Bottom(ref cube, direction, this.vmb);
long baseA = Bottom(cube, direction, this.vma); long baseA = Bottom(ref cube, direction, this.vma);
long baseW = Bottom(cube, direction, this.vwt); long baseW = Bottom(ref cube, direction, this.vwt);
float max = 0F; float max = 0F;
cut = -1; cut = -1;
for (int i = first; i < last; i++) for (int i = first; i < last; i++)
{ {
float halfR = baseR + Top(cube, direction, i, this.vmr); float halfR = baseR + Top(ref cube, direction, i, this.vmr);
float halfG = baseG + Top(cube, direction, i, this.vmg); float halfG = baseG + Top(ref cube, direction, i, this.vmg);
float halfB = baseB + Top(cube, direction, i, this.vmb); float halfB = baseB + Top(ref cube, direction, i, this.vmb);
float halfA = baseA + Top(cube, direction, i, this.vma); float halfA = baseA + Top(ref cube, direction, i, this.vma);
float halfW = baseW + Top(cube, direction, i, this.vwt); float halfW = baseW + Top(ref cube, direction, i, this.vwt);
float temp;
if (MathF.Abs(halfW) < Constants.Epsilon) if (MathF.Abs(halfW) < Constants.Epsilon)
{ {
continue; continue;
} }
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; halfW = wholeW - halfW;
if (MathF.Abs(halfW) < Constants.Epsilon) if (MathF.Abs(halfW) < Constants.Epsilon)
@ -638,7 +635,14 @@ namespace SixLabors.ImageSharp.Quantizers
continue; 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) if (temp > max)
{ {
@ -656,24 +660,24 @@ namespace SixLabors.ImageSharp.Quantizers
/// <param name="set1">The first set.</param> /// <param name="set1">The first set.</param>
/// <param name="set2">The second set.</param> /// <param name="set2">The second set.</param>
/// <returns>Returns a value indicating whether the box has been split.</returns> /// <returns>Returns a value indicating whether the box has been split.</returns>
private bool Cut(Box set1, Box set2) private bool Cut(ref Box set1, ref Box set2)
{ {
float wholeR = Volume(set1, this.vmr); float wholeR = Volume(ref set1, this.vmr);
float wholeG = Volume(set1, this.vmg); float wholeG = Volume(ref set1, this.vmg);
float wholeB = Volume(set1, this.vmb); float wholeB = Volume(ref set1, this.vmb);
float wholeA = Volume(set1, this.vma); float wholeA = Volume(ref set1, this.vma);
float wholeW = Volume(set1, this.vwt); 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 maxr = this.Maximize(ref set1, 3, 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 maxg = this.Maximize(ref set1, 2, 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 maxb = this.Maximize(ref set1, 1, 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 maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW);
int dir; int dir;
if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa)) if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa))
{ {
dir = 0; dir = 3;
if (cutr < 0) if (cutr < 0)
{ {
@ -682,15 +686,15 @@ namespace SixLabors.ImageSharp.Quantizers
} }
else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa)) else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa))
{ {
dir = 1; dir = 2;
} }
else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa)) else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa))
{ {
dir = 2; dir = 1;
} }
else else
{ {
dir = 3; dir = 0;
} }
set2.R1 = set1.R1; set2.R1 = set1.R1;
@ -701,7 +705,7 @@ namespace SixLabors.ImageSharp.Quantizers
switch (dir) switch (dir)
{ {
// Red // Red
case 0: case 3:
set2.R0 = set1.R1 = cutr; set2.R0 = set1.R1 = cutr;
set2.G0 = set1.G0; set2.G0 = set1.G0;
set2.B0 = set1.B0; set2.B0 = set1.B0;
@ -709,7 +713,7 @@ namespace SixLabors.ImageSharp.Quantizers
break; break;
// Green // Green
case 1: case 2:
set2.G0 = set1.G1 = cutg; set2.G0 = set1.G1 = cutg;
set2.R0 = set1.R0; set2.R0 = set1.R0;
set2.B0 = set1.B0; set2.B0 = set1.B0;
@ -717,7 +721,7 @@ namespace SixLabors.ImageSharp.Quantizers
break; break;
// Blue // Blue
case 2: case 1:
set2.B0 = set1.B1 = cutb; set2.B0 = set1.B1 = cutb;
set2.R0 = set1.R0; set2.R0 = set1.R0;
set2.G0 = set1.G0; set2.G0 = set1.G0;
@ -725,7 +729,7 @@ namespace SixLabors.ImageSharp.Quantizers
break; break;
// Alpha // Alpha
case 3: case 0:
set2.A0 = set1.A1 = cuta; set2.A0 = set1.A1 = cuta;
set2.R0 = set1.R0; set2.R0 = set1.R0;
set2.G0 = set1.G0; set2.G0 = set1.G0;
@ -744,7 +748,7 @@ namespace SixLabors.ImageSharp.Quantizers
/// </summary> /// </summary>
/// <param name="cube">The cube.</param> /// <param name="cube">The cube.</param>
/// <param name="label">A label.</param> /// <param name="label">A label.</param>
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++) for (int r = cube.R0 + 1; r <= cube.R1; r++)
{ {
@ -769,23 +773,21 @@ namespace SixLabors.ImageSharp.Quantizers
this.colorCube = new Box[this.colors]; this.colorCube = new Box[this.colors];
float[] vv = new float[this.colors]; float[] vv = new float[this.colors];
for (int i = 0; i < this.colors; i++) ref var cube = ref this.colorCube[0];
{ cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0;
this.colorCube[i] = new Box(); cube.R1 = cube.G1 = cube.B1 = IndexCount - 1;
} cube.A1 = IndexAlphaCount - 1;
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;
int next = 0; int next = 0;
for (int i = 1; i < this.colors; i++) for (int i = 1; i < this.colors; i++)
{ {
if (this.Cut(this.colorCube[next], 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(this.colorCube[next]) : 0F; vv[next] = nextCube.Volume > 1 ? this.Variance(ref nextCube) : 0F;
vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(this.colorCube[i]) : 0F; vv[i] = currentCube.Volume > 1 ? this.Variance(ref currentCube) : 0F;
} }
else else
{ {
@ -805,7 +807,7 @@ namespace SixLabors.ImageSharp.Quantizers
} }
} }
if (temp <= 0.0) if (temp <= 0F)
{ {
this.colors = i + 1; this.colors = i + 1;
break; break;

Loading…
Cancel
Save