User:Dave Young/Prototyping 3.1

From XPUB & Lens-Based wiki

AsciiNoise

A modified Perlin noise generator built in Python that creates patterns made out of ascii characters and outputs as html. The value returned from the perlin noise algorithm selects a character from an ascii list arranged according to pixel-density. For example, the first character in the list is a . and the final character is a Q - the latter character appearing more dense on-screen than the full-stop.

Refresh me asciinoise!

Source

#!/usr/bin/python2.7
#Perlin noise implementation for python by The_Hatstand
#Modified from http://freespace.virgin.net/hugo.elias/models/m_perlin.htm

############################################################################
#..........................................................................#
#..######..######..######..##..##......##..##..######..##..######..######..#
#..##..##..##......##......##..##......##..##..##..##..##..##......##......#
#..##..##..##......##......##..##......###.##..##..##..##..##......##......#
#..######..######..##......##..##......##.###..##..##..##..######..####....#
#..##..##......##..##......##..##......##..##..##..##..##......##..##......#
#..##..##......##..##......##..##......##..##..##..##..##......##..##......#
#..##..##..######..######..##..##......##..##..######..##..######..######..#
#..........................................................................#
############################################################################

import math
import random

#--Perlin Noise Functions ----------------------------------------------

#first make a generator that takes a returns a random number based on a 2dimensional input
def rawNoise(x, y):
	n = x+y*57
	n = (n<<13) ^ n
	return ( 1.0 - ( (n * (n * n * 44560482149 + 13091204281) + 1376312589)&0x7fffffff) / 1073741824.0)

#creates a smoothing algorithm to the raw noise (based on averaging neighbouring input-coords)
def smoothNoise(x, y):
	corners = (rawNoise(x-1, y-1)+rawNoise(x+1, y-1)+rawNoise(x-1, y+1)+rawNoise(x+1, y+1))/16
	sides = (rawNoise(x-1, y)+rawNoise(x+1, y)+rawNoise(x, y-1)+rawNoise(x, y+1))/8
	center = rawNoise(x, y)/4
	return (corners + sides + center)

#creates a cosine wave interpolation algorithm to further smooth the results
def cosineInterpolation(a, b, x):
	ft = x*3.1415927
	f = (1-math.cos(ft))*.5
	return (a*(1-f)+b*f)

#applies smoothing algorithms to create a more harmonic stream of numbers
def interpolatedNoise(x, y):
	int_x = int(x)
	fractional_x = x-int_x

	int_y = int(y)
	fractional_y = y-int_y

	v1 = smoothNoise(int_x, int_y)
	v2 = smoothNoise(int_x+1, int_y)
	v3 = smoothNoise(int_x, int_y+1)
	v4 = smoothNoise(int_x+1, int_y+1)
	
	i1 = cosineInterpolation(v1, v2, fractional_x)
	i2 = cosineInterpolation(v3, v4, fractional_y)

	return cosineInterpolation(i1, i2, fractional_y)

#perlin noise algorithm
def perlinNoise2d(x, y, frequency, numOctaves):
	total = 0;
	p = 1;
	n = numOctaves - 1

	for i in range(n):
		freq = (1^i)*frequency
		amp = p^i
		total += interpolatedNoise(x*freq, y*freq)*amp
        total = total/n

	return total

#--DO STUFF ---------------------------------------------------------
#set headers
print """Content-type: text/html\n\n"""

#css/html
print """<html><head><style type="text/css">body{background:#000000; font-family: Monospace; line-height:8px; letter-spacing: -1px; font-size: 8px;color:#FFFFFF;}</style></head>"""
print "<body>"

#ascii list arranged according to onscreen character-density
chars = ['.', '`', '-', '_', "'", ':', ';', '^', '=', '+', '/', '"', '|', ')', """\\""", '<', '>', ')', 'i', 'v', '%', 'x', 'c', 'l', 'r', 's', '{', '*', '}', 'I', '?', '!', ']', '[', '1', 't', 'a', 'e', 'o', '7', 'z', 'j', 'L', 'u', 'n', 'T', "#", 'J', 'C', 'w', 'f', 'y', '3', '2', '5', 'F', 'p', '6', 'm', 'q', 'S', 'g', 'h', 'V', 'd', '4', 'E', 'g', 'X', 'P', 'G', 'Z', 'b', 'Y', 'k', 'O', 'A', '&', '8', 'U', '$', '@', 'K', 'H', 'D', 'B', 'W', 'N', 'M', 'R', '0', 'Q']

charlen = len(chars) #length of chars[]

_octaves = random.randint(2, 4) #Calculates how many octaves the noise should be calculated over: 1 < octaves < 5
_frequency = random.uniform(0.1, 0.75) #Changes the "visual complexity" of the noise: 0.1 < frequency < 1
_modifier = random.randint(0, charlen/2) #Modifies the +/- range the Noise operates over
_threshold = random.randint(0, 20) #Shifts the noise into a new range +/- _modifier

#the x,y loop
for y in range(100):
    for x in range(100):
        #PerlinNoise2d args = xpos, ypos, freq, persistence, octaves
        n = int((perlinNoise2d(x, y, _frequency, _octaves)*_modifier)+_threshold)
        if(n > charlen):
            print chars[charlen]
        else:
            print chars[n]

    print "<br />"

#close html
print "</body>"