         xMax:  2.0
         yMin: -2.0
         yMax:  2.0
-    # Reset the iteration counts on zoom.
+
+    # Recalibrate maxIterations and reset the distribute on each each.
     beforeZoom: () ->
+        maxIterations = Math.round(MAX_ITERATIONS_SCALE_FACTOR * recalibrateMaxIterations 0.1)
+        maxIterations = Math.max(maxIterations, INITIAL_MAX_ITERATIONS)
+        console.log "new maxIterations: " + maxIterations
+        escapeTimeDistribution = {}
+
 map.zoomIn()
 map.zoomIn()

    return (c_x + 1) * (c_x + 1) + c_y * c_y < 1 / 16.0


# Iterate until we leave the ball of radius 2, up to a given max # of iterations.
# If we escape after k iterations, return an escape time value (approx. k).
# If we never escape, return 0.
getEscapeValue = (c_x, c_y, maxIterations) ->
    NO_ESCAPE = 0

    # Bypass the escape time computation if we can determine algebraically that

    # Give up, assume no escape.
    if i == maxIterations then return NO_ESCAPE


    if USE_SMOOTH_ESCAPE_TIMES
        # Compute a fractional escape time using the modulus in addition to i.

        # A few more iterations reduces the normalization error.
        extraIterations = 4
        for j in [0...extraIterations]
            x2 = z_x * z_x
            y2 = z_y * z_y
            z_y = 2 * z_x * z_y + c_y
            z_x = x2 - y2 + c_x

        norm = z_x * z_x + z_y * z_y
        modulus = Math.sqrt norm
        escapeTime = i + extraIterations - Math.log(Math.log(modulus)) / Math.log(2)

        # Ensure the value is >= 1.
        escapeTime = Math.max(1, escapeTime)
    else
        # Using the iteration count as escape time is simple but produces bands of color.
        escapeTime = i


    incrementEscapeTime escapeTime
    return escapeTime


# Given the current distribution of escape times, return the smallest escape time
# such that larger ones account for only MAX_ITERATIONS_ERROR % of the distribution.
# I.e., we could have used this smaller value of maxIterations without
# any significant visual difference.
recalibrateMaxIterations = () ->
    # Convert raw pixel counts into a percent distribution.
    percents = {}
    sum = 0
    sum += count for time, count of escapeTimeDistribution

    # Sum escape time %s in reverse order until they exceed err.
    times = _.map(_.keys(escapeTimeDistribution), Math.round)

    index = times.length - 1
    totalError = 0
    while index >= 0 and totalError / sum * 100 < MAX_ITERATIONS_ERROR
        time = times[index]
        if time
            totalError += escapeTimeDistribution[time]
        index--

    console.log "Was: " + times[times.length - 1] + " ; Now: " + time
    return time


# Return a color to indicate the escape time at a point.
getColor = (x, y) ->
    value = getEscapeValue(x, y)
    if value == 0 then return BLACK

    value = Math.sqrt(value - 1)
