OSDN Git Service

testing: test_performance.py can show callgraph
[mypaint-anime/master.git] / tests / test_mypaintlib.py
1 #!/usr/bin/env python
2 from pylab import *
3 from time import time
4 import sys, os, gc
5
6 os.chdir(os.path.dirname(sys.argv[0]))
7 sys.path.insert(0, '..')
8
9 from lib import mypaintlib, tiledsurface, brush, document, command, helpers
10
11 def tileConversions():
12     # fully transparent tile stays fully transparent (without noise)
13     N = mypaintlib.TILE_SIZE
14     src = zeros((N, N, 4), 'uint16')
15     dst = ones((N, N, 4), 'uint8')
16     mypaintlib.tile_convert_rgba16_to_rgba8(src, dst)
17     assert not dst.any()
18     # fully opaque tile stays fully opaque
19     src[:,:,3] = 1<<15
20     src[:,:,:3] = randint(0, 1<<15, (N, N, 3))
21     dst = zeros((N, N, 4), 'uint8')
22     mypaintlib.tile_convert_rgba16_to_rgba8(src, dst)
23     assert (dst[:,:,3] == 255).all()
24
25 def directPaint():
26
27     s = tiledsurface.Surface()
28     events = loadtxt('painting30sec.dat.gz')
29
30     s.begin_atomic()
31     for t, x, y, pressure in events:
32         r = g = b = 0.5*(1.0+sin(t))
33         r *= 0.8
34         s.draw_dab(x, y, 12, r, g, b, pressure, 0.6)
35     s.end_atomic()
36     s.save('test_directPaint.png')
37
38 def brushPaint():
39
40     s = tiledsurface.Surface()
41     b = brush.Brush()
42     #b.load_from_string(open('../brushes/s006.myb').read())
43     b.load_from_string(open('../brushes/charcoal.myb').read())
44
45     events = loadtxt('painting30sec.dat.gz')
46
47     b.set_color_rgb((0.0, 0.9, 1.0))
48
49     t0 = time()
50     for i in range(10):
51         t_old = events[0][0]
52         s.begin_atomic()
53         for t, x, y, pressure in events:
54             dtime = t - t_old
55             t_old = t
56             b.stroke_to (s, x, y, pressure, 0.0, 0.0, dtime)
57         s.end_atomic()
58     print 'Brushpaint time:', time()-t0
59     print s.get_bbox(), b.stroke_total_painting_time # FIXME: why is this time so different each run?
60
61     s.save('test_brushPaint.png')
62
63 def files_equal(a, b):
64     return open(a, 'rb').read() == open(b, 'rb').read()
65
66 def pngs_equal(a, b):
67     if files_equal(a, b):
68         print a, 'and', b, 'are perfectly equal'
69         return True
70     im_a = imread(a)*255.0
71     im_b = imread(b)*255.0
72     if im_a.shape != im_b.shape:
73         print a, 'and', b, 'have different size:', im_a.shape, im_b.shape
74         return False
75     diff = im_b - im_a
76     alpha = im_a.shape[-1] == 4
77     if alpha:
78         diff_alpha = diff[:,:,3]
79
80     equal = True
81     print a, 'and', b, 'are different, analyzing whether it is just the undefined colors...'
82     print 'Average difference (255=white): (R, G, B, A)'
83     print mean(mean(diff, 0), 0)
84     print 'Average difference with premultiplied alpha (255=white): (R, G, B, A)'
85     diff = diff[:,:,0:3]
86     if alpha:
87         diff *= imread(a)[:,:,3:4]
88     res = mean(mean(diff, 0), 0)
89     print res
90     if mean(res) > 0.01:
91         # dithering should make this value nearly zero...
92         equal = False
93     print 'Maximum abs difference with premultiplied alpha (255=white): (R, G, B, A)'
94     res = amax(amax(abs(diff), 0), 0)
95     print res
96     if max(abs(res)) > 1.1:
97         # this error will be visible
98         # - smaller errors are hidden by the weak alpha
99         #   (but we should pay attention not to accumulate such errors at each load/save cycle...)
100         equal = False
101
102     if not equal:
103         print 'Not equal enough!'
104         if alpha:
105             figure(1)
106             title('Alpha')
107             imshow(im_b[:,:,3], interpolation='nearest')
108             colorbar()
109         figure(2)
110         title('Green Error (multiplied with alpha)')
111         imshow(diff[:,:,1], interpolation='nearest')
112         colorbar()
113         if alpha:
114             figure(3)
115             title('Alpha Error')
116             imshow(diff_alpha, interpolation='nearest')
117             colorbar()
118         show()
119
120     return equal
121
122 def docPaint():
123     b1 = brush.Brush()
124     b1.load_from_string(open('../brushes/s008.myb').read())
125     b2 = brush.Brush()
126     b2.load_from_string(open('../brushes/redbrush.myb').read())
127     b2.set_color_hsv((0.3, 0.4, 0.35))
128
129     # test some actions
130     doc = document.Document()
131     doc.undo() # nop
132     events = loadtxt('painting30sec.dat.gz')
133     events = events[:len(events)/8]
134     t_old = events[0][0]
135     n = len(events)
136     for i, (t, x, y, pressure) in enumerate(events):
137         dtime = t - t_old
138         t_old = t
139         #print dtime
140         doc.stroke_to(dtime, x, y, pressure, 0.0, 0.0)
141         if i == n*1/8:
142             doc.set_brush(b2)
143         if i == n*2/8:
144             doc.clear_layer()
145             doc.undo()
146             assert not doc.get_bbox().empty()
147             doc.redo()
148             assert doc.get_bbox().empty()
149         if i == n*3/8:
150             doc.undo()
151             doc.set_brush(b1)
152         if i == n*4/8:
153             doc.set_brush(b2)
154         if i == n*5/8:
155             doc.undo()
156             doc.redo()
157         if i == n*6/8:
158             doc.set_brush(b2)
159         if i == n*7/8:
160             doc.add_layer(1)
161
162     doc.layers[0].surface.save('test_docPaint_a.png')
163     doc.layers[0].surface.save('test_docPaint_a1.png')
164     # the resulting images will look slightly different because of dithering
165     assert pngs_equal('test_docPaint_a.png', 'test_docPaint_a1.png')
166
167     # test save/load
168     doc.save('test_f1.ora')
169     doc2 = document.Document()
170     doc2.load('test_f1.ora')
171     print doc.get_bbox(), doc2.get_bbox()
172     # TODO: fix this one?!
173     #assert doc.get_bbox() == doc2.get_bbox()
174     doc2.layers[0].surface.save('test_docPaint_b.png')
175     assert pngs_equal('test_docPaint_a.png', 'test_docPaint_b.png')
176     doc2.save('test_f2.ora')
177     #check not possible, because PNGs not exactly equal:
178     #assert files_equal('test_f1.ora', 'test_f2.ora')
179
180     # less strict test than above (just require load-save-load-save not to alter the file)
181     doc3 = document.Document()
182     doc3.load('test_f2.ora')
183     assert doc2.get_bbox() == doc3.get_bbox()
184     doc3.layers[0].surface.save('test_docPaint_c.png')
185     assert pngs_equal('test_docPaint_b.png', 'test_docPaint_c.png')
186     doc2.save('test_f3.ora')
187     #check not possible, because PNGs not exactly equal:
188     #assert files_equal('test_f2.ora', 'test_f3.ora')
189
190     # note: this is not supposed to be strictly reproducible because
191     # of different random seeds [huh? what does that mean?]
192     bbox = doc.get_bbox()
193     print 'document bbox is', bbox
194
195     # test for appearance changes (make sure they are intended)
196     doc.save('test_docPaint_flat.png', alpha=False)
197     doc.save('test_docPaint_alpha.png', alpha=True)
198     assert pngs_equal('test_docPaint_flat.png', 'correct_docPaint_flat.png')
199     assert pngs_equal('test_docPaint_alpha.png', 'correct_docPaint_alpha.png')
200
201 from optparse import OptionParser
202 parser = OptionParser('usage: %prog [options]')
203 options, tests = parser.parse_args()
204
205 tileConversions()
206 directPaint()
207 brushPaint()
208 docPaint()
209
210 print 'Tests passed.'