diff options
Diffstat (limited to 'intern/cycles/render/image.cpp')
-rw-r--r-- | intern/cycles/render/image.cpp | 108 |
1 files changed, 89 insertions, 19 deletions
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 7465fbd43a7..11193bf4974 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -19,6 +19,7 @@ #include "scene.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_path.h" #include "util_progress.h" #include "util_texture.h" @@ -476,6 +477,7 @@ template<TypeDesc::BASETYPE FileFormat, typename DeviceType> bool ImageManager::file_load_image(Image *img, ImageDataType type, + int texture_limit, device_vector<DeviceType>& tex_img) { const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1; @@ -485,9 +487,15 @@ bool ImageManager::file_load_image(Image *img, return false; } /* Read RGBA pixels. */ - StorageType *pixels = (StorageType*)tex_img.resize(width, height, depth); - if(pixels == NULL) { - return false; + vector<StorageType> pixels_storage; + StorageType *pixels; + const size_t max_size = max(max(width, height), depth); + if(texture_limit > 0 && max_size > texture_limit) { + pixels_storage.resize(((size_t)width)*height*depth*4); + pixels = &pixels_storage[0]; + } + else { + pixels = (StorageType*)tex_img.resize(width, height, depth); } bool cmyk = false; if(in) { @@ -526,12 +534,12 @@ bool ImageManager::file_load_image(Image *img, if(FileFormat == TypeDesc::FLOAT) { builtin_image_float_pixels_cb(img->filename, img->builtin_data, - (float*)pixels); + (float*)&pixels[0]); } else if(FileFormat == TypeDesc::UINT8) { builtin_image_pixels_cb(img->filename, img->builtin_data, - (uchar*)pixels); + (uchar*)&pixels[0]); } else { /* TODO(dingto): Support half for ImBuf. */ @@ -540,10 +548,10 @@ bool ImageManager::file_load_image(Image *img, /* Check if we actually have a float4 slot, in case components == 1, * but device doesn't support single channel textures. */ - if(type == IMAGE_DATA_TYPE_FLOAT4 || - type == IMAGE_DATA_TYPE_HALF4 || - type == IMAGE_DATA_TYPE_BYTE4) - { + bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 || + type == IMAGE_DATA_TYPE_HALF4 || + type == IMAGE_DATA_TYPE_BYTE4); + if(is_rgba) { size_t num_pixels = ((size_t)width) * height * depth; if(cmyk) { /* CMYK */ @@ -587,14 +595,41 @@ bool ImageManager::file_load_image(Image *img, } } } + if(pixels_storage.size() > 0) { + float scale_factor = 1.0f; + while(max_size * scale_factor > texture_limit) { + scale_factor *= 0.5f; + } + VLOG(1) << "Scaling image " << img->filename + << " by a factor of " << scale_factor << "."; + vector<StorageType> scaled_pixels; + size_t scaled_width, scaled_height, scaled_depth; + util_image_resize_pixels(pixels_storage, + width, height, depth, + is_rgba ? 4 : 1, + scale_factor, + &scaled_pixels, + &scaled_width, &scaled_height, &scaled_depth); + StorageType *texture_pixels = (StorageType*)tex_img.resize(scaled_width, + scaled_height, + scaled_depth); + memcpy(texture_pixels, + &scaled_pixels[0], + scaled_pixels.size() * sizeof(StorageType)); + } return true; } -void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress) +void ImageManager::device_load_image(Device *device, + DeviceScene *dscene, + Scene *scene, + ImageDataType type, + int slot, + Progress *progress) { if(progress->get_cancel()) return; - + Image *img = images[type][slot]; if(osl_texture_system && !img->builtin_data) @@ -603,6 +638,8 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD string filename = path_filename(images[type][slot]->filename); progress->set_status("Updating Images", "Loading " + filename); + const int texture_limit = scene->params.texture_limit; + /* Slot assignment */ int flat_slot = type_index_to_flattened_slot(slot, type); @@ -622,7 +659,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::FLOAT, float>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::FLOAT, float>(img, + type, + texture_limit, + tex_img)) + { /* on failure to load, we set a 1x1 pixels pink image */ float *pixels = (float*)tex_img.resize(1, 1); @@ -648,7 +689,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::FLOAT, float>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::FLOAT, float>(img, + type, + texture_limit, + tex_img)) + { /* on failure to load, we set a 1x1 pixels pink image */ float *pixels = (float*)tex_img.resize(1, 1); @@ -671,7 +716,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::UINT8, uchar>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::UINT8, uchar>(img, + type, + texture_limit, + tex_img)) + { /* on failure to load, we set a 1x1 pixels pink image */ uchar *pixels = (uchar*)tex_img.resize(1, 1); @@ -697,7 +746,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::UINT8, uchar>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::UINT8, uchar>(img, + type, + texture_limit, + tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ uchar *pixels = (uchar*)tex_img.resize(1, 1); @@ -720,7 +772,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::HALF, half>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::HALF, half>(img, + type, + texture_limit, + tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ half *pixels = (half*)tex_img.resize(1, 1); @@ -746,7 +801,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_image<TypeDesc::HALF, half>(img, type, tex_img)) { + if(!file_load_image<TypeDesc::HALF, half>(img, + type, + texture_limit, + tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ half *pixels = (half*)tex_img.resize(1, 1); @@ -842,7 +900,10 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD } } -void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& progress) +void ImageManager::device_update(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress& progress) { if(!need_update) return; @@ -859,7 +920,14 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& } else if(images[type][slot]->need_load) { if(!osl_texture_system || images[type][slot]->builtin_data) - pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, (ImageDataType)type, slot, &progress)); + pool.push(function_bind(&ImageManager::device_load_image, + this, + device, + dscene, + scene, + (ImageDataType)type, + slot, + &progress)); } } } @@ -874,6 +942,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& void ImageManager::device_update_slot(Device *device, DeviceScene *dscene, + Scene *scene, int flat_slot, Progress *progress) { @@ -890,6 +959,7 @@ void ImageManager::device_update_slot(Device *device, if(!osl_texture_system || image->builtin_data) device_load_image(device, dscene, + scene, type, slot, progress); |