Beispiel #1
0
        protected override void Initialize(AVSValue args)
        {
            base.Initialize(args);
            var srcInfo  = Source.GetVideoInfo();
            var overInfo = Overlay.GetVideoInfo();

            overlaySettings = new OverlayInfo
            {
                X            = X,
                Y            = Y,
                Angle        = (int)Math.Round(Angle * 100),
                Width        = OverlayWidth == 0 ? overInfo.width : OverlayWidth,
                Height       = OverlayHeight == 0 ? overInfo.height : OverlayHeight,
                Diff         = Diff,
                BaseWidth    = overInfo.width,
                BaseHeight   = overInfo.height,
                SourceWidth  = srcInfo.width,
                SourceHeight = srcInfo.height
            };
            overlaySettings.SetCrop(RectangleF.FromLTRB(
                                        (float)CropLeft,
                                        (float)CropTop,
                                        (float)CropRight,
                                        (float)CropBottom));
        }
        protected override VideoFrame GetFrame(int n)
        {
            OverlayInfo info;

            lock (Child)
                using (var infoFrame = Child.GetFrame(n, StaticEnv))
                    info = OverlayInfo.FromFrame(infoFrame).First();
            var crop   = info.GetCrop();
            var hybrid = DynamicEnv.Invoke(Function,
                                           Engine, Source, Overlay, info.X, info.Y, info.Angle / 100.0, info.Width, info.Height,
                                           crop.Left, crop.Top, crop.Right, crop.Bottom, info.Diff);

            if (Debug)
            {
                hybrid = hybrid.Subtitle(info.ToString().Replace("\n", "\\n"), lsp: 0);
            }
            var res = NewVideoFrame(StaticEnv);

            using (VideoFrame frame = hybrid[n])
            {
                Parallel.ForEach(new[] { YUVPlanes.PLANAR_Y, YUVPlanes.PLANAR_U, YUVPlanes.PLANAR_V }, plane =>
                {
                    for (var y = 0; y < frame.GetHeight(plane); y++)
                    {
                        OverlayUtils.CopyMemory(res.GetWritePtr(plane) + y * res.GetPitch(plane),
                                                frame.GetReadPtr(plane) + y * frame.GetPitch(plane), res.GetRowSize(plane));
                    }
                });
            }
            return(res);
        }
        protected override VideoFrame GetFrame(int n)
        {
            OverlayInfo info;

            lock (Child)
                using (var infoFrame = Child.GetFrame(n, StaticEnv))
                    info = OverlayInfo.FromFrame(infoFrame);
            var hybrid = RenderFrame(info);

            if (debug)
            {
                hybrid = hybrid.Subtitle(info.ToString().Replace("\n", "\\n"), lsp: 0);
            }
            var res = NewVideoFrame(StaticEnv);

            using (VideoFrame frame = hybrid[n])
            {
                Parallel.ForEach(new[] { YUVPlanes.PLANAR_Y, YUVPlanes.PLANAR_U, YUVPlanes.PLANAR_V }, plane =>
                {
                    for (var y = 0; y < frame.GetHeight(plane); y++)
                    {
                        OverlayUtils.CopyMemory(res.GetWritePtr(plane) + y * res.GetPitch(plane),
                                                frame.GetReadPtr(plane) + y * frame.GetPitch(plane), res.GetRowSize(plane));
                    }
                });
            }
            return(res);
        }
 public FrameInterval(OverlayInfo frame)
 {
     if (frame == null)
     {
         throw new ArgumentException();
     }
     Add(frame);
 }
 private static void WriteInfo(BinaryWriter writer, OverlayInfo info)
 {
     writer.Write(info.FrameNumber + 1);
     writer.Write((int)(info.Diff * 1000));
     writer.Write((short)info.X);
     writer.Write((short)info.Y);
     writer.Write((short)info.Width);
     writer.Write((short)info.Height);
     writer.Write((short)info.CropLeft);
     writer.Write((short)info.CropTop);
     writer.Write((short)info.CropRight);
     writer.Write((short)info.CropBottom);
     writer.Write((short)info.Angle);
 }
