diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-01-12 14:59:13 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-01-12 14:59:13 +0400 |
commit | 7a90af7b5a50bac5bb9fa6bf8ec785dac145a90c (patch) | |
tree | 661f808af738e2d06ee5a436fe4e59b3daa67797 /intern/cycles/render/image.cpp | |
parent | 5e6917a18e288b06cc8130aa8311453c9893dd0b (diff) |
Packed and generated images support for Cycles
This commit adds support of packed and generated images
for Cycles when using SVM backend. Movies are still not
supported. This changes also doesn't touch OSL which is
much less trivial to adopt for any images which are not
saved to disk.
Implementation details:
- When adding images to Image Manager is now possible
to mark image as builtin. Builtin images will bypass
OIIO loader and will use special loading callbacks.
- Callbacks are set by Blender Session and they're
using C++ RNA interface to obtain needed data (pixels,
dimensions, is_float flag).
- Image Manager assumes file path is used as reference
to a builtin images, but in fact currently image
datablock name is used for reference. This makes it
easy to find an image in BlendData database.
- Added some extra properties to Image RNA:
* channels, which denotes actual number of channels
in ImBuf. This is needed to treat image's pixels
correct (before it wasn't possible because API
used internal number of channels for pixels which
is in fact doesn't correlate with image depth)
* is_float, which is truth if image is stored in
float buffer of ImBuf.
- Implemented string lookup for C++ RNA collections
for cases there's no manual lookup function.
OSL is not supported because it used own image loading
and filtering routines and there's seems to be no API
to feed pre-loaded pixels directly to the library.
Think we'll either need to add some API to support
such kind of feeding or consider OSL does not have
support of packed images at all.
Movies are not supported at this moment because of lack
of RNA API to load specified frame. It's not difficult
to solve, just need to consider what to best here:
* Either write some general python interface for ImBuf
and use it via C++ API, or
* Write a PY API function which will return pixels for
given frame, or
* Use bad-level BKE_* call
Anyway, small steps, further improvements later.
Reviewed by Brecht, thanks!
Diffstat (limited to 'intern/cycles/render/image.cpp')
-rw-r--r-- | intern/cycles/render/image.cpp | 151 |
1 files changed, 102 insertions, 49 deletions
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 230a12f9ff2..e6f8ab4a5d9 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -85,11 +85,21 @@ bool ImageManager::set_animation_frame_update(int frame) return false; } -bool ImageManager::is_float_image(const string& filename) +bool ImageManager::is_float_image(const string& filename, bool is_builtin) { - ImageInput *in = ImageInput::create(filename); bool is_float = false; + if(is_builtin) { + if(builtin_image_info_cb) { + int width, height, channels; + builtin_image_info_cb(filename, is_float, width, height, channels); + } + + return is_float; + } + + ImageInput *in = ImageInput::create(filename); + if(in) { ImageSpec spec; @@ -113,13 +123,13 @@ bool ImageManager::is_float_image(const string& filename) return is_float; } -int ImageManager::add_image(const string& filename, bool animated, bool& is_float) +int ImageManager::add_image(const string& filename, bool is_builtin, bool animated, bool& is_float) { Image *img; size_t slot; /* load image info and find out if we need a float texture */ - is_float = (pack_images)? false: is_float_image(filename); + is_float = (pack_images)? false: is_float_image(filename, is_builtin); if(is_float) { /* find existing image */ @@ -150,6 +160,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa /* add new image */ img = new Image(); img->filename = filename; + img->is_builtin = is_builtin; img->need_load = true; img->animated = animated; img->users = 1; @@ -184,6 +195,7 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa /* add new image */ img = new Image(); img->filename = filename; + img->is_builtin = is_builtin; img->need_load = true; img->animated = animated; img->users = 1; @@ -197,12 +209,12 @@ int ImageManager::add_image(const string& filename, bool animated, bool& is_floa return slot; } -void ImageManager::remove_image(const string& filename) +void ImageManager::remove_image(const string& filename, bool is_builtin) { size_t slot; for(slot = 0; slot < images.size(); slot++) { - if(images[slot] && images[slot]->filename == filename) { + if(images[slot] && images[slot]->filename == filename && images[slot]->is_builtin == is_builtin) { /* decrement user count */ images[slot]->users--; assert(images[slot]->users >= 0); @@ -220,7 +232,7 @@ void ImageManager::remove_image(const string& filename) if(slot == images.size()) { /* see if it's in a float texture slot */ for(slot = 0; slot < float_images.size(); slot++) { - if(float_images[slot] && float_images[slot]->filename == filename) { + if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->is_builtin == is_builtin) { /* decrement user count */ float_images[slot]->users--; assert(float_images[slot]->users >= 0); @@ -242,27 +254,43 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) if(img->filename == "") return false; - /* load image from file through OIIO */ - ImageInput *in = ImageInput::create(img->filename); + ImageInput *in = NULL; + int width, height, components; - if(!in) - return false; + if(!img->is_builtin) { + /* load image from file through OIIO */ + in = ImageInput::create(img->filename); - ImageSpec spec; + if(!in) + return false; - if(!in->open(img->filename, spec)) { - delete in; - return false; + ImageSpec spec; + + if(!in->open(img->filename, spec)) { + delete in; + return false; + } + + width = spec.width; + height = spec.height; + components = spec.nchannels; + } + else { + /* load image using builtin images callbacks */ + if(!builtin_image_info_cb || !builtin_image_pixels_cb) + return false; + + bool is_float; + builtin_image_info_cb(img->filename, is_float, width, height, components); } /* we only handle certain number of components */ - int width = spec.width; - int height = spec.height; - int components = spec.nchannels; - if(!(components == 1 || components == 3 || components == 4)) { - in->close(); - delete in; + if(in) { + in->close(); + delete in; + } + return false; } @@ -270,14 +298,19 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img) uchar *pixels = (uchar*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(uchar); - in->read_image(TypeDesc::UINT8, - (uchar*)pixels + (height-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); + if(in) { + in->read_image(TypeDesc::UINT8, + (uchar*)pixels + (height-1)*scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); - in->close(); - delete in; + in->close(); + delete in; + } + else { + builtin_image_pixels_cb(img->filename, pixels); + } if(components == 3) { for(int i = width*height-1; i >= 0; i--) { @@ -304,27 +337,42 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_ if(img->filename == "") return false; - /* load image from file through OIIO */ - ImageInput *in = ImageInput::create(img->filename); + ImageInput *in = NULL; + int width, height, components; - if(!in) - return false; + if(!img->is_builtin) { + /* load image from file through OIIO */ + in = ImageInput::create(img->filename); - ImageSpec spec; + if(!in) + return false; - if(!in->open(img->filename, spec)) { - delete in; - return false; + ImageSpec spec; + + if(!in->open(img->filename, spec)) { + delete in; + return false; + } + + /* we only handle certain number of components */ + width = spec.width; + height = spec.height; + components = spec.nchannels; } + else { + /* load image using builtin images callbacks */ + if(!builtin_image_info_cb || !builtin_image_float_pixels_cb) + return false; - /* we only handle certain number of components */ - int width = spec.width; - int height = spec.height; - int components = spec.nchannels; + bool is_float; + builtin_image_info_cb(img->filename, is_float, width, height, components); + } if(!(components == 1 || components == 3 || components == 4)) { - in->close(); - delete in; + if(in) { + in->close(); + delete in; + } return false; } @@ -332,14 +380,19 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_ float *pixels = (float*)tex_img.resize(width, height); int scanlinesize = width*components*sizeof(float); - in->read_image(TypeDesc::FLOAT, - (uchar*)pixels + (height-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); + if(in) { + in->read_image(TypeDesc::FLOAT, + (uchar*)pixels + (height-1)*scanlinesize, + AutoStride, + -scanlinesize, + AutoStride); - in->close(); - delete in; + in->close(); + delete in; + } + else { + builtin_image_float_pixels_cb(img->filename, pixels); + } if(components == 3) { for(int i = width*height-1; i >= 0; i--) { |