[Edit Linked Library] Fixes based on code review from Campbell
[blender-addons-contrib.git] / render_auto_save.py
1 #Simplified BSD License
2 #
3 #Copyright (c) 2012, Florian Meyer
4 #tstscr@web.de
5 #All rights reserved.
6 #
7 #Redistribution and use in source and binary forms, with or without
8 #modification, are permitted provided that the following conditions are met: 
9 #
10 #1. Redistributions of source code must retain the above copyright notice, this
11 #   list of conditions and the following disclaimer. 
12 #2. Redistributions in binary form must reproduce the above copyright notice,
13 #   this list of conditions and the following disclaimer in the documentation
14 #   and/or other materials provided with the distribution. 
15 #
16 #THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 #ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 #WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 #DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20 #ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 #(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 #LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 #ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 #(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 #SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #################################################################
27 bl_info = {
28     "name": "Auto Save Render",
29     "author": "tstscr",
30     "version": (1, 0),
31     "blender": (2, 63, 0),
32     "location": "Rendertab -> Render Panel",
33     "description": "Automatically save the image after rendering",
34     "warning": "",
35     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Render/Auto_Save",
36     "tracker_url": "http://projects.blender.org/tracker/index.php?func=detail&aid=32491",
37     "category": "Render"}
38 ###########################################################################
39 import bpy
40 from bpy.props import BoolProperty, EnumProperty
41 from bpy.app.handlers import persistent
42 from os.path import dirname, exists, join
43 from bpy.path import basename
44 from os import mkdir, listdir
45 from re import findall
46
47
48 @persistent
49 def auto_save_render(scene):
50     if not scene.save_after_render or not bpy.data.filepath:
51         return
52     rndr = scene.render
53     original_format = rndr.image_settings.file_format
54
55     format = rndr.image_settings.file_format = scene.auto_save_format
56     if format == 'OPEN_EXR_MULTILAYER': extension = '.exr'
57     if format == 'JPEG': extension = '.jpg'
58     if format == 'PNG': extension = '.png'
59     
60     blendname = basename(bpy.data.filepath).rpartition('.')[0]
61     filepath = dirname(bpy.data.filepath) + '/auto_saves'
62     
63     if not exists(filepath):
64         mkdir(filepath)
65         
66     if scene.auto_save_subfolders:
67         filepath = join(filepath, blendname)
68         if not exists(filepath):
69             mkdir(filepath)
70
71     #imagefiles starting with the blendname
72     files = [f for f in listdir(filepath) \
73             if f.startswith(blendname) \
74             and f.lower().endswith(('.png', '.jpg', '.jpeg', '.exr'))]
75     
76     highest = 0
77     if files:
78         for f in files:
79             #find last numbers in the filename after the blendname
80             suffix = findall('\d+', f.split(blendname)[-1])
81             if suffix:
82                 if int(suffix[-1]) > highest:
83                     highest = int(suffix[-1])
84     
85     save_name = join(filepath, blendname) + '_' + str(highest+1).zfill(3) + extension
86
87     image = bpy.data.images['Render Result']
88     if not image:
89         print('Auto Save: Render Result not found. Image not saved')
90         return
91     
92     print('Auto_Save:', save_name)
93     image.save_render(save_name, scene=None)
94
95     rndr.image_settings.file_format = original_format
96
97 ###########################################################################
98 def auto_save_UI(self, context):
99     layout = self.layout
100     
101     split=layout.split(percentage=0.66, align=True)
102     row = split.row()
103     row.prop(context.scene, 'save_after_render', text='Auto Save', toggle=False)
104     row.prop(context.scene, 'auto_save_subfolders', toggle=False)
105     #split=layout.split()
106     row=split.row()
107     row.prop(context.scene, 'auto_save_format', text='as', expand=False)
108     
109 def register():
110     bpy.types.Scene.save_after_render = BoolProperty(
111                     name='Save after render',
112                     default=True,
113                     description='Automatically save rendered images into: //auto_save/')
114     bpy.types.Scene.auto_save_format = EnumProperty(
115                     name='Auto Save File Format',
116                     description='File Format for the auto saves.',
117                     items={
118                     ('PNG', 'png', 'Save as png'),
119                     ('JPEG', 'jpg', 'Save as jpg'),
120                     ('OPEN_EXR_MULTILAYER', 'exr', 'Save as multilayer exr')},
121                     default='PNG')
122     bpy.types.Scene.auto_save_subfolders = BoolProperty(
123                     name='subfolder',
124                     default=False,
125                     description='Save into individual subfolders per blend name')
126     bpy.app.handlers.render_post.append(auto_save_render)
127     bpy.types.RENDER_PT_render.append(auto_save_UI)
128     
129 def unregister():
130     del(bpy.types.Scene.save_after_render)
131     del(bpy.types.Scene.auto_save_format)
132     del(bpy.types.Scene.auto_save_subfolders)
133     bpy.app.handlers.render_post.remove(auto_save_render)
134     bpy.types.RENDER_PT_render.remove(auto_save_UI)
135
136 if __name__ == "__main__":
137     register()