Really Big Render version 4

A big “thank you” to macouno for making ReallyBigRender available. I modified the script to work with a camera that has shifts in X and/or Y before the script is run; please find an updated version attached that does this. Your web page said to contact you here, so that’s why I posted it rather than just sending it to you.

#!BPY
“”"
Name: ‘Really Big Render 4’
Blender: 248
Group: ‘Wizards’
Tooltip: ‘Render tiles that will make up an image that is way too big for blender to normally render.’
“”"

author = [“macouno”]
url = (“http://www.alienhelpdesk.com”)
version = “4”
bpydoc = “”"\

Really Big Render!

This script is written for people that want to render really really big images with blender.
Images that either blender doesn’t want to render, or your system can’t normally handle.

The script will render to 2, 3, 4, or 5 times your orignal rendersize. You can select the multiplier you want from a popup window.
So say your rendersettings are 800 x 600 and you select 3X multiplication, then the script will render nine images at 800 x 600.
If you combine these images in your favoured image editor the end result will be a single image of 3200 x 1800 pixels

Make sure that Blender can render at your current render settings! If it can’t then it won’t render the tiles either!

The tiles are rendered left to right, top to bottom and numbered as such, so 0_0 will be the left top, and 1_1 the right bottom (for a 4 tile render).

New in version 2: It can now use the PIL library to combine your tiles and create the final image… if your system can handle it and you have the PIL library for python installed.

New in version 3: You can now render at 25%/50%/75%, and some fixes were made to the code.

New in version 4: Handles cameras that have image shifts.

“”"

***** BEGIN GPL LICENSE BLOCK *****

Script copyright © macouno 2008

This program is free software; you can redistribute it and/or

modify it under the terms of the GNU General Public License

as published by the Free Software Foundation; either version 2

of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,

but WITHOUT ANY WARRANTY; without even the implied warranty of

MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

GNU General Public License for more details.

You should have received a copy of the GNU General Public License

along with this program; if not, write to the Free Software Foundation,

Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

***** END GPL LICENCE BLOCK *****

--------------------------------------------------------------------------

import Blender
from Blender import *
import math

PRESET THE GLOBAL STATE VARIABLE

STATE = {}

Preset the start values for lens shift

STATE[‘tileNr’] = [0, 2, 3, 4, 5]
STATE[‘tileMin’] = [0, -0.5, -1.0, -1.5, -2.0]

try:
import PIL
from PIL import Image
STATE[‘PIL’] = 1
except:
STATE[‘PIL’] = 0

GET THE SCENE SETTINGS FOR REFERENCE AND RESET

def GetSettings(fileName):

imageExtensions = ['.tga','.rgb','.tga','3','.jpg','5','6','7','8','9','10','11','12','13','.tga','.avi','.avi','.png','.avi','19','.bmp','.hdr','.tiff','.exr','24','.tga','.cin','27','.exr','.dds']

##try:
STATE['SCN'] = Scene.GetCurrent()
STATE['CAM'] = Camera.Get(STATE['SCN'].objects.camera.name)
STATE['CNTX'] = STATE['SCN'].render
STATE['PATH'] = STATE['CNTX'].renderPath
STATE['FILENAME'] = fileName
STATE['EXTENSION'] = imageExtensions[STATE['CNTX'].imageType]
STATE['DEPTH'] = STATE['CNTX'].imagePlanes
STATE['ASPX'] = float(STATE['CNTX'].sizeX) / float(STATE['CNTX'].sizeY)
STATE['ASPY'] = float(STATE['CNTX'].sizeY) / float(STATE['CNTX'].sizeX)
STATE['PERCENTAGE'] = STATE['CNTX'].renderwinSize / 100.0
STATE['LENS'] = STATE['CAM'].lens
##print 'Originally, lens = ',STATE['LENS']
STATE['SCALE'] = STATE['CAM'].scale
##print 'Originally, scale = ',STATE['SCALE']
STATE['SHIFTX'] = STATE['CAM'].shiftX
STATE['SHIFTY'] = STATE['CAM'].shiftY
##print 'Originally, xShift = ',STATE['SHIFTX'],' and yShift = ',STATE['SHIFTY']
return 1
##except:
##    Draw.PupMenu('Error! The script could not find a camera in your scene.')
##    return 0

SET GLOBAL SCENE SETTINGS FOR RENDERING

def SetSettings(tileNr):
STATE[‘CAM’].scale = (STATE[‘SCALE’] / tileNr)
STATE[‘CAM’].lens = (STATE[‘LENS’] * tileNr)

PUT THE SCENE BACK IN IT’S ORIGINAL STATE

def ResetSettings():
STATE[‘CNTX’].renderPath = STATE[‘PATH’]
STATE[‘CAM’].lens = STATE[‘LENS’]
STATE[‘CAM’].scale = STATE[‘SCALE’]
STATE[‘CAM’].shiftX = STATE[‘SHIFTX’]
STATE[‘CAM’].shiftY = STATE[‘SHIFTY’]
STATE[‘SCN’].update()

RENDER A TILE

def RenderTile(xShift, yShift, fileName):

if STATE['ASPX'] > 1:
    yShift /= STATE['ASPX']
else:
    xShift /= STATE['ASPY']

STATE['CAM'].shiftX = xShift
STATE['CAM'].shiftY = yShift
STATE['SCN'].update()
STATE['CNTX'].renderPath = str(STATE['FILENAME'])
print 'rendering', str(STATE['FILENAME'] + fileName)
STATE['CNTX'].render()
STATE['CNTX'].saveRenderedImage(fileName, 0)

PREPARE EACH TILE FOR RENDER

def MakeTiles(tileSel, composite):

# Find the total nr of tiles to render
tileSquare = STATE['tileNr'][tileSel]
tileStart = STATE['tileMin'][tileSel]

# Now that we have all data, set everything up
SetSettings(tileSquare)
tiles = [];

# Loop through the columns of tiles
for y in range(tileSquare):

    # We need to add back in the original shift on the camera.
    # This has to be scaled by the new camera size and the aspect-ratio
    # adjustment that will happen in RenderTile.
    xShiftScale = yShiftScale = 1
    if STATE['ASPX'] > 1:
        yShiftScale = STATE['ASPX']
    else:
        xShiftScale = STATE['ASPY']
    ##print 'xShiftScale = ',xShiftScale,', yShiftscale = ',yShiftScale
    yShift = ((-tileStart) - float(y) + float(STATE['SHIFTY'])*tileSquare*yShiftScale)

    # Loop through the rows of tiles
    for x in range(tileSquare):
    
        xShift = (float(x) + tileStart + float(STATE['SHIFTX'])*tileSquare*xShiftScale)
        
        # Make the name for the tile
        fileName = '_tile_' + str(str(y) + '_' + str(x)) + STATE['EXTENSION']

        # Render the current tile
        ##print 'xShift = ',xShift,', yShift = ',yShift
        RenderTile(xShift, yShift, fileName)
        
        fileName = STATE['FILENAME']  + fileName
        
        if(composite == 1):
            tiles.append([fileName , x, y])
        
ResetSettings()

if(composite == 1):
    MakeComposite(tileSel, tileSquare, tiles)

MAKE A COMPOSITE OF THE RESULTING TILES

def MakeComposite(tileSel, tileSquare, tiles):

print 'creating composite'

# Get the image sizes
tileX = int(STATE['CNTX'].sizeX * STATE['PERCENTAGE'])
tileY = int(STATE['CNTX'].sizeY * STATE['PERCENTAGE'])

# Find the size of the final composite
sizeX = (tileX * tileSquare)
sizeY = (tileY * tileSquare) 

# Loop through the columns of tiles
for  i, t in enumerate(tiles):

    print t[0]

    tile = Image.open(t[0])

    if not i:
    
        mo = tile.mode
        
        print 'mode = ',mo,sizeX,sizeY
    
        # Hold your breath whilst the PIL library creates an image at the required size and depth
        if mo is 'RGBA':
            im = Image.new(mo, (sizeX, sizeY), (0,0,0,0))
        else:
            im = Image.new(mo, (sizeX, sizeY))


    offX = t[1] * tileX
    offY = t[2] * tileY
    
    ## Paste in the tile at the proper offset
    im.paste(tile, (offX,offY))

fileName = STATE['FILENAME'] + '_composite' + STATE['EXTENSION']
im.save(fileName)
print 'saved composite' + str(STATE['FILENAME'] + '_composite' + STATE['EXTENSION'])

PREPARE THE SCRIPT TO RUN

def PrepScript(fileName):

## Draw popup selector
tileSel = Draw.PupMenu("How much bigger?%t|2X    4 tiles (2x2)|3X    9 tiles (3x3)|4X    16 tiles (4x4)|5X    25 tiles (5x5)|cancel")
if tileSel and tileSel < 5:

    if STATE['PIL']:
        composite = Draw.PupMenu("Create a composite?%t|Yes|No")
    else:
        print 'Unable to import PIL, will render the tiles but can not create a composite image.'
        composite = 2

    if GetSettings(fileName):
    
        Window.WaitCursor(1)
    
        MakeTiles(tileSel, composite)

        Window.RedrawAll()

        Window.WaitCursor(0)

SET WHAT FILE TO RENDER TO BEFORE DOING ANYTHING ELSE

def SetFile(): Window.FileSelector(PrepScript, “Render to”, sys.makename(ext=’’))

START

SetFile()

Hey dude, nice… That’s a useful addition. Though… there’s limits to the shift factor. So if people already have a shift in place, that may limit the nr of tiles you can render. I think it’ll need a bit more math and possibly “warning messages” in case people already have a big shift, for it to work properly.

Doing 25 tiles is definitely only possible if people have no shift at all. And for instance… if someone already has a shift of 2… then it’s at the limit and hence the script is no longer capable of rendering any tiles properly. And if it’s a shift of one… then it can render tiles (9 as maximum I think), but not as many (which limits ultimate render size).

So… a little extra code is needed for it to work properly.

I have to have a look at this script myself sometime because there’s a flaw in the camera selection technique (doesn’t always work properly).

BTW, for sharing code here… maybe it’s a better idea to post it at pasteall.org and post a link to it here.