예제 #1
0
        unsafe public static KernelMap MakeBlurMap(uint size, double radius)
        {
            int[] blurkernel = new MathUtil.GaussianFactory(radius).MakeKernel().Select(f => MathUtil.ScaleToInt32(f)).ToArray();
            int   blurdist   = blurkernel.Length;

            var map = new KernelMap((int)size, (int)size, blurdist);

            fixed(int *mstart = map.Map, kstart = blurkernel)
            {
                int *mp = mstart, kp = kstart;

                for (int i = 0; i < size; i++)
                {
                    int end   = i + blurdist / 2;
                    int start = end - blurdist + 1;

                    *mp++ = start;

                    for (int j = 0; j < blurdist; j++)
                    {
                        *mp++ = kp[j];
                    }
                }
            }

            return(map.clamp());
        }
예제 #2
0
        unsafe public static KernelMap <T> MakeBlurMap(uint size, double radius, uint colorChannels, bool alphaChannel)
        {
            double[] blurkernel = new MathUtil.GaussianFactory(radius).MakeKernel();
            int      blurdist   = Math.Min(blurkernel.Length, (int)size);
            int      channels   = (int)colorChannels + (alphaChannel ? 1 : 0);

            var map = new KernelMap <T>((int)size, (int)size, blurdist, channels);

            fixed(byte *mstart = map.Map.Array)
            fixed(double *kstart = blurkernel)
            {
                int *   mp = (int *)mstart;
                double *kp = kstart;

                for (int i = 0; i < size; i++)
                {
                    int start = i - blurdist / 2;
                    *mp++ = start;

                    for (int j = 0; j < blurdist; j++)
                    {
                        T w = convertWeight(kp[j]);
                        for (int k = 0; k < channels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }
                    }
                }
            }

            return(map.clamp());
        }
예제 #3
0
        unsafe public static KernelMap <T> MakeScaleMap(uint isize, uint osize, int colorChannels, bool alphaChannel, bool vectored, InterpolationSettings interpolator)
        {
            var ainterpolator = interpolator.WeightingFunction.Support > 1d ? InterpolationSettings.Hermite : interpolator;

            double offs = interpolator.WeightingFunction.Support < 0.1 ? 0.5 : 0.0;
            double ratio = Math.Min((double)osize / isize, 1d);
            double cscale = ratio / interpolator.Blur, ascale = ratio / ainterpolator.Blur;
            double support = Math.Min(interpolator.WeightingFunction.Support / cscale, isize / 2d);

            int channels = colorChannels + (alphaChannel ? 1 : 0);
            int ksize    = (int)Math.Ceiling(support * 2d);
            int kpad     = vectored ? getKernelPadding((int)isize, ksize, channels) : 0;

            var map = new KernelMap <T>((int)isize, (int)osize, ksize + kpad, channels);

            fixed(byte *mstart = map.Map.Array)
            {
                double *ckern = stackalloc double[ksize];
                double *akern = stackalloc double[alphaChannel ? ksize : 0];
                int *   mp    = (int *)mstart;

                double inc    = (double)isize / osize;
                double spoint = ((double)isize - osize) / (osize * 2d) + offs;

                for (int i = 0; i < osize; i++)
                {
                    int start = (int)(spoint + support) - ksize + 1;
                    fillKernelWeights(interpolator.WeightingFunction, ckern, ksize, start, spoint, cscale);

                    if (alphaChannel)
                    {
                        fillKernelWeights(ainterpolator.WeightingFunction, akern, ksize, start, spoint, ascale);
                    }

                    spoint += inc;
                    *mp++   = start;

                    for (int j = 0; j < ksize; j++)
                    {
                        var w = convertWeight(ckern[j]);
                        for (int k = 0; k < colorChannels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }

                        if (alphaChannel)
                        {
                            Unsafe.Write(mp++, convertWeight(akern[j]));
                        }
                    }

                    mp += kpad * channels;
                }
            }

            return(map.clamp());
        }
예제 #4
0
        unsafe public KernelMap MakeAlphaMap()
        {
            if (InPixelCount == OutPixelCount)
            {
                return(this);
            }

            var    interpolator = InterpolationSettings.Hermite.WeightingFunction;
            double blur         = 0.9;

            double wfactor = Math.Min((double)OutPixelCount / InPixelCount, 1d);
            double wdist   = Math.Min(interpolator.Support / wfactor * blur, InPixelCount / 2d);
            int    wsize   = (int)Math.Ceiling(wdist * 2d);

            if (wsize >= SampleCount)
            {
                return(this);
            }

            wsize = SampleCount;
            int osize = OutPixelCount;
            var map   = new KernelMap(InPixelCount, OutPixelCount, SampleCount);

            fixed(int *istart = Map, ostart = map.Map)
            {
                double *wp = stackalloc double[wsize];
                int *   ip = istart, op = ostart;

                double inc      = (double)InPixelCount / OutPixelCount;
                double midpoint = ((double)InPixelCount - OutPixelCount) / (OutPixelCount * 2d);

                for (int i = 0; i < osize; i++)
                {
                    int start = *ip++;
                    *   op++  = start;

                    double weightsum = 0d;
                    for (int j = 0; j < wsize; j++)
                    {
                        double weight = interpolator.GetValue(Math.Abs(((double)start + j - midpoint) * wfactor / blur));
                        weightsum += weight;
                        wp[j]      = weight;
                    }

                    for (int j = 0; j < wsize; j++, ip++)
                    {
                        *op++ = MathUtil.ScaleToInt32(wp[j] / weightsum);
                    }

                    midpoint += inc;
                }
            }

            return(map.clamp());
        }
