/
Drawer.py
162 lines (116 loc) · 3.24 KB
/
Drawer.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
from PIL import Image, ImageDraw
import numpy as np
class DrawObj():
"""
Used for executing any draw functionality
"""
def draw(
self,
x,
y,
radius,):
"""
Used to draw the circle around the current position (emulates brush strokes)
Draws the circle through the use of recursion
:param x: x coordinate of the current position
:param y: y coordinate of the current position
:param radius: radius of the circle to be drawn
"""
if (radius == 0) or 1000 <= x or x < 0 or 1000 <= y or y < 0:
return
else:
if(self._lastX == None):
self._lastX = x;
self._lastY = y;
self._undo_stack.push(self._current)
self._current = []
self._draw.line((self._lastX,self._lastY,x,y),fill=0,width=radius,)
self._lastX = x;
self._lastY = y;
self._current.append([x,y])
def erase(
self,
x,
y,
radius,):
"""
Used to draw the circle around the current position (emulates brush strokes)
Draws the circle through the use of recursion
:param x: x coordinate of the current position
:param y: y coordinate of the current position
:param radius: radius of the circle to be drawn
"""
if (radius == 0) or 1000 <= x or x < 0 or 1000 <= y or y < 0:
return
else:
if(self._lastX == None):
self._lastX = x
self._lastY = y
self._draw.line((self._lastX,self._lastY,x,y),fill=(255, 255, 255),width=radius)
self._lastX = x
self._lastY = y
def undo(self):
for num in range(0, len(self._current)-2):
self._draw.line((self._current[num][0],self._current[num][1],self._current[num+1][0],self._current[num+1][1]),fill=(255, 255, 255),width=20)
if not self._undo_stack.is_empty():
self._current = self._undo_stack.pop();
def __init__(
self,
image):
"""
Creates a drawer object
:Param image: path of the image to be edited
"""
self._path = image
self._image = None
self._lastX = None
self._lastY = None
self._draw = None
self._r = []
self._g = []
self._b = []
self._current = []
self._undo_stack = Stack()
self.isDrawing = False
def start(
self
):
"""
Seperates the stored image into its r,g,b components
"""
self._image = Image.open(self._path)
self._draw = ImageDraw.Draw(self._image)
# In this case, it's a 3-band (red, green, blue) image
# so we'll unpack the bands into 3 separate 2D arrays.
self._r, self._g, self._b = np.array(self._image).T
self.isDrawing = True
def clear(
self
):
self._image = Image.open(self._path)
self._draw = ImageDraw.Draw(self._image)
def end(
self
):
"""
Compiles the seperated r,g,b into an output image
:return the path to the output image from the updated r,g,b arrays
"""
# Put things back together and save the result...
#self._image = Image.fromarray(np.dstack([item.T for item in (self._r,self._g,self._b,)]))
self.isDrawing = False
self._image.save('output.png')
return "output.png"
class Stack():
def __init__(self):
self._container = []
self._limit = 10
def push(self, elem):
if (len(self._container) == self._limit):
self._container = []
self._container.append(elem)
def pop(self):
if (not self.is_empty()):
return self._container.pop()
def is_empty(self):
return len(self._container) == 0