forked from bartvdbraak/blender
Fix T94712: Cycles missing colorspace transform on grayscale images
This commit is contained in:
parent
2559d79d2f
commit
24e00c115c
@ -263,7 +263,9 @@ template<typename T> inline void cast_from_float4(T *data, float4 value)
|
|||||||
|
|
||||||
/* Slower versions for other all data types, which needs to convert to float and back. */
|
/* Slower versions for other all data types, which needs to convert to float and back. */
|
||||||
template<typename T, bool compress_as_srgb = false>
|
template<typename T, bool compress_as_srgb = false>
|
||||||
inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels, size_t num_pixels)
|
inline void processor_apply_pixels_rgba(const OCIO::Processor *processor,
|
||||||
|
T *pixels,
|
||||||
|
size_t num_pixels)
|
||||||
{
|
{
|
||||||
/* TODO: implement faster version for when we know the conversion
|
/* TODO: implement faster version for when we know the conversion
|
||||||
* is a simple matrix transform between linear spaces. In that case
|
* is a simple matrix transform between linear spaces. In that case
|
||||||
@ -310,25 +312,79 @@ inline void processor_apply_pixels(const OCIO::Processor *processor, T *pixels,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, bool compress_as_srgb = false>
|
||||||
|
inline void processor_apply_pixels_grayscale(const OCIO::Processor *processor,
|
||||||
|
T *pixels,
|
||||||
|
size_t num_pixels)
|
||||||
|
{
|
||||||
|
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
|
||||||
|
|
||||||
|
/* Process large images in chunks to keep temporary memory requirement down. */
|
||||||
|
const size_t chunk_size = std::min((size_t)(16 * 1024 * 1024), num_pixels);
|
||||||
|
vector<float> float_pixels(chunk_size * 3);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < num_pixels; j += chunk_size) {
|
||||||
|
size_t width = std::min(chunk_size, num_pixels - j);
|
||||||
|
|
||||||
|
/* Convert to 3 channels, since that's the minimum required by OpenColorIO. */
|
||||||
|
{
|
||||||
|
const T *pixel = pixels + j;
|
||||||
|
float *fpixel = float_pixels.data();
|
||||||
|
for (size_t i = 0; i < width; i++, pixel++, fpixel += 3) {
|
||||||
|
const float f = util_image_cast_to_float<T>(*pixel);
|
||||||
|
fpixel[0] = f;
|
||||||
|
fpixel[1] = f;
|
||||||
|
fpixel[2] = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OCIO::PackedImageDesc desc((float *)float_pixels.data(), width, 1, 3);
|
||||||
|
device_processor->apply(desc);
|
||||||
|
|
||||||
|
{
|
||||||
|
T *pixel = pixels + j;
|
||||||
|
const float *fpixel = float_pixels.data();
|
||||||
|
for (size_t i = 0; i < width; i++, pixel++, fpixel += 3) {
|
||||||
|
float f = average(make_float3(fpixel[0], fpixel[1], fpixel[2]));
|
||||||
|
if (compress_as_srgb) {
|
||||||
|
f = color_linear_to_srgb(f);
|
||||||
|
}
|
||||||
|
*pixel = util_image_cast_from_float<T>(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ColorSpaceManager::to_scene_linear(ustring colorspace,
|
void ColorSpaceManager::to_scene_linear(
|
||||||
T *pixels,
|
ustring colorspace, T *pixels, size_t num_pixels, bool is_rgba, bool compress_as_srgb)
|
||||||
size_t num_pixels,
|
|
||||||
bool compress_as_srgb)
|
|
||||||
{
|
{
|
||||||
#ifdef WITH_OCIO
|
#ifdef WITH_OCIO
|
||||||
const OCIO::Processor *processor = (const OCIO::Processor *)get_processor(colorspace);
|
const OCIO::Processor *processor = (const OCIO::Processor *)get_processor(colorspace);
|
||||||
|
|
||||||
if (processor) {
|
if (processor) {
|
||||||
|
if (is_rgba) {
|
||||||
if (compress_as_srgb) {
|
if (compress_as_srgb) {
|
||||||
/* Compress output as sRGB. */
|
/* Compress output as sRGB. */
|
||||||
processor_apply_pixels<T, true>(processor, pixels, num_pixels);
|
processor_apply_pixels_rgba<T, true>(processor, pixels, num_pixels);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Write output as scene linear directly. */
|
/* Write output as scene linear directly. */
|
||||||
processor_apply_pixels<T>(processor, pixels, num_pixels);
|
processor_apply_pixels_rgba<T>(processor, pixels, num_pixels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (compress_as_srgb) {
|
||||||
|
/* Compress output as sRGB. */
|
||||||
|
processor_apply_pixels_grayscale<T, true>(processor, pixels, num_pixels);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Write output as scene linear directly. */
|
||||||
|
processor_apply_pixels_grayscale<T>(processor, pixels, num_pixels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@ -348,6 +404,11 @@ void ColorSpaceManager::to_scene_linear(ColorSpaceProcessor *processor_,
|
|||||||
|
|
||||||
if (processor) {
|
if (processor) {
|
||||||
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
|
OCIO::ConstCPUProcessorRcPtr device_processor = processor->getDefaultCPUProcessor();
|
||||||
|
if (channels == 1) {
|
||||||
|
float3 rgb = make_float3(pixel[0], pixel[0], pixel[0]);
|
||||||
|
device_processor->applyRGB(&rgb.x);
|
||||||
|
pixel[0] = average(rgb);
|
||||||
|
}
|
||||||
if (channels == 3) {
|
if (channels == 3) {
|
||||||
device_processor->applyRGB(pixel);
|
device_processor->applyRGB(pixel);
|
||||||
}
|
}
|
||||||
@ -390,9 +451,9 @@ void ColorSpaceManager::free_memory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Template instantiations so we don't have to inline functions. */
|
/* Template instantiations so we don't have to inline functions. */
|
||||||
template void ColorSpaceManager::to_scene_linear(ustring, uchar *, size_t, bool);
|
template void ColorSpaceManager::to_scene_linear(ustring, uchar *, size_t, bool, bool);
|
||||||
template void ColorSpaceManager::to_scene_linear(ustring, ushort *, size_t, bool);
|
template void ColorSpaceManager::to_scene_linear(ustring, ushort *, size_t, bool, bool);
|
||||||
template void ColorSpaceManager::to_scene_linear(ustring, half *, size_t, bool);
|
template void ColorSpaceManager::to_scene_linear(ustring, half *, size_t, bool, bool);
|
||||||
template void ColorSpaceManager::to_scene_linear(ustring, float *, size_t, bool);
|
template void ColorSpaceManager::to_scene_linear(ustring, float *, size_t, bool, bool);
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
@ -43,10 +43,8 @@ class ColorSpaceManager {
|
|||||||
/* Convert pixels in the specified colorspace to scene linear color for
|
/* Convert pixels in the specified colorspace to scene linear color for
|
||||||
* rendering. Must be a colorspace returned from detect_known_colorspace. */
|
* rendering. Must be a colorspace returned from detect_known_colorspace. */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void to_scene_linear(ustring colorspace,
|
static void to_scene_linear(
|
||||||
T *pixels,
|
ustring colorspace, T *pixels, size_t num_pixels, bool is_rgba, bool compress_as_srgb);
|
||||||
size_t num_pixels,
|
|
||||||
bool compress_as_srgb);
|
|
||||||
|
|
||||||
/* Efficiently convert pixels to scene linear colorspace at render time,
|
/* Efficiently convert pixels to scene linear colorspace at render time,
|
||||||
* for OSL where the image texture cache contains original pixels. The
|
* for OSL where the image texture cache contains original pixels. The
|
||||||
|
@ -576,13 +576,13 @@ bool ImageManager::file_load_image(Image *img, int texture_limit)
|
|||||||
pixels[i * 4 + 3] = one;
|
pixels[i * 4 + 3] = one;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (img->metadata.colorspace != u_colorspace_raw &&
|
if (img->metadata.colorspace != u_colorspace_raw &&
|
||||||
img->metadata.colorspace != u_colorspace_srgb) {
|
img->metadata.colorspace != u_colorspace_srgb) {
|
||||||
/* Convert to scene linear. */
|
/* Convert to scene linear. */
|
||||||
ColorSpaceManager::to_scene_linear(
|
ColorSpaceManager::to_scene_linear(
|
||||||
img->metadata.colorspace, pixels, num_pixels, img->metadata.compress_as_srgb);
|
img->metadata.colorspace, pixels, num_pixels, is_rgba, img->metadata.compress_as_srgb);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we don't have buggy values. */
|
/* Make sure we don't have buggy values. */
|
||||||
|
Loading…
Reference in New Issue
Block a user