From edbb2d22791f04af6b775f5d46321f533c705781 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 15 Jul 2018 18:34:31 +0200 Subject: Fix Cycles incorrect resize and CMYK conversion of uint16/half images. --- intern/cycles/render/image.cpp | 37 +++++++++++--------- intern/cycles/util/util_half.h | 2 +- intern/cycles/util/util_image.h | 62 +++++++++++++++++++++++++++++++++ intern/cycles/util/util_image_impl.h | 66 ++---------------------------------- 4 files changed, 86 insertions(+), 81 deletions(-) diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 7f0660cee07..27d6ae78289 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -33,15 +33,15 @@ CCL_NAMESPACE_BEGIN /* Some helpers to silence warning in templated function. */ static bool isfinite(uchar /*value*/) { - return false; + return true; } static bool isfinite(half /*value*/) { - return false; + return true; } static bool isfinite(uint16_t /*value*/) { - return false; + return true; } ImageManager::ImageManager(const DeviceInfo& info) @@ -508,7 +508,6 @@ bool ImageManager::file_load_image(Image *img, int texture_limit, device_vector& tex_img) { - const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1; ImageInput *in = NULL; if(!file_load_image_generic(img, &in)) { return false; @@ -601,13 +600,19 @@ bool ImageManager::file_load_image(Image *img, type == IMAGE_DATA_TYPE_BYTE4 || type == IMAGE_DATA_TYPE_USHORT4); if(is_rgba) { + const StorageType one = util_image_cast_from_float(1.0f); + if(cmyk) { /* CMYK */ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; - pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; - pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; - pixels[i*4+3] = alpha_one; + float c = util_image_cast_to_float(pixels[i*4+0]); + float m = util_image_cast_to_float(pixels[i*4+1]); + float y = util_image_cast_to_float(pixels[i*4+2]); + float k = util_image_cast_to_float(pixels[i*4+3]); + pixels[i*4+0] = util_image_cast_from_float((1.0f - c) * (1.0f - k)); + pixels[i*4+1] = util_image_cast_from_float((1.0f - m) * (1.0f - k)); + pixels[i*4+2] = util_image_cast_from_float((1.0f - y) * (1.0f - k)); + pixels[i*4+3] = one; } } else if(components == 2) { @@ -622,7 +627,7 @@ bool ImageManager::file_load_image(Image *img, else if(components == 3) { /* RGB */ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = alpha_one; + pixels[i*4+3] = one; pixels[i*4+2] = pixels[i*3+2]; pixels[i*4+1] = pixels[i*3+1]; pixels[i*4+0] = pixels[i*3+0]; @@ -631,7 +636,7 @@ bool ImageManager::file_load_image(Image *img, else if(components == 1) { /* grayscale */ for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = alpha_one; + pixels[i*4+3] = one; pixels[i*4+2] = pixels[i]; pixels[i*4+1] = pixels[i]; pixels[i*4+0] = pixels[i]; @@ -639,7 +644,7 @@ bool ImageManager::file_load_image(Image *img, } if(img->use_alpha == false) { for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = alpha_one; + pixels[i*4+3] = one; } } } @@ -871,7 +876,7 @@ void ImageManager::device_load_image(Device *device, thread_scoped_lock device_lock(device_mutex); uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); - pixels[0] = TEX_IMAGE_MISSING_R; + pixels[0] = (TEX_IMAGE_MISSING_R * 65535); } img->mem = tex_img; @@ -893,10 +898,10 @@ void ImageManager::device_load_image(Device *device, thread_scoped_lock device_lock(device_mutex); uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); - pixels[0] = TEX_IMAGE_MISSING_R; - pixels[1] = TEX_IMAGE_MISSING_G; - pixels[2] = TEX_IMAGE_MISSING_B; - pixels[3] = TEX_IMAGE_MISSING_A; + pixels[0] = (TEX_IMAGE_MISSING_R * 65535); + pixels[1] = (TEX_IMAGE_MISSING_G * 65535); + pixels[2] = (TEX_IMAGE_MISSING_B * 65535); + pixels[3] = (TEX_IMAGE_MISSING_A * 65535); } img->mem = tex_img; diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h index 58f3f903619..53b7f2472bd 100644 --- a/intern/cycles/util/util_half.h +++ b/intern/cycles/util/util_half.h @@ -42,7 +42,7 @@ public: half() : v(0) {} half(const unsigned short& i) : v(i) {} operator unsigned short() { return v; } - half & operator =(const unsigned short& i) { v = i; return *this; } + half& operator =(const unsigned short& i) { v = i; return *this; } private: unsigned short v; }; diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h index 18876841b5b..85bdb0d8050 100644 --- a/intern/cycles/util/util_image.h +++ b/intern/cycles/util/util_image.h @@ -38,6 +38,68 @@ void util_image_resize_pixels(const vector& input_pixels, size_t *output_height, size_t *output_depth); +/* Cast input pixel from unknown storage to float. */ +template +inline float util_image_cast_to_float(T value); + +template<> +inline float util_image_cast_to_float(float value) +{ + return value; +} +template<> +inline float util_image_cast_to_float(uchar value) +{ + return (float)value / 255.0f; +} +template<> +inline float util_image_cast_to_float(uint16_t value) +{ + return (float)value / 65535.0f; +} +template<> +inline float util_image_cast_to_float(half value) +{ + return half_to_float(value); +} + +/* Cast float value to output pixel type. */ +template +inline T util_image_cast_from_float(float value); + +template<> +inline float util_image_cast_from_float(float value) +{ + return value; +} +template<> +inline uchar util_image_cast_from_float(float value) +{ + if(value < 0.0f) { + return 0; + } + else if(value > (1.0f - 0.5f / 255.0f)) { + return 255; + } + return (uchar)((255.0f * value) + 0.5f); +} +template<> +inline uint16_t util_image_cast_from_float(float value) +{ + if(value < 0.0f) { + return 0; + } + else if(value > (1.0f - 0.5f / 65535.0f)) { + return 65535; + } + return (uint16_t)((65535.0f * value) + 0.5f); +} +template<> +inline half util_image_cast_from_float(float value) +{ + return float_to_half(value); +} + CCL_NAMESPACE_END #endif /* __UTIL_IMAGE_H__ */ diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h index fb953a43ab2..5bc1c727595 100644 --- a/intern/cycles/util/util_image_impl.h +++ b/intern/cycles/util/util_image_impl.h @@ -38,68 +38,6 @@ const T *util_image_read(const vector& pixels, return &pixels[index]; } -/* Cast input pixel from unknown storage to float. */ -template -inline float cast_to_float(T value); - -template<> -inline float cast_to_float(float value) -{ - return value; -} -template<> -inline float cast_to_float(uchar value) -{ - return (float)value / 255.0f; -} -template<> -inline float cast_to_float(uint16_t value) -{ - return (float)value / 65535.0f; -} -template<> -inline float cast_to_float(half value) -{ - return half_to_float(value); -} - -/* Cast float value to output pixel type. */ -template -inline T cast_from_float(float value); - -template<> -inline float cast_from_float(float value) -{ - return value; -} -template<> -inline uchar cast_from_float(float value) -{ - if(value < 0.0f) { - return 0; - } - else if(value > (1.0f - 0.5f / 255.0f)) { - return 255; - } - return (uchar)((255.0f * value) + 0.5f); -} -template<> -inline uint16_t cast_from_float(float value) -{ - if(value < 0.0f) { - return 0; - } - else if(value >(1.0f - 0.5f / 65535.0f)) { - return 65535; - } - return (uchar)((65535.0f * value) + 0.5f); -} -template<> -inline half cast_from_float(float value) -{ - return float_to_half(value); -} - template void util_image_downscale_sample(const vector& pixels, const size_t width, @@ -133,7 +71,7 @@ void util_image_downscale_sample(const vector& pixels, components, nx, ny, nz); for(size_t k = 0; k < components; ++k) { - accum[k] += cast_to_float(pixel[k]); + accum[k] += util_image_cast_to_float(pixel[k]); } ++count; } @@ -142,7 +80,7 @@ void util_image_downscale_sample(const vector& pixels, if(count != 0) { const float inv_count = 1.0f / (float)count; for(size_t k = 0; k < components; ++k) { - result[k] = cast_from_float(accum[k] * inv_count); + result[k] = util_image_cast_from_float(accum[k] * inv_count); } } else { -- cgit v1.2.3