예제 #5
0
        unsafe public static KernelMap MakeScaleMap(uint isize, uint osize, InterpolationSettings interpolator)
        {
            double offs = interpolator.WeightingFunction.Support <= 0.1 ? 0.5 : 0.0;
            double blur = interpolator.Blur;

            if (interpolator.WeightingFunction.Support <= 0.5)
            {
                blur = 1d;
            }

            double wfactor = Math.Min((double)osize / isize, 1d);
            double wdist   = Math.Min(interpolator.WeightingFunction.Support / wfactor * blur, isize / 2d);
            int    wsize   = (int)Math.Ceiling(wdist * 2d);

            var map = new KernelMap((int)isize, (int)osize, wsize);

            fixed(int *mapstart = map.Map)
            {
                double *wp = stackalloc double[wsize];
                int *   mp = mapstart;

                double inc      = (double)isize / osize;
                double midpoint = ((double)isize - osize) / (osize * 2d) + offs;

                for (int i = 0; i < osize; i++)
                {
                    int end   = (int)(midpoint + wdist);
                    int start = end - wsize + 1;

                    *mp++ = start;

                    double weightsum = 0d;
                    for (int j = 0; j < wsize; j++)
                    {
                        double weight = interpolator.WeightingFunction.GetValue(Math.Abs(((double)start + j - midpoint) * wfactor / blur));
                        weightsum += weight;
                        wp[j]      = weight;
                    }

                    for (int j = 0; j < wsize; j++)
                    {
                        *mp++ = MathUtil.ScaleToInt32(wp[j] / weightsum);
                    }

                    midpoint += inc;
                }
            }

            return(map.clamp());
        }
예제 #6
0
        unsafe public static KernelMap <T> CreateBlur(int size, double radius, int ichannels, bool vectored)
        {
            var interpolator = radius switch {
                0.50 => blur_0_50,
                0.60 => blur_0_60,
                0.75 => blur_0_75,
                1.00 => blur_1_00,
                1.50 => blur_1_50,
                _ => new GaussianInterpolator(radius)
            };

            int channels = vectored ? ichannels : 1;
            int dist     = (int)Math.Ceiling(interpolator.Support);
            int ksize    = Math.Min(dist * 2 + 1, size);
            int kpad     = vectored ? getPadding(size, ksize, channels) : 0;

            var map = new KernelMap <T>(size, ksize + kpad, channels);

            fixed(byte *mstart = map.Map)
            {
                int *mp = (int *)mstart;

                Span <float> kernel = stackalloc float[ksize];

                fillWeights(kernel, interpolator, 0d, dist, 1d);

                for (int i = 0; i < size; i++)
                {
                    int start = i - ksize / 2;
                    *mp++ = start;

                    for (int j = 0; j < kernel.Length; j++)
                    {
                        var w = convertWeight(kernel[j]);
                        for (int k = 0; k < channels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }
                    }

                    mp += kpad * channels;
                }
            }

            return(map.clamp(size));
        }
예제 #7
0
        unsafe public static KernelMap <T> CreateResample(int isize, int osize, InterpolationSettings interpolator, int ichannels, bool subsampleOffset, bool vectored)
        {
            double offs    = interpolator.WeightingFunction.Support < 0.1 ? 0.5 : subsampleOffset ? 0.25 : 0.0;
            double ratio   = Math.Min((double)osize / isize, 1d);
            double cscale  = ratio / interpolator.Blur;
            double support = Math.Min(interpolator.WeightingFunction.Support / cscale, isize / 2d);

            int channels = vectored ? ichannels : 1;
            int ksize    = (int)Math.Ceiling(support * 2d);
            int kpad     = vectored ? getPadding(isize, ksize, channels) : 0;

            var map = new KernelMap <T>(osize, ksize + kpad, channels);

            fixed(byte *mstart = map.Map)
            {
                int *  mp     = (int *)mstart;
                double inc    = (double)isize / osize;
                double spoint = ((double)isize - osize) / (osize * 2d) + offs;

                Span <float> kernel = stackalloc float[ksize];

                for (int i = 0; i < osize; i++)
                {
                    int start = (int)(spoint + support) - ksize + 1;
                    fillWeights(kernel, interpolator.WeightingFunction, start, spoint, cscale);

                    spoint += inc;
                    *mp++   = start;

                    for (int j = 0; j < kernel.Length; j++)
                    {
                        var w = convertWeight(kernel[j]);
                        for (int k = 0; k < channels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }
                    }

                    mp += kpad * channels;
                }
            }

            return(map.clamp(isize));
        }
