public static void AddHighQualityScaler(WicProcessingContext ctx)
        {
            uint width = (uint)ctx.Settings.Width, height = (uint)ctx.Settings.Height;
            var  fmt           = ctx.Source.Format;
            var  interpolator  = ctx.Settings.Interpolation.WeightingFunction.Support > 1d && fmt.ColorRepresentation == PixelColorRepresentation.Unspecified ? InterpolationSettings.Hermite : ctx.Settings.Interpolation;
            var  interpolatorx = width == ctx.Source.Width ? InterpolationSettings.NearestNeighbor : interpolator;
            var  interpolatory = height == ctx.Source.Height ? InterpolationSettings.NearestNeighbor : interpolator;

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mx = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Width, width, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatorx));
                var my = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Height, height, fmt.ChannelCount == 3 ? 4 : fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatory));

                ctx.Source = ctx.AddDispose(new ConvolutionTransform <float, float>(ctx.Source, mx, my));
            }
            else
            {
                var mx = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Width, width, 1, false, false, interpolatorx));
                var my = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Height, height, 1, false, false, interpolatory));

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <ushort, int>(ctx.Source, mx, my));
                }
                else
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <byte, int>(ctx.Source, mx, my));
                }
            }
        }
Beispiel #2
0
        public static void AddUnsharpMask(WicProcessingContext ctx)
        {
            var ss = ctx.Settings.UnsharpMask;

            if (!ctx.Settings.Sharpen || ss.Radius <= 0d || ss.Amount <= 0)
            {
                return;
            }

            var fmt = ctx.Source.Format;

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mapx = ctx.AddDispose(KernelMap <float> .MakeBlurMap(ctx.Source.Width, ss.Radius, 1, false, true));
                var mapy = ctx.AddDispose(KernelMap <float> .MakeBlurMap(ctx.Source.Height, ss.Radius, 1, false, true));

                ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <float, float>(ctx.Source, mapx, mapy, ss));
            }
            else
            {
                var mapx = ctx.AddDispose(KernelMap <int> .MakeBlurMap(ctx.Source.Width, ss.Radius, 1, false, false));
                var mapy = ctx.AddDispose(KernelMap <int> .MakeBlurMap(ctx.Source.Height, ss.Radius, 1, false, false));

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <ushort, int>(ctx.Source, mapx, mapy, ss));
                }
                else
                {
                    ctx.Source = ctx.AddDispose(new UnsharpMaskTransform <byte, int>(ctx.Source, mapx, mapy, ss));
                }
            }
        }
Beispiel #3
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 #4
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());
        }
        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());
        }
Beispiel #6
0
        public ConvolutionTransform(PixelSource source, KernelMap <TWeight> mapx, KernelMap <TWeight> mapy, bool lumaMode = false) : base(source)
        {
            var fmt = Format;

            if (lumaMode)
            {
                if (fmt.ColorRepresentation == PixelColorRepresentation.Bgr || fmt.ColorRepresentation == PixelColorRepresentation.Grey)
                {
                    fmt = fmt.NumericRepresentation == PixelNumericRepresentation.Float ? PixelFormat.Grey32BppFloat :
                          fmt.NumericRepresentation == PixelNumericRepresentation.Fixed ? PixelFormat.Grey16BppUQ15 :
                          fmt.NumericRepresentation == PixelNumericRepresentation.UnsignedInteger ? PixelFormat.Cache[Consts.GUID_WICPixelFormat8bppGray] :
                          throw new NotSupportedException("Unsupported pixel format");
                }
                else
                {
                    throw new NotSupportedException("Unsupported pixel format");
                }
            }

            if (!ProcessorMap.TryGetValue(fmt.FormatGuid, out XProcessor))
            {
                throw new NotSupportedException("Unsupported pixel format");
            }

            if (fmt == PixelFormat.Bgr96BppLinearFloat)
            {
                Format = fmt = PixelFormat.Bgrx128BppLinearFloat;
            }
            else if (fmt == PixelFormat.Bgr96BppFloat)
            {
                Format = fmt = PixelFormat.Bgrx128BppFloat;
            }

            YProcessor = ProcessorMap[fmt.FormatGuid];
            XMap       = mapx;
            YMap       = mapy;

            BufferSource = lumaMode;
            SourceRect   = new WICRect {
                Width = (int)Width, Height = 1
            };
            IntStartLine = -mapy.Samples;

            IntBpp     = fmt.BitsPerPixel / 8 / Unsafe.SizeOf <TPixel>() * Unsafe.SizeOf <TWeight>();
            IntStride  = mapy.Samples * IntBpp;
            WorkStride = fmt.BitsPerPixel / 8 * (int)Width + (IntPtr.Size - 1) & ~(IntPtr.Size - 1);

            int lineBuffLen = (BufferSource ? mapy.Samples : 1) * (int)BufferStride;
            int intBuffLen  = mapx.OutPixels * IntStride;
            int workBuffLen = mapy.Samples * WorkStride;

            LineBuff = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(lineBuffLen), 0, lineBuffLen).Zero();
            IntBuff  = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(intBuffLen), 0, intBuffLen).Zero();
            WorkBuff = lumaMode && !Format.IsBinaryCompatibleWith(fmt) ? new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(workBuffLen), 0, workBuffLen).Zero() : LineBuff;

            Width  = (uint)mapx.OutPixels;
            Height = (uint)mapy.OutPixels;
        }
