< Summary

Line coverage
96%
Covered lines: 215
Uncovered lines: 7
Coverable lines: 222
Total lines: 599
Line coverage: 96.8%
Branch coverage
93%
Covered branches: 67
Total branches: 72
Branch coverage: 93%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
Quantize(...)100%11100%
Quantize(...)100%66100%
GetIndex(...)100%11100%
Volume(...)100%11100%
Bottom(...)75%4.01492.3%
Top(...)75%4.01492.3%
Clear()100%11100%
Build3DHistogram(...)100%22100%
Get3DMoments()100%66100%
Variance(...)100%11100%
Maximize(...)100%88100%
Cut(...)100%1414100%
Mark(...)100%66100%
BuildCube(...)87.5%16.021695.65%
GenerateResult(...)83.33%6.29680%

File(s)

https://raw.githubusercontent.com/JeremyAnsel/JeremyAnsel.ColorQuant/c10d236cc66f271c33ae73d6471e0c94607a8d9c/JeremyAnsel.ColorQuant/JeremyAnsel.ColorQuant/WuColorQuantizer.cs

#LineLine coverage
 1// <copyright file="WuColorQuantizer.cs" company="Jérémy Ansel">
 2// Copyright (c) 2014-2019 Jérémy Ansel
 3// </copyright>
 4// <license>
 5// Licensed under the MIT license. See LICENSE.txt
 6// </license>
 7
 8namespace JeremyAnsel.ColorQuant
 9{
 10    using System;
 11    using System.Diagnostics.CodeAnalysis;
 12
 13    /// <summary>
 14    /// A Wu's color quantizer.
 15    /// </summary>
 16    /// <remarks>
 17    /// <para>
 18    /// Based on C Implementation of Xiaolin Wu's Color Quantizer (v. 2)
 19    /// (see Graphics Gems volume II, pages 126-133)
 20    /// (<see href="http://www.ece.mcmaster.ca/~xwu/cq.c"/>).
 21    /// </para>
 22    /// <para>
 23    /// Algorithm: Greedy orthogonal bipartition of RGB space for variance
 24    /// minimization aided by inclusion-exclusion tricks.
 25    /// For speed no nearest neighbor search is done. Slightly
 26    /// better performance can be expected by more sophisticated
 27    /// but more expensive versions.
 28    /// </para>
 29    /// </remarks>
 30    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Wu", Justification = "
 31    public sealed class WuColorQuantizer : IColorQuantizer
 32    {
 33        /// <summary>
 34        /// The index bits.
 35        /// </summary>
 36        private const int IndexBits = 7;
 37
 38        /// <summary>
 39        /// The index count.
 40        /// </summary>
 41        private const int IndexCount = (1 << WuColorQuantizer.IndexBits) + 1;
 42
 43        /// <summary>
 44        /// The table length.
 45        /// </summary>
 46        private const int TableLength = WuColorQuantizer.IndexCount * WuColorQuantizer.IndexCount * WuColorQuantizer.Ind
 47
 48        /// <summary>
 49        /// Moment of <c>P(c)</c>.
 50        /// </summary>
 351        private readonly long[] vwt = new long[WuColorQuantizer.TableLength];
 52
 53        /// <summary>
 54        /// Moment of <c>r*P(c)</c>.
 55        /// </summary>
 356        private readonly long[] vmr = new long[WuColorQuantizer.TableLength];
 57
 58        /// <summary>
 59        /// Moment of <c>g*P(c)</c>.
 60        /// </summary>
 361        private readonly long[] vmg = new long[WuColorQuantizer.TableLength];
 62
 63        /// <summary>
 64        /// Moment of <c>b*P(c)</c>.
 65        /// </summary>
 366        private readonly long[] vmb = new long[WuColorQuantizer.TableLength];
 67
 68        /// <summary>
 69        /// Moment of <c>c^2*P(c)</c>.
 70        /// </summary>
 371        private readonly double[] m2 = new double[WuColorQuantizer.TableLength];
 72
 73        /// <summary>
 74        /// Color space tag.
 75        /// </summary>
 376        private readonly byte[] tag = new byte[WuColorQuantizer.TableLength];
 77
 78        /// <summary>
 79        /// Quantizes an image.
 80        /// </summary>
 81        /// <param name="image">The image (XRGB).</param>
 82        /// <returns>The result.</returns>
 83        public ColorQuantizerResult Quantize(byte[] image)
 84        {
 2185            return this.Quantize(image, 256);
 86        }
 87
 88        /// <summary>
 89        /// Quantizes an image.
 90        /// </summary>
 91        /// <param name="image">The image (XRGB).</param>
 92        /// <param name="colorCount">The color count.</param>
 93        /// <returns>The result.</returns>
 94        public ColorQuantizerResult Quantize(byte[] image, int colorCount)
 95        {
 3096            if (image == null)
 97            {
 698                throw new ArgumentNullException(nameof(image));
 99            }
 100
 24101            if (colorCount < 1 || colorCount > 256)
 102            {
 6103                throw new ArgumentOutOfRangeException(nameof(colorCount));
 104            }
 105
 18106            this.Clear();
 107
 18108            this.Build3DHistogram(image);
 18109            this.Get3DMoments();
 110
 111            Box[] cube;
 18112            this.BuildCube(out cube, ref colorCount);
 113
 18114            return this.GenerateResult(image, colorCount, cube);
 115        }
 116
 117        /// <summary>
 118        /// Gets an index.
 119        /// </summary>
 120        /// <param name="r">The red value.</param>
 121        /// <param name="g">The green value.</param>
 122        /// <param name="b">The blue value.</param>
 123        /// <returns>The index.</returns>
 124        private static int GetIndex(int r, int g, int b)
 125        {
 127659966126            return (r << (WuColorQuantizer.IndexBits * 2)) + (r << (WuColorQuantizer.IndexBits + 1)) + (g << WuColorQuan
 127        }
 128
 129        /// <summary>
 130        /// Computes sum over a box of any given statistic.
 131        /// </summary>
 132        /// <param name="cube">The cube.</param>
 133        /// <param name="moment">The moment.</param>
 134        /// <returns>The result.</returns>
 135        private static double Volume(Box cube, long[] moment)
 136        {
 42840137            return moment[WuColorQuantizer.GetIndex(cube.R1, cube.G1, cube.B1)]
 42840138               - moment[WuColorQuantizer.GetIndex(cube.R1, cube.G1, cube.B0)]
 42840139               - moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B1)]
 42840140               + moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B0)]
 42840141               - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B1)]
 42840142               + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B0)]
 42840143               + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B1)]
 42840144               - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B0)];
 145        }
 146
 147        /// <summary>
 148        /// Computes part of Volume(cube, moment) that doesn't depend on r1, g1, or b1 (depending on direction).
 149        /// </summary>
 150        /// <param name="cube">The cube.</param>
 151        /// <param name="direction">The direction.</param>
 152        /// <param name="moment">The moment.</param>
 153        /// <returns>The result.</returns>
 154        private static long Bottom(Box cube, int direction, long[] moment)
 155        {
 156            switch (direction)
 157            {
 158                // Red
 159                case 2:
 15312160                    return -moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B1)]
 15312161                        + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B0)]
 15312162                        + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B1)]
 15312163                        - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B0)];
 164
 165                // Green
 166                case 1:
 15312167                    return -moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B1)]
 15312168                        + moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B0)]
 15312169                        + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B1)]
 15312170                        - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B0)];
 171
 172                // Blue
 173                case 0:
 15312174                    return -moment[WuColorQuantizer.GetIndex(cube.R1, cube.G1, cube.B0)]
 15312175                        + moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B0)]
 15312176                        + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B0)]
 15312177                        - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B0)];
 178
 179                default:
 0180                    throw new ArgumentOutOfRangeException(nameof(direction));
 181            }
 182        }
 183
 184        /// <summary>
 185        /// Computes remainder of Volume(cube, moment), substituting position for r1, g1, or b1 (depending on direction)
 186        /// </summary>
 187        /// <param name="cube">The cube.</param>
 188        /// <param name="direction">The direction.</param>
 189        /// <param name="position">The position.</param>
 190        /// <param name="moment">The moment.</param>
 191        /// <returns>The result.</returns>
 192        private static long Top(Box cube, int direction, int position, long[] moment)
 193        {
 194            switch (direction)
 195            {
 196                // Red
 197                case 2:
 881712198                    return moment[WuColorQuantizer.GetIndex(position, cube.G1, cube.B1)]
 881712199                       - moment[WuColorQuantizer.GetIndex(position, cube.G1, cube.B0)]
 881712200                       - moment[WuColorQuantizer.GetIndex(position, cube.G0, cube.B1)]
 881712201                       + moment[WuColorQuantizer.GetIndex(position, cube.G0, cube.B0)];
 202
 203                // Green
 204                case 1:
 1278000205                    return moment[WuColorQuantizer.GetIndex(cube.R1, position, cube.B1)]
 1278000206                       - moment[WuColorQuantizer.GetIndex(cube.R1, position, cube.B0)]
 1278000207                       - moment[WuColorQuantizer.GetIndex(cube.R0, position, cube.B1)]
 1278000208                       + moment[WuColorQuantizer.GetIndex(cube.R0, position, cube.B0)];
 209
 210                // Blue
 211                case 0:
 1301040212                    return moment[WuColorQuantizer.GetIndex(cube.R1, cube.G1, position)]
 1301040213                       - moment[WuColorQuantizer.GetIndex(cube.R1, cube.G0, position)]
 1301040214                       - moment[WuColorQuantizer.GetIndex(cube.R0, cube.G1, position)]
 1301040215                       + moment[WuColorQuantizer.GetIndex(cube.R0, cube.G0, position)];
 216
 217                default:
 0218                    throw new ArgumentOutOfRangeException(nameof(direction));
 219            }
 220        }
 221
 222        /// <summary>
 223        /// Clears the tables.
 224        /// </summary>
 225        private void Clear()
 226        {
 18227            Array.Clear(this.vwt, 0, WuColorQuantizer.TableLength);
 18228            Array.Clear(this.vmr, 0, WuColorQuantizer.TableLength);
 18229            Array.Clear(this.vmg, 0, WuColorQuantizer.TableLength);
 18230            Array.Clear(this.vmb, 0, WuColorQuantizer.TableLength);
 18231            Array.Clear(this.m2, 0, WuColorQuantizer.TableLength);
 232
 18233            Array.Clear(this.tag, 0, WuColorQuantizer.TableLength);
 18234        }
 235
 236        /// <summary>
 237        /// Builds a 3-D color histogram of <c>counts, r/g/b, c^2</c>.
 238        /// </summary>
 239        /// <param name="image">The image.</param>
 240        private void Build3DHistogram(byte[] image)
 241        {
 7722242            for (int i = 0; i < image.Length; i += 4)
 243            {
 3843244                int r = image[i + 2];
 3843245                int g = image[i + 1];
 3843246                int b = image[i];
 247
 3843248                int inr = r >> (8 - WuColorQuantizer.IndexBits);
 3843249                int ing = g >> (8 - WuColorQuantizer.IndexBits);
 3843250                int inb = b >> (8 - WuColorQuantizer.IndexBits);
 251
 3843252                int ind = WuColorQuantizer.GetIndex(inr + 1, ing + 1, inb + 1);
 253
 3843254                this.vwt[ind]++;
 3843255                this.vmr[ind] += r;
 3843256                this.vmg[ind] += g;
 3843257                this.vmb[ind] += b;
 3843258                this.m2[ind] += (r * r) + (g * g) + (b * b);
 259            }
 18260        }
 261
 262        /// <summary>
 263        /// Converts the histogram into moments so that we can rapidly calculate
 264        /// the sums of the above quantities over any desired box.
 265        /// </summary>
 266        private void Get3DMoments()
 267        {
 18268            long[] area = new long[WuColorQuantizer.IndexCount];
 18269            long[] areaR = new long[WuColorQuantizer.IndexCount];
 18270            long[] areaG = new long[WuColorQuantizer.IndexCount];
 18271            long[] areaB = new long[WuColorQuantizer.IndexCount];
 18272            double[] area2 = new double[WuColorQuantizer.IndexCount];
 273
 4644274            for (int r = 1; r < WuColorQuantizer.IndexCount; r++)
 275            {
 2304276                Array.Clear(area, 0, WuColorQuantizer.IndexCount);
 2304277                Array.Clear(areaR, 0, WuColorQuantizer.IndexCount);
 2304278                Array.Clear(areaG, 0, WuColorQuantizer.IndexCount);
 2304279                Array.Clear(areaB, 0, WuColorQuantizer.IndexCount);
 2304280                Array.Clear(area2, 0, WuColorQuantizer.IndexCount);
 281
 594432282                for (int g = 1; g < WuColorQuantizer.IndexCount; g++)
 283                {
 294912284                    long line = 0;
 294912285                    long lineR = 0;
 294912286                    long lineG = 0;
 294912287                    long lineB = 0;
 294912288                    double line2 = 0;
 289
 76087296290                    for (int b = 1; b < WuColorQuantizer.IndexCount; b++)
 291                    {
 37748736292                        int ind1 = WuColorQuantizer.GetIndex(r, g, b);
 293
 37748736294                        line += this.vwt[ind1];
 37748736295                        lineR += this.vmr[ind1];
 37748736296                        lineG += this.vmg[ind1];
 37748736297                        lineB += this.vmb[ind1];
 37748736298                        line2 += this.m2[ind1];
 299
 37748736300                        area[b] += line;
 37748736301                        areaR[b] += lineR;
 37748736302                        areaG[b] += lineG;
 37748736303                        areaB[b] += lineB;
 37748736304                        area2[b] += line2;
 305
 37748736306                        int ind2 = ind1 - WuColorQuantizer.GetIndex(1, 0, 0);
 307
 37748736308                        this.vwt[ind1] = this.vwt[ind2] + area[b];
 37748736309                        this.vmr[ind1] = this.vmr[ind2] + areaR[b];
 37748736310                        this.vmg[ind1] = this.vmg[ind2] + areaG[b];
 37748736311                        this.vmb[ind1] = this.vmb[ind2] + areaB[b];
 37748736312                        this.m2[ind1] = this.m2[ind2] + area2[b];
 313                    }
 314                }
 315            }
 18316        }
 317
 318        /// <summary>
 319        /// Computes the weighted variance of a box.
 320        /// </summary>
 321        /// <param name="cube">The cube.</param>
 322        /// <returns>The result.</returns>
 323        private double Variance(Box cube)
 324        {
 4575325            double dr = WuColorQuantizer.Volume(cube, this.vmr);
 4575326            double dg = WuColorQuantizer.Volume(cube, this.vmg);
 4575327            double db = WuColorQuantizer.Volume(cube, this.vmb);
 328
 4575329            double xx = this.m2[WuColorQuantizer.GetIndex(cube.R1, cube.G1, cube.B1)]
 4575330             - this.m2[WuColorQuantizer.GetIndex(cube.R1, cube.G1, cube.B0)]
 4575331             - this.m2[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B1)]
 4575332             + this.m2[WuColorQuantizer.GetIndex(cube.R1, cube.G0, cube.B0)]
 4575333             - this.m2[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B1)]
 4575334             + this.m2[WuColorQuantizer.GetIndex(cube.R0, cube.G1, cube.B0)]
 4575335             + this.m2[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B1)]
 4575336             - this.m2[WuColorQuantizer.GetIndex(cube.R0, cube.G0, cube.B0)];
 337
 4575338            return xx - (((dr * dr) + (dg * dg) + (db * db)) / WuColorQuantizer.Volume(cube, this.vwt));
 339        }
 340
 341        /// <summary>
 342        /// We want to minimize the sum of the variances of two sub-boxes.
 343        /// The sum(c^2) terms can be ignored since their sum over both sub-boxes
 344        /// is the same (the sum for the whole box) no matter where we split.
 345        /// The remaining terms have a minus sign in the variance formula,
 346        /// so we drop the minus sign and maximize the sum of the two terms.
 347        /// </summary>
 348        /// <param name="cube">The cube.</param>
 349        /// <param name="direction">The direction.</param>
 350        /// <param name="first">The first position.</param>
 351        /// <param name="last">The last position.</param>
 352        /// <param name="cut">The cutting point.</param>
 353        /// <param name="wholeR">The whole red.</param>
 354        /// <param name="wholeG">The whole green.</param>
 355        /// <param name="wholeB">The whole blue.</param>
 356        /// <param name="wholeW">The whole weight.</param>
 357        /// <returns>The result.</returns>
 358        private double Maximize(Box cube, int direction, int first, int last, out int cut, double wholeR, double wholeG,
 359        {
 11484360            long baseR = WuColorQuantizer.Bottom(cube, direction, this.vmr);
 11484361            long baseG = WuColorQuantizer.Bottom(cube, direction, this.vmg);
 11484362            long baseB = WuColorQuantizer.Bottom(cube, direction, this.vmb);
 11484363            long baseW = WuColorQuantizer.Bottom(cube, direction, this.vwt);
 364
 11484365            double max = 0.0;
 11484366            cut = -1;
 367
 1753344368            for (int i = first; i < last; i++)
 369            {
 865188370                double halfR = baseR + WuColorQuantizer.Top(cube, direction, i, this.vmr);
 865188371                double halfG = baseG + WuColorQuantizer.Top(cube, direction, i, this.vmg);
 865188372                double halfB = baseB + WuColorQuantizer.Top(cube, direction, i, this.vmb);
 865188373                double halfW = baseW + WuColorQuantizer.Top(cube, direction, i, this.vwt);
 374
 865188375                if (halfW == 0)
 376                {
 377                    continue;
 378                }
 379
 728268380                double temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB)) / halfW;
 381
 728268382                halfR = wholeR - halfR;
 728268383                halfG = wholeG - halfG;
 728268384                halfB = wholeB - halfB;
 728268385                halfW = wholeW - halfW;
 386
 728268387                if (halfW == 0)
 388                {
 389                    continue;
 390                }
 391
 48927392                temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB)) / halfW;
 393
 48927394                if (temp > max)
 395                {
 9600396                    max = temp;
 9600397                    cut = i;
 398                }
 399            }
 400
 11484401            return max;
 402        }
 403
 404        /// <summary>
 405        /// Cuts a box.
 406        /// </summary>
 407        /// <param name="set1">The first set.</param>
 408        /// <param name="set2">The second set.</param>
 409        /// <returns>Returns a value indicating whether the box has been split.</returns>
 410        private bool Cut(Box set1, Box set2)
 411        {
 3828412            double wholeR = WuColorQuantizer.Volume(set1, this.vmr);
 3828413            double wholeG = WuColorQuantizer.Volume(set1, this.vmg);
 3828414            double wholeB = WuColorQuantizer.Volume(set1, this.vmb);
 3828415            double wholeW = WuColorQuantizer.Volume(set1, this.vwt);
 416
 417            int cutr;
 418            int cutg;
 419            int cutb;
 420
 3828421            double maxr = this.Maximize(set1, 2, set1.R0 + 1, set1.R1, out cutr, wholeR, wholeG, wholeB, wholeW);
 3828422            double maxg = this.Maximize(set1, 1, set1.G0 + 1, set1.G1, out cutg, wholeR, wholeG, wholeB, wholeW);
 3828423            double maxb = this.Maximize(set1, 0, set1.B0 + 1, set1.B1, out cutb, wholeR, wholeG, wholeB, wholeW);
 424
 425            int dir;
 426
 3828427            if ((maxr >= maxg) && (maxr >= maxb))
 428            {
 2547429                dir = 2;
 430
 2547431                if (cutr < 0)
 432                {
 1539433                    return false;
 434                }
 435            }
 1281436            else if ((maxg >= maxr) && (maxg >= maxb))
 437            {
 408438                dir = 1;
 439            }
 440            else
 441            {
 873442                dir = 0;
 443            }
 444
 2289445            set2.R1 = set1.R1;
 2289446            set2.G1 = set1.G1;
 2289447            set2.B1 = set1.B1;
 448
 449            switch (dir)
 450            {
 451                // Red
 452                case 2:
 1008453                    set2.R0 = set1.R1 = cutr;
 1008454                    set2.G0 = set1.G0;
 1008455                    set2.B0 = set1.B0;
 1008456                    break;
 457
 458                // Green
 459                case 1:
 408460                    set2.G0 = set1.G1 = cutg;
 408461                    set2.R0 = set1.R0;
 408462                    set2.B0 = set1.B0;
 408463                    break;
 464
 465                // Blue
 466                case 0:
 873467                    set2.B0 = set1.B1 = cutb;
 873468                    set2.R0 = set1.R0;
 873469                    set2.G0 = set1.G0;
 470                    break;
 471            }
 472
 2289473            set1.Volume = (set1.R1 - set1.R0) * (set1.G1 - set1.G0) * (set1.B1 - set1.B0);
 2289474            set2.Volume = (set2.R1 - set2.R0) * (set2.G1 - set2.G0) * (set2.B1 - set2.B0);
 475
 2289476            return true;
 477        }
 478
 479        /// <summary>
 480        /// Marks a color space tag.
 481        /// </summary>
 482        /// <param name="cube">The cube.</param>
 483        /// <param name="label">A label.</param>
 484        private void Mark(Box cube, byte label)
 485        {
 228102486            for (int r = cube.R0 + 1; r <= cube.R1; r++)
 487            {
 13986048488                for (int g = cube.G0 + 1; g <= cube.G1; g++)
 489                {
 89260032490                    for (int b = cube.B0 + 1; b <= cube.B1; b++)
 491                    {
 37748736492                        this.tag[WuColorQuantizer.GetIndex(r, g, b)] = label;
 493                    }
 494                }
 495            }
 2307496        }
 497
 498        /// <summary>
 499        /// Builds the cube.
 500        /// </summary>
 501        /// <param name="cube">The cube.</param>
 502        /// <param name="colorCount">The color count.</param>
 503        private void BuildCube(out Box[] cube, ref int colorCount)
 504        {
 18505            cube = new Box[colorCount];
 18506            double[] vv = new double[colorCount];
 507
 9252508            for (int i = 0; i < colorCount; i++)
 509            {
 4608510                cube[i] = new Box();
 511            }
 512
 18513            cube[0].R0 = cube[0].G0 = cube[0].B0 = 0;
 18514            cube[0].R1 = cube[0].G1 = cube[0].B1 = WuColorQuantizer.IndexCount - 1;
 515
 18516            int next = 0;
 517
 7656518            for (int i = 1; i < colorCount; i++)
 519            {
 3828520                if (this.Cut(cube[next], cube[i]))
 521                {
 2289522                    vv[next] = cube[next].Volume > 1 ? this.Variance(cube[next]) : 0.0;
 2289523                    vv[i] = cube[i].Volume > 1 ? this.Variance(cube[i]) : 0.0;
 524                }
 525                else
 526                {
 1539527                    vv[next] = 0.0;
 1539528                    i--;
 529                }
 530
 3828531                next = 0;
 532
 3828533                double temp = vv[0];
 788712534                for (int k = 1; k <= i; k++)
 535                {
 390528536                    if (vv[k] > temp)
 537                    {
 3705538                        temp = vv[k];
 3705539                        next = k;
 540                    }
 541                }
 542
 3828543                if (temp <= 0.0)
 544                {
 18545                    colorCount = i + 1;
 18546                    break;
 547                }
 548            }
 0549        }
 550
 551        /// <summary>
 552        /// Generates the quantized result.
 553        /// </summary>
 554        /// <param name="image">The image.</param>
 555        /// <param name="colorCount">The color count.</param>
 556        /// <param name="cube">The cube.</param>
 557        /// <returns>The result.</returns>
 558        private ColorQuantizerResult GenerateResult(byte[] image, int colorCount, Box[] cube)
 559        {
 18560            var quantizedImage = new ColorQuantizerResult(image.Length / 4, colorCount);
 561
 4650562            for (int k = 0; k < colorCount; k++)
 563            {
 2307564                this.Mark(cube[k], (byte)k);
 565
 2307566                double weight = WuColorQuantizer.Volume(cube[k], this.vwt);
 567
 2307568                if (weight != 0)
 569                {
 2307570                    quantizedImage.Palette[(k * 4) + 3] = 0xff;
 2307571                    quantizedImage.Palette[(k * 4) + 2] = (byte)(WuColorQuantizer.Volume(cube[k], this.vmr) / weight);
 2307572                    quantizedImage.Palette[(k * 4) + 1] = (byte)(WuColorQuantizer.Volume(cube[k], this.vmg) / weight);
 2307573                    quantizedImage.Palette[k * 4] = (byte)(WuColorQuantizer.Volume(cube[k], this.vmb) / weight);
 574                }
 575                else
 576                {
 0577                    quantizedImage.Palette[(k * 4) + 3] = 0xff;
 0578                    quantizedImage.Palette[(k * 4) + 2] = 0;
 0579                    quantizedImage.Palette[(k * 4) + 1] = 0;
 0580                    quantizedImage.Palette[k * 4] = 0;
 581                }
 582            }
 583
 7722584            for (int i = 0; i < image.Length / 4; i++)
 585            {
 3843586                int r = image[(i * 4) + 2] >> (8 - WuColorQuantizer.IndexBits);
 3843587                int g = image[(i * 4) + 1] >> (8 - WuColorQuantizer.IndexBits);
 3843588                int b = image[i * 4] >> (8 - WuColorQuantizer.IndexBits);
 589
 3843590                int ind = WuColorQuantizer.GetIndex(r + 1, g + 1, b + 1);
 591
 3843592                quantizedImage.Bytes[i] = this.tag[ind];
 593            }
 594
 18595            return quantizedImage;
 596        }
 597    }
 598}
 599