Cycles: add cycles.merge_images operator for combing EXR renders.

This is only available through the API, mainly intended for render farms to
combine rendered multilayer EXR Files with different samples. The images are
currently expected to have the exact same render layers and passes, just with
different samples.

Variance passes are still simply a weighted average, ideally these should be
merged more intelligently.

Differential Revision: https://developer.blender.org/D4554
This commit is contained in:
Brecht Van Lommel
2019-03-19 14:38:57 +01:00
parent 5b7b7101c8
commit 83de13f75a
6 changed files with 582 additions and 6 deletions

View File

@@ -23,6 +23,7 @@
#include "blender/blender_session.h"
#include "render/denoising.h"
#include "render/merge.h"
#include "util/util_debug.h"
#include "util/util_foreach.h"
@@ -638,9 +639,8 @@ static PyObject *opencl_compile_func(PyObject * /*self*/, PyObject *args)
}
#endif
static bool denoise_parse_filepaths(PyObject *pyfilepaths, vector<string>& filepaths)
static bool image_parse_filepaths(PyObject *pyfilepaths, vector<string>& filepaths)
{
if(PyUnicode_Check(pyfilepaths)) {
const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
filepaths.push_back(filepath);
@@ -709,12 +709,12 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
/* Parse file paths list. */
vector<string> input, output;
if(!denoise_parse_filepaths(pyinput, input)) {
if(!image_parse_filepaths(pyinput, input)) {
return NULL;
}
if(pyoutput) {
if(!denoise_parse_filepaths(pyoutput, output)) {
if(!image_parse_filepaths(pyoutput, output)) {
return NULL;
}
}
@@ -753,6 +753,42 @@ static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *key
Py_RETURN_NONE;
}
static PyObject *merge_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
{
static const char *keyword_list[] = {"input", "output", NULL};
PyObject *pyinput, *pyoutput = NULL;
if (!PyArg_ParseTupleAndKeywords(args, keywords, "OO", (char**)keyword_list, &pyinput, &pyoutput)) {
return NULL;
}
/* Parse input list. */
vector<string> input;
if(!image_parse_filepaths(pyinput, input)) {
return NULL;
}
/* Parse output string. */
if(!PyUnicode_Check(pyoutput)) {
PyErr_SetString(PyExc_ValueError, "Output must be a string.");
return NULL;
}
string output = PyUnicode_AsUTF8(pyoutput);
/* Merge. */
ImageMerger merger;
merger.input = input;
merger.output = output;
if(!merger.run()) {
PyErr_SetString(PyExc_ValueError, merger.error.c_str());
return NULL;
}
Py_RETURN_NONE;
}
static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
{
PyObject *pyscene;
@@ -916,6 +952,7 @@ static PyMethodDef methods[] = {
/* Standalone denoising */
{"denoise", (PyCFunction)denoise_func, METH_VARARGS|METH_KEYWORDS, ""},
{"merge", (PyCFunction)merge_func, METH_VARARGS|METH_KEYWORDS, ""},
/* Debugging routines */
{"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},