#!BPY """ Registration info for Blender menus: Name: 'Post DOF...' Blender: 236 Group: 'Animation' Tip: 'Creates DOF postprocessing the render of the current scene.' """ __author__ = "Arben (Ben) Omari" __url__ = ("blender", "elysiun", "Author's site, http://www.omariben.too.it") __version__ = "0.4" __bpydoc__ = """\ What this does? -This script postprocess the rendered image of the current scene and blurs corresponding of the depth.Th focus is determined by the selected object. Requires PIL (Python Image Library) Notes:
Check author's site or the elYsiun forum for a new beta version of the script. """ # PostDOF.py version 0.4 # Copyright (C) 2005 Arben OMARI -- omariarben@everyday.com # # 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. # Grab the latest version here :www.omariben.too.it import Blender from Blender import Object, Draw, BGL from Blender.Mathutils import * from Blender.BGL import* import PIL.Image as Image import PIL.ImageDraw as ImageDraw import PIL.ImageFilter as Filter import math ##### User Settings ############################### w = 640 name_file = "" ext = ".JPG" ################################################## EVENT_Button = 10 EVENT_Button_0 = 11 EVENT_Menu = 12 EVENT_Number = 13 EVENT_String = 14 EVENT_Button_1 = 15 EVENT_Toggle = 9 Object_Button = Draw.Create(0) Object_Button_0 = Draw.Create(0) Object_Menu = Draw.Create(1) Object_Number = Draw.Create(5) Object_String = Draw.Create("") Object_Button_1 = Draw.Create(0) Object_Toggle = Draw.Create(1) Object_Text = Draw.Create("") Object_Text_0 = Draw.Create("") Object_Text_1 = Draw.Create("") Object_Text_2 = Draw.Create("") Object_Text_3 = Draw.Create("") Object_Text_4 = Draw.Create("") Object_Text_5 = Draw.Create("") Object_Text_6 = Draw.Create("") Object_Text_7 = Draw.Create("") Object_Text_8 = Draw.Create("") def draw(): global EVENT_Button global EVENT_Button_0 global EVENT_Menu global EVENT_Number global EVENT_String global EVENT_Button_1 global EVENT_Toggle global Object_Button global Object_Button_0 global Object_Menu global Object_Number global Object_String global Object_Button_1 global Object_Toggle BGL.glClearColor(.600000, .6300000, .600000, 0.0) BGL.glClear(GL_COLOR_BUFFER_BIT) BGL.glColor3f(0.000000, 0.000000, 0.000000) Object_Button = Draw.Button("DOF", EVENT_Button, 24, 56, 91, 40, "Run the script") Object_Button_0 = Draw.Button("EXIT", EVENT_Button_0, 184, 56, 90, 40, "EXIT") Object_Menu = Draw.Menu("Save AS%t|JPG%x1|BMP%x2|PNG%x3|TIFF%x4", EVENT_Menu, 24, 128, 60, 20, Object_Menu.val, "the format of the saved file") Object_Number = Draw.Number("", EVENT_Number, 24, 168, 60, 20, Object_Number.val, 0, 100, "Max value of blur (in pixels)") Object_String = Draw.String("", EVENT_String, 24, 208, 200, 20,Object_String.val, 1024, "the path of the rendered file (with Blender)") Object_Button_1 = Draw.Button("Open", EVENT_Button_1, 224, 208, 60, 20, "Select file") Object_Toggle = Draw.Toggle("Save B\\W", EVENT_Toggle, 200, 128, 60, 20, Object_Toggle.val, "") BGL.glColor3f(0.1, 0.1, 1.0) BGL.glRasterPos2i(32, 300) Object_Text = Draw.Text("DOF Script 0.1 by Ben Omari (omariarben@everyday.com)") BGL.glRasterPos2i(32, 292) Object_Text_0 = Draw.Text("-------------------------------") BGL.glColor3f(1.0, 0.0, 0.0) BGL.glRasterPos2i(10, 275) BGL.glColor3f(1.0, 1.0, 1.0) Object_Text_9 = Draw.Text("WARNING!!!! THIS SCRIPT WORKS ONLY WITH TEXT WINDOW IN FULLSCREEN(Ctrl+DownArrow)") BGL.glRasterPos2i(24, 256) Object_Text_1 = Draw.Text("1-Render the scene with Blender and save the image.") BGL.glRasterPos2i(24, 232) Object_Text_2 = Draw.Text("2-Select the rendered image file(below)") BGL.glRasterPos2i(24, 192) Object_Text_3 = Draw.Text("3-Select a value for the max. blur in pixels(maximum depth)") BGL.glRasterPos2i(24, 152) Object_Text_4 = Draw.Text("4-Select an image format for the blurred file") BGL.glRasterPos2i(24, 117) Object_Text_5 = Draw.Text("5-Select an object(which will be in the focus) and click on 'DOF' button") BGL.glRasterPos2i(24, 102) Object_Text_9 = Draw.Text("and wait.It may need some minutes.(especially for large images)") BGL.glRasterPos2i(24, 40) Object_Text_6 = Draw.Text("6-In the path of the .blend file will be created a new image file with DOF") BGL.glRasterPos2i(32, 24) Object_Text_7 = Draw.Text("(yourfilenameDOF) and black and white version (if Save B\\W is selected)") BGL.glRasterPos2i(32, 8) Object_Text_8 = Draw.Text("of the z-depth ") def event(event, value): if event == Draw.ESCKEY and not value: Draw.Exit() def b_event(event): global EVENT_Button global EVENT_Button_0 global EVENT_Menu global EVENT_Number global EVENT_String global EVENT_Button_1 global EVENT_Toggle global Object_Button global Object_Button_0 global Object_Menu global Object_Number global Object_String global Object_Button_1 global Object_Toggle if event == 0: pass elif event == EVENT_Button: BGL.glRasterPos2i(32, 350) Object_Text_11 = Draw.Text("Wait please!!It may need a few minutes..........!!!! ") Draw.Redraw(1) prepareScene() elif event == EVENT_Button_0: Draw.Exit() elif event == EVENT_Menu: if Object_Menu.val == 1: ext = ".JPG" elif Object_Menu.val == 2: ext = ".BMP" elif Object_Menu.val == 3: ext = ".PNG" elif Object_Menu.val == 4: ext = ".TIFF" elif event == EVENT_Button_1: filename =Blender.Window.FileSelector(my_callback, "Select Image") Draw.Draw() Draw.Register(draw, event, b_event) ######################################################################### def render(): global out_img colBuff = BGL.Buffer(GL_FLOAT, (h,w,3)) glClearColor( 1, 1, 1, 1 ) glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) glEnable(GL_DEPTH_TEST) glMatrixMode( GL_PROJECTION ) glLoadIdentity() glViewport(0,30,w,h) gluPerspective(fov, pr, z_near, z_far) glMatrixMode( GL_MODELVIEW ) glLoadIdentity() glShadeModel( GL_SMOOTH) for obj in Blender.Object.Get(): mesh = obj.getData() if type(mesh) == Blender.Types.NMeshType : for face in mesh.faces: glBegin(GL_POLYGON) for n in range(len(face.v)): vec = Vector([face.v[n].co[0], face.v[n].co[1], face.v[n].co[2], 1]) w_vec = VecMultMat(vec, obj.getMatrix()) wld_vec = VecMultMat(w_vec, matx) col = Zcolor(wld_vec[2]) glColor3f(col,col,col) glVertex3f(wld_vec[0],wld_vec[1],wld_vec[2]) glEnd() X = 0 Y = 30 buff_img = Image.new("RGB",(w,h),(255,255,255)) drw = ImageDraw.Draw(buff_img) glReadPixels(X, Y, w, h, GL_RGB, GL_FLOAT,colBuff ) for y in range (0,h): for x in range(0,w): col = colBuff[y][x] r = int(col[0]*255) g = int(col[1]*255) b = int(col[2]*255) drw.point((x,y),(r,g,b)) out = buff_img.rotate(180) out_1 = out.transpose(Image.FLIP_LEFT_RIGHT) out_3 = out_1.resize((width,height)) if Object_Toggle.val == 1: bw_file = Blender.sys.join(path, "bw.jpg") out_3.save(bw_file) return out_3 def Zcolor(z_r): dist_n = z_focus - z_near dist_f = z_far - z_focus f_r = z_focus - math.fabs(z_r) if f_r < 0: fac = math.fabs(f_r / dist_n) elif f_r > 0: fac = math.fabs(f_r / dist_n) else : fac = 1 return fac def Blur(img, buff_img): source = img.split() sou_buff = buff_img.split() size = img.size width = size[0] height = size[1] for y in range(0,height-1): for x in range(0,width-1): pix = sou_buff[0].getpixel((x,y)) bl = int((float(pix) / 255.0)*Object_Number.val) lim = (Object_Number.val * 2) + 1 pix_r = 0 pix_g = 0 pix_b = 0 sum = 0 for i in range(-bl, bl+1): x2 = x + i if x2 >= 0 and x2 < width: pix = sou_buff[0].getpixel((x2,y)) if pix < lim+10: pix_r += source[0].getpixel((x,y)) pix_g += source[1].getpixel((x,y)) pix_b += source[2].getpixel((x,y)) sum += 1 else: pix_r += source[0].getpixel((x2,y)) pix_g += source[1].getpixel((x2,y)) pix_b += source[2].getpixel((x2,y)) sum += 1 pix_finalR = pix_r / sum pix_finalG = pix_g / sum pix_finalB = pix_b / sum source[0].putpixel((x,y), pix_finalR) source[1].putpixel((x,y), pix_finalG) source[2].putpixel((x,y), pix_finalB) img_ne = Image.merge(img.mode, source) sourc = img_ne.split() for x in range(0,width-1): for y in range(0,height-1): piy = sou_buff[0].getpixel((x,y)) bl = int((float(piy) / 255.0)*Object_Number.val) piy_r = 0 piy_g = 0 piy_b = 0 sum_y = 0 for j in range(-bl, bl+1): y2 = y + j if y2 >= 0 and y2 < height: piy = sou_buff[0].getpixel((x,y2)) if piy < lim+10: piy_r += sourc[0].getpixel((x,y)) piy_g += sourc[1].getpixel((x,y)) piy_b += sourc[2].getpixel((x,y)) sum_y += 1 else: piy_r += sourc[0].getpixel((x,y2)) piy_g += sourc[1].getpixel((x,y2)) piy_b += sourc[2].getpixel((x,y2)) sum_y += 1 piy_finalR = piy_r / sum_y piy_finalG = piy_g / sum_y piy_finalB = piy_b / sum_y sourc[0].putpixel((x,y), piy_finalR) sourc[1].putpixel((x,y), piy_finalG) sourc[2].putpixel((x,y), piy_finalB) img_new = Image.merge(img_ne.mode, sourc) return img_new def my_callback(filename): global name_file,fileout,path path = Blender.sys.dirname(filename) base = Blender.sys.basename(filename) path_base = Blender.sys.join(path,base) Object_String.val = path_base f = Blender.sys.splitext(base) fi = f[0] + "DOF" + ext fileout = Blender.sys.join(path, fi) name_file = filename def prepareScene(): global matx,obj,width,height,fov,z_near,z_far,z_focus,pr,h img = Image.open(name_file) obj = Blender.Object.GetSelected()[0] loc = obj.getLocation() scene = Blender.Scene.GetCurrent() context = scene.getRenderingContext() width = context.imageSizeX() height = context.imageSizeY() h = int((float(height) / float(width))*w) camera = scene.getCurrentCamera() cam_name = camera.name cam = camera.getData() z_near = cam.getClipStart() z_far = cam.getClipEnd() lens = cam.getLens() factor = lens / 32.0 pr = float(width) / float(height) fovx = math.atan(.5/factor) fovy = math.atan(.5/pr/factor) fov = fovy * 360 /math.pi matx = camera.getInverseMatrix() l = Vector([loc[0], loc[1], loc[2], 1]) focus = VecMultMat(l,matx) z_focus = math.fabs(focus[2]) out_img = render() img_new = Blur(img, out_img) ##### time ellapsed ################# new_time = Blender.sys.time()-old_time min = str(int(new_time/60)) min = min.zfill(2) sec = str(int(math.fmod(new_time,60))) sec = sec.zfill(2) print " filtered in 00 :",min,".",sec ###################################### img_new.save(fileout) Draw.Exit() ###### MAIN ######################## old_time = Blender.sys.time() print "...finished"