Notifications
Clear all

[Closed] Save on Render Finish

Hey guys, I’d like to create a script that’ll always run in the background in max so that whenever any render finishes rendering, it’ll save a jpg img of the render to the same file each time. I’d like a sort of “most recent render” image that’s always updated. Problem is I don’t know what the command is, nor how to handle a maxscript detecting a render finish and then saving it. Any ideas? Thanks.

12 Replies

You might want to check out the #postRender calback function. As for the actual saving of the bitmap, there are a number of ways you could handle this.

I assume what you want to do is whenever you render something (animations, stills, whatever) that regardless of where you have saved it you make another copy of that render in another location.

Or do you just want to see what you last rendered?

Yeah, regardless of whether I saved it or not or where i’m saving it I want it to be saved in a certain location as a constant overwrite of the same file.

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

[left]getLastRenderedImage()
[/left]
[left]The getLastRenderedImage() method returns the last image rendered via Render Scene, Render Last, or Quick Render as a bitmap value.


Use the above method in the postRender callback to get the last rendered image as a bitmap value. Then set the file name and call the SAVE method.

For a much more advanced implementation, see RealRenderHistory.
http://www.scriptspot.com/bobo/darkmoon/rrh/

It will save a copy of EVERY image rendered so you can browse through iterations just like in some competing applications

[/left]
[left]

[/left]

Here is the full code:


  callbacks.removeScripts id:#saveLastRendered
  fn saveLastRenderedImage =
  (
  	local theBitmap = getLastRenderedImage()
  	theBitmap.filename = GetDir #image + "/lastRender.tga"
  	save theBitmap
)
  callbacks.addScript #postRender "saveLastRenderedImage()" id:#saveLastRendered

Thanks bobo, that really helps alot. I am, however, having some trouble. I’ve tried to modify it so that it’ll resize the image to 320 x 240 no matter what it initially renders at. Originally I tried using bitmap 320 240, but i realized shortly thereafter that just creates a new bitmap… Could you help me out on this one?

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

There are two ways to resize a bitmap in Max – one is using “Nearest” pixels via the COPY method, just skipping pixels as it goes.
The other one is using the renderMap function which actually calls the renderer to perform nice filtering. The latter might interfere with the callback you are using though!

For the first trick, you simply create a new bitmap and copy the rendered one into it, then save the new one instead of the old one.


theBitmap = bitmap 320 240
copy (getLastRenderedImage()) theBitmap
theBitmap.filename = GetDir #image + “/lastRender.tga”
save theBitmap

Of course, the resulting image will not be resized using bi- or tri-linear filtering and will not look perfect, but if you just need an IDEA what it was, it is probably the fastest way…

Cheers,
Bobo

Ok thanks alot! That worked. Now i’m trying to maintain aspect ratio. I used the basic math below to try an get it (that might be incorrect, but i haven’t gotten it to work yet, so I don’t know if that theory is correct). However, the bitmap command isn’t happy with my trying to use variables to define the width and height rather than simply numbers…

I’m trying to keep the width under or at 320 and adjusting the height accordingly in order to maintain aspect ratio…

 local theBitmap = getLastRenderedImage()
 if (renderwidth > 320) ( 
     local thewidth = ((renderwidth - 320))
     local theheight = ((renderheight - thewidth))
 )
 theBitmap = bitmap thewidth theheight
 copy (getLastRenderedImage()) theBitmap
 theBitmap.filename = GetDir #image + "/lastRender.jpg"
 save theBitmap

Belay that question, I figured it out. Just needed to divide the height by the aspect ratio to get it and then reset it properly. The code below is the final working code. Saves the bitmap and resizes it down so it will fit within an iframe with a width that is at most 320 and the height is changed to maintain the aspect ratio of the initial render. Now I’ll reveal what this is used for other than fun. See my portfolio below (Elysium 3d)! I have an mIRC bot that constantly checks the date of the render and if it changes, it automatically reads the ini file generated and creates an on-the-fly html file linked as an iframe on my main page of my portfolio. That way, people can always see what i’m working on. I figure it might draw bored people to sit there and watch the frame refresh as I work… Thanks alot for all your help guys!

---
callbacks.removeScripts id:#saveLastRendered
fn saveLastRenderedImage =
(
    local theBitmap = getLastRenderedImage()
   if (renderwidth > 320) then ( 
       local theaspect = getRendImageAspect()
       local thewidth = 320
       local theheight = (320/theaspect)
   )
   else (
       thewidth = 320
       the height = 240
   )
   theBitmap = bitmap thewidth theheight
   copy (getLastRenderedImage()) theBitmap
   theBitmap.filename = GetDir #image + "/lastRender.jpg"
   save theBitmap
   close theBitmap
   local theInfo = GetDir #image + "/lastRender.ini"
   setIniSetting theInfo "Info" "SceneName" (getFileNameFile maxFileName)
   setIniSetting theInfo "Info" "Date" localtime
)
callbacks.addScript #postRender "saveLastRenderedImage()" id:#saveLastRendered
print "Last Render Saved"
---

Well, upon expanding this script, i’ve been having some problems. I tried to have it save a version of the latest render of its normal size, then continue on with saving the smaller version. It seems to work every now and then. But only at certain times; like when I reinitialize the script. Here’s the current version of the code:

callbacks.removeScripts id:#saveLastRendered
fn saveLastRenderedImage =
(
local theBitmap = getLastRenderedImage()
theBitmap.filename = GetDir #image + “/lastRender_big.jpg”
save theBitmap
close theBitmap
theBitmap = getLastRenderedImage()
if (renderwidth > 320) then (
local theaspect = getRendImageAspect()
local thewidth = 320
local theheight = (320/theaspect)
)
else (
thewidth = 320
theheight = 240
)
theBitmap = bitmap thewidth theheight
copy (getLastRenderedImage()) theBitmap
theBitmap.filename = GetDir #image + “/lastRender.jpg”
save theBitmap
close theBitmap
local theInfo = GetDir #image + “/lastRender.ini”
setIniSetting theInfo “Info” “SceneName” (getFileNameFile maxFileName)
setIniSetting theInfo “Info” “Date” localtime
)
callbacks.addScript #postRender “saveLastRenderedImage()” id:#saveLastRendered
print “Last Render Saved”

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

I don’t see a problem – it works every time here.
Of course, the PRINT statement will be executed just once when you run the script, because it is in the end of the initializing part and NOT in the function!
So if you were expecting to see the line “Last Render Saved” in the Listener after rendering, you are going to wait for a looong time

Move the print line right after the setIniSetting lines…

Cheers,
Bobo

Indeed, that makes no sense. It appears moving the print code seems to have fixed it… I’m sure thats almost impossible that that is the fix, but oh well, it works now… Cheers.

Alas, it was the age old problem in which I was working on the file that wasn’t the same as the one in my startup folder. It’s fixed now… /smacks forehead. Thanks again.