Fix Cycles incorrect resize and CMYK conversion of uint16/half images.

This commit is contained in:
Brecht Van Lommel 2018-07-15 18:34:31 +02:00
parent 83a4e1aaf9
commit edbb2d2279
4 changed files with 86 additions and 81 deletions

@ -33,15 +33,15 @@ CCL_NAMESPACE_BEGIN
/* Some helpers to silence warning in templated function. */ /* Some helpers to silence warning in templated function. */
static bool isfinite(uchar /*value*/) static bool isfinite(uchar /*value*/)
{ {
return false; return true;
} }
static bool isfinite(half /*value*/) static bool isfinite(half /*value*/)
{ {
return false; return true;
} }
static bool isfinite(uint16_t /*value*/) static bool isfinite(uint16_t /*value*/)
{ {
return false; return true;
} }
ImageManager::ImageManager(const DeviceInfo& info) ImageManager::ImageManager(const DeviceInfo& info)
@ -508,7 +508,6 @@ bool ImageManager::file_load_image(Image *img,
int texture_limit, int texture_limit,
device_vector<DeviceType>& tex_img) device_vector<DeviceType>& tex_img)
{ {
const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1;
ImageInput *in = NULL; ImageInput *in = NULL;
if(!file_load_image_generic(img, &in)) { if(!file_load_image_generic(img, &in)) {
return false; return false;
@ -601,13 +600,19 @@ bool ImageManager::file_load_image(Image *img,
type == IMAGE_DATA_TYPE_BYTE4 || type == IMAGE_DATA_TYPE_BYTE4 ||
type == IMAGE_DATA_TYPE_USHORT4); type == IMAGE_DATA_TYPE_USHORT4);
if(is_rgba) { if(is_rgba) {
const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
if(cmyk) { if(cmyk) {
/* CMYK */ /* CMYK */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { 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; float c = util_image_cast_to_float(pixels[i*4+0]);
pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; float m = util_image_cast_to_float(pixels[i*4+1]);
pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; float y = util_image_cast_to_float(pixels[i*4+2]);
pixels[i*4+3] = alpha_one; float k = util_image_cast_to_float(pixels[i*4+3]);
pixels[i*4+0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
pixels[i*4+1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
pixels[i*4+2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
pixels[i*4+3] = one;
} }
} }
else if(components == 2) { else if(components == 2) {
@ -622,7 +627,7 @@ bool ImageManager::file_load_image(Image *img,
else if(components == 3) { else if(components == 3) {
/* RGB */ /* RGB */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { 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+2] = pixels[i*3+2];
pixels[i*4+1] = pixels[i*3+1]; pixels[i*4+1] = pixels[i*3+1];
pixels[i*4+0] = pixels[i*3+0]; pixels[i*4+0] = pixels[i*3+0];
@ -631,7 +636,7 @@ bool ImageManager::file_load_image(Image *img,
else if(components == 1) { else if(components == 1) {
/* grayscale */ /* grayscale */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { 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+2] = pixels[i];
pixels[i*4+1] = pixels[i]; pixels[i*4+1] = pixels[i];
pixels[i*4+0] = pixels[i]; pixels[i*4+0] = pixels[i];
@ -639,7 +644,7 @@ bool ImageManager::file_load_image(Image *img,
} }
if(img->use_alpha == false) { if(img->use_alpha == false) {
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { 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); thread_scoped_lock device_lock(device_mutex);
uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); 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; img->mem = tex_img;
@ -893,10 +898,10 @@ void ImageManager::device_load_image(Device *device,
thread_scoped_lock device_lock(device_mutex); thread_scoped_lock device_lock(device_mutex);
uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1); uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
pixels[0] = TEX_IMAGE_MISSING_R; pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
pixels[1] = TEX_IMAGE_MISSING_G; pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
pixels[2] = TEX_IMAGE_MISSING_B; pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
pixels[3] = TEX_IMAGE_MISSING_A; pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
} }
img->mem = tex_img; img->mem = tex_img;

@ -38,6 +38,68 @@ void util_image_resize_pixels(const vector<T>& input_pixels,
size_t *output_height, size_t *output_height,
size_t *output_depth); size_t *output_depth);
/* Cast input pixel from unknown storage to float. */
template<typename T>
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<typename T>
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 CCL_NAMESPACE_END
#endif /* __UTIL_IMAGE_H__ */ #endif /* __UTIL_IMAGE_H__ */

@ -38,68 +38,6 @@ const T *util_image_read(const vector<T>& pixels,
return &pixels[index]; return &pixels[index];
} }
/* Cast input pixel from unknown storage to float. */
template<typename T>
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<typename T>
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<typename T> template<typename T>
void util_image_downscale_sample(const vector<T>& pixels, void util_image_downscale_sample(const vector<T>& pixels,
const size_t width, const size_t width,
@ -133,7 +71,7 @@ void util_image_downscale_sample(const vector<T>& pixels,
components, components,
nx, ny, nz); nx, ny, nz);
for(size_t k = 0; k < components; ++k) { 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; ++count;
} }
@ -142,7 +80,7 @@ void util_image_downscale_sample(const vector<T>& pixels,
if(count != 0) { if(count != 0) {
const float inv_count = 1.0f / (float)count; const float inv_count = 1.0f / (float)count;
for(size_t k = 0; k < components; ++k) { for(size_t k = 0; k < components; ++k) {
result[k] = cast_from_float<T>(accum[k] * inv_count); result[k] = util_image_cast_from_float<T>(accum[k] * inv_count);
} }
} }
else { else {