예제 #1
0
        public static void AddPlanarConverter(PipelineContext ctx)
        {
            Debug.Assert(ctx.PlanarContext is not null);

            if (ctx.Source.Format.Encoding == PixelValueEncoding.Linear || ctx.PlanarContext.SourceCb.Format.NumericRepresentation != ctx.Source.Format.NumericRepresentation)
            {
                if (ctx.Source.Format.NumericRepresentation == PixelNumericRepresentation.Float && ctx.PlanarContext.SourceCb.Format.NumericRepresentation == ctx.Source.Format.NumericRepresentation)
                {
                    AddInternalFormatConverter(ctx, PixelValueEncoding.Companded);
                }
                else
                {
                    AddPlanarExternalFormatConverter(ctx);
                }
            }

            var  matrix      = YccMatrix.Rec601;
            bool videoLevels = false;

            if (ctx.ImageFrame is IYccImageFrame frame)
            {
                matrix      = frame.RgbYccMatrix;
                videoLevels = !frame.IsFullRange;
            }

            ctx.Source        = ctx.AddDispose(new PlanarConversionTransform(ctx.Source, ctx.PlanarContext.SourceCb, ctx.PlanarContext.SourceCr, matrix, videoLevels));
            ctx.PlanarContext = null;
        }
예제 #2
0
        public static void AddInternalFormatConverter(PipelineContext ctx, PixelValueEncoding enc = PixelValueEncoding.Unspecified, bool allow96bppFloat = false)
        {
            var  ifmt   = ctx.Source.Format;
            var  ofmt   = ifmt;
            bool linear = enc == PixelValueEncoding.Unspecified ? ctx.Settings.BlendingMode == GammaMode.Linear : enc == PixelValueEncoding.Linear;

            if (allow96bppFloat && MagicImageProcessor.EnableSimd && ifmt == PixelFormat.Bgr24Bpp)
            {
                ofmt = linear ? PixelFormat.Bgr96BppLinearFloat : PixelFormat.Bgr96BppFloat;
            }
            else if (linear && (MagicImageProcessor.EnableSimd ? internalFormatMapLinearSimd : internalFormatMapLinear).TryGetValue(ifmt, out var ofmtl))
            {
                ofmt = ofmtl;
            }
            else if (MagicImageProcessor.EnableSimd && internalFormatMapSimd.TryGetValue(ifmt, out var ofmts))
            {
                ofmt = ofmts;
            }

            bool videoLevels = ifmt == PixelFormat.Y8Bpp && ctx.ImageFrame is IYccImageFrame frame && !frame.IsFullRange;

            if (ofmt == ifmt && !videoLevels)
            {
                return;
            }

            bool forceSrgb = (ofmt == PixelFormat.Y32BppLinearFloat || ofmt == PixelFormat.Y16BppLinearUQ15) && ctx.SourceColorProfile != ColorProfile.sRGB;

            ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, forceSrgb ? ColorProfile.sRGB : ctx.SourceColorProfile, forceSrgb ? ColorProfile.sRGB : ctx.DestColorProfile, ofmt, videoLevels));
        }
예제 #3
0
        public static void AddMatte(PipelineContext ctx)
        {
            var fmt = ctx.Source.Format;

            if (ctx.Settings.MatteColor.IsEmpty || fmt.ColorRepresentation != PixelColorRepresentation.Bgr || fmt.AlphaRepresentation == PixelAlphaRepresentation.None)
            {
                return;
            }

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float && fmt.Encoding == PixelValueEncoding.Companded)
            {
                AddInternalFormatConverter(ctx, PixelValueEncoding.Linear);
            }

            ctx.Source = new MatteTransform(ctx.Source, ctx.Settings.MatteColor, !ctx.IsAnimatedGifPipeline);

            if (!ctx.IsAnimatedGifPipeline && ctx.Source.Format.AlphaRepresentation != PixelAlphaRepresentation.None && !ctx.Settings.MatteColor.IsTransparent())
            {
                var oldFmt = ctx.Source.Format;
                var newFmt = oldFmt == PixelFormat.Pbgra64BppLinearUQ15 ? PixelFormat.Bgr48BppLinearUQ15
                                        : oldFmt == PixelFormat.Bgra32Bpp ? PixelFormat.Bgr24Bpp
                                        : throw new NotSupportedException("Unsupported pixel format");

                ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, null, null, newFmt));
            }
        }
예제 #4
0
        public static void AddMatte(PipelineContext ctx)
        {
            var fmt = ctx.Source.Format;

            if (ctx.Settings.MatteColor.IsEmpty || fmt.ColorRepresentation != PixelColorRepresentation.Bgr || fmt.AlphaRepresentation == PixelAlphaRepresentation.None)
            {
                return;
            }

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float && fmt.Encoding == PixelValueEncoding.Companded)
            {
                AddInternalFormatConverter(ctx, PixelValueEncoding.Linear);
            }

            ctx.Source = new MatteTransform(ctx.Source, ctx.Settings.MatteColor);

            if (ctx.Source.Format.AlphaRepresentation != PixelAlphaRepresentation.None && ctx.Settings.MatteColor.A == byte.MaxValue)
            {
                var oldFmt = ctx.Source.Format;
                var newFmt = oldFmt == PixelFormat.Pbgra64BppLinearUQ15 ? PixelFormat.Bgr48BppLinearUQ15
                                        : oldFmt.FormatGuid == Consts.GUID_WICPixelFormat32bppBGRA ? PixelFormat.FromGuid(Consts.GUID_WICPixelFormat24bppBGR)
                                        : throw new NotSupportedException("Unsupported pixel format");

                ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, null, null, newFmt.FormatGuid));
            }
        }
