Example #1
0
        private static VBox[] MedianCutApply(IReadOnlyList <int> histo, VBox vbox)
        {
            switch (vbox.Count(false))
            {
            case 0:
                return(null);

            case 1:
                return(new[] { vbox.Clone(), null });
            }

            // only one pixel, no split

            var rw   = vbox.R2 - vbox.R1 + 1;
            var gw   = vbox.G2 - vbox.G1 + 1;
            var bw   = vbox.B2 - vbox.B1 + 1;
            var maxw = Math.Max(Math.Max(rw, gw), bw);

            // Find the partial sum arrays along the selected axis.
            var total      = 0;
            var partialsum = new int[VboxLength];

            // -1 = not set / 0 = 0
            partialsum.Fill(-1);

            // -1 = not set / 0 = 0
            var lookaheadsum = new int[VboxLength];

            lookaheadsum.Fill(-1);
            int i, j, k, sum, index;

            if (maxw == rw)
            {
                for (i = vbox.R1; i <= vbox.R2; i++)
                {
                    sum = 0;
                    for (j = vbox.G1; j <= vbox.G2; j++)
                    {
                        for (k = vbox.B1; k <= vbox.B2; k++)
                        {
                            index = GetColorIndex(i, j, k);
                            sum  += histo[index];
                        }
                    }
                    total        += sum;
                    partialsum[i] = total;
                }
            }
            else if (maxw == gw)
            {
                for (i = vbox.G1; i <= vbox.G2; i++)
                {
                    sum = 0;
                    for (j = vbox.R1; j <= vbox.R2; j++)
                    {
                        for (k = vbox.B1; k <= vbox.B2; k++)
                        {
                            index = GetColorIndex(j, i, k);
                            sum  += histo[index];
                        }
                    }
                    total        += sum;
                    partialsum[i] = total;
                }
            }
            else
            /* maxw == bw */
            {
                for (i = vbox.B1; i <= vbox.B2; i++)
                {
                    sum = 0;
                    for (j = vbox.R1; j <= vbox.R2; j++)
                    {
                        for (k = vbox.G1; k <= vbox.G2; k++)
                        {
                            index = GetColorIndex(j, k, i);
                            sum  += histo[index];
                        }
                    }
                    total        += sum;
                    partialsum[i] = total;
                }
            }

            for (i = 0; i < VboxLength; i++)
            {
                if (partialsum[i] != -1)
                {
                    lookaheadsum[i] = total - partialsum[i];
                }
            }

            // determine the cut planes
            return(maxw == rw
                ? DoCut('r', vbox, partialsum, lookaheadsum, total)
                : maxw == gw
                    ? DoCut('g', vbox, partialsum, lookaheadsum, total)
                    : DoCut('b', vbox, partialsum, lookaheadsum, total));
        }
Example #2
0
        private static VBox[] DoCut(
            char color,
            VBox vbox,
            IReadOnlyList <int> partialsum,
            IReadOnlyList <int> lookaheadsum,
            int total)
        {
            int vboxDim1;
            int vboxDim2;

            switch (color)
            {
            case 'r':
                vboxDim1 = vbox.R1;
                vboxDim2 = vbox.R2;
                break;

            case 'g':
                vboxDim1 = vbox.G1;
                vboxDim2 = vbox.G2;
                break;

            default:
                vboxDim1 = vbox.B1;
                vboxDim2 = vbox.B2;
                break;
            }

            for (var i = vboxDim1; i <= vboxDim2; i++)
            {
                if (partialsum[i] > total / 2)
                {
                    var vbox1 = vbox.Clone();
                    var vbox2 = vbox.Clone();

                    var left  = i - vboxDim1;
                    var right = vboxDim2 - i;

                    var d2 = left <= right
                        ? Math.Min(vboxDim2 - 1, ~~(i + right / 2))
                        : Math.Max(vboxDim1, ~~((int)(i - 1 - left / 2.0)));

                    // avoid 0-count boxes
                    while (d2 < 0 || partialsum[d2] <= 0)
                    {
                        d2++;
                    }
                    var count2 = lookaheadsum[d2];
                    while (count2 == 0 && d2 > 0 && partialsum[d2 - 1] > 0)
                    {
                        count2 = lookaheadsum[--d2];
                    }

                    // set dimensions
                    switch (color)
                    {
                    case 'r':
                        vbox1.R2 = d2;
                        vbox2.R1 = d2 + 1;
                        break;

                    case 'g':
                        vbox1.G2 = d2;
                        vbox2.G1 = d2 + 1;
                        break;

                    default:
                        vbox1.B2 = d2;
                        vbox2.B1 = d2 + 1;
                        break;
                    }

                    return(new[] { vbox1, vbox2 });
                }
            }

            throw new Exception("VBox can't be cut");
        }