-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
selfDrawingCode.py
193 lines (141 loc) · 4.75 KB
/
selfDrawingCode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# by Kristin Henry, 2013 @KristinHenry
#
# other monospaced fonts can be found here http://www.fontsquirrel.com/fonts/list/classification/monospaced
import random, math
import PIL
from PIL import Image, ImageFont, ImageDraw
class selfDrawingCode :
def __init__(self, fontname=None) :
self.fontname = "Anonymous_Pro.ttf" # change this to a font you have
self.buff = 50
self.dx = 0
self.dy = 0
self.dxMax = 0
self.dyMax = 0
imgSize = [200, 200] # set default size of image, will be resized
border = 10
# get code as text data
filename = "selfDrawingCode.py" # ToDo: get the name of this file automatically
try :
data = open(filename).readlines()
except :
data = ""
print "Error reading file: ", filename
# preprocess data
letterCounts = self.getLetters(data)
# get random base color, use as common seed for colors based on letter frequencies in the code
baseColor = [random.randrange(0,255), random.randrange(0,255), random.randrange(0,255), 100]
letterColors = self.getLetterColors(letterCounts, baseColor)
# set initial position, then set positions and colors for each char in code
angle_initial = 0
x_initial = (imgSize[0] - (2*border))/2
y_initial = (imgSize[1] - (2*border))/2
xya = [x_initial, y_initial, angle_initial] # ToDo: better name for this variable
dots = self.getDots(data, letterColors, xya)
# get extreme positions of the resulting dots
minmax = self.getDotsMinMax(dots)
# adjust positions of dots and image size, so that image contains all dots
rMax = 60
self.shiftDots(dots, minmax, rMax)
imgSize = self.resizeImage(minmax, rMax)
# create background and image to draw into
backgroundColor = "white"
backgroundColorAlpha = "white"
bkg = Image.new("RGB", (imgSize[0], imgSize[1]), backgroundColor)
im = Image.new("RGBA", (imgSize[0], imgSize[1]), backgroundColorAlpha)
draw = ImageDraw.Draw(im)
# Do the drawing
r = 60
self.drawDots(draw, dots, r)
#drawChars(draw) # if on linux, you may uncomment this
# paste drawing onto image background--attempting to blend alphas of dots
bkg.paste(im, (0,0), im)
# save image with source file name, but with png suffix
bkg.save(filename[:-2] + "png")
def getLetters(self, data):
letterCounts = {}
for line in data:
for char in line:
if (char != '\n') & (char != '\t'):
self.countLetters(char, letterCounts)
return letterCounts
def countLetters(self, char, letterCounts):
if char in letterCounts:
letterCounts[char] += 1
else:
letterCounts[char] = 1
def getLetterColors(self, letterCounts, baseColor):
letterColors = {}
for char in letterCounts:
count = letterCounts[char]
red = (baseColor[0] + (count * random.randrange(1, 5))) % 255
grn = (baseColor[1] + (count * random.randrange(1, 5))) % 255
blu = (baseColor[2] + (count * random.randrange(1, 5))) % 255
color = [red, grn, blu, baseColor[3]]
letterColors[char] = color
return letterColors
def getXYfromChar(self, char, xya):
angle = xya[2]
r = random.randrange(10, 20)
if char == ' ':
# change direction of growth for next dots
xya[2] += random.randrange(10, 20)
if xya[2] >= 360:
xya[2] = 0
xya[0] += int(math.floor(r * math.cos(angle)))
xya[1] += int(math.floor(r * math.sin(angle)))
return xya
def getDots(self, data, letterColors, xya):
pos = xya
dots = []
# determin position and color of each character in code from text file
for line in data:
for char in line:
if char == '\n':
char = ' '
if (char != '\n') & (char != '\t'):
xya = self.getXYfromChar(char, xya)
pos = [xya[0], xya[1], xya[2]]
c = letterColors[char]
dot = [char, pos, c]
dots.append(dot)
return dots
def getDotsMinMax(self, dots):
xMin = xMax = 500
yMin = yMax = 500
i = 0
for dot in dots:
p = dot[1]
xMin = p[0] if p[0] < xMin else xMin
xMax = p[0] if p[0] > xMax else xMax
yMin = p[1] if p[1] < yMin else yMin
yMax = p[1] if p[1] > yMax else yMax
return [xMin, yMin, xMax, yMax]
def shiftDots(self, dots, minmax, rMax):
# shoudl rMax be r?
dx = self.dx
dy = self.dy
dx = -int(minmax[0]) if minmax[0] > 0 else int(math.fabs(minmax[0]))
dy = -int(minmax[1]) if minmax[1] > 0 else int(math.fabs(minmax[1]))
for dot in dots:
p = dot[1]
p[0] += dx + rMax + self.buff
p[1] += dy + rMax + self.buff
def resizeImage(self, minmax, rMax):
width = (minmax[2] - minmax[0]) + 2*rMax
height = (minmax[3] - minmax[1]) + 2*rMax
return [width, height]
def drawDots(self, draw, dots, r):
for dot in dots:
x1 = dot[1][0] - r
y1 = dot[1][1] - r
x2 = x1 + r
y2 = y1 + r
c = dot[2]
char = dot[0]
c[3] = 60
dx = 0
dy = 0
draw.ellipse((x1, y1, x2, y2), fill=tuple(c))
list(c)
artist = selfDrawingCode()