Beispiel #6
0
        protected override void Initialize(AVSValue args)
        {
            srcClip         = args[0].AsClip();
            overClip        = args[1].AsClip();
            overlaySettings = new OverlayInfo
            {
                X      = args[2].AsInt(),
                Y      = args[3].AsInt(),
                Angle  = (int)Math.Round(args[4].AsFloat() * 100),
                Width  = args[5].AsInt(overClip.GetVideoInfo().width),
                Height = args[6].AsInt(overClip.GetVideoInfo().height),
                Diff   = args[11].AsFloat(-1)
            };
            overlaySettings.SetCrop(RectangleF.FromLTRB(
                                        (float)args[7].AsFloat(),
                                        (float)args[8].AsFloat(),
                                        (float)args[9].AsFloat(),
                                        (float)args[10].AsFloat()));
            srcSize      = new Size(srcClip.GetVideoInfo().width, srcClip.GetVideoInfo().height);
            overSize     = new Size(overClip.GetVideoInfo().width, overClip.GetVideoInfo().height);
            srcMaskClip  = args[12].IsClip() ? args[12].AsClip() : null;
            overMaskClip = args[13].IsClip() ? args[13].AsClip() : null;
            lumaOnly     = args[14].AsBool(lumaOnly);
            var width  = args[15].AsInt(srcClip.GetVideoInfo().width);
            var height = args[16].AsInt(srcClip.GetVideoInfo().height);

            var vi = srcClip.GetVideoInfo();

            vi.width      = width;
            vi.height     = height;
            vi.pixel_type = srcClip.GetVideoInfo().pixel_type;
            SetVideoInfo(ref vi);

            gradient     = args[17].AsInt(gradient);
            noise        = args[18].AsInt(noise);
            dynamicNoise = args[19].AsBool(dynamicNoise);
            overlayMode  = (OverlayMode)args[20].AsInt((int)overlayMode);
            opacity      = args[21].AsFloat(opacity);
            colorAdjust  = (ColorAdjustMode)args[22].AsInt((int)colorAdjust);
            matrix       = args[23].AsString(matrix);
            upsizeFunc   = args[24].AsString(upsizeFunc);
            downsizeFunc = args[25].AsString(downsizeFunc);
            rotateFunc   = args[26].AsString(rotateFunc);
            debug        = args[27].AsBool(debug);
        }
