1 """
2 NetworkRender.py helperfunctions/classes for Network Rendering in Blender
3
4 This file is called __init__.py since there is both a module NetworkRender and
5 a package NetworkRender
6 """
7
8 __author__ ='Michel Anders (varkenvarken)'
9 __copyright__='(cc) non commercial use only and attribution by'
10 __url__ =["Author's site, http://www.swineworld.org/blender"]
11 __email__ =['varkenvarken is my nick at blendernation.org, PM me there']
12 __version__ ='1.00 2008-10-20'
13 __history__ =['1.00 2008-10-20, code refactoring and documentation update',
14 '0.03 2008-10-9, code cleanup and bug fixes',
15 '0.02 2008-10-8 better debugging and robustness (requeueing failed frames)',
16 '0.01 2008-10-6 initital version'
17 ]
18
20 """
21 Check whether two ip addresses are local to eachother.
22 @param own: ip-address as dotted quad, i.e. 1.2.3.4
23 @param other: ip-address as dotted quad, i.e. 1.2.3.4
24
25 The 'other' address is considered local (and therefor allowed) to the
26 'own'address if it is:
27 - a localhost address 127.*.*.*
28 - in a local C-address range and shares the first 3 quads
29 - in a local B-address range and shares the first 2 quads
30 - in a local A-address range and shares the first quad
31 """
32 a,b,c,d= own.split('.')
33 A,B,C,D= other.split('.')
34 if A=="127": return True
35 elif a=="192" and b=="168":
36 if a==A and b==B and c==C: return True
37 elif a=="172" and int(b)>=16 and int(b)<=31:
38 if a==A and b==B: return True
39 elif a=="10":
40 if a==A: return True
41 return False
42
43 import Blender
44
47
49
51 """
52 Enable debuging output if the Blender 'rt' variable is set to 7
53 """
54 global debug
55 if Blender.Get('rt') == 7 :
56 print 'debugmode on'
57 debug = _debug
58 else :
59 print 'debugmode off'
60 debug = _nodebug
61
62
63 import Blender.Window
64 from threading import Thread
65
67 """
68 unfortunately, as of yet this does not seem to work :-(
69 """
71 from time import sleep
72 global running
73 while not Blender.Window.TestBreak():
74 sleep(5)
75 running=False
76
77 import os
78 from Blender import Scene
79
81 """
82 Save the current .blend file as a temporary file.
83 @returns: (scn,context,scenename,name)
84
85 scn is the current scene object
86 context the current rendering context
87 scenename the name of the current scene
88 name the name of the temporary file
89
90 @warning: sideeffect: sets displaymode to 0 (=rendering in imagewindow) to
91 prevent rendering window popping up
92 """
93 Blender.PackAll()
94 from tempfile import mkstemp
95 fd,name = mkstemp(suffix='.blend')
96 os.close(fd)
97 Blender.Set('compressfile',True)
98 Blender.Save(name,1)
99 scn=Scene.getCurrent()
100 scenename=scn.getName()
101 context = scn.getRenderingContext()
102 context.displayMode=0
103 return (scn,context,scenename,name)
104
106 """
107 Print rendertime statistics for the various remote and local threads.
108 @param stats: a queue of tuples (frames, seconds, errorframes)
109 @type stats: Queue.queue
110 @param n: total number of frames to render
111 @type n: int
112 @param starttime: start time in seconds since epoch
113 @type starttime: float
114 @param endtime: end time in second since epoch
115 @type endtime: float
116 @returns: per frame filenames sorted by framenumber
117 """
118 from collections import defaultdict
119 stats_f = defaultdict(int)
120 stats_t = defaultdict(float)
121 stats_e = defaultdict(int)
122 namelist={}
123 while not stats.empty():
124 s = stats.get()
125 stats.task_done()
126 stats_f[s[0]]=stats_f[s[0]]+1
127 stats_t[s[0]]=stats_t[s[0]]+s[2]
128 stats_e[s[0]]=stats_e[s[0]]+s[3]
129 if s[3] == 0 : namelist[s[1]]=s[4]
130 te = 0.0
131 for i in stats_e :
132 te += stats_e[i]
133 print '\nrender statistics\n-----------------'
134 print '%30s %7s %s'%('server','frames','time')
135 for i in stats_f :
136 print '%30s %3d/%3d %5.1f'%(i,stats_f[i],stats_e[i],stats_t[i])
137 print '%30s %3d/%3d %5.1f'%('total',n,te,endtime-starttime)
138 org = (n)*stats_t['localhost']/stats_f['localhost']
139 gain= 1.0-(endtime-starttime)/org
140 print 'done. gain is %4.1f%%'% (gain*100.0)
141
142 return [namelist[key] for key in sorted(namelist.keys())]
143
144 -def collate(imagelist,outputfilename):
145 """
146 Collate a list of images to a single image.
147 @param imagelist: list of filenames
148 @param outputfilename: file to write collated images to
149 """
150 try:
151 import PIL
152 from PIL import Image
153 debug('trying to import Python Image Library')
154 except ImportError,NameError:
155 debug('no luck importing Python Image Library')
156 return None
157 from math import sqrt
158 nparts=len(imagelist)
159 n=int(sqrt(nparts))
160 debug(imagelist)
161 im=Image.open(imagelist[0])
162 size=im.size
163 im=Image.new('RGBA',(n*size[0],n*size[1]))
164 i=0
165 for part in imagelist:
166 debug('adding image part %d from %s' % (i,part))
167 pim=Image.open(part)
168 size=pim.size
169 dy=int(i/n)
170 dx=i%n
171 im.paste(pim,(dx*size[0],dy*size[1]))
172 i += 1
173
174 im.save(outputfilename)
175 debug('saved collated images to %s'% outputfilename)
176