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