6
\$\begingroup\$

I've made the following to draw a series of zooming in images of a fractal.

using Distributed, FileIO, ImageCore, Images, ImageView

@everywhere function mandel_pow(z::Complex, p::Number)
    c = z
    maxiter::UInt8 = 255
    for n = 1:maxiter
        if abs2(z) > 4
            return n-1
        end
        z = z^p + c
    end
    return maxiter
end

@everywhere function mandel(z)
    mandel_pow(z, 2)
end

@everywhere function julia_pow(z::Complex, c::Complex, p::Number)
    maxiter::UInt8 = 255
    for n = 1:maxiter
        if abs2(z) > 4
            return n-1
        end
        z = z^p + c
    end
    return maxiter
end

@everywhere function julia(z)
    julia(z, 2)
end

function gen_frame(min_coord::Complex,
                       max_coord::Complex, res, fn)
    x_res, y_res = res
    arr = @distributed hcat for i in range(real(min_coord), real(max_coord), length=x_res)
        col = Vector{UInt8}(undef, y_res)
        for j in enumerate(range(imag(max_coord), imag(min_coord), length=y_res))
            col[j[1]] = fn(i+j[2]*im)
        end
        col
    end
    fetch(arr)
end

function zoom_in(image, zoom, scale)
    y_res, x_res = size(image)
    zoom = zoom/2
    xmin = 1+round(Int, x_res*(.5-zoom))
    xmax = round(Int, x_res*(.5+zoom))
    ymin = 1+round(Int, y_res*(.5-zoom))
    ymax = round(Int, y_res*(.5+zoom))
    v = @view image[ymin:ymax, xmin:xmax]
    imresize(v, div.(size(image), scale))
end

function draw_zoom(center, half_size, fps, seconds, fn)
    res = (1920,1080)
    scale = 2

    for t in 0:seconds
        print(t)
        zoom = scale^convert(Float64, -t)
        base = normedview(gen_frame(center - half_size*zoom,
                                    center + half_size*zoom,
                                    res.*scale, fn));
        println(size(base))
        for i in 0:fps
            zoom = scale^(-i/fps)
            save("mandel" * lpad(string(i+fps*t),4,'0') * ".jpg", zoom_in(base, zoom, scale))
        end
        println(" done.")
    end
end

c = -0.5-0im
half_size = 1.5+1im
draw_zoom(c, half_size, 1, 1, mandel)

It can draw 10 seconds of frames at 30fps in about a minute using all cores of my computer. I'm specifically looking for ways to improve the way gen_frame is parallelized, and ideally make the saving zoomed in strings happen while the next computation is being done.

\$\endgroup\$
  • 1
    \$\begingroup\$ Quick comment, asserting maxiter::UInt8 = 255 has no effect, since 1:maxiter will make a UnitRange{Int} anyway. \$\endgroup\$ – Luapulu Nov 14 at 12:33
  • \$\begingroup\$ Wow. This is a blast from the past. I think this was the first real program I wrote in Julia. The pre 1.3 is really showing (as is me not knowing what I'm doing) \$\endgroup\$ – Oscar Smith Nov 14 at 17:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.