/// <inheritdoc/>
        public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
        {
            if (!this.mutate && this.destination is null)
            {
                // This will only work if the first processor applied is the cloning one thus
                // realistically for this optimization to work the resize must the first processor
                // applied any only up processors will take the double data path.
                using (IImageProcessor <TPixel> specificProcessor = processor.CreatePixelSpecificProcessor(this.source, rectangle))
                {
                    // TODO: if 'specificProcessor' is not an ICloningImageProcessor<TPixel> we are unnecessarily disposing and recreating it.
                    // This should be solved in a future refactor.
                    if (specificProcessor is ICloningImageProcessor <TPixel> cloningImageProcessor)
                    {
                        this.destination = cloningImageProcessor.CloneAndApply();
                        return(this);
                    }
                }

                this.destination = this.source.Clone();
            }

            using (IImageProcessor <TPixel> specificProcessor = processor.CreatePixelSpecificProcessor(this.destination, rectangle))
            {
                specificProcessor.Apply();
            }

            return(this);
        }
        /// <inheritdoc/>
        public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
        {
            if (!this.mutate && this.destination is null)
            {
                // When cloning an image we can optimize the processing pipeline by avoiding an unnecessary
                // interim clone if the first processor in the pipeline is a cloning processor.
                if (processor is ICloningImageProcessor cloningImageProcessor)
                {
                    using (ICloningImageProcessor <TPixel> pixelProcessor = cloningImageProcessor.CreatePixelSpecificCloningProcessor(this.Configuration, this.source, rectangle))
                    {
                        this.destination = pixelProcessor.CloneAndExecute();
                        return(this);
                    }
                }

                // Not a cloning processor? We need to create a clone to operate on.
                this.destination = this.source.Clone();
            }

            // Standard processing pipeline.
            using (IImageProcessor <TPixel> specificProcessor = processor.CreatePixelSpecificProcessor(this.Configuration, this.destination, rectangle))
            {
                specificProcessor.Execute();
            }

            return(this);
        }
        /// <summary>
        /// Apply an <see cref="IImageProcessor"/> to a frame.
        /// Only works from processors implemented by an <see cref="ImageProcessor{TPixel}"/> subclass.
        /// </summary>
        internal static void Apply <TPixel>(
            this IImageProcessor processor,
            ImageFrame <TPixel> frame,
            Rectangle sourceRectangle,
            Configuration configuration)
            where TPixel : struct, IPixel <TPixel>
        {
            var processorImpl = (ImageProcessor <TPixel>)processor.CreatePixelSpecificProcessor <TPixel>();

            processorImpl.Apply(frame, sourceRectangle, configuration);
        }
        public IImageProcessingContext ApplyProcessor(IImageProcessor processor)
        {
            var processorImplementation = processor.CreatePixelSpecificProcessor <TPixel>();

            return(this.ApplyProcessor(processorImplementation));
        }