public void Process(string[] args)
        {
            var arguments    = new RawArguments();
            var allRawInputs = new List <string>();

            var options = new OptionSet();

            options.Add("h|?|help",
                        "Show this help message.",
                        x => ShowHelp(options));

            options.Add("in|input=",
                        @"Accepted inputs:
- a file path
- a directory path
- a file pattern (simple '?' and '*' wildcards are accepted)
- a directory path followed by a file pattern
This parameter can be set multiple times.",
                        x => allRawInputs.Add(x));

            options.Add("out|output:",
                        "Output file or directory. Default: current directory, same name as the input file.",
                        x => arguments.RawOutput = x);

            options.Add("x|overwrite",
                        "If set, existing files will be overwritten instead of being ignored.",
                        x => arguments.Overwrite = true);

            options.Add("r|recursive",
                        "If set, input is browsed recursively.",
                        x => arguments.Recursive = true);

            options.Add("w|width:",
                        $"Width of the output image. Default: {RawArguments.DefaultWidth}",
                        x => arguments.RawWidth = x);

            options.Add("H|height:",
                        "Height of the output image. If this argument is not set, the input height will be used.",
                        x => arguments.RawHeight = x);

            options.Add("b|barwidth|barWidth:",
                        $"Width of each bar in the output image. Default: {RawArguments.DefaultBarWidth}",
                        x => arguments.RawBarWidth = x);

            options.Add("s|smooth",
                        "Also generate a smooth version of the output, suffixed with '_smoothed'.",
                        x => arguments.Smooth = true);

            options.Parse(args);

            if (arguments.RawHeight == null)
            {
                arguments.UseInputHeight = true;
            }

            var expandedInputFileList = CLIUtils.GetExpandedAndValidatedFilePaths(allRawInputs, arguments.Recursive).ToList();

            if (expandedInputFileList.Any())
            {
                foreach (var file in expandedInputFileList)
                {
                    arguments.RawInput = file; // FIXME: copy instead of changing in place...
                    DealWithOneInputFile(arguments);
                }
            }
            else
            {
                Console.WriteLine("No input.");
            }

            Console.WriteLine($"Exiting...");
        }
        private void DealWithOneInputFile(RawArguments arguments)
        {
            Console.WriteLine($"Processing file '{arguments.RawInput}':");

            CompleteBarCodeGenerationParameters parameters;

            try
            {
                parameters = _barCodeParametersValidator.GetValidatedParameters(
                    rawInputPath: arguments.RawInput,
                    rawOutputPath: arguments.RawOutput,
                    rawBarWidth: arguments.RawBarWidth,
                    rawImageWidth: arguments.RawWidth,
                    rawImageHeight: arguments.RawHeight,
                    useInputHeightForOutput: arguments.UseInputHeight,
                    generateSmoothVersion: arguments.Smooth,
                    // Choosing whether to overwrite or not is done after validating parameters, not here
                    shouldOverwriteOutput: x => true);
            }
            catch (ParameterValidationException ex)
            {
                Console.Error.WriteLine($"Invalid parameters: {ex.Message}");
                return;
            }

            if (File.Exists(parameters.OutputPath) && arguments.Overwrite == false)
            {
                // Check once before generating the image, and once just before saving.
                Console.WriteLine($"WARNING: skipped file {parameters.OutputPath} because it already exists.");
                return;
            }

            var result = _imageProcessor.CreateBarCode(
                parameters.InputPath,
                parameters.BarCode,
                _ffmpegWrapper,
                CancellationToken.None,
                null,
                x => Console.WriteLine(x));

            try
            {
                if (File.Exists(parameters.OutputPath) && arguments.Overwrite == false)
                {
                    // Check once before generating the image, and once just before saving.
                    Console.WriteLine($"WARNING: skipped file {parameters.OutputPath} because it already exists.");
                }
                else
                {
                    result.Save(parameters.OutputPath);
                    Console.WriteLine($"File {parameters.OutputPath} saved successfully!");
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"Unable to save the image: {ex}");
            }

            if (parameters.GenerateSmoothedOutput)
            {
                Bitmap smoothed;
                try
                {
                    smoothed = _imageProcessor.GetSmoothedCopy(result);

                    try
                    {
                        if (File.Exists(parameters.OutputPath) && arguments.Overwrite == false)
                        {
                            Console.WriteLine($"WARNING: skipped file {parameters.OutputPath} because it already exists.");
                        }
                        else
                        {
                            smoothed.Save(parameters.SmoothedOutputPath);
                            Console.WriteLine($"File {parameters.SmoothedOutputPath} saved successfully!");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine($"Unable to save the smoothed image: {ex}");
                    }
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine($"An error occured while creating the smoothed version of the barcode. Error: {ex}");
                }
            }
        }