Julia Blend (Animated Julia Sets)

Draw Julia set animations by simply defining a 2d line though the complex plane.

A Julia set is simply a recursive function or iterative process that takes the form z=z^2+c
where the initial value of z is a complex number representing a point in 2d space, and c is any complex.
The z argument is updated until the desired number of iterations, or until it’s magnitude exceeds 2, if it exceeds 2 then we know it will eventually trend to infinity and it’s in the set.

A general definition may look something like this:

def julia(z,c,iterations=10):#z and c are both complex numbers (they may be solely imaginary or real but usually a mixture of the two) 
	if abs(z)>2: #if the magnitude of z is greater than 2, the point is outside the julia set
		return False
	elif iterations<=0: #If the desired amount of iterations have elapsed and z still doesn't have a magnitude of at least 2 then that point can be considered in the set. 
		return True 
	else: #If iterations still remain and the magnitude of z is under 2, the recursively call the julia set function again, with z replaced by z squared + c and iterations replaced with iterations-1. 
		return julia(z**2+c,c,iterations-1)

This function is then mapped to a (usually 2d Euclidean) space, represented as complex numbers (x+yi), ,and it’s features can be zoomed/scaled to reveal more details indefinitely.
This mapping in its simplest form may look like this:

def complexgraph(func,minX=-1,minY=-1,maxX=1,maxY=1):
    resolution=(1080,720)
    xdifference=maxX-minX
    ydifference=maxY-minY
    out=[]
    for i in range(resolution[0]):
        row=[]
        for j in range(resolution[1]):
            x=minX+xdifference/resolution[0]*i
            y=minY+ydifference/resolution[1]*i
            z=x+y*1j #in python the imaginary number is j (it's an electricians convention where I already means current)
            row.append(func(z))
        out.append(row)
    return out

#With the Julia set called as such
complexgraph(lambda z:julia(z,.62-.75j))
#This will make the julia set c=.62-.75j

My current definition for animated Julia sets is as follows

from __future__ import division
from PIL import Image,ImageDraw
def julia(b,c,d,iterations=30):
    c=c+d*1j
    def inner(x,y): 
        z=x+y*1j
        for i in range(iterations):
            z=z**b+c
            absol=abs(z)
            if absol<2:
                return (60+(absol%2)*50,64+(absol%2)*40,(64+(absol**1.1)%2)*90)
        return (absol*260,absol*80,absol*140)
    return inner

def drawfunc(f,resolution=(1080,720),view=(-1.2,-.7,1.2,.7),frame=0):
    resolution=(int(resolution[0]),int(resolution[1]))
    im=Image.new("RGB",resolution,(0,0,0))
    for i in range(resolution[0]):
        for j in range(resolution[1]):
            x=view[0]+(view[2]-view[0])*i/resolution[0]
            y=view[1]+(view[3]-view[1])*j/resolution[1]
            col=f(x,y)
            col=tuple([int(min(255,max(0,i))) for i in col])
            im.putpixel((i,j),col)
    im.save("A%04d.png"%frame)

def midpoint(a,b,r):
    return a+(b-a)*r

def drawpath(b1,b2,c1,c2,d1,d2,resolution=(1080,720),iterations=6,steps=10000):
    for frame in range(2000,3000):
        r=frame/steps
        drawfunc(julia(midpoint(b1,b2,r),midpoint(c1,c2,r),midpoint(d1,d2,r)),resolution=resolution,frame=frame)

drawpath(2,2,-.8,-1.2,.4,-.2)

While quite short it can produce an endless array of intricate patterns and pairing with a kaleidoscope can force symmetry and produce amazing shapes.
Here are a few renders I’ve made throughout the years:

Kaleidoscope Renders

Back to top