Beispiel #1
0
            public static KernelMap <T> GetOrAdd(int isize, int osize, InterpolationSettings interpolator, int ichannels, double offset)
            {
                if (!(interpolator.WeightingFunction is IUniquelyIdentifiable iwf))
                {
                    return(KernelMap <T> .create(isize, osize, interpolator, ichannels, offset));
                }

                var hasher = Blake2b.CreateIncrementalHasher(Unsafe.SizeOf <Guid>());

                hasher.Update(isize);
                hasher.Update(osize);
                hasher.Update(ichannels);
                hasher.Update(offset);
                hasher.Update(iwf.UniqueID);
                hasher.Update(interpolator.Blur);

                Span <byte> hash = stackalloc byte[Unsafe.SizeOf <Guid>()];

                hasher.Finish(hash);
                var key = MemoryMarshal.Read <Guid>(hash);

                if (lruCache.TryGet(key, out var map))
                {
                    return(map);
                }

                return(lruCache.GetOrAdd(key, KernelMap <T> .create(isize, osize, interpolator, ichannels, offset)));
            }
Beispiel #2
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());
        }
Beispiel #3
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));
        }
        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());
        }
Beispiel #5
0
        unsafe public static KernelMap <T> MakeScaleMap(uint isize, uint osize, int colorChannels, bool alphaChannel, bool vectored, InterpolationSettings 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;
            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[0])
            {
                int *   mp = (int *)mstart;
                double *kp = stackalloc double[ksize];

                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, kp, ksize, start, spoint, cscale);

                    spoint += inc;
                    *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());
        }