Пример #1
0
        /// <summary>
        /// Generates the quantized result.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="colorCount">The color count.</param>
        /// <param name="width">Width of image</param>
        /// <param name="height">Height of image</param>
        /// <param name="destPixels">Pixel values are written here. Must provide width*height memory.</param>
        /// <param name="padMultiple4">True to write zero padding to make row bytes multiple of 4</param>
        /// <returns>Receives colors</returns>
        private unsafe uint[] GenerateResult(uint *image, int colorCount, int width, int height, byte *destPixels, bool padMultiple4)
        {
            uint[] palette = new uint[colorCount];

            // rows must be a multiple of 4, hence padding up to 3 bytes for 8-bit indexed pixels
            int widthMod4  = width % 4;
            int widthZeros = widthMod4 != 0 ? 4 - widthMod4 : 0;

            for (int k = 0; k < colorCount; k++)
            {
                this.Mark(ref this.cube[k], (byte)k);

                float weight = WuQuant.Volume(ref this.cube[k], this.vwt);

                if (weight != 0)
                {
                    uint a = (byte)(WuQuant.Volume(ref this.cube[k], this.vma) / weight);
                    uint r = (byte)(WuQuant.Volume(ref this.cube[k], this.vmr) / weight);
                    uint g = (byte)(WuQuant.Volume(ref this.cube[k], this.vmg) / weight);
                    uint b = (byte)(WuQuant.Volume(ref this.cube[k], this.vmb) / weight);

                    palette[k] = (a << 24) | (r << 16) | (g << 8) | b;
                }
                else
                {
                    palette[k] = 0xFF000000;
                }
            }

            for (int ri = 0; ri < height; ri++)
            {
                for (int ci = 0; ci < width; ci++)
                {
                    uint pix = image[0];

                    uint a = ((pix & 0xFF000000) >> 24) >> (8 - WuQuant.INDEXALPHABITS);
                    uint r = ((pix & 0x00FF0000) >> 16) >> (8 - WuQuant.INDEXBITS);
                    uint g = ((pix & 0x0000FF00) >> 8) >> (8 - WuQuant.INDEXBITS);
                    uint b = (pix & 0x000000FF) >> (8 - WuQuant.INDEXBITS);

                    int ind = WuQuant.GetIndex((int)r + 1, (int)g + 1, (int)b + 1, (int)a + 1);

                    destPixels[0] = this.tag[ind];
                    destPixels++;
                    image++;
                }

                // write additional zero bytes if requested
                if (padMultiple4)
                {
                    for (int c = 0; c < widthZeros; c++)
                    {
                        destPixels[0] = 0x00;
                        destPixels++;
                    }
                }
            }

            return(palette);
        }
Пример #2
0
        /// <summary>
        /// Computes the weighted variance of a box.
        /// </summary>
        /// <param name="c">The cube.</param>
        /// <returns>The result.</returns>
        private float Variance(ref Data.Box c)
        {
            float dr = WuQuant.Volume(ref c, this.vmr);
            float dg = WuQuant.Volume(ref c, this.vmg);
            float db = WuQuant.Volume(ref c, this.vmb);
            float da = WuQuant.Volume(ref c, this.vma);

            float xx =
                this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B1, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B1, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B0, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G1, c.B0, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B1, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B1, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B0, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R1, c.G0, c.B0, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B1, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B1, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B0, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G1, c.B0, c.A0)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B1, c.A1)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B1, c.A0)]
                - this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B0, c.A1)]
                + this.m2[WuQuant.GetIndex(c.R0, c.G0, c.B0, c.A0)];

            return(xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / WuQuant.Volume(ref c, this.vwt)));
        }
Пример #3
0
        /// <summary>
        /// Cuts a box.
        /// </summary>
        /// <param name="set1">The first set.</param>
        /// <param name="set2">The second set.</param>
        /// <returns>Returns a value indicating whether the box has been split.</returns>
        private bool Cut(ref Data.Box set1, ref Data.Box set2)
        {
            float wholeR = WuQuant.Volume(ref set1, this.vmr);
            float wholeG = WuQuant.Volume(ref set1, this.vmg);
            float wholeB = WuQuant.Volume(ref set1, this.vmb);
            float wholeA = WuQuant.Volume(ref set1, this.vma);
            float wholeW = WuQuant.Volume(ref set1, this.vwt);

            int cutr;
            int cutg;
            int cutb;
            int cuta;

            float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out cutr, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out cutg, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out cutb, wholeR, wholeG, wholeB, wholeA, wholeW);
            float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out cuta, wholeR, wholeG, wholeB, wholeA, wholeW);

            int dir;

            if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa))
            {
                dir = 3;

                if (cutr < 0)
                {
                    return(false);
                }
            }
            else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa))
            {
                dir = 2;
            }
            else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa))
            {
                dir = 1;
            }
            else
            {
                dir = 0;
            }

            set2.R1 = set1.R1;
            set2.G1 = set1.G1;
            set2.B1 = set1.B1;
            set2.A1 = set1.A1;

            switch (dir)
            {
            // Red
            case 3:
                set2.R0 = set1.R1 = cutr;
                set2.G0 = set1.G0;
                set2.B0 = set1.B0;
                set2.A0 = set1.A0;
                break;

            // Green
            case 2:
                set2.G0 = set1.G1 = cutg;
                set2.R0 = set1.R0;
                set2.B0 = set1.B0;
                set2.A0 = set1.A0;
                break;

            // Blue
            case 1:
                set2.B0 = set1.B1 = cutb;
                set2.R0 = set1.R0;
                set2.G0 = set1.G0;
                set2.A0 = set1.A0;
                break;

            // Alpha
            case 0:
                set2.A0 = set1.A1 = cuta;
                set2.R0 = set1.R0;
                set2.G0 = set1.G0;
                set2.B0 = set1.B0;
                break;
            }

            set1.Volume = (set1.R1 - set1.R0) * (set1.G1 - set1.G0) * (set1.B1 - set1.B0) * (set1.A1 - set1.A0);
            set2.Volume = (set2.R1 - set2.R0) * (set2.G1 - set2.G0) * (set2.B1 - set2.B0) * (set2.A1 - set2.A0);

            return(true);
        }