/// <summary>
        /// Blur and transpose a block of ARGB pixels.
        /// </summary>
        /// <param name="kernel"></param>
        /// <param name="inPixels"></param>
        /// <param name="outPixels"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="alpha"></param>
        /// <param name="premultiply"></param>
        /// <param name="unpremultiply"></param>
        /// <param name="edgeAction"></param>
        public static void ConvolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, bool premultiply, bool unpremultiply, EdgeMode edgeAction) {
            float[] matrix = kernel.GetKernel();
            int cols = kernel.Width;
            int cols2 = cols/2;

            for (int y = 0; y < height; y++) {
                int index = y;
                int ioffset = y*width;
                for (int x = 0; x < width; x++) {
                    float r = 0, g = 0, b = 0, a = 0;
                    int moffset = cols2;
                    for (int col = -cols2; col <= cols2; col++) {
                        float f = matrix[moffset + col];

                        if (f != 0) {
                            int ix = x + col;
                            if (ix < 0) {
                                if (edgeAction == EdgeMode.Clamp)
                                    ix = 0;
                                else if (edgeAction == EdgeMode.Wrap)
                                    ix = (x + width)%width;
                            }
                            else if (ix >= width) {
                                if (edgeAction == EdgeMode.Clamp)
                                    ix = width - 1;
                                else if (edgeAction == EdgeMode.Wrap)
                                    ix = (x + width)%width;
                            }
                            int rgb = inPixels[ioffset + ix];
                            int pa = (rgb >> 24) & 0xff;
                            int pr = (rgb >> 16) & 0xff;
                            int pg = (rgb >> 8) & 0xff;
                            int pb = rgb & 0xff;
                            if (premultiply) {
                                float a255 = pa*(1.0f/255.0f);
                                pr = (int)(pr*a255);
                                pg = (int)(pg*a255);
                                pb = (int)(pb*a255);
                            }
                            a += f*pa;
                            r += f*pr;
                            g += f*pg;
                            b += f*pb;
                        }
                    }
                    if (unpremultiply && a != 0 && a != 255) {
                        float f = 255.0f/a;
                        r *= f;
                        g *= f;
                        b *= f;
                    }
                    int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff;
                    int ir = PixelUtils.Clamp((int)(r + 0.5));
                    int ig = PixelUtils.Clamp((int)(g + 0.5));
                    int ib = PixelUtils.Clamp((int)(b + 0.5));
                    outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
                    index += height;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Convolve with a kernel consisting of one row.
        /// </summary>
        /// <param name="kernel"></param>
        /// <param name="inPixels"></param>
        /// <param name="outPixels"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="alpha"></param>
        /// <param name="edgeAction"></param>
        public static void ConvolveH(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction)
        {
            int index = 0;

            float[] matrix = kernel.GetKernel();
            int     cols   = kernel.Width;
            int     cols2  = cols / 2;

            for (int y = 0; y < height; y++)
            {
                int ioffset = y * width;
                for (int x = 0; x < width; x++)
                {
                    float r = 0, g = 0, b = 0, a = 0;
                    int   moffset = cols2;
                    for (int col = -cols2; col <= cols2; col++)
                    {
                        float f = matrix[moffset + col];

                        if (f != 0)
                        {
                            int ix = x + col;
                            if (ix < 0)
                            {
                                if (edgeAction == EdgeMode.Clamp)
                                {
                                    ix = 0;
                                }
                                else if (edgeAction == EdgeMode.Wrap)
                                {
                                    ix = (x + width) % width;
                                }
                            }
                            else if (ix >= width)
                            {
                                if (edgeAction == EdgeMode.Clamp)
                                {
                                    ix = width - 1;
                                }
                                else if (edgeAction == EdgeMode.Wrap)
                                {
                                    ix = (x + width) % width;
                                }
                            }
                            int rgb = inPixels[ioffset + ix];
                            a += f * ((rgb >> 24) & 0xff);
                            r += f * ((rgb >> 16) & 0xff);
                            g += f * ((rgb >> 8) & 0xff);
                            b += f * (rgb & 0xff);
                        }
                    }
                    int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff;
                    int ir = PixelUtils.Clamp((int)(r + 0.5));
                    int ig = PixelUtils.Clamp((int)(g + 0.5));
                    int ib = PixelUtils.Clamp((int)(b + 0.5));
                    outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
                }
            }
        }
        private static void Sharpen(KalikoImage image, float amount, float radius, int threshold)
        {
            var inPixels   = image.IntArray;
            var workPixels = new int[inPixels.Length];
            var outPixels  = new int[inPixels.Length];

            if (radius > 0)
            {
                var kernel = GaussianBlurFilter.CreateKernel(radius);
                GaussianBlurFilter.ConvolveAndTranspose(kernel, inPixels, workPixels, image.Width, image.Height, true, true, false, ConvolveFilter.EdgeMode.Clamp);
                GaussianBlurFilter.ConvolveAndTranspose(kernel, workPixels, outPixels, image.Height, image.Width, true, false, true, ConvolveFilter.EdgeMode.Clamp);
            }

            for (int index = 0; index < inPixels.Length; index++)
            {
                int rgb1 = inPixels[index];
                int r1   = (rgb1 >> 16) & 0xff;
                int g1   = (rgb1 >> 8) & 0xff;
                int b1   = rgb1 & 0xff;

                int rgb2 = outPixels[index];
                int r2   = (rgb2 >> 16) & 0xff;
                int g2   = (rgb2 >> 8) & 0xff;
                int b2   = rgb2 & 0xff;

                if (Math.Abs(r1 - r2) >= threshold)
                {
                    r1 = PixelUtils.Clamp((int)((amount + 1) * (r1 - r2) + r2));
                }
                if (Math.Abs(g1 - g2) >= threshold)
                {
                    g1 = PixelUtils.Clamp((int)((amount + 1) * (g1 - g2) + g2));
                }
                if (Math.Abs(b1 - b2) >= threshold)
                {
                    b1 = PixelUtils.Clamp((int)((amount + 1) * (b1 - b2) + b2));
                }

                inPixels[index] = (int)(rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1;
            }

            image.IntArray = inPixels;
        }
Example #4
0
        /// <summary>
        /// Convolve with a kernel consisting of one column.
        /// </summary>
        /// <param name="kernel"></param>
        /// <param name="inPixels"></param>
        /// <param name="outPixels"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="alpha"></param>
        /// <param name="edgeAction"></param>
        public static void ConvolveV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction)
        {
            int index = 0;

            float[] matrix = kernel.GetKernel();
            int     rows   = kernel.Height;
            int     rows2  = rows / 2;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    float r = 0, g = 0, b = 0, a = 0;

                    for (int row = -rows2; row <= rows2; row++)
                    {
                        int iy = y + row;
                        int ioffset;
                        if (iy < 0)
                        {
                            if (edgeAction == EdgeMode.Clamp)
                            {
                                ioffset = 0;
                            }
                            else if (edgeAction == EdgeMode.Wrap)
                            {
                                ioffset = ((y + height) % height) * width;
                            }
                            else
                            {
                                ioffset = iy * width;
                            }
                        }
                        else if (iy >= height)
                        {
                            if (edgeAction == EdgeMode.Clamp)
                            {
                                ioffset = (height - 1) * width;
                            }
                            else if (edgeAction == EdgeMode.Wrap)
                            {
                                ioffset = ((y + height) % height) * width;
                            }
                            else
                            {
                                ioffset = iy * width;
                            }
                        }
                        else
                        {
                            ioffset = iy * width;
                        }

                        float f = matrix[row + rows2];

                        if (f != 0)
                        {
                            int rgb = inPixels[ioffset + x];
                            a += f * ((rgb >> 24) & 0xff);
                            r += f * ((rgb >> 16) & 0xff);
                            g += f * ((rgb >> 8) & 0xff);
                            b += f * (rgb & 0xff);
                        }
                    }
                    int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff;
                    int ir = PixelUtils.Clamp((int)(r + 0.5));
                    int ig = PixelUtils.Clamp((int)(g + 0.5));
                    int ib = PixelUtils.Clamp((int)(b + 0.5));
                    outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
                }
            }
        }
Example #5
0
        /// <summary>
        /// Convolve with a 2D kernel.
        /// </summary>
        /// <param name="kernel"></param>
        /// <param name="inPixels"></param>
        /// <param name="outPixels"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="alpha"></param>
        /// <param name="edgeAction"></param>
        public static void ConvolveHV(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, EdgeMode edgeAction)
        {
            int index = 0;

            float[] matrix = kernel.GetKernel();
            int     rows   = kernel.Height;
            int     cols   = kernel.Width;
            int     rows2  = rows / 2;
            int     cols2  = cols / 2;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    float r = 0, g = 0, b = 0, a = 0;

                    for (int row = -rows2; row <= rows2; row++)
                    {
                        int iy = y + row;
                        int ioffset;
                        if (0 <= iy && iy < height)
                        {
                            ioffset = iy * width;
                        }
                        else if (edgeAction == EdgeMode.Clamp)
                        {
                            ioffset = y * width;
                        }
                        else if (edgeAction == EdgeMode.Wrap)
                        {
                            ioffset = ((iy + height) % height) * width;
                        }
                        else
                        {
                            continue;
                        }
                        int moffset = cols * (row + rows2) + cols2;
                        for (int col = -cols2; col <= cols2; col++)
                        {
                            float f = matrix[moffset + col];

                            if (f != 0)
                            {
                                int ix = x + col;
                                if (!(0 <= ix && ix < width))
                                {
                                    if (edgeAction == EdgeMode.Clamp)
                                    {
                                        ix = x;
                                    }
                                    else if (edgeAction == EdgeMode.Wrap)
                                    {
                                        ix = (x + width) % width;
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }
                                int rgb = inPixels[ioffset + ix];
                                a += f * ((rgb >> 24) & 0xff);
                                r += f * ((rgb >> 16) & 0xff);
                                g += f * ((rgb >> 8) & 0xff);
                                b += f * (rgb & 0xff);
                            }
                        }
                    }
                    int ia = alpha ? PixelUtils.Clamp((int)(a + 0.5)) : 0xff;
                    int ir = PixelUtils.Clamp((int)(r + 0.5));
                    int ig = PixelUtils.Clamp((int)(g + 0.5));
                    int ib = PixelUtils.Clamp((int)(b + 0.5));
                    outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
                }
            }
        }