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()); }
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()); }
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()); }
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()); }
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()); }
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)); }
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> 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()); }
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()); }