/// <summary>
        /// Post processes the image.
        /// </summary>
        /// <param name="context">The current context.</param>
        /// <param name="stream">The source image stream.</param>
        /// <param name="extension">The image extension.</param>
        /// <returns>
        /// The <see cref="MemoryStream" />.
        /// </returns>
        public static async Task <MemoryStream> PostProcessImageAsync(HttpContext context, MemoryStream stream, string extension)
        {
            if (!PostProcessorBootstrapper.Instance.IsInstalled)
            {
                return(stream);
            }

            string sourceFile = null, destinationFile = null;
            var    timeout = PostProcessorBootstrapper.Instance.Timout;

            try
            {
                // Save source file length
                var length = stream.Length;

                // Create a temporary source file with the correct extension
                var tempSourceFile = Path.GetTempFileName();
                sourceFile = Path.ChangeExtension(tempSourceFile, extension);
                File.Move(tempSourceFile, sourceFile);

                // Give our destination file a unique name
                destinationFile = sourceFile.Replace(extension, "-out" + extension);

                // Get processes to start
                var processStartInfos = GetProcessStartInfos(extension, length, sourceFile, destinationFile).ToList();
                if (processStartInfos.Count > 0)
                {
                    // Save the input stream to our source temp file for post processing
                    using (var fileStream = File.Create(sourceFile))
                    {
                        await stream.CopyToAsync(fileStream).ConfigureAwait(false);
                    }

                    // Create cancellation token with timeout
                    using (var cancellationTokenSource = new CancellationTokenSource(timeout))
                    {
                        foreach (var processStartInfo in processStartInfos)
                        {
                            // Use destination file as new source (if previous process created one).
                            if (File.Exists(destinationFile))
                            {
                                File.Copy(destinationFile, sourceFile, true);
                            }

                            // Set default properties
                            processStartInfo.FileName       = Path.Combine(PostProcessorBootstrapper.Instance.WorkingPath, processStartInfo.FileName);
                            processStartInfo.CreateNoWindow = true;
                            processStartInfo.WindowStyle    = ProcessWindowStyle.Hidden;

                            // Run process
                            using (var processResults = await ProcessEx.RunAsync(processStartInfo, cancellationTokenSource.Token).ConfigureAwait(false))
                            {
                                if (processResults.ExitCode == 1)
                                {
                                    ImageProcessorBootstrapper.Instance.Logger.Log(typeof(PostProcessor), $"Unable to post process image for request {context.Request.Unvalidated.Url}, {processStartInfo.FileName} {processStartInfo.Arguments} exited with error code 1. Original image returned.");
                                    break;
                                }
                            }
                        }
                    }

                    // Save result
                    if (!File.Exists(destinationFile))
                    {
                        File.Copy(sourceFile, destinationFile, true);
                    }

                    var result = new PostProcessingResultEventArgs(destinationFile, length);
                    if (result.ResultFileSize > 0 && result.Saving > 0)
                    {
                        using (var fileStream = File.OpenRead(destinationFile))
                        {
                            stream.SetLength(0);
                            await fileStream.CopyToAsync(stream).ConfigureAwait(false);
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
                ImageProcessorBootstrapper.Instance.Logger.Log(typeof(PostProcessor), $"Unable to post process image for request {context.Request.Unvalidated.Url} within {timeout}ms. Original image returned.");
            }
            catch (Exception ex)
            {
                // Some security policies don't allow execution of programs in this way
                ImageProcessorBootstrapper.Instance.Logger.Log(typeof(PostProcessor), ex.Message);
            }
            finally
            {
                // Always cleanup files
                try
                {
                    // Ensure files exist, are not read only, and delete
                    if (sourceFile != null && File.Exists(sourceFile))
                    {
                        File.SetAttributes(sourceFile, FileAttributes.Normal);
                        File.Delete(sourceFile);
                    }

                    if (destinationFile != null && File.Exists(destinationFile))
                    {
                        File.SetAttributes(destinationFile, FileAttributes.Normal);
                        File.Delete(destinationFile);
                    }
                }
                catch
                {
                    // Normally a no no, but logging would be excessive + temp files get cleaned up eventually.
                }
            }

            // ALways return stream (even if it's not optimized)
            stream.Position = 0;
            return(stream);
        }