[Bf-blender-cvs] [fd5ee4d] multiview: Support for saving singlelayer multiview openexr from Image Editor
Dalai Felinto
noreply at git.blender.org
Wed Sep 17 14:12:38 CEST 2014
Commit: fd5ee4dd18891d39375722bafce43d7a8874e699
Author: Dalai Felinto
Date: Tue Sep 16 17:44:37 2014 +0200
Branches: multiview
https://developer.blender.org/rBfd5ee4dd18891d39375722bafce43d7a8874e699
Support for saving singlelayer multiview openexr from Image Editor
Note, this approach could be generalized to any multiview format, but at
the moment only OpenExr supports that.
===================================================================
M source/blender/blenkernel/BKE_image.h
M source/blender/blenkernel/intern/image.c
M source/blender/editors/space_image/image_ops.c
M source/blender/imbuf/IMB_imbuf_types.h
M source/blender/imbuf/intern/openexr/openexr_api.cpp
M source/blender/imbuf/intern/openexr/openexr_multi.h
M source/blender/imbuf/intern/openexr/openexr_stub.cpp
===================================================================
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 629cd4d..4575a1f 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -216,7 +216,10 @@ bool BKE_image_is_openexr(struct Image *ima);
/* for multiple slot render, call this before render */
void BKE_image_backup_render(struct Scene *scene, struct Image *ima);
-
+
+/* for singlelayer openexr saving */
+bool BKE_image_save_openexr_multiview(struct Image *ima, struct ImBuf *ibuf, const char *filepath, const int flags);
+
/* goes over all textures that use images */
void BKE_image_free_all_textures(void);
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 5ca7b1d..938e316 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -100,6 +100,7 @@ static SpinLock image_spin;
/* prototypes */
static size_t image_num_files(struct Image *ima);
+static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r);
/* max int, to indicate we don't store sequences in ibuf */
#define IMA_NO_INDEX 0x7FEFEFEF
@@ -2683,7 +2684,17 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
{
if (iuser) {
bool is_stereo = (ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO);
- iuser->multi_index = is_stereo ? iuser->eye : iuser->view;
+ if (is_stereo) {
+ iuser->multi_index = iuser->eye;
+ }
+ else {
+ if ((iuser->view < 0) || (iuser->view >= BLI_countlist(&ima->views))) {
+ iuser->multi_index = iuser->view = 0;
+ }
+ else {
+ iuser->multi_index = iuser->view;
+ }
+ }
}
}
@@ -2786,6 +2797,43 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
ima->last_render_slot = slot;
}
+/**************************** multiview save openexr *********************************/
+static const char *image_get_view_cb(void *base, const size_t view_id)
+{
+ Image *ima = base;
+ ImageView *iv = BLI_findlink(&ima->views, view_id);
+ return iv ? iv->name : "";
+}
+
+static ImBuf *image_get_buffer_cb(void *base, const size_t view_id)
+{
+ Image *ima = base;
+ ImageUser iuser = {0};
+
+ iuser.view = view_id;
+ iuser.ok = 1;
+
+ BKE_image_multiview_index(ima, &iuser);
+
+ return image_acquire_ibuf(ima, &iuser, NULL);
+}
+
+bool BKE_image_save_openexr_multiview(Image *ima, ImBuf *ibuf, const char *filepath, const int flags)
+{
+ char name[FILE_MAX];
+ bool ok;
+
+ BLI_strncpy(name, filepath, sizeof(name));
+ BLI_path_abs(name, G.main->name);
+
+ ibuf->userdata = ima;
+ ok = IMB_exr_save_openexr_multiview(ibuf, name, flags, BLI_countlist(&ima->views), image_get_view_cb, image_get_buffer_cb);
+ ibuf->userdata = NULL;
+
+ return ok;
+}
+
+/**************************** multiview load openexr *********************************/
static void image_add_view_cb(void *base, const char *str)
{
Image *ima = base;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 159ab47..c6ec9f5 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -73,6 +73,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_moviecache.h"
+#include "intern/openexr/openexr_multi.h"
#include "RE_pipeline.h"
@@ -1776,6 +1777,12 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
ED_space_image_release_buffer(sima, ibuf, lock);
}
}
+ else if ((imf->imtype == R_IMF_IMTYPE_OPENEXR) && (simopts->im_format.views_format == R_IMF_VIEWS_MULTIVIEW)) {
+ /* treat special Openexr case separetely (this is the singlelayer multiview OpenEXR */
+ BKE_imbuf_prepare_write(ibuf, imf);
+ ok = BKE_image_save_openexr_multiview(ima, ibuf, simopts->filepath, (IB_rect | IB_zbuf | IB_zbuffloat | IB_multiview));
+ IMB_freeImBuf(ibuf);
+ }
/* stereo (multiview) images */
else if (simopts->im_format.views_format == R_IMF_VIEWS_STEREO_3D) {
if (imf->imtype == R_IMF_IMTYPE_MULTILAYER) {
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index ff6941b..adc9e28 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -112,7 +112,7 @@ typedef struct ImBuf {
int index; /* reference index for ImBuf lists */
int userflags; /* used to set imbuf to dirty and other stuff */
struct ImMetaData *metadata; /* image metadata */
- void *userdata; /* temporary storage, only used by baking at the moment */
+ void *userdata; /* temporary storage */
/* file information */
int ftype; /* file type we are going to save as */
@@ -175,6 +175,7 @@ typedef struct ImBuf {
#define IB_alphamode_detect (1 << 13) /* if this flag is set, alpha mode would be guessed from file */
#define IB_ignore_alpha (1 << 14) /* ignore alpha on load and substitude it with 1.0f */
#define IB_thumbnail (1 << 15)
+#define IB_multiview (1 << 16)
/*
* The bit flag is stored in the ImBuf.ftype variable.
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index fce79ee..8d808aa 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -336,13 +336,21 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf)
addXDensity(*header, ibuf->ppm[0] / 39.3700787); /* 1 meter = 39.3700787 inches */
}
-static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags)
+static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags, const size_t totviews,
+ const char * (*getview)(void *base, size_t view_id),
+ ImBuf * (*getbuffer)(void *base, const size_t view_id))
{
const int channels = ibuf->channels;
const int is_alpha = (channels >= 4) && (ibuf->planes == 32);
const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
+ const bool is_multiview = (flags & IB_multiview) && ibuf->userdata;
+
+ BLI_assert((!is_multiview) || (getview && getbuffer));
+
+ std::vector <string> views;
+ size_t view_id;
try
{
@@ -351,13 +359,22 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
openexr_header_compression(&header, ibuf->ftype & OPENEXR_COMPRESS);
openexr_header_metadata(&header, ibuf);
- header.channels().insert("R", Channel(HALF));
- header.channels().insert("G", Channel(HALF));
- header.channels().insert("B", Channel(HALF));
- if (is_alpha)
- header.channels().insert("A", Channel(HALF));
- if (is_zbuf) // z we do as float always
- header.channels().insert("Z", Channel(Imf::FLOAT));
+ /* create views when possible */
+ for (view_id = 0; view_id < totviews; view_id ++)
+ views.push_back(is_multiview ? getview(ibuf->userdata, view_id) : "");
+
+ if (is_multiview)
+ addMultiView(header, views);
+
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ header.channels().insert(insertViewName("R", views, view_id), Channel(HALF));
+ header.channels().insert(insertViewName("G", views, view_id), Channel(HALF));
+ header.channels().insert(insertViewName("B", views, view_id), Channel(HALF));
+ if (is_alpha)
+ header.channels().insert(insertViewName("A", views, view_id), Channel(HALF));
+ if (is_zbuf) // z we do as float always
+ header.channels().insert(insertViewName("Z", views, view_id), Channel(Imf::FLOAT));
+ }
FrameBuffer frameBuffer;
@@ -366,52 +383,60 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
OutputFile file(file_stream, header);
/* we store first everything in half array */
- RGBAZ *pixels = new RGBAZ[height * width];
- RGBAZ *to = pixels;
+ RGBAZ *pixels = new RGBAZ[height * width * totviews];
int xstride = sizeof(RGBAZ);
int ystride = xstride * width;
- /* indicate used buffers */
- frameBuffer.insert("R", Slice(HALF, (char *) &pixels[0].r, xstride, ystride));
- frameBuffer.insert("G", Slice(HALF, (char *) &pixels[0].g, xstride, ystride));
- frameBuffer.insert("B", Slice(HALF, (char *) &pixels[0].b, xstride, ystride));
- if (is_alpha)
- frameBuffer.insert("A", Slice(HALF, (char *) &pixels[0].a, xstride, ystride));
- if (is_zbuf)
- frameBuffer.insert("Z", Slice(Imf::FLOAT, (char *)(ibuf->zbuf_float + (height - 1) * width),
- sizeof(float), sizeof(float) * -width));
- if (ibuf->rect_float) {
- float *from;
-
- for (int i = ibuf->y - 1; i >= 0; i--) {
- from = ibuf->rect_float + channels * i * width;
-
- for (int j = ibuf->x; j > 0; j--) {
- to->r = from[0];
- to->g = (channels >= 2) ? from[1] : from[0];
- to->b = (channels >= 3) ? from[2] : from[0];
- to->a = (channels >= 4) ? from[3] : 1.0f;
- to++; from += channels;
+ for (view_id = 0; view_id < totviews; view_id ++) {
+ ImBuf *view_ibuf = is_multiview ? getbuffer(ibuf->userdata, view_id) : ibuf;
+ const size_t offset = view_id * width * height;
+ RGBAZ *to = pixels + offset;
+
+ /* indicate used buffers */
+ frameBuffer.insert(insertViewName("R", views, view_id), Slice(HALF, (char *) &pixels[offset].r, xstride, ystride));
+ frameBuffer.insert(insertViewName("G", views, view_id), Slice(HALF, (char *) &pixels[offset].g, xstride, ystride));
+ frameBuffer.insert(insertViewName("B", views, view_id), Slice(HALF, (char *) &pixels[offset].b, xstride, ystride));
+ if (is_alpha)
+ frameBuffer.insert(insertViewName("A", views, view_id), Slice(HALF, (char *) &pixels[offset].a, xstride, ystride));
+ if (is_zbuf)
+ frameBuffer.insert(insertViewName("Z", views, view_id), Slice(Imf::FLOAT, (char *)(view_ibuf->zbuf_float + (height - 1) * width),
+ sizeof(float), sizeof(float) * -width));
+ if (view_ibuf->rect_float) {
+ float *from;
+
+ for (int i = view_ibuf->y - 1; i >= 0; i--) {
+ from = view_ibuf->rect_float + channels * i * width;
+
+ for (int j = view_ibuf->x; j > 0; j--) {
+ to->r
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list