Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/compositor/operations/COM_OutputFileOperation.cpp')
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
new file mode 100644
index 00000000000..e410dd966c8
--- /dev/null
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor:
+ * Jeroen Bakker
+ * Monique Dewanchand
+ * Lukas Tönne
+ */
+
+#include "COM_OutputFileOperation.h"
+#include "COM_SocketConnection.h"
+#include <string.h>
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "DNA_scene_types.h"
+#include "BKE_image.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+
+extern "C" {
+ #include "MEM_guardedalloc.h"
+ #include "IMB_imbuf.h"
+ #include "IMB_imbuf_types.h"
+}
+
+static int get_datatype_size(DataType datatype)
+{
+ switch (datatype) {
+ case COM_DT_VALUE: return 1;
+ case COM_DT_VECTOR: return 3;
+ case COM_DT_COLOR: return 4;
+ default: return 0;
+ }
+}
+
+static float *init_buffer(unsigned int width, unsigned int height, DataType datatype) {
+ // When initializing the tree during initial load the width and height can be zero.
+ if (width != 0 && height != 0) {
+ int size = get_datatype_size(datatype);
+ return (float *)MEM_callocN(width*height*size*sizeof(float), "OutputFile buffer");
+ }
+ else
+ return NULL;
+}
+
+static void write_buffer_rect(rcti *rect, MemoryBuffer** memoryBuffers, const bNodeTree *tree,
+ SocketReader *reader, float* buffer, unsigned int width, DataType datatype)
+{
+ float color[4];
+ int i, size = get_datatype_size(datatype);
+
+ if (!buffer) return;
+ int x1 = rect->xmin;
+ int y1 = rect->ymin;
+ int x2 = rect->xmax;
+ int y2 = rect->ymax;
+ int offset = (y1*width + x1 ) * size;
+ int x;
+ int y;
+ bool breaked = false;
+
+ for (y = y1 ; y < y2 && (!breaked); y++) {
+ for (x = x1 ; x < x2 && (!breaked) ; x++) {
+ reader->read(color, x, y, COM_PS_NEAREST, memoryBuffers);
+
+ for (i=0; i < size; ++i)
+ buffer[offset+i] = color[i];
+ offset += size;
+
+ if (tree->test_break && tree->test_break(tree->tbh))
+ breaked = true;
+ }
+ offset += (width-(x2-x1)) * size;
+ }
+}
+
+
+OutputSingleLayerOperation::OutputSingleLayerOperation(
+ const Scene *scene, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path)
+{
+ this->scene = scene;
+ this->tree = tree;
+
+ this->addInputSocket(datatype);
+
+ this->outputBuffer = NULL;
+ this->datatype = datatype;
+ this->imageInput = NULL;
+
+ this->format = format;
+ BLI_strncpy(this->path, path, sizeof(this->path));
+}
+
+void OutputSingleLayerOperation::initExecution() {
+ this->imageInput = getInputSocketReader(0);
+ this->outputBuffer = init_buffer(this->getWidth(), this->getHeight(), this->datatype);
+}
+
+void OutputSingleLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer** memoryBuffers) {
+ write_buffer_rect(rect, memoryBuffers, this->tree, imageInput, this->outputBuffer, this->getWidth(), this->datatype);
+}
+
+void OutputSingleLayerOperation::deinitExecution()
+{
+ if (this->getWidth() * this->getHeight() != 0) {
+
+ int size = get_datatype_size(this->datatype);
+ ImBuf *ibuf= IMB_allocImBuf(this->getWidth(), this->getHeight(), size*8, 0);
+ Main *bmain= G.main; /* TODO, have this passed along */
+ char filename[FILE_MAX];
+
+ ibuf->channels = size;
+ ibuf->rect_float= this->outputBuffer;
+ ibuf->mall |= IB_rectfloat;
+ ibuf->dither= scene->r.dither_intensity;
+
+ if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
+ ibuf->profile = IB_PROFILE_LINEAR_RGB;
+
+ BKE_makepicstring(filename, this->path, bmain->name, this->scene->r.cfra, this->format->imtype,
+ (this->scene->r.scemode & R_EXTENSION), true);
+
+ if (0 == BKE_imbuf_write(ibuf, filename, this->format))
+ printf("Cannot save Node File Output to %s\n", filename);
+ else
+ printf("Saved: %s\n", filename);
+
+ IMB_freeImBuf(ibuf);
+ }
+ this->outputBuffer = NULL;
+ this->imageInput = NULL;
+}
+
+
+OutputOpenExrLayer::OutputOpenExrLayer(const char *name, DataType datatype)
+{
+ BLI_strncpy(this->name, name, sizeof(this->name));
+ this->datatype = datatype;
+ /* these are created in initExecution */
+ this->outputBuffer = 0;
+ this->imageInput = 0;
+}
+
+OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(
+ const Scene *scene, const bNodeTree *tree, const char *path, char exr_codec)
+{
+ this->scene = scene;
+ this->tree = tree;
+
+ BLI_strncpy(this->path, path, sizeof(this->path));
+ this->exr_codec = exr_codec;
+}
+
+void OutputOpenExrMultiLayerOperation::add_layer(const char *name, DataType datatype)
+{
+ this->addInputSocket(datatype);
+ layers.push_back(OutputOpenExrLayer(name, datatype));
+}
+
+void OutputOpenExrMultiLayerOperation::initExecution()
+{
+ for (int i=0; i < layers.size(); ++i) {
+ layers[i].imageInput = getInputSocketReader(i);
+ layers[i].outputBuffer = init_buffer(this->getWidth(), this->getHeight(), layers[i].datatype);
+ }
+}
+
+void OutputOpenExrMultiLayerOperation::executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer** memoryBuffers)
+{
+ for (int i=0; i < layers.size(); ++i) {
+ write_buffer_rect(rect, memoryBuffers, this->tree, layers[i].imageInput, layers[i].outputBuffer, this->getWidth(), layers[i].datatype);
+ }
+}
+
+void OutputOpenExrMultiLayerOperation::deinitExecution()
+{
+ unsigned int width = this->getWidth();
+ unsigned int height = this->getHeight();
+ if (width != 0 && height != 0) {
+ Main *bmain= G.main; /* TODO, have this passed along */
+ char filename[FILE_MAX];
+ void *exrhandle= IMB_exr_get_handle();
+
+ BKE_makepicstring(filename, this->path, bmain->name, this->scene->r.cfra, R_IMF_IMTYPE_MULTILAYER,
+ (this->scene->r.scemode & R_EXTENSION), true);
+ BLI_make_existing_file(filename);
+
+ for (int i=0; i < layers.size(); ++i) {
+ char channelname[EXR_TOT_MAXNAME];
+ BLI_strncpy(channelname, layers[i].name, sizeof(channelname)-2);
+ char *channelname_ext = channelname + strlen(channelname);
+
+ float *buf = layers[i].outputBuffer;
+
+ /* create channels */
+ switch (layers[i].datatype) {
+ case COM_DT_VALUE:
+ strcpy(channelname_ext, ".V");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 1, width, buf);
+ break;
+ case COM_DT_VECTOR:
+ strcpy(channelname_ext, ".X");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3*width, buf);
+ strcpy(channelname_ext, ".Y");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3*width, buf+1);
+ strcpy(channelname_ext, ".Z");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 3, 3*width, buf+2);
+ break;
+ case COM_DT_COLOR:
+ strcpy(channelname_ext, ".R");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4*width, buf);
+ strcpy(channelname_ext, ".G");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4*width, buf+1);
+ strcpy(channelname_ext, ".B");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4*width, buf+2);
+ strcpy(channelname_ext, ".A");
+ IMB_exr_add_channel(exrhandle, 0, channelname, 4, 4*width, buf+3);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ /* when the filename has no permissions, this can fail */
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->exr_codec)) {
+ IMB_exr_write_channels(exrhandle);
+ }
+ else {
+ /* TODO, get the error from openexr's exception */
+ /* XXX nice way to do report? */
+ printf("Error Writing Render Result, see console\n");
+ }
+
+ IMB_exr_close(exrhandle);
+ for (int i=0; i < layers.size(); ++i) {
+ if (layers[i].outputBuffer) {
+ MEM_freeN(layers[i].outputBuffer);
+ layers[i].outputBuffer = NULL;
+ }
+
+ layers[i].imageInput = NULL;
+ }
+ }
+}