Ejemplo n.º 1
0
/* called from within UI, saves both rendered result as a file-read result */
int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
{
	RenderLayer *rl;
	RenderPass *rpass;
	void *exrhandle = IMB_exr_get_handle();
	int success;

	BLI_make_existing_file(filename);
	
	/* composite result */
	if (rr->rectf) {
		IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf);
		IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1);
		IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2);
		IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3);
	}
	
	/* add layers/passes and assign channels */
	for (rl = rr->layers.first; rl; rl = rl->next) {
		
		/* combined */
		if (rl->rectf) {
			int a, xstride = 4;
			for (a = 0; a < xstride; a++) {
				IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a),
				                    xstride, xstride * rr->rectx, rl->rectf + a);
			}
		}
		
		/* passes are allocated in sync */
		for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
			int a, xstride = rpass->channels;
			for (a = 0; a < xstride; a++) {
				if (rpass->passtype) {
					IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a),
					                    xstride, xstride * rr->rectx, rpass->rect + a);
				}
				else {
					IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a),
					                    xstride, xstride * rr->rectx, rpass->rect + a);
				}
			}
		}
	}

	/* when the filename has no permissions, this can fail */
	if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
		IMB_exr_write_channels(exrhandle);
		success = TRUE;
	}
	else {
		/* TODO, get the error from openexr's exception */
		BKE_report(reports, RPT_ERROR, "Error writing render result (see console)");
		success = FALSE;
	}
	IMB_exr_close(exrhandle);

	return success;
}
void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename)
{
	unsigned int width = this->getWidth();
	unsigned int height = this->getHeight();

	if (width != 0 && height != 0) {

		void *exrhandle;
		SceneRenderView *srv;

		/* get a new global handle */
		exrhandle = IMB_exr_get_handle_name(filename);

		if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
			return exrhandle;

		IMB_exr_clear_channels(exrhandle);

		/* check renderdata for amount of views */
		for (srv = (SceneRenderView *) this->m_rd->views.first; srv; srv = srv->next) {

			if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
				continue;

			IMB_exr_add_view(exrhandle, srv->name);

			for (unsigned int i = 0; i < this->m_layers.size(); ++i)
				add_exr_channels(exrhandle, this->m_layers[i].name, this->m_layers[i].datatype, srv->name, width, NULL);
		}

		BLI_make_existing_file(filename);

		/* prepare the file with all the channels for the header */
		if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec) == 0) {
			printf("Error Writing Multilayer Multiview Openexr\n");
			IMB_exr_close(exrhandle);
		}
		else {
			IMB_exr_clear_channels(exrhandle);
			return exrhandle;
		}
	}
	return NULL;
}
void *OutputOpenExrSingleLayerMultiViewOperation::get_handle(const char *filename)
{
	size_t width = this->getWidth();
	size_t height = this->getHeight();
	SceneRenderView *srv;

	if (width != 0 && height != 0) {
		void *exrhandle;

		exrhandle = IMB_exr_get_handle_name(filename);

		if (!BKE_scene_multiview_is_render_view_first(this->m_rd, this->m_viewName))
			return exrhandle;

		IMB_exr_clear_channels(exrhandle);

		for (srv = (SceneRenderView *)this->m_rd->views.first; srv; srv = srv->next) {
			if (BKE_scene_multiview_is_render_view_active(this->m_rd, srv) == false)
				continue;

			IMB_exr_add_view(exrhandle, srv->name);
			add_exr_channels(exrhandle, NULL, this->m_datatype, srv->name, width, NULL);
		}

		BLI_make_existing_file(filename);

		/* prepare the file with all the channels */

		if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_format->exr_codec) == 0) {
			printf("Error Writing Singlelayer Multiview Openexr\n");
			IMB_exr_close(exrhandle);
		}
		else {
			IMB_exr_clear_channels(exrhandle);
			return exrhandle;
		}
	}
	return NULL;
}
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_from_type(filename, this->m_path, bmain->name, this->m_rd->cfra, R_IMF_IMTYPE_MULTILAYER,
		                  (this->m_rd->scemode & R_EXTENSION), true);
		BLI_make_existing_file(filename);
		
		for (unsigned int i = 0; i < this->m_layers.size(); ++i) {
			OutputOpenExrLayer &layer = this->m_layers[i];
			if (!layer.imageInput)
				continue; /* skip unconnected sockets */
			
			char channelname[EXR_TOT_MAXNAME];
			BLI_strncpy(channelname, this->m_layers[i].name, sizeof(channelname) - 2);
			char *channelname_ext = channelname + strlen(channelname);
			
			float *buf = this->m_layers[i].outputBuffer;
			
			/* create channels */
			switch (this->m_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->m_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 (unsigned int i = 0; i < this->m_layers.size(); ++i) {
			if (this->m_layers[i].outputBuffer) {
				MEM_freeN(this->m_layers[i].outputBuffer);
				this->m_layers[i].outputBuffer = NULL;
			}
			
			this->m_layers[i].imageInput = NULL;
		}
	}
}
Ejemplo n.º 5
0
/* called from within UI and render pipeline, saves both rendered result as a file-read result
 * if multiview is true saves all views in a multiview exr
 * else if view is not NULL saves single view
 * else saves stereo3d
 */
bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const bool multiview, const char *view)
{
	RenderLayer *rl;
	RenderPass *rpass;
	RenderView *rview;
	void *exrhandle = IMB_exr_get_handle();
	bool success;
	int a, nr;
	const char *chan_view = NULL;
	int compress = (imf ? imf->exr_codec : 0);
	size_t width, height;

	const bool is_mono = view && !multiview;
	const bool use_half_float = (imf != NULL) ? (imf->depth == R_IMF_CHAN_DEPTH_16) : false;

	width = rr->rectx;
	height = rr->recty;

	if (imf && imf->imtype == R_IMF_IMTYPE_OPENEXR && multiview) {
		/* single layer OpenEXR */
		const char *RGBAZ[] = {"R", "G", "B", "A", "Z"};
		for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
			IMB_exr_add_view(exrhandle, rview->name);

			if (rview->rectf) {
				for (a = 0; a < 4; a++) {
					IMB_exr_add_channel(exrhandle, "", RGBAZ[a],
					                    rview->name, 4, 4 * width, rview->rectf + a,
					                    use_half_float);
				}
				if (rview->rectz) {
					/* Z pass is always stored as float. */
					IMB_exr_add_channel(exrhandle, "", RGBAZ[4],
					                    rview->name, 1, width, rview->rectz,
					                    false);
				}
			}
		}
	}
	else {
		for (nr = 0, rview = rr->views.first; rview; rview = rview->next, nr++) {
			if (is_mono) {
				if (!STREQ(view, rview->name)) {
					continue;
				}
				chan_view = "";
			}
			else {
				/* if rendered only one view, we treat as a a non-view render */
				chan_view = rview->name;
			}

			IMB_exr_add_view(exrhandle, rview->name);

			if (rview->rectf) {
				for (a = 0; a < 4; a++) {
					IMB_exr_add_channel(exrhandle, "Composite", name_from_passtype(SCE_PASS_COMBINED, a),
					                    chan_view, 4, 4 * width, rview->rectf + a,
					                    use_half_float);
				}
			}
		}

		/* add layers/passes and assign channels */
		for (rl = rr->layers.first; rl; rl = rl->next) {

			/* passes are allocated in sync */
			for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
				const int xstride = rpass->channels;

				if (is_mono) {
					if (!STREQ(view, rpass->view)) {
						continue;
					}
					chan_view = "";
				}
				else {
					/* if rendered only one view, we treat as a a non-view render */
					chan_view = (nr > 1 ? rpass->view :"");
				}

				for (a = 0; a < xstride; a++) {
					if (rpass->passtype) {
						IMB_exr_add_channel(exrhandle, rl->name, name_from_passtype(rpass->passtype, a), chan_view,
						                    xstride, xstride * width, rpass->rect + a,
						                    rpass->passtype == SCE_PASS_Z ? false : use_half_float);
					}
					else {
						IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), chan_view,
						                    xstride, xstride * width, rpass->rect + a,
						                    use_half_float);
					}
				}
			}
		}
	}

	BLI_make_existing_file(filename);

	if (IMB_exr_begin_write(exrhandle, filename, width, height, compress, rr->stamp_data)) {
		IMB_exr_write_channels(exrhandle);
		success = true;
	}
	else {
		/* TODO, get the error from openexr's exception */
		BKE_report(reports, RPT_ERROR, "Error writing render result (see console)");
		success = false;
	}

	IMB_exr_close(exrhandle);
	return success;
}
/* write input data into layers */
static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in)
{
	Main *bmain= G.main; /* TODO, have this passed along */
	NodeImageMultiFile *nimf= node->storage;
	void *exrhandle= IMB_exr_get_handle();
	char filename[FILE_MAX];
	bNodeSocket *sock;
	int i;
	/* Must have consistent pixel size for exr file, simply take the first valid input size. */
	int rectx = -1;
	int recty = -1;
	int has_preview = 0;
	
	BKE_makepicstring(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE);
	BLI_make_existing_file(filename);
	
	for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) {
		if (in[i]->data) {
			NodeImageMultiFileSocket *sockdata = sock->storage;
			CompBuf *cbuf = in[i]->data;
			char channelname[EXR_TOT_MAXNAME];	/* '.' and single character channel name is appended */
			char *channelname_ext;
			
			if (cbuf->rect_procedural) {
				printf("Error writing multilayer EXR: Procedural buffer not supported\n");
				continue;
			}
			if (rectx < 0) {
				rectx = cbuf->x;
				recty = cbuf->y;
			}
			else if (cbuf->x != rectx || cbuf->y != recty) {
				printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name);
				continue;
			}
			
			BLI_strncpy(channelname, sockdata->layer, sizeof(channelname)-2);
			channelname_ext = channelname + strlen(channelname);
			
			/* create channels */
			switch (cbuf->type) {
			case CB_VAL:
				strcpy(channelname_ext, ".V");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 1, rectx, cbuf->rect);
				break;
			case CB_VEC2:
				strcpy(channelname_ext, ".X");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect);
				strcpy(channelname_ext, ".Y");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect+1);
				break;
			case CB_VEC3:
				strcpy(channelname_ext, ".X");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect);
				strcpy(channelname_ext, ".Y");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+1);
				strcpy(channelname_ext, ".Z");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+2);
				break;
			case CB_RGBA:
				strcpy(channelname_ext, ".R");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect);
				strcpy(channelname_ext, ".G");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+1);
				strcpy(channelname_ext, ".B");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+2);
				strcpy(channelname_ext, ".A");
				IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+3);
				break;
			}
			
			/* simply pick the first valid input for preview */
			if (!has_preview) {
				generate_preview(rd, node, cbuf);
				has_preview = 1;
			}
		}
	}
	
	/* when the filename has no permissions, this can fail */
	if (IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.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);
}