Created
March 20, 2015 13:17
-
-
Save x-or/9f16646f226ca9cba276 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Copyright (c) 2015, Sergey Shishmintzev | |
### License: Apache/GPLv3 | |
### Examples: http://youtu.be/2kckHKCVvDs https://youtu.be/aFN02gJUJ0o | |
### Interpreter: Python 2.7.5 with NumPy 1.9.1 and Pillow 2.7.0 | |
power = 19 | |
name = "spiral" | |
frame_count = 12000 | |
image_width = 1080 | |
image_height = 1080 | |
alpha_z = 55 | |
import numpy as np | |
import numpy.random as nr | |
from PIL import Image | |
import colorsys | |
np.set_printoptions(linewidth = 180, edgeitems=10, suppress = True) | |
def additive_binary_construction(components, n): | |
result = 0 | |
bit_index = 0 | |
while n > 0: | |
if (n & 1) == 1: | |
result += components[bit_index] | |
n >>= 1 | |
bit_index += 1 | |
return result | |
def multiplicative_binary_construction(components, n): | |
result = 1 | |
bit_index = 0 | |
while n > 0: | |
if (n & 1) == 1: | |
result *= components[bit_index] | |
n >>= 1 | |
bit_index += 1 | |
return result | |
# generate palette | |
palette = [0] * 256 | |
for i, h in enumerate(np.linspace(0, 3, 256)): | |
c = colorsys.hsv_to_rgb(h, 1.0, 1.0) | |
palette[i] = (int(c[0]*255), int(c[1]*255), int(c[2]*255)) | |
def alphablend(dst, src, alpha): | |
return ((dst[0]*(255-alpha) + src[0]*alpha)>>8, (dst[1]*(255-alpha) + src[1]*alpha)>>8, (dst[2]*(255-alpha) + src[2]*alpha)>>8) | |
spiral_components = np.linspace(1.0/power, 1.0, power) + 1j | |
print "spiral_components:" | |
print spiral_components | |
print "abs:", np.abs(spiral_components) | |
print "arg:", np.angle(spiral_components) | |
# Recombination examples | |
#recombination_components = nr.randint(0, 2, power) | |
#recombination_components = np.ones(power) | |
#recombination_components = np.arange(power)+1 | |
#recombination_components = np.array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3,]) | |
#recombination_components = np.array([1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1,]) | |
#recombination_components = np.array([1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,]) | |
recombination_components = np.array([1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,]) | |
#recombination_components = np.array([5, 4, 4, 3, 3, 2, 2, 1, 1, 0, -1, -1, -2, -2, -3, -3, -4, -4, -5]) | |
assert len(recombination_components) == power, len(recombination_components) | |
print "recombination_components", recombination_components | |
hamming_weight_components = np.ones(power) | |
print "Generate data..." | |
spiral_points = np.empty(2**power, np.complex128) | |
hamming_weight = np.empty(2**power, np.uint16) | |
recombination = np.empty(2**power, np.int32) | |
for i in xrange(2**power): | |
spiral_points[i] = multiplicative_binary_construction(spiral_components, i) | |
hamming_weight[i] = additive_binary_construction(hamming_weight_components, i) | |
recombination[i] = additive_binary_construction(recombination_components, i) | |
spiral_magnitude = np.prod(np.abs(spiral_components)) | |
#spiral_magnitude = np.max(np.abs(spiral_points)) | |
print "spiral_magnitude=", spiral_magnitude | |
print "Render complex plane" | |
step_x = 1.0*(image_width-1) / (2*spiral_magnitude) | |
step_y = 1.0*(image_height-1) / (2*spiral_magnitude) | |
recombination_widdle_factor = np.exp(2j*np.pi*recombination/frame_count) | |
color_index = np.uint16(255*hamming_weight/power) | |
for frame in xrange(frame_count+1): | |
print "frame #", frame | |
image = Image.new("RGB", (image_width, image_height), (255, 255, 255)) | |
pixels = image.load() | |
spiral_points_x = np.int32((spiral_points.real+spiral_magnitude)*step_x) | |
spiral_points_y = np.int32((spiral_magnitude-spiral_points.imag)*step_y) | |
# range checks | |
assert np.all(spiral_points_x >= 0) | |
assert np.all(spiral_points_y >= 0) | |
assert np.all(spiral_points_x < image_width) | |
assert np.all(spiral_points_y < image_height) | |
# render | |
for i in xrange(2**power): | |
x = spiral_points_x[i] | |
y = spiral_points_y[i] | |
pixels[x, y] = alphablend(pixels[x, y], palette[color_index[i]], alpha_z) | |
image.save("%s-frame%05d-z.png"%(name, frame), "PNG") | |
spiral_points *= recombination_widdle_factor |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment