BitMiracle.LibJpeg.Classic.Internal.my_2pass_cquantizer.median_cut C# (CSharp) Method

median_cut() private method

Repeatedly select and split the largest box until we have enough boxes
private median_cut ( box boxlist, int numboxes, int desired_colors ) : int
boxlist box
numboxes int
desired_colors int
return int
        private int median_cut(box[] boxlist, int numboxes, int desired_colors)
        {
            while (numboxes < desired_colors)
            {
                /* Select box to split.
                 * Current algorithm: by population for first half, then by volume.
                 */
                int foundIndex;
                if (numboxes * 2 <= desired_colors)
                    foundIndex = find_biggest_color_pop(boxlist, numboxes);
                else
                    foundIndex = find_biggest_volume(boxlist, numboxes);

                if (foundIndex == -1)     /* no splittable boxes left! */
                    break;

                /* Copy the color bounds to the new box. */
                boxlist[numboxes].c0max = boxlist[foundIndex].c0max;
                boxlist[numboxes].c1max = boxlist[foundIndex].c1max;
                boxlist[numboxes].c2max = boxlist[foundIndex].c2max;
                boxlist[numboxes].c0min = boxlist[foundIndex].c0min;
                boxlist[numboxes].c1min = boxlist[foundIndex].c1min;
                boxlist[numboxes].c2min = boxlist[foundIndex].c2min;

                /* Choose which axis to split the box on.
                 * Current algorithm: longest scaled axis.
                 * See notes in update_box about scaling distances.
                 */
                int c0 = ((boxlist[foundIndex].c0max - boxlist[foundIndex].c0min) << C0_SHIFT) * R_SCALE;
                int c1 = ((boxlist[foundIndex].c1max - boxlist[foundIndex].c1min) << C1_SHIFT) * G_SCALE;
                int c2 = ((boxlist[foundIndex].c2max - boxlist[foundIndex].c2min) << C2_SHIFT) * B_SCALE;

                /* We want to break any ties in favor of green, then red, blue last.
                 * This code does the right thing for R,G,B or B,G,R color orders only.
                 */
                int cmax = c1;
                int n = 1;

                if (c0 > cmax)
                {
                    cmax = c0;
                    n = 0;
                }

                if (c2 > cmax)
                {
                    n = 2;
                }

                /* Choose split point along selected axis, and update box bounds.
                 * Current algorithm: split at halfway point.
                 * (Since the box has been shrunk to minimum volume,
                 * any split will produce two nonempty subboxes.)
                 * Note that lb value is max for lower box, so must be < old max.
                 */
                int lb;
                switch (n)
                {
                    case 0:
                        lb = (boxlist[foundIndex].c0max + boxlist[foundIndex].c0min) / 2;
                        boxlist[foundIndex].c0max = lb;
                        boxlist[numboxes].c0min = lb + 1;
                        break;
                    case 1:
                        lb = (boxlist[foundIndex].c1max + boxlist[foundIndex].c1min) / 2;
                        boxlist[foundIndex].c1max = lb;
                        boxlist[numboxes].c1min = lb + 1;
                        break;
                    case 2:
                        lb = (boxlist[foundIndex].c2max + boxlist[foundIndex].c2min) / 2;
                        boxlist[foundIndex].c2max = lb;
                        boxlist[numboxes].c2min = lb + 1;
                        break;
                }

                /* Update stats for boxes */
                update_box(boxlist, foundIndex);
                update_box(boxlist, numboxes);
                numboxes++;
            }

            return numboxes;
        }