예제 #8
0
        unsafe public static KernelMap <T> MakeBlurMap(uint size, double radius, int colorChannels, bool alphaChannel, bool vectored)
        {
            var interpolator = new GaussianInterpolator(radius);

            int channels = colorChannels + (alphaChannel ? 1 : 0);
            int dist     = (int)Math.Ceiling(interpolator.Support);
            int ksize    = Math.Min(dist * 2 + 1, (int)size);
            int kpad     = vectored ? getKernelPadding((int)size, ksize, channels) : 0;

            var map = new KernelMap <T>((int)size, (int)size, ksize + kpad, channels);

            fixed(byte *mstart = &map.Map.Array[0])
            {
                int *   mp = (int *)mstart;
                double *kp = stackalloc double[ksize];

                fillKernelWeights(interpolator, kp, ksize, 0d, dist, 1d);

                for (int i = 0; i < size; i++)
                {
                    int start = i - ksize / 2;
                    *mp++ = start;

                    for (int j = 0; j < ksize; j++)
                    {
                        var w = convertWeight(kp[j]);
                        for (int k = 0; k < channels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }
                    }

                    mp += kpad * channels;
                }
            }

            return(map.clamp());
        }
예제 #9
0
        unsafe public static KernelMap <T> MakeScaleMap(uint isize, uint osize, int colorChannels, bool alphaChannel, bool vectored, InterpolationSettings interpolator)
        {
            var ainterpolator = interpolator.WeightingFunction.Support > 1d ? InterpolationSettings.Hermite : interpolator;

            double offs    = interpolator.WeightingFunction.Support < 0.1 ? 0.5 : 0.0;
            double wfactor = Math.Min((double)osize / isize, 1d);
            double wscale  = wfactor / interpolator.Blur;
            double awscale = wfactor / ainterpolator.Blur;
            double wdist   = Math.Min(interpolator.WeightingFunction.Support / wscale, isize / 2d);

            int channels = colorChannels + (alphaChannel ? 1 : 0);
            int wsize    = (int)Math.Ceiling(wdist * 2d);

            if (vectored && wsize * channels % (Vector <T> .Count * channels) >= (Vector <T> .Count * channels) / 2)
            {
                wsize = (wsize * channels + (Vector <T> .Count * channels - 1) & ~(Vector <T> .Count * channels - 1)) / channels;
            }
            wsize = Math.Min(wsize, (int)isize);

            var map = new KernelMap <T>((int)isize, (int)osize, wsize, channels);

            fixed(byte *mapstart = map.Map.Array)
            {
                double *wp  = stackalloc double[wsize];
                double *awp = stackalloc double[wsize];
                int *   mp  = (int *)mapstart;

                double inc    = (double)isize / osize;
                double spoint = ((double)isize - osize) / (osize * 2d) + offs;

                for (int i = 0; i < osize; i++)
                {
                    int start = (int)(spoint + wdist) - wsize + 1;
                    *mp++ = start;

                    double weightsum = 0d;
                    for (int j = 0; j < wsize; j++)
                    {
                        double weight = interpolator.WeightingFunction.GetValue(Math.Abs(((double)start + j - spoint) * wscale));
                        weightsum += weight;
                        wp[j]      = weight;
                    }
                    weightsum = 1d / weightsum;
                    for (int j = 0; j < wsize; j++)
                    {
                        wp[j] *= weightsum;
                    }

                    if (alphaChannel)
                    {
                        double aweightsum = 0d;
                        for (int j = 0; j < wsize; j++)
                        {
                            double weight = ainterpolator.WeightingFunction.GetValue(Math.Abs(((double)start + j - spoint) * awscale));
                            aweightsum += weight;
                            awp[j]      = weight;
                        }
                        aweightsum = 1d / aweightsum;
                        for (int j = 0; j < wsize; j++)
                        {
                            awp[j] *= aweightsum;
                        }
                    }

                    for (int j = 0; j < wsize; j++)
                    {
                        T w = convertWeight(wp[j]);
                        for (int k = 0; k < colorChannels; k++)
                        {
                            Unsafe.Write(mp++, w);
                        }

                        if (alphaChannel)
                        {
                            Unsafe.Write(mp++, convertWeight(awp[j]));
                        }
                    }

                    spoint += inc;
                }
            }

            return(map.clamp());
        }