private static unsafe void DrawMandelbrotSet(Bitmap bitmap, IterationValue[,] iterations, int maxIterationDepth)
        {
            var entireImageArea = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData imageData = bitmap.LockBits(entireImageArea, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
            const int bytesPerPixel = 3;

            byte* firstPixel = (byte*)imageData.Scan0.ToPointer();
            int stride = imageData.Stride;

            var interpolatedColors = InterpolateColors(maxIterationDepth);

            for (int y = 0; y < imageData.Height; y++)
            {
                byte* row = firstPixel + y * stride;

                for (int x = 0; x < imageData.Width; x++)
                {
                    // Order: BGR
                    int blueIndex = x * bytesPerPixel;
                    int greenIndex = blueIndex + 1;
                    int redIndex = blueIndex + 2;

                    var color = GetInterpolatedColor(interpolatedColors, iterations[x, y], maxIterationDepth);

                    row[blueIndex] = color.B;
                    row[greenIndex] = color.G;
                    row[redIndex] = color.R;
                }
            }

            bitmap.UnlockBits(imageData);
        }
        private static IterationValue[,] CalculateIterationDepths(Size imageSize, ComplexNumber topLeft, ComplexNumber bottomRight, int maxIterationDepth, double threshold)
        {
            IterationValue[,] iterations = new IterationValue[imageSize.Width, imageSize.Height];

            double realRange      = bottomRight.RealPart - topLeft.RealPart;
            double imaginaryRange = topLeft.ImaginaryPart - bottomRight.ImaginaryPart;

            var mandelbrotComputer = new MandelbrotComputer(maxIterationDepth, threshold);

            double realResolution      = realRange / imageSize.Width;
            double imaginaryResolution = imaginaryRange / imageSize.Height;

            Action <int> computeIteration = x =>
            {
                double xResolution = x * realResolution;

                for (int y = 0; y < imageSize.Height; y++)
                {
                    double realPart      = topLeft.RealPart + xResolution;
                    double imaginaryPart = topLeft.ImaginaryPart - y * imaginaryResolution;

                    var z = new ComplexNumber(realPart, imaginaryPart);
                    iterations[x, y] = mandelbrotComputer.ComputeIterationDepthFor(z);
                }
            };

            Parallel.For(0, imageSize.Width, computeIteration);

            return(iterations);
        }
        private static IterationValue[,] CalculateIterationDepths(Size imageSize, ComplexNumber topLeft, ComplexNumber bottomRight, int maxIterationDepth, double threshold)
        {
            IterationValue[,] iterations = new IterationValue[imageSize.Width, imageSize.Height];

            double realRange = bottomRight.RealPart - topLeft.RealPart;
            double imaginaryRange = topLeft.ImaginaryPart - bottomRight.ImaginaryPart;

            var mandelbrotComputer = new MandelbrotComputer(maxIterationDepth, threshold);

            double realResolution = realRange / imageSize.Width;
            double imaginaryResolution = imaginaryRange / imageSize.Height;

            Action<int> computeIteration = x =>
            {
                double xResolution = x * realResolution;

                for (int y = 0; y < imageSize.Height; y++)
                {
                    double realPart = topLeft.RealPart + xResolution;
                    double imaginaryPart = topLeft.ImaginaryPart - y * imaginaryResolution;

                    var z = new ComplexNumber(realPart, imaginaryPart);
                    iterations[x, y] = mandelbrotComputer.ComputeIterationDepthFor(z);
                }
            };

            Parallel.For(0, imageSize.Width, computeIteration);

            return iterations;
        }
        private static Color GetInterpolatedColor(IList<HsvColor> interpolatedColors, IterationValue iterationValue, int maxIterationDepth)
        {
            if (iterationValue.Depth == maxIterationDepth)
                return Color.Black;

            double v = iterationValue.Depth - Math.Log(Math.Log(iterationValue.AbsoluteValue) / Math.Log(maxIterationDepth), 2);
            double index = (int)(v * COLOR_DENSITY * COLOR_INTERPOLATION_FACTOR) % interpolatedColors.Count;

            return interpolatedColors[(int)index].ToColor();
        }
        private static Color GetInterpolatedColor(IList <HsvColor> interpolatedColors, IterationValue iterationValue, int maxIterationDepth)
        {
            if (iterationValue.Depth == maxIterationDepth)
            {
                return(Color.Black);
            }

            double v     = iterationValue.Depth - Math.Log(Math.Log(iterationValue.AbsoluteValue) / Math.Log(maxIterationDepth), 2);
            double index = (int)(v * COLOR_DENSITY * COLOR_INTERPOLATION_FACTOR) % interpolatedColors.Count;

            return(interpolatedColors[(int)index].ToColor());
        }