public MainViewModel(IImageProcessingStrategy imageProcessingStrategy, IFileChooser fileChooser, ITaskExecutor <Bitmap> imageLoadingExecutor,
                             ITaskExecutor <ImageProcessingOutput> imageProcessingExecutor)
        {
            imageProcessor               = imageProcessingStrategy;
            this.fileChooser             = fileChooser;
            this.imageLoadingExecutor    = imageLoadingExecutor;
            this.imageProcessingExecutor = imageProcessingExecutor;

            SetupImageLoadingExecutor();
            SetupImageProcessingExecutor();
        }
        public static async Task Main(string[] args)
        {
            Stopwatch st = new Stopwatch();

            st.Start();

            IMutableImageFactory <MutableByteImage> factory    = null;
            List <IFilter <MutableByteImage> >      filters    = null;
            IImageReader <MutableByteImage>         inputMode  = null;
            IImageWriter <MutableByteImage>         outputMode = null;
            ILogger logger = null;

            IImageProcessingStrategy <MutableByteImage> processingStrategy = null;
            bool throwMe = false;

            void setupCommons(CommonOptions info)
            {
                logger = CreateLogger(info);
                bool throwMeHere = false;

                (filters, throwMeHere) = ParseFilterParameters(info.Filters);
                throwMe |= throwMeHere;

                factory = new MutableByteImageFactory(logger);

                logger?.WriteLine(info.ToString().Replace(",", Environment.NewLine), Verbosity.Info);

                (inputMode, throwMeHere) = SetInput(info, factory, logger);
                throwMe |= throwMeHere;

                (outputMode, throwMeHere) = SetOutput(info, logger, factory);
                throwMe |= throwMeHere;
            }

            var result = Parser.Default
                         .ParseArguments <InfoOptions,
                                          StackAllOptions,
                                          StackProgressiveOptions,
                                          StackContinuousOptions,
                                          TestOptions>(args)
                         .WithParsed <InfoOptions>(info =>
            {
                GetInfo(info);
                return;
            })
                         .WithParsed <StackAllOptions>(info =>
            {
                setupCommons(info);

                // todo switch between stackall and stackallmerge, if supported by filter
                // processingStrategy = new StackAllStrategy();
                // might be unsafe

                processingStrategy = new StackAllMergeStrategy <MutableByteImage>(logger, factory);
            })
                         .WithParsed <StackProgressiveOptions>(info =>
            {
                setupCommons(info);
                processingStrategy = new StackProgressiveStrategy <MutableByteImage>(logger, factory);
            })
                         .WithParsed <StackContinuousOptions>(info =>
            {
                setupCommons(info);

                if (info.Count == 0)
                {
                    logger?.WriteLine("You have to define --stackCount for continuous stacking", Verbosity.Error);
                    throwMe = true;
                }

                processingStrategy = new StackContinousStrategy <MutableByteImage>(info.Count, logger, factory);
            })
                         .WithParsed <TestOptions>(info =>
            {
                info.UseOutputPipe = false;
                info.OutputFile    = ".";
                info.OutputFolder  = ".";

                logger = new Logger(Console.Out);

                factory = new MutableByteImageFactory(logger);

                inputMode = new TestImageReader <MutableByteImage>
                                (info.Count,
                                info.Width,
                                info.Height,
                                PixelFormat.Format24bppRgb,
                                logger,
                                factory);

                outputMode = new TestImageWriter <MutableByteImage>(logger, factory);

                processingStrategy = new StackAllMergeStrategy <MutableByteImage>(logger, factory);

                RunBenchmark(info, logger, new MutableByteImageFactory(logger)).Wait();

                Process.GetCurrentProcess().Close();
            })
                         .WithNotParsed(x =>
                                        logger?.WriteLine(String.Join(Environment.NewLine, x.Select(y => y.ToString()).ToArray()), Verbosity.Error));

            if (throwMe)
            {
                logger?.WriteLine("Invalid Configuration, see issues above.", Verbosity.Error);
                return;
            }

            if (inputMode == null || outputMode == null)
            {
                logger?.WriteLine($"Input: {inputMode}, Output:{outputMode}", Verbosity.Error);
                logger?.WriteLine("IO undefined", Verbosity.Error);
                return;
            }
            if (processingStrategy == null)
            {
                logger?.WriteLine("Not processing strategy defined", Verbosity.Error);
            }

            logger?.WriteLine($"{inputMode} {outputMode} {processingStrategy}", Verbosity.Info);

            await processingStrategy.Process(inputMode, filters, outputMode);

            st.Stop();
            logger?.WriteLine($"Processing took {st.ElapsedMilliseconds / 1000d}", Verbosity.Info);

            logger?.Dispose();
        }