Last active
September 8, 2018 01:39
-
-
Save EnigmaCurry/12cb7fa20664c43074afed27ba53e751 to your computer and use it in GitHub Desktop.
Serverless Psychedelic Art
This file contains hidden or 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
#!/bin/sh | |
gcloud beta functions deploy psychedelic_art --runtime python37 --trigger-http |
This file contains hidden or 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
# Random Psychedelic Art - https://jeremykun.com/2012/01/01/random-psychedelic-art/ | |
# Deterministic Refactor by EnigmaCurry | |
from PIL import Image | |
import random, math | |
from flask import send_file | |
from io import BytesIO | |
def make_image(seed=None, size=150, debug=False): | |
rng = random.Random(seed) | |
def buildExpr(prob = 0.99): | |
if rng.random() < prob: | |
return rng.choice([SinPi, CosPi, Times])(prob) | |
else: | |
return rng.choice([X, Y])() | |
class X: | |
def eval(self, x, y): | |
return x | |
def __str__(self): | |
return "x" | |
class Y: | |
def eval(self, x, y): | |
return y | |
def __str__(self): | |
return "y" | |
class SinPi: | |
def __init__(self, prob): | |
self.arg = buildExpr(prob * prob) | |
def __str__(self): | |
return "sin(pi*" + str(self.arg) + ")" | |
def eval(self, x, y): | |
return math.sin(math.pi * self.arg.eval(x,y)) | |
class CosPi: | |
def __init__(self, prob): | |
self.arg = buildExpr(prob * prob) | |
def __str__(self): | |
return "cos(pi*" + str(self.arg) + ")" | |
def eval(self, x, y): | |
return math.cos(math.pi * self.arg.eval(x,y)) | |
class Times: | |
def __init__(self, prob): | |
self.lhs = buildExpr(prob * prob) | |
self.rhs = buildExpr(prob * prob) | |
def __str__(self): | |
return str(self.lhs) + "*" + str(self.rhs) | |
def eval(self, x, y): | |
return self.lhs.eval(x,y) * self.rhs.eval(x,y) | |
def plotIntensity(exp, pixelsPerUnit = size): | |
canvasWidth = 2 * pixelsPerUnit + 1 | |
canvas = Image.new("L", (canvasWidth, canvasWidth)) | |
for py in range(canvasWidth): | |
for px in range(canvasWidth): | |
# Convert pixel location to [-1,1] coordinates | |
x = float(px - pixelsPerUnit) / pixelsPerUnit | |
y = -float(py - pixelsPerUnit) / pixelsPerUnit | |
z = exp.eval(x,y) | |
# Scale [-1,1] result to [0,255]. | |
intensity = int(z * 127.5 + 127.5) | |
canvas.putpixel((px,py), intensity) | |
return canvas | |
def plotColor(exp, pixelsPerUnit = size): | |
redPlane = plotIntensity(exp['red'], pixelsPerUnit) | |
greenPlane = plotIntensity(exp['green'], pixelsPerUnit) | |
bluePlane = plotIntensity(exp['blue'], pixelsPerUnit) | |
return Image.merge("RGB", (redPlane, greenPlane, bluePlane)) | |
exp = {"red": buildExpr(), | |
"green": buildExpr(), | |
"blue": buildExpr()} | |
if(debug): | |
print(f"seed = {seed}") | |
print(f"red = {exp['red']}") | |
print(f"green = {exp['green']}") | |
print(f"blue = {exp['blue']}") | |
return plotColor(exp, (size//2)) | |
def psychedelic_art(req): | |
size = int(req.args.get('size', default=100)) | |
assert size <= 300 | |
img = make_image(seed=req.path, size=size) | |
out = BytesIO() | |
img.save(out, 'JPEG', quality=70) | |
out.seek(0) | |
return send_file(out, mimetype="image/jpeg") |
This file contains hidden or 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
Pillow |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment