netrender

jpeg versions of the render results are downloadable from the web interface. 

Notes:

1) They are generated (and written to disk) on demand on the master in the same Blender instance, so this will increase memory usage (until there's a way to free and image buffer from memory or it's run in a separate process).
2) They are darker then the real results, since multilayer exr contain the result before gamma correction (for the linear workflow) and that's not applied when loading them as an image.
3) They are NOT thumbnails, they are the same size as the results (albeit at 90% quality jpeg compression)
This commit is contained in:
Martin Poirier 2010-01-07 18:54:47 +00:00
parent 6426a43c3c
commit cfaa1e5db1
4 changed files with 36 additions and 9 deletions

@ -161,7 +161,7 @@ class MinimumTimeBetweenDispatchPriority(PriorityRule):
class ExcludeQueuedEmptyJob(ExclusionRule):
def __str__(self):
return "Exclude non queued and empty jobs"
return "Exclude non queued or empty jobs"
def test(self, job):
return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0

@ -174,7 +174,7 @@ class MRenderFrame(netrender.model.RenderFrame):
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
file_pattern = re.compile("/file_([a-zA-Z0-9]+)_([0-9]+)")
render_pattern = re.compile("/render_([a-zA-Z0-9]+)_([0-9]+).exr")
render_pattern = re.compile("/render_([a-zA-Z0-9]+)_([0-9]+).(exr|jpg)")
log_pattern = re.compile("/log_([a-zA-Z0-9]+)_([0-9]+).log")
reset_pattern = re.compile("/reset(all|)_([a-zA-Z0-9]+)_([0-9]+)")
cancel_pattern = re.compile("/cancel_([a-zA-Z0-9]+)")
@ -230,6 +230,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
if match:
job_id = match.groups()[0]
frame_number = int(match.groups()[1])
exr = match.groups()[2] == "exr"
job = self.server.getJobID(job_id)
@ -241,9 +243,25 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.send_head(http.client.ACCEPTED)
elif frame.status == DONE:
self.server.stats("", "Sending result to client")
f = open(job.save_path + "%04d" % frame_number + ".exr", 'rb')
if exr:
f = open(job.save_path + "%04d" % frame_number + ".exr", 'rb')
self.send_head(content = "image/x-exr")
else:
filename = job.save_path + "%04d" % frame_number + ".jpg"
if not os.path.exists(filename):
import bpy
sce = bpy.data.scenes[0]
sce.render_data.file_format = "JPEG"
sce.render_data.quality = 90
bpy.ops.image.open(path = job.save_path + "%04d" % frame_number + ".exr")
img = bpy.data.images["%04d" % frame_number + ".exr"]
img.save(filename)
f = open(filename, 'rb')
self.send_head(content = "image/jpeg")
self.send_head()
shutil.copyfileobj(f, self.wfile)

@ -166,7 +166,7 @@ def get(handler):
"done",
"dispatched",
"error",
"first",
"priority",
"exception"
)
@ -195,7 +195,8 @@ def get(handler):
results[DISPATCHED],
str(results[ERROR]) +
"""<button title="reset error frames" onclick="request('/reset_%s_0', null);" %s>R</button>""" % (job.id, "disabled=True" if not results[ERROR] else ""),
handler.server.balancer.applyPriorities(job), handler.server.balancer.applyExceptions(job)
"yes" if handler.server.balancer.applyPriorities(job) else "no",
"yes" if handler.server.balancer.applyExceptions(job) else "no"
)
endTable()
@ -261,7 +262,15 @@ def get(handler):
headerTable("no", "status", "render time", "slave", "log", "result")
for frame in job.frames:
rowTable(frame.number, frame.statusText(), "%.1fs" % frame.time, frame.slave.name if frame.slave else "&nbsp;", link("view log", logURL(job_id, frame.number)) if frame.log_path else "&nbsp;", link("view result", renderURL(job_id, frame.number)) if frame.status == DONE else "&nbsp;")
rowTable(
frame.number,
frame.statusText(),
"%.1fs" % frame.time,
frame.slave.name if frame.slave else "&nbsp;",
link("view log", logURL(job_id, frame.number)) if frame.log_path else "&nbsp;",
link("view result", renderURL(job_id, frame.number)) + " [" +
link("jpeg", renderURL(job_id, frame.number, exr = False)) + "]" if frame.status == DONE else "&nbsp;"
)
endTable()
else:

@ -148,8 +148,8 @@ def fileURL(job_id, file_index):
def logURL(job_id, frame_number):
return "/log_%s_%i.log" % (job_id, frame_number)
def renderURL(job_id, frame_number):
return "/render_%s_%i.exr" % (job_id, frame_number)
def renderURL(job_id, frame_number, exr = True):
return "/render_%s_%i.%s" % (job_id, frame_number, "exr" if exr else "jpg")
def cancelURL(job_id):
return "/cancel_%s" % (job_id)