Beispiel #7
0
        protected dynamic RenderFrame(OverlayInfo info)
        {
            var src  = srcClip.Dynamic();
            var crop = info.GetCrop();
            var over = overClip.Dynamic();

            if (info.GetCrop() != RectangleF.Empty || info.Width != overSize.Width || info.Height != overSize.Height)
            {
                over = over.Invoke(
                    info.Width > overClip.GetVideoInfo().width ? upsizeFunc : downsizeFunc,
                    info.Width, info.Height, crop.Left, crop.Top, -crop.Right, -crop.Bottom);
            }
            var overMask = overMaskClip?.Dynamic().BilinearResize(info.Width, info.Height);

            var mergedWidth  = srcSize.Width + Math.Max(-info.X, 0) + Math.Max(info.Width + info.X - srcSize.Width, 0);
            var mergedHeight = srcSize.Height + Math.Max(-info.Y, 0) + Math.Max(info.Height + info.Y - srcSize.Height, 0);
            var mergedAr     = mergedWidth / (double)mergedHeight;
            var outAr        = GetVideoInfo().width / (double)GetVideoInfo().height;
            var wider        = mergedAr > outAr;

            if (overlayMode == OverlayMode.FitBorders)
            {
                wider = !wider;
            }
            var finalWidth  = wider ? GetVideoInfo().width : (int)Math.Round(GetVideoInfo().width *(mergedAr / outAr));
            var finalHeight = wider ? (int)Math.Round(GetVideoInfo().height *(outAr / mergedAr)) : GetVideoInfo().height;
            var finalX      = wider ? 0 : (GetVideoInfo().width - finalWidth) / 2;
            var finalY      = wider ? (GetVideoInfo().height - finalHeight) / 2 : 0;

            if (colorAdjust != ColorAdjustMode.None && colorAdjust != ColorAdjustMode.Average)
            {
                var clip2Adjust = colorAdjust == ColorAdjustMode.AsOverlay ? src : over;
                var srcTest     = src.Crop(Math.Max(0, info.X), Math.Max(0, info.Y),
                                           -Math.Max(0, srcSize.Width - info.X - info.Width),
                                           -Math.Max(0, srcSize.Height - info.Y - info.Height));
                var overTest = over.Crop(Math.Max(0, -info.X), Math.Max(0, -info.Y),
                                         -Math.Max(0, -(srcSize.Width - info.X - info.Width)),
                                         -Math.Max(0, -(srcSize.Height - info.Y - info.Height)));
                var maskTest = srcMaskClip?.Dynamic();
                if (overMask != null)
                {
                    maskTest = (maskTest ?? GetBlankClip(srcClip, true).Dynamic())
                               .Overlay(overMask, info.X, info.Y, mode: "darken")
                               .Crop(Math.Max(0, -info.X), Math.Max(0, -info.Y),
                                     -Math.Max(0, -(srcSize.Width - info.X - info.Width)),
                                     -Math.Max(0, -(srcSize.Height - info.Y - info.Height)));
                }
                if (!GetVideoInfo().IsRGB() && !string.IsNullOrEmpty(matrix))
                {
                    srcTest     = srcTest.ConvertToRgb24(matrix: matrix);
                    overTest    = overTest.ConvertToRgb24(matrix: matrix);
                    maskTest    = maskTest?.ConvertToRgb24(matrix: matrix);
                    clip2Adjust = clip2Adjust.ConvertToRgb24(matrix: matrix);
                }
                var sample    = colorAdjust == ColorAdjustMode.AsOverlay ? srcTest : overTest;
                var reference = colorAdjust == ColorAdjustMode.AsOverlay ? overTest : srcTest;
                var adjusted  = clip2Adjust.ColorAdjust(sample, reference, maskTest);
                if (!GetVideoInfo().IsRGB() && !string.IsNullOrEmpty(matrix))
                {
                    adjusted = adjusted.ConvertToYV24(matrix: matrix);
                }
                if (colorAdjust == ColorAdjustMode.AsOverlay)
                {
                    src = adjusted;
                }
                else
                {
                    over = adjusted;
                }
            }

            if (colorAdjust == ColorAdjustMode.Average)
            {
                var srcTest = src.Crop(Math.Max(0, info.X), Math.Max(0, info.Y),
                                       -Math.Max(0, srcSize.Width - info.X - info.Width),
                                       -Math.Max(0, srcSize.Height - info.Y - info.Height));
                var overTest = over.Crop(Math.Max(0, -info.X), Math.Max(0, -info.Y),
                                         -Math.Max(0, -(srcSize.Width - info.X - info.Width)),
                                         -Math.Max(0, -(srcSize.Height - info.Y - info.Height)));
                src     = src.ConvertToRgb24().ColorAdjust(srcTest.ConvertToRgb24(), overTest.ConvertToRgb24()).ConvertToYV24();
                srcTest = src.Crop(Math.Max(0, info.X), Math.Max(0, info.Y),
                                   -Math.Max(0, srcSize.Width - info.X - info.Width),
                                   -Math.Max(0, srcSize.Height - info.Y - info.Height));
                over = over.ConvertToRgb24().ColorAdjust(overTest.ConvertToRgb24(), srcTest.ConvertToRgb24()).ConvertToYV24();
            }

            dynamic GetOverMask(int length, bool gradientMask, bool noiseMask)
            {
                return(over.OverlayMask(
                           left: info.X > 0 ? length : 0,
                           top: info.Y > 0 ? length : 0,
                           right: srcSize.Width - info.X - info.Width > 0 ? length : 0,
                           bottom: srcSize.Height - info.Y - info.Height > 0 ? length : 0,
                           gradient: gradientMask, noise: noiseMask, seed: dynamicNoise ? info.FrameNumber : 0));
            }

            dynamic GetSourceMask(int length, bool gradientMask, bool noiseMask)
            {
                return(src.OverlayMask(
                           left: info.X < 0 ? length : 0,
                           top: info.Y < 0 ? length : 0,
                           right: srcSize.Width - info.X - info.Width < 0 ? length : 0,
                           bottom: srcSize.Height - info.Y - info.Height < 0 ? length : 0,
                           gradient: gradientMask, noise: noiseMask, seed: dynamicNoise ? info.FrameNumber : 0));
            }

            dynamic GetMask(Func <int, bool, bool, dynamic> func)
            {
                if (gradient > 0 && gradient == noise)
                {
                    return(func(gradient, true, true));
                }
                dynamic mask = null;

                if (gradient > 0)
                {
                    mask = func(gradient, true, false);
                }
                if (noise > 0)
                {
                    var noiseMask = func(noise, false, true);
                    mask = mask == null ? noiseMask : mask.Overlay(noiseMask, mode: "darken");
                }
                return(mask);
            }

            dynamic Rotate(dynamic clip, bool invert) => clip == null
                ? null
                : (info.Angle == 0 ? clip : clip.Invoke(rotateFunc, (invert ? -info.Angle : info.Angle) / 100.0));

            switch (overlayMode)
            {
            case OverlayMode.Fit:
            case OverlayMode.Difference:
            {
                if (opacity < double.Epsilon)
                {
                    return(src);
                }
                var mode = lumaOnly ? "luma" : "blend";
                if (overlayMode == OverlayMode.Difference)
                {
                    mode = "difference";
                }
                var mask = GetMask(GetOverMask);
                if (overMask != null && mask != null)
                {
                    mask = mask.Overlay(overMask, mode: "darken");
                }
                if (srcMaskClip != null && mask != null)
                {
                    mask = mask.Overlay(Rotate(srcMaskClip.Dynamic().Invert(), true), -info.X, -info.Y, mode: "lighten");
                }
                if (mask == null && info.Angle != 0)
                {
                    mask = ((Clip)GetBlankClip(over, true)).Dynamic();
                }
                var hybrid = src.Overlay(Rotate(over, false), info.X, info.Y, mask: Rotate(mask, false), opacity: opacity, mode: mode);
                if (GetVideoInfo().width == srcSize.Width && GetVideoInfo().height == srcSize.Height)
                {
                    return(hybrid);
                }
                return(hybrid.Invoke(downsizeFunc, GetVideoInfo().width, GetVideoInfo().height));
            }

            case OverlayMode.Fill:
            {
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (srcMaskClip != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(srcMaskClip.Dynamic().Invert().Invoke(rotateFunc, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                dynamic hybrid = src.BlankClip(width: mergedWidth, height: mergedHeight);
                if (opacity - 1 < double.Epsilon)
                {
                    hybrid = hybrid.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y));
                }
                else
                {
                    maskSrc = null;
                }
                if (maskOver != null || opacity - 1 < double.Epsilon)
                {
                    hybrid = hybrid.Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y));
                }
                if (maskOver == null && info.Angle != 0)
                {
                    maskOver = GetBlankClip(over, true);
                }
                return(hybrid.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y), mask: maskSrc)
                       .Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y),
                                opacity: opacity, mask: maskOver?.Invoke(rotateFunc, info.Angle / 100.0))
                       .Invoke(downsizeFunc, finalWidth, finalHeight)
                       .AddBorders(finalX, finalY, GetVideoInfo().width - finalX - finalWidth, GetVideoInfo().height - finalY - finalHeight));
            }

            case OverlayMode.FillRectangle:
            case OverlayMode.FitBorders:
            {
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (srcMaskClip != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(srcMaskClip.Dynamic().Invert().Invoke(rotateFunc, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                var background = src.BilinearResize(mergedWidth / 3, mergedHeight / 3).Overlay(over.BilinearResize(mergedWidth / 3, mergedHeight / 3), opacity: 0.5); //TODO !!!!!!!!!!
                for (var i = 0; i < 15; i++)
                {
                    background = background.Blur(1.5);
                }
                background = background.GaussResize(mergedWidth, mergedHeight, p: 3);
                if (opacity - 1 < double.Epsilon)
                {
                    background = background.Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y), mask: maskOver?.Invoke(rotateFunc, info.Angle / 100.0));
                }
                var hybrid = background.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y), mask: maskSrc)
                             .Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y), mask: maskOver?.Invoke(rotateFunc, info.Angle / 100.0), opacity: opacity)
                             .Invoke(downsizeFunc, finalWidth, finalHeight);
                if (overlayMode == OverlayMode.FillRectangle)
                {
                    return(hybrid.AddBorders(finalX, finalY, GetVideoInfo().width - finalX - finalWidth, GetVideoInfo().height - finalY - finalHeight));
                }
                var srcRect        = new Rectangle(0, 0, srcSize.Width, srcSize.Height);
                var overRect       = new Rectangle(info.X, info.Y, info.Width, info.Height);
                var union          = Rectangle.Union(srcRect, overRect);
                var intersect      = Rectangle.Intersect(srcRect, overRect);
                var cropLeft       = intersect.Left - union.Left;
                var cropTop        = intersect.Top - union.Top;
                var cropRight      = union.Right - intersect.Right;
                var cropBottom     = union.Bottom - intersect.Bottom;
                var cropWidthCoef  = cropRight == 0 ? 1 : ((double)cropLeft / cropRight) / ((double)cropLeft / cropRight + 1);
                var cropHeightCoef = cropBottom == 0 ? 1 : ((double)cropTop / cropBottom) / ((double)cropTop / cropBottom + 1);
                cropLeft   = (int)((finalWidth - GetVideoInfo().width) * cropWidthCoef);
                cropTop    = (int)((finalHeight - GetVideoInfo().height) * cropHeightCoef);
                cropRight  = finalWidth - GetVideoInfo().width - cropLeft;
                cropBottom = finalHeight - GetVideoInfo().height - cropTop;
                return(hybrid.Crop(cropLeft, cropTop, -cropRight, -cropBottom));
            }

            case OverlayMode.FillFull:
            {
                finalWidth  = wider ? mergedWidth : (int)Math.Round(mergedHeight * outAr);
                finalHeight = wider ? (int)Math.Round(mergedWidth / outAr) : mergedHeight;
                finalX      = (finalWidth - mergedWidth) / 2;
                finalY      = (finalHeight - mergedHeight) / 2;
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (maskSrc != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(maskSrc.Invert().Invoke(rotateFunc, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (srcMaskClip != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(srcMaskClip.Dynamic().Invert().Invoke(rotateFunc, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                var background = over.BilinearResize(finalWidth / 4, finalHeight / 4);
                for (var i = 0; i < 10; i++)
                {
                    background = background.Blur(1.5);
                }
                var hybrid = background.GaussResize(finalWidth, finalHeight, p: 3);
                if (maskOver != null)
                {
                    hybrid = hybrid.Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), finalX + Math.Max(0, info.X), finalY + Math.Max(0, info.Y));
                }
                if (maskOver == null && info.Angle != 0)
                {
                    maskOver = GetBlankClip(over, true);
                }
                return(hybrid.Overlay(src, finalX + Math.Max(0, -info.X), finalY + Math.Max(0, -info.Y))
                       .Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), finalX + Math.Max(0, info.X), finalY + Math.Max(0, info.Y), mask: maskOver?.Invoke(rotateFunc, info.Angle / 100.0))
                       .Invoke(downsizeFunc, GetVideoInfo().width, GetVideoInfo().height));
            }

            case OverlayMode.Mask:
            {
                src  = GetBlankClip((Clip)src, true).Dynamic();
                over = GetBlankClip((Clip)over, true).Dynamic();
                return(src.BlankClip(width: mergedWidth, height: mergedHeight)
                       .Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y))
                       .Overlay(over.Invoke(rotateFunc, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y))
                       .Invoke(downsizeFunc, finalWidth, finalHeight)
                       .AddBorders(finalX, finalY, GetVideoInfo().width - finalX - finalWidth, GetVideoInfo().height - finalY - finalHeight));
            }

            default:
                throw new AvisynthException();
            }
        }
 public void Add(OverlayInfo frame)
 {
     frames[frame.FrameNumber] = frame;
     ClearCache();
 }