예제 #5
0
        public static void AddHighQualityScaler(PipelineContext ctx)
        {
            bool swap  = ctx.Orientation.SwapsDimensions();
            var  tsize = ctx.Settings.InnerSize;

            int width = swap ? tsize.Height : tsize.Width, height = swap ? tsize.Width : tsize.Height;

            if (ctx.Source.Width == width && ctx.Source.Height == height)
            {
                return;
            }

            var interpolatorx = width == ctx.Source.Width ? InterpolationSettings.NearestNeighbor : ctx.Settings.Interpolation;
            var interpolatory = height == ctx.Source.Height ? InterpolationSettings.NearestNeighbor : ctx.Settings.Interpolation;

            if (interpolatorx.WeightingFunction.Support >= 0.1 || interpolatory.WeightingFunction.Support >= 0.1)
            {
                AddInternalFormatConverter(ctx, allow96bppFloat: true);
            }

            var  fmt = ctx.Source.Format;
            bool offsetX = false, offsetY = false;

            if (ctx.ImageFrame is IYccImageFrame frame && ctx.PlanarContext is not null && fmt.Encoding == PixelValueEncoding.Unspecified)
            {
                offsetX = frame.ChromaPosition.HasFlag(ChromaPosition.CositedHorizontal) && ctx.PlanarContext.ChromaSubsampling.IsSubsampledX();
                offsetY = frame.ChromaPosition.HasFlag(ChromaPosition.CositedVertical) && ctx.PlanarContext.ChromaSubsampling.IsSubsampledY();
            }

            if (fmt.NumericRepresentation == PixelNumericRepresentation.Float)
            {
                ctx.Source = ctx.AddDispose(ConvolutionTransform <float, float> .CreateResize(ctx.Source, width, height, interpolatorx, interpolatory, offsetX, offsetY));
            }
            else if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
            {
                ctx.Source = ctx.AddDispose(ConvolutionTransform <ushort, int> .CreateResize(ctx.Source, width, height, interpolatorx, interpolatory, offsetX, offsetY));
            }
            else
            {
                ctx.Source = ctx.AddDispose(ConvolutionTransform <byte, int> .CreateResize(ctx.Source, width, height, interpolatorx, interpolatory, offsetX, offsetY));
            }
        }
예제 #6
0
        public static void AddHybridScaler(PipelineContext ctx, int ratio = default)
        {
            ratio = ratio == default ? ctx.Settings.HybridScaleRatio : ratio;
            if (ratio == 1 || ctx.Settings.Interpolation.WeightingFunction.Support < 0.1 || ctx.Source.Format.BitsPerPixel / ctx.Source.Format.ChannelCount != 8)
            {
                return;
            }

            ctx.Source = ctx.AddDispose(new HybridScaleTransform(ctx.Source, ratio));
            ctx.Settings.HybridMode = HybridScaleMode.Off;
        }
예제 #7
0
        public static void AddExternalFormatConverter(PipelineContext ctx)
        {
            var ifmt = ctx.Source.Format;

            if (!externalFormatMap.TryGetValue(ifmt, out var ofmt) || ofmt == ifmt)
            {
                return;
            }

            bool forceSrgb = (ifmt == PixelFormat.Y32BppLinearFloat || ifmt == PixelFormat.Y16BppLinearUQ15) && ctx.SourceColorProfile != ColorProfile.sRGB;

            ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, forceSrgb ? ColorProfile.sRGB : ctx.SourceColorProfile, forceSrgb ? ColorProfile.sRGB : ctx.DestColorProfile, ofmt));
        }
예제 #8
0
        public static void AddPad(PipelineContext ctx)
        {
            if (ctx.Settings.InnerSize == ctx.Settings.OuterSize)
            {
                return;
            }

            AddExternalFormatConverter(ctx);

            var fmt = ctx.Source.Format;

            if (fmt.AlphaRepresentation == PixelAlphaRepresentation.None && ctx.Settings.MatteColor.IsTransparent())
            {
                ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, null, null, PixelFormat.Bgra32Bpp));
            }
            else if (fmt.ColorRepresentation == PixelColorRepresentation.Grey && !ctx.Settings.MatteColor.IsGrey())
            {
                ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, null, null, PixelFormat.Bgr24Bpp));
            }

            ctx.Source = new PadTransformInternal(ctx.Source, ctx.Settings.MatteColor, PixelArea.FromGdiRect(ctx.Settings.InnerRect), PixelArea.FromGdiSize(ctx.Settings.OuterSize));
        }
예제 #9
0
        public static void AddUnsharpMask(PipelineContext 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)
            {
                ctx.Source = ctx.AddDispose(UnsharpMaskTransform <float, float> .CreateSharpen(ctx.Source, ss));
            }
            else if (fmt.NumericRepresentation == PixelNumericRepresentation.Fixed)
            {
                ctx.Source = ctx.AddDispose(UnsharpMaskTransform <ushort, int> .CreateSharpen(ctx.Source, ss));
            }
            else
            {
                ctx.Source = ctx.AddDispose(UnsharpMaskTransform <byte, int> .CreateSharpen(ctx.Source, ss));
            }
        }
예제 #10
0
        void IPixelTransformInternal.Init(PipelineContext ctx)
        {
            MagicTransforms.AddExternalFormatConverter(ctx);

            if (ctx.Source.Format.FormatGuid != outFormat)
                ctx.Source = ctx.AddDispose(new ConversionTransform(ctx.Source, null, null, PixelFormat.FromGuid(outFormat))); }