Beispiel #7
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());
        }
Beispiel #8
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());
        }
Beispiel #9
0
        public static void AddHighQualityScaler(WicProcessingContext ctx, bool hybrid = false)
        {
            uint   width = (uint)ctx.Settings.Width, height = (uint)ctx.Settings.Height;
            double rat = ctx.Settings.HybridScaleRatio;

            if ((ctx.Source.Width == width && ctx.Source.Height == height) || (hybrid && rat == 1d))
            {
                return;
            }

            if (hybrid)
            {
                if (ctx.Source.Format.FormatGuid != Consts.GUID_WICPixelFormat32bppCMYK)
                {
                    return;
                }

                width  = (uint)Math.Ceiling(ctx.Source.Width / rat);
                height = (uint)Math.Ceiling(ctx.Source.Height / rat);
                ctx.Settings.HybridMode = HybridScaleMode.Off;
            }

            AddInternalFormatConverter(ctx, allow96bppFloat: true);

            var fmt           = ctx.Source.Format;
            var interpolator  = ctx.Settings.Interpolation.WeightingFunction.Support > 1d && fmt.ColorRepresentation == PixelColorRepresentation.Unspecified ? InterpolationSettings.Hermite : ctx.Settings.Interpolation;
            var interpolatorx = width == ctx.Source.Width ? InterpolationSettings.NearestNeighbor : hybrid ? InterpolationSettings.Average : interpolator;
            var interpolatory = height == ctx.Source.Height ? InterpolationSettings.NearestNeighbor : hybrid ? InterpolationSettings.Average : interpolator;

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mx = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Width, width, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatorx));
                var my = ctx.AddDispose(KernelMap <float> .MakeScaleMap(ctx.Source.Height, height, fmt.ChannelCount == 3 ? 4 : fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatory));

                ctx.Source = ctx.AddDispose(new ConvolutionTransform <float, float>(ctx.Source, mx, my));
            }
            else
            {
                var mx = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Width, width, 1, false, false, interpolatorx));
                var my = ctx.AddDispose(KernelMap <int> .MakeScaleMap(ctx.Source.Height, height, 1, false, false, interpolatory));

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <ushort, int>(ctx.Source, mx, my));
                }
                else
                {
                    ctx.Source = ctx.AddDispose(new ConvolutionTransform <byte, int>(ctx.Source, mx, my));
                }
            }
        }
Beispiel #10
0
        public WicUnsharpMask(WicTransform prev) : base(prev)
        {
            var ss = Context.Settings.UnsharpMask;

            if (ss.Radius <= 0 || ss.Amount <= 0)
            {
                return;
            }

            var mapx = KernelMap.MakeBlurMap(Context.Width, ss.Radius);
            var mapy = KernelMap.MakeBlurMap(Context.Height, ss.Radius);

            Source = new WicUnsharpMask8bpc(Source, mapx, mapy, ss);
        }