Beispiel #9
0
        protected dynamic RenderFrame(OverlayContext ctx, OverlayInfo info)
        {
            info = info.Resize(ctx.SourceInfo.Size, ctx.OverlayInfo.Size);

            var src      = ctx.Source;
            var over     = ctx.Overlay;
            var srcSize  = ctx.SourceInfo.Size;
            var overSize = ctx.OverlayInfo.Size;

            if (Mode == FramingMode.Fit && srcSize != ctx.TargetInfo.Size)
            {
                info    = info.Resize(ctx.TargetInfo.Size, overSize);
                src     = src.Invoke(srcSize.GetArea() < ctx.TargetInfo.Size.GetArea() ? Upsize : Downsize, ctx.TargetInfo.Width, ctx.TargetInfo.Height);
                srcSize = ctx.TargetInfo.Size;
            }

            if (Mode == FramingMode.Fit)
            {
                info = info.Shrink(srcSize, overSize);
            }

            var resizeFunc = info.Width > overSize.Width ? Upsize : Downsize;

            var crop = info.GetCrop();

            if (!crop.IsEmpty || info.Width != overSize.Width || info.Height != overSize.Height)
            {
                over = ResizeRotate(over, resizeFunc, null, info.Width, info.Height, 0, crop);
            }
            var overMask = ctx.OverlayMask?.Dynamic().BicubicResize(info.Width, info.Height);


            if (ColorAdjust > -double.Epsilon && Mode != FramingMode.Mask)
            {
                Func <dynamic, bool, dynamic> adjCrop = (clp, invert) =>
                {
                    var sign = invert ? -1 : 1;
                    return(clp?.Crop(
                               Math.Max(SrcColorBorderOffset.Left, sign * (info.X + OverColorBorderOffset.Left)),
                               Math.Max(SrcColorBorderOffset.Top, sign * (info.Y + OverColorBorderOffset.Top)),
                               -Math.Max(SrcColorBorderOffset.Right, sign * (srcSize.Width - info.X - info.Width + OverColorBorderOffset.Right)),
                               -Math.Max(SrcColorBorderOffset.Bottom, sign * (srcSize.Height - info.Y - info.Height + OverColorBorderOffset.Bottom))));
                };

                var srcTest  = adjCrop(src, false);
                var overTest = adjCrop(over, true);
                var maskTest = adjCrop(ctx.SourceMask, false);
                if (overMask != null)
                {
                    var input = (maskTest ?? GetBlankClip(src, true).Dynamic())
                                .Overlay(overMask, info.X, info.Y, mode: "darken");
                    maskTest = adjCrop(input, true);
                }
                if (!GetVideoInfo().IsRGB() && !string.IsNullOrEmpty(Matrix))
                {
                    srcTest  = srcTest.ConvertToRgb24(matrix: Matrix);
                    overTest = overTest.ConvertToRgb24(matrix: Matrix);
                    maskTest = maskTest?.ConvertToRgb24(matrix: Matrix);
                    if (ColorAdjust > double.Epsilon)
                    {
                        src = src.ConvertToRgb24(matrix: Matrix);
                    }
                    if (ColorAdjust < 1 - double.Epsilon)
                    {
                        over = over.ConvertToRgb24(matrix: Matrix);
                    }
                }
                if (ColorAdjust > double.Epsilon)
                {
                    src = src.ColorAdjust(srcTest, overTest, maskTest, maskTest, intensity: ColorAdjust,
                                          channels: AdjustChannels, debug: Debug, SIMD: SIMD, extrapolation: Extrapolation, dynamicNoise: DynamicNoise);
                    if (!GetVideoInfo().IsRGB() && !string.IsNullOrEmpty(Matrix))
                    {
                        src = src.ConvertToYV24(matrix: Matrix);
                    }
                }
                if (ColorAdjust < 1 - double.Epsilon)
                {
                    over = over.ColorAdjust(overTest, srcTest, maskTest, maskTest, intensity: 1 - ColorAdjust,
                                            channels: AdjustChannels, debug: Debug, SIMD: SIMD, extrapolation: Extrapolation, dynamicNoise: DynamicNoise);
                    if (!GetVideoInfo().IsRGB() && !string.IsNullOrEmpty(Matrix))
                    {
                        over = over.ConvertToYV24(matrix: Matrix);
                    }
                }
            }

            dynamic GetOverMask(int length, bool gradientMask, bool noiseMask)
            {
                return(over.OverlayMask(
                           left: info.X > BorderOffset.Left ? length : 0,
                           top: info.Y > BorderOffset.Top ? length : 0,
                           right: srcSize.Width - info.X - info.Width > BorderOffset.Right ? length : 0,
                           bottom: srcSize.Height - info.Y - info.Height > BorderOffset.Bottom ? length : 0,
                           gradient: gradientMask, noise: noiseMask,
                           seed: DynamicNoise ? info.FrameNumber : 0));
            }

            dynamic GetSourceMask(int length, bool gradientMask, bool noiseMask)
            {
                return(src.OverlayMask( //TODO BorderOffset
                           left: info.X < 0 ? length : 0,
                           top: info.Y < 0 ? length : 0,
                           right: srcSize.Width - info.X - info.Width < 0 ? length : 0,
                           bottom: srcSize.Height - info.Y - info.Height < 0 ? length : 0,
                           gradient: gradientMask, noise: noiseMask,
                           seed: DynamicNoise ? info.FrameNumber : 0));
            }

            dynamic GetMask(Func <int, bool, bool, dynamic> func)
            {
                if (Gradient > 0 && Gradient == Noise)
                {
                    return(func(Gradient, true, true));
                }
                dynamic mask = null;

                if (Gradient > 0)
                {
                    mask = func(Gradient, true, false);
                }
                if (Noise > 0)
                {
                    var noiseMask = func(Noise, false, true);
                    mask = mask == null ? noiseMask : mask.Overlay(noiseMask, mode: "darken");
                }
                return(mask);
            }

            dynamic Rotate(dynamic clip, bool invert) => clip == null
                ? null
                : (info.Angle == 0 ? clip : clip.Invoke(this.Rotate, (invert ? -info.Angle : info.Angle) / 100.0));

            dynamic GetBackground(int width, int height)
            {
                var background = src.BilinearResize(width / 3, height / 3)
                                 .Overlay(over.BilinearResize(width / 3, height / 3),
                                          opacity: (Background + 1) / 2,
                                          mask: overMask?.BilinearResize(width / 3, height / 3));

                for (var i = 0; i < BackBlur; i++)
                {
                    background = background.Blur(1.5);
                }
                return(background.GaussResize(width, height, p: 3));
            }

            var frameParams = ctx.CalcFrame(info);

            switch (Mode)
            {
            case FramingMode.Fit:
            {
                var mask = GetMask(GetOverMask);
                if (overMask != null && mask != null)
                {
                    mask = mask.Overlay(overMask, mode: "darken");
                }
                if (ctx.SourceMask != null && mask != null)
                {
                    mask = mask.Overlay(Rotate(ctx.SourceMask.Invert(), true), -info.X, -info.Y, mode: "lighten");
                }
                if (mask == null && info.Angle != 0)
                {
                    mask = ((Clip)GetBlankClip(over, true)).Dynamic();
                }
                return(Opacity < double.Epsilon ? src : src.Overlay(Rotate(over, false), info.X, info.Y, mask: Rotate(mask, false), opacity: Opacity, mode: OverlayMode));
            }

            case FramingMode.Fill:
            {
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (ctx.SourceMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(ctx.SourceMask.Invert().Invoke(this.Rotate, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                dynamic hybrid = InitClip(src, frameParams.MergedWidth, frameParams.MergedHeight, ctx.BlankColor);
                if (maskSrc != null || Opacity - 1 <= -double.Epsilon)
                {
                    hybrid = hybrid.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y));
                }
                if (maskOver != null || Opacity - 1 < double.Epsilon)
                {
                    hybrid = hybrid.Overlay(over.Invoke(this.Rotate, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y));
                }
                if (maskOver == null && info.Angle != 0)
                {
                    maskOver = GetBlankClip(over, true).Dynamic()?.Invoke(this.Rotate, info.Angle / 100.0);
                }

                var merged = hybrid.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y), mask: maskSrc)
                             .Overlay(over.Invoke(this.Rotate, info.Angle / 100.0),
                                      Math.Max(0, info.X), Math.Max(0, info.Y),
                                      opacity: Opacity, mask: maskOver, mode: OverlayMode);

                var resized = merged.Invoke(Downsize, frameParams.FinalWidth, frameParams.FinalHeight);

                return(InitClip(src, ctx.TargetInfo.Width, ctx.TargetInfo.Height, ctx.DefaultColor)
                       .Overlay(resized, frameParams.FinalX, frameParams.FinalY));
            }

            case FramingMode.FillRectangle:
            case FramingMode.FitBorders:
            {
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (ctx.SourceMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(ctx.SourceMask.Dynamic().Invert().Invoke(this.Rotate, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                var background = GetBackground(frameParams.MergedWidth, frameParams.MergedHeight);
                if (Opacity - 1 <= -double.Epsilon)
                {
                    background = background.Overlay(over.Invoke(this.Rotate, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y), mask: maskOver?.Invoke(this.Rotate, info.Angle / 100.0));
                }
                var hybrid = background.Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y), mask: maskSrc)
                             .Overlay(over.Invoke(this.Rotate, info.Angle / 100.0),
                                      x: Math.Max(0, info.X),
                                      y: Math.Max(0, info.Y),
                                      mask: maskOver?.Invoke(this.Rotate, info.Angle / 100.0),
                                      mode: OverlayMode,
                                      opacity: Opacity)
                             .Invoke(Downsize, frameParams.FinalWidth, frameParams.FinalHeight);
                if (Mode == FramingMode.FillRectangle)
                {
                    return(InitClip(src, ctx.TargetInfo.Width, ctx.TargetInfo.Height, ctx.BlankColor)
                           .Overlay(hybrid, frameParams.FinalX, frameParams.FinalY));
                }
                var srcRect        = new Rectangle(0, 0, srcSize.Width, srcSize.Height);
                var overRect       = new Rectangle(info.X, info.Y, info.Width, info.Height);
                var union          = Rectangle.Union(srcRect, overRect);
                var intersect      = Rectangle.Intersect(srcRect, overRect);
                var cropLeft       = intersect.Left - union.Left;
                var cropTop        = intersect.Top - union.Top;
                var cropRight      = union.Right - intersect.Right;
                var cropBottom     = union.Bottom - intersect.Bottom;
                var cropWidthCoef  = cropRight == 0 ? 1 : ((double)cropLeft / cropRight) / ((double)cropLeft / cropRight + 1);
                var cropHeightCoef = cropBottom == 0 ? 1 : ((double)cropTop / cropBottom) / ((double)cropTop / cropBottom + 1);
                cropLeft   = (int)((frameParams.FinalWidth - ctx.TargetInfo.Width) * cropWidthCoef);
                cropTop    = (int)((frameParams.FinalHeight - ctx.TargetInfo.Height) * cropHeightCoef);
                cropRight  = frameParams.FinalWidth - ctx.TargetInfo.Width - cropLeft;
                cropBottom = frameParams.FinalHeight - ctx.TargetInfo.Height - cropTop;
                return(hybrid.Crop(cropLeft, cropTop, -cropRight, -cropBottom));
            }

            case FramingMode.FillFull:
            {
                frameParams.FinalWidth  = !frameParams.Wider ? frameParams.MergedWidth : (int)Math.Round(frameParams.MergedHeight * frameParams.OutAr);
                frameParams.FinalHeight = !frameParams.Wider ? (int)Math.Round(frameParams.MergedWidth / frameParams.OutAr) : frameParams.MergedHeight;
                frameParams.FinalX      = (frameParams.FinalWidth - frameParams.MergedWidth) / 2;
                frameParams.FinalY      = (frameParams.FinalHeight - frameParams.MergedHeight) / 2;
                var maskOver = GetMask(GetOverMask);
                var maskSrc  = GetMask(GetSourceMask);
                if (maskSrc != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(maskSrc.Invert().Invoke(this.Rotate, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                if (overMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(overMask, mode: "darken");
                }
                if (ctx.SourceMask != null && maskOver != null)
                {
                    maskOver = maskOver.Overlay(ctx.SourceMask.Dynamic().Invert().Invoke(this.Rotate, -info.Angle / 100.0), -info.X, -info.Y, mode: "lighten");
                }
                var hybrid = GetBackground(frameParams.FinalWidth, frameParams.FinalHeight);
                if (maskOver != null)
                {
                    hybrid = hybrid.Overlay(over.Invoke(this.Rotate, info.Angle / 100.0),
                                            frameParams.FinalX + Math.Max(0, info.X), frameParams.FinalY + Math.Max(0, info.Y));
                }
                if (maskOver == null && info.Angle != 0)
                {
                    maskOver = GetBlankClip(over, true).Dynamic();
                }
                return(hybrid.Overlay(src, frameParams.FinalX + Math.Max(0, -info.X), frameParams.FinalY + Math.Max(0, -info.Y))
                       .Overlay(over.Invoke(this.Rotate, info.Angle / 100.0),
                                frameParams.FinalX + Math.Max(0, info.X), frameParams.FinalY + Math.Max(0, info.Y),
                                mask: maskOver?.Invoke(this.Rotate, info.Angle / 100.0))
                       .Invoke(Downsize, ctx.TargetInfo.Width, ctx.TargetInfo.Height));
            }

            case FramingMode.Mask:
            {
                if (ctx.Plane.IsChroma())
                {
                    return(InitClip(src, ctx.TargetInfo.Width, ctx.TargetInfo.Height, ctx.DefaultColor));
                }
                src = GetBlankClip((Clip)src, true).Dynamic();
                if (ctx.SourceMask != null)
                {
                    src = src.Overlay(ctx.SourceMask, mode: "darken");
                }
                over = GetBlankClip((Clip)over, true).Dynamic();
                return(InitClip(src, frameParams.MergedWidth, frameParams.MergedHeight, ctx.DefaultColor)
                       .Overlay(src, Math.Max(0, -info.X), Math.Max(0, -info.Y))
                       .Overlay(over.Invoke(this.Rotate, info.Angle / 100.0), Math.Max(0, info.X), Math.Max(0, info.Y))
                       .Invoke(Downsize, frameParams.FinalWidth, frameParams.FinalHeight)
                       .ColorRangeMask((1 << ctx.TargetInfo.ColorSpace.GetBitDepth()) - 1)
                       .AddBorders(frameParams.FinalX, frameParams.FinalY, ctx.TargetInfo.Width - frameParams.FinalX - frameParams.FinalWidth,
                                   ctx.TargetInfo.Height - frameParams.FinalY - frameParams.FinalHeight));
            }

            default:
                throw new AvisynthException();
            }
        }
 public dynamic ResizeRotate(Clip clip, string resizeFunc, string rotateFunc, OverlayInfo info)
 {
     return(ResizeRotate(clip, resizeFunc, rotateFunc, info.Width, info.Height, info.Angle, info.GetCrop(), info.Warp));
 }
Beispiel #11
0
 protected override OverlayInfo GetOverlayInfo(int n)
 {
     using (var infoFrame = Child.GetFrame(n, StaticEnv))
         return(OverlayInfo.FromFrame(infoFrame));
 }
 protected override List <OverlayInfo> GetOverlayInfo(int n)
 {
     using var frame = Child.GetFrame(n, StaticEnv);
     return(OverlayInfo.FromFrame(frame));
 }