Esempio 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;
}
/* 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;
}