Cleanup: simplify file name incrementing logic
[blender-addons.git] / render_povray / df3.py
blobb84342875f0115206f13ac53f3eb2d34639cf153
1 ################################################################################
3 # df3.py
5 # Copyright (C) 2005 Mike Kost <contact@povray.tashcorp.net>
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 ################################################################################
24 # Creation functions
25 # __init__(x=1, y=1, z=1) : default constructor
26 # clone(indf3) : make this df3 look like indf3
28 # Info functions
29 # sizeX(): returns X dimension
30 # sizeY(): returns Y dimension
31 # sizeZ(): returns Z dimension
33 # Scalar functions
34 # mult():
35 # add():
36 # max(): returns highest voxel value in df3
37 # min(): returns lowest voxel value in df3
39 # Vector functions
41 # Import/Export functions
42 # exportDF3():
43 # importDF3():
45 ################################################################################
47 import struct
48 import os
49 import stat
50 import array
51 import sys
53 # -+-+-+- Start df3 Class -+-+-+-
55 class df3:
56 __version__ = '0.2'
58 __arraytype__ = 'f'
60 __struct4byte__ = '>I'
61 __struct2byte__ = '>H'
62 __struct2byte3__ = '>HHH'
63 __struct1byte__ = '>B'
64 __array4byte__ = 'I'
65 __array2byte__ = 'H'
66 __array1byte__ = 'B'
68 def __init__(self, x=1, y=1, z=1):
69 self.maxX = x
70 self.maxY = y
71 self.maxZ = z
72 self.voxel = self.__create__(x, y, z)
74 def clone(self, indf3):
75 self.voxel = array.array(self.__arraytype__)
76 for i in range(indf3.sizeX()*indf3.sizeY()*indf3.sizeZ()):
77 self.voxel[i] = indf3.voxel[i]
78 return self
80 #### Info Functions
82 def sizeX(self):
83 return self.maxX
85 def sizeY(self):
86 return self.maxY
88 def sizeZ(self):
89 return self.maxZ
91 def size(self):
92 tmp = []
93 tmp.append(self.sizeX())
94 tmp.append(self.sizeY())
95 tmp.append(self.sizeZ())
96 return tmp
98 #### Voxel Access Functions
100 def get(self, x, y, z):
101 return self.voxel[self.__voxa__(x,y,z)]
103 def getB(self, x, y, z):
104 if (x > self.sizeX() or x < 0): return 0
105 if (y > self.sizeX() or y < 0): return 0
106 if (z > self.sizeX() or z < 0): return 0
108 return self.voxel[self.__voxa__(x,y,z)]
110 def set(self, x, y, z, val):
111 self.voxel[self.__voxa__(x,y,z)] = val
113 def setB(self, x, y, z, val):
114 if (x > self.sizeX() or x < 0): return
115 if (y > self.sizeX() or y < 0): return
116 if (z > self.sizeX() or z < 0): return
118 self.voxel[self.__voxa__(x,y,z)] = val
120 #### Scalar Functions
122 def mult(self, val):
123 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
124 self.voxel[i] = self.voxel[i] * val
126 return self
128 def add(self, val):
129 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
130 self.voxel[i] = self.voxel[i] + val
132 return self
134 def max(self):
135 tmp = self.voxel[0]
137 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
138 if (self.voxel[i] > tmp):
139 tmp = self.voxel[i]
141 return tmp
143 def min(self):
144 tmp = self.voxel[0]
146 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
147 if (self.voxel[i] < tmp):
148 tmp = self.voxel[i]
150 return tmp
152 #### Vector Functions
154 def compare(self, indf3):
155 if (self.__samesize__(indf3) == 0): return 0
157 if (self.voxel == indf3.voxel):
158 return 1
160 return 0
162 def multV(self, indf3):
163 if (self.__samesize__(indf3) == 0):
164 print("Cannot multiply voxels - not same size")
165 return
167 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
168 self.voxel[i] = self.voxel[i]*indf3.voxel[i]
170 return self
172 def addV(self, indf3):
173 if (self.__samesize__(indf3) == 0):
174 print("Cannot add voxels - not same size")
175 return
177 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
178 self.voxel[i] = self.voxel[i]+indf3.voxel[i]
180 return self
182 def convolveV(self, filt):
183 fx = filt.sizeX()
184 fy = filt.sizeY()
185 fz = filt.sizeZ()
186 if (fx % 2 != 1):
187 print("Incompatible filter - must be odd number of X")
188 return self
189 if (fy % 2 != 1):
190 print("Incompatible filter - must be odd number of Y")
191 return self
192 if (fz % 2 != 1):
193 print("Incompatible filter - must be odd number of Z")
194 return self
196 fdx = (fx-1)/2
197 fdy = (fy-1)/2
198 fdz = (fz-1)/2
199 flen = fx*fy*fz
201 newV = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ());
203 for x in range(self.sizeX()):
204 for y in range(self.sizeY()):
205 for z in range(self.sizeZ()):
206 rip = self.__rip__(x-fdx, x+fdx, y-fdy, y+fdy, z-fdz, z+fdz)
207 tmp = 0.0
208 for i in range(flen):
209 tmp += rip[i]*filt.voxel[i]
210 newV[self.__voxa__(x,y,z)] = tmp
212 self.voxel = newV
214 return self
216 #### Import/Export Functions
218 def exportDF3(self, file, depth=8, rescale=1):
219 x = self.sizeX()
220 y = self.sizeY()
221 z = self.sizeZ()
223 try:
224 f = open(file, 'wb');
225 except:
226 print("Could not open " + file + " for write");
227 return
229 f.write(struct.pack(self.__struct2byte3__, x, y, z));
231 tmp = self.__toInteger__(pow(2,depth)-1, rescale)
233 if (depth > 16): # 32-bit
234 for i in range( x*y*z ):
235 f.write(struct.pack(self.__struct4byte__, tmp[i]))
236 elif (depth > 8): # 16-bit
237 for i in range( x*y*z ):
238 f.write(struct.pack(self.__struct2byte__, tmp[i]))
239 else:
240 for i in range( x*y*z ):
241 f.write(struct.pack(self.__struct1byte__, tmp[i]))
243 def importDF3(self, file, scale=1):
244 try:
245 f = open(file, 'rb');
246 size = os.stat(file)[stat.ST_SIZE]
248 except:
249 print("Could not open " + file + " for read");
250 return []
252 (x, y, z) = struct.unpack(self.__struct2byte3__, f.read(6) )
254 self.voxel = self.__create__(x, y, z)
255 self.maxX = x
256 self.maxY = y
257 self.maxZ = z
259 size = size-6
260 if (size == x*y*z): format = 8
261 elif (size == 2*x*y*z): format = 16
262 elif (size == 4*x*y*z): format = 32
264 if (format == 32):
265 for i in range(x*y*z):
266 self.voxel[i] = float(struct.unpack(self.__struct4byte__, f.read(4) )[0])
267 elif (format == 16):
268 for i in range(x*y*z):
269 self.voxel[i] = float(struct.unpack(self.__struct2byte__, f.read(2) )[0])
270 elif (format == 8):
271 for i in range(x*y*z):
272 self.voxel[i] = float(struct.unpack(self.__struct1byte__, f.read(1) )[0])
274 return self
276 #### Local classes not intended for user use
278 def __rip__(self, minX, maxX, minY, maxY, minZ, maxZ):
279 sizeX = maxX-minX+1
280 sizeY = maxY-minY+1
281 sizeZ = maxZ-minZ+1
283 tmpV = self.__create__(sizeX, sizeY, sizeZ)
285 for x in range(sizeX):
286 for y in range(sizeY):
287 for z in range(sizeZ):
288 # Check X
289 if ((minX + x) < 0):
290 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
291 elif ((minX + x) > self.sizeX()-1):
292 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
293 # Check Y
294 elif ((minY + y) < 0):
295 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
296 elif ((minY + y) > self.sizeY()-1):
297 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
298 # Check Z
299 elif ((minZ + z) < 0):
300 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
301 elif ((minZ + z) > self.sizeZ()-1):
302 tmpV[(z*sizeZ+y)*sizeY+x] = 0.0
303 else:
304 tmpV[(z*sizeZ+y)*sizeY+x] = self.get(minX+x,minY+y,minZ+z)
306 return tmpV
308 def __samesize__(self, indf3):
309 if (self.sizeX() != indf3.sizeX()): return 0
310 if (self.sizeY() != indf3.sizeY()): return 0
311 if (self.sizeZ() != indf3.sizeZ()): return 0
312 return 1
314 def __voxa__(self, x, y, z):
315 return ((z*self.sizeY()+y)*self.sizeX()+x)
317 def __create__(self, x, y, z, atype='0', init=1):
318 if (atype == '0'):
319 tmp = self.__arraytype__
320 else:
321 tmp = atype
323 if (init == 1):
324 if tmp in ('f','d'):
325 voxel = array.array(tmp, [0.0 for i in range(x*y*z)])
326 else:
327 voxel = array.array(tmp, [0 for i in range(x*y*z)])
328 else:
329 voxel = array.array(tmp)
331 return voxel
333 def __toInteger__(self, scale, rescale=1):
334 if (scale < pow(2,8)): # 8-bit
335 tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array1byte__)
336 elif (scale < pow(2,16)): # 16-bit
337 tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array2byte__)
338 else: # 32-bit
339 tmp = self.__create__(self.sizeX(), self.sizeY(), self.sizeZ(), self.__array4byte__)
341 maxVal = self.max()
343 print(scale)
345 for i in range(self.sizeX()*self.sizeY()*self.sizeZ()):
346 if (rescale == 1):
347 tmp[i] = max(0,int(round(scale*self.voxel[i]/maxVal)))
348 else:
349 tmp[i] = max(0,min(scale,int(round(self.voxel[i]))))
351 return tmp
353 # -=-=-=- End df3 Class -=-=-=-
354 ##########DEFAULT EXAMPLES
355 # if __name__ == '__main__':
356 # localX = 80
357 # localY = 90
358 # localZ = 100
359 ## Generate an output
360 # temp = df3(localX, localY, localZ)
362 # for i in range(localX):
363 # for j in range(localY):
364 # for k in range(localZ):
365 # if (i >= (localX/2)):
366 # temp.set(i, j, k, 1.0)
368 # temp.exportDF3('temp.df3', 16)
369 ###############################################################################
370 ## Import
371 # temp2 = df3().importDF3('temp.df3')
372 # temp2.mult(1/temp2.max())
374 ## Compare
375 # print(temp2.size())
377 # if (temp.compare(temp2) == 0): print("DF3's Do Not Match")
379 ###############################################################################
380 # ChangeLog
381 # ---------
382 # 08/09/05: 0.20 released
383 # + Change internal representation to floating point
384 # + Rewrite import/export for speed
385 # + Convert from 3-d list structure to Array class for data storage
386 # + Add element access, scalar, and vector functions
387 # 07/13/05: 0.10 released
388 ###############################################################################