Beispiel #11
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 #12
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));
        }
        public WicUnsharpMask(WicTransform prev) : base(prev)
        {
            var ss = Context.Settings.UnsharpMask;

            if (ss.Radius <= 0d || ss.Amount <= 0)
            {
                return;
            }

            var fmt = PixelFormat.Cache[Source.GetPixelFormat()];

            mapx = KernelMap <int> .MakeBlurMap(Context.Width, ss.Radius, 1u, fmt.AlphaRepresentation != PixelAlphaRepresentation.None);

            mapy = KernelMap <int> .MakeBlurMap(Context.Height, ss.Radius, 1u, fmt.AlphaRepresentation != PixelAlphaRepresentation.None);

            Source = source = new WicUnsharpMask <byte, int>(Source, mapx, mapy, ss);
        }
Beispiel #14
0
        public WicConvolution8bpc(IWICBitmapSource source, KernelMap mapx, KernelMap mapy, bool bufferSource = false) : base(source)
        {
            BufferSource = bufferSource;
            XMap         = mapx;
            YMap         = mapy;
            XMapAlpha    = mapx.MakeAlphaMap();
            YMapAlpha    = mapy.MakeAlphaMap();
            OutWidth     = (uint)mapx.OutPixelCount;
            OutHeight    = (uint)mapy.OutPixelCount;
            SourceRect   = new WICRect()
            {
                Width = (int)Width, Height = 1
            };

            if (Format == Consts.GUID_WICPixelFormat32bppPBGRA)
            {
                Processor = new ConvolverBgra8bpc();
            }
            else if (Format == Consts.GUID_WICPixelFormat32bppBGRA)
            {
                Processor = new ConvolverBgra8bpc();
            }
            else if (Format == Consts.GUID_WICPixelFormat24bppBGR)
            {
                Processor = new ConvolverBgr8bpc();
            }
            else if (Format == Consts.GUID_WICPixelFormat8bppGray)
            {
                Processor = new ConvolverGrey8bpc();
            }
            else if (Format == Consts.GUID_WICPixelFormat8bppY)
            {
                Processor = new ConvolverGrey8bpc();
            }
            else
            {
                throw new NotSupportedException("Unsupported pixel format");
            }

            Stride   /= sizeof(byte);
            IntStride = (int)(mapy.SampleCount * Channels);

            LineBuff     = new byte[(bufferSource ? mapy.SampleCount : 1) * Stride];
            IntBuff      = new int[OutWidth * IntStride];
            IntStartLine = -mapy.SampleCount;
        }
Beispiel #15
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));
        }
Beispiel #16
0
        public WicHighQualityScaler(WicTransform prev) : base(prev)
        {
            uint width = (uint)Context.Settings.Width, height = (uint)Context.Settings.Height;
            var  interpolatorx = width == Context.Width ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation;
            var  interpolatory = height == Context.Height ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation;

            var mapx = KernelMap.MakeScaleMap(Context.Width, width, interpolatorx);
            var mapy = KernelMap.MakeScaleMap(Context.Height, height, interpolatory);

            if (Context.Settings.BlendingMode == GammaMode.Linear)
            {
                Source = new WicConvolution16bpc(Source, mapx, mapy);
            }
            else
            {
                Source = new WicConvolution8bpc(Source, mapx, mapy);
            }

            Source.GetSize(out Context.Width, out Context.Height);
        }
        public WicHighQualityScaler(WicTransform prev) : base(prev)
        {
            uint width = (uint)Context.Settings.Width, height = (uint)Context.Settings.Height;
            var  interpolatorx = width == Context.Width ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation;
            var  interpolatory = height == Context.Height ? InterpolationSettings.NearestNeighbor : Context.Settings.Interpolation;

            var fmt = PixelFormat.Cache[Source.GetPixelFormat()];

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                var mx = KernelMap <float> .MakeScaleMap(Context.Width, width, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatorx);

                var my = KernelMap <float> .MakeScaleMap(Context.Height, height, fmt.ColorChannelCount, fmt.AlphaRepresentation != PixelAlphaRepresentation.None, true, interpolatory);

                source = new WicConvolution <float, float>(Source, mx, my);

                mapx = mx;
                mapy = my;
            }
            else
            {
                var mx = KernelMap <int> .MakeScaleMap(Context.Width, width, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatorx);

                var my = KernelMap <int> .MakeScaleMap(Context.Height, height, 1, fmt.AlphaRepresentation == PixelAlphaRepresentation.Unassociated, false, interpolatory);

                if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
                {
                    source = new WicConvolution <ushort, int>(Source, mx, my);
                }
                else
                {
                    source = new WicConvolution <byte, int>(Source, mx, my);
                }

                mapx = mx;
                mapy = my;
            }

            Source = source;
            Source.GetSize(out Context.Width, out Context.Height);
        }
Beispiel #18
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());
        }
 public UnsharpMaskTransform(PixelSource source, KernelMap <TWeight> mapx, KernelMap <TWeight> mapy, UnsharpMaskSettings ss) : base(source, mapx, mapy, true)
 {
     sharpenSettings = ss;
     processor       = ProcessorMap[Format.FormatGuid];
     blurBuff        = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(WorkStride), 0, WorkStride);
 }
        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 #21
0
        public WicConvolution(IWICBitmapSource source, KernelMap <TWeight> mapx, KernelMap <TWeight> mapy, bool bufferSource = false) : base(source)
        {
            if (Format.FormatGuid == Consts.GUID_WICPixelFormat32bppPBGRA)
            {
                Processor = new Convolver4ChanByte();
            }
            else if (Format.FormatGuid == Consts.GUID_WICPixelFormat32bppBGRA)
            {
                Processor = new ConvolverBgraByte();
            }
            else if (Format.FormatGuid == Consts.GUID_WICPixelFormat24bppBGR)
            {
                Processor = new ConvolverBgrByte();
            }
            else if (Format.FormatGuid == Consts.GUID_WICPixelFormat16bppCbCr)
            {
                Processor = new Convolver2ChanByte();
            }
            else if (Format.FormatGuid == Consts.GUID_WICPixelFormat8bppGray || Format.FormatGuid == Consts.GUID_WICPixelFormat8bppY)
            {
                Processor = new Convolver1ChanByte();
            }
            else if (Format == PixelFormat.Pbgra64BppLinearUQ15)
            {
                Processor = new Convolver4ChanUQ15();
            }
            else if (Format == PixelFormat.Bgra64BppLinearUQ15)
            {
                Processor = new ConvolverBgraUQ15();
            }
            else if (Format == PixelFormat.Bgr48BppLinearUQ15)
            {
                Processor = new ConvolverBgrUQ15();
            }
            else if (Format == PixelFormat.Grey16BppLinearUQ15 || Format == PixelFormat.Y16BppLinearUQ15)
            {
                Processor = new Convolver1ChanUQ15();
            }
            else if (Format == PixelFormat.Pbgra128BppLinearFloat || Format == PixelFormat.Pbgra128BppFloat)
            {
                Processor = new Convolver4ChanFloat();
            }
            else if (Format == PixelFormat.Bgr96BppLinearFloat || Format == PixelFormat.Bgr96BppFloat)
            {
                Processor = new Convolver3ChanFloat();
            }
            else if (Format == PixelFormat.CbCr64BppFloat)
            {
                Processor = new Convolver2ChanFloat();
            }
            else if (Format == PixelFormat.Grey32BppLinearFloat || Format.FormatGuid == Consts.GUID_WICPixelFormat32bppGrayFloat || Format == PixelFormat.Y32BppLinearFloat || Format == PixelFormat.Y32BppFloat)
            {
                Processor = new Convolver1ChanFloat();
            }
            else
            {
                throw new NotSupportedException("Unsupported pixel format");
            }

            BufferSource = bufferSource;
            OutWidth     = (uint)mapx.OutPixels;
            OutHeight    = (uint)mapy.OutPixels;
            SourceRect   = new WICRect {
                Width = (int)Width, Height = 1
            };
            XMap = mapx;
            YMap = mapy;

            IntBpp       = Bpp / Unsafe.SizeOf <TPixel>() * Unsafe.SizeOf <TWeight>();
            IntStride    = mapy.Samples * IntBpp;
            IntStartLine = -mapy.Samples;

            int lineBuffLen = (bufferSource ? mapy.Samples : 1) * (int)Stride;
            int intBuffLen  = mapx.OutPixels * IntStride;

            LineBuff = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(lineBuffLen), 0, lineBuffLen);
            IntBuff  = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(intBuffLen), 0, intBuffLen);
        }
Beispiel #22
0
 public WicUnsharpMask16bpc(IWICBitmapSource source, KernelMap mapx, KernelMap mapy, UnsharpMaskSettings ss) : base(source, mapx, mapy, true)
 {
     sharpenSettings = ss;
     blurBuff        = new ushort[Stride];
 }