diff options
Diffstat (limited to 'source/blender/imbuf/intern/colormanagement.c')
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 133 |
1 files changed, 75 insertions, 58 deletions
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 0a85b31ef7b..33873b5daa7 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -2211,21 +2211,14 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer, const int width, const int height, const struct ImBuf *ibuf, - const bool compress_as_srgb, const bool store_premultiplied) { - /* Convert byte buffer for texture storage on the GPU. These have builtin - * support for converting sRGB to linear, which allows us to store textures - * without precision or performance loss at minimal memory usage. */ + /* Byte buffer storage, only for sRGB and data texture since other + * color space conversions can't be done on the GPU. */ BLI_assert(ibuf->rect && ibuf->rect_float == NULL); + BLI_assert(IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace) || + IMB_colormanagement_space_is_data(ibuf->rect_colorspace)); - OCIO_ConstCPUProcessorRcPtr *processor = NULL; - if (compress_as_srgb && ibuf->rect_colorspace && - !IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) { - processor = colorspace_to_scene_linear_cpu_processor(ibuf->rect_colorspace); - } - - /* TODO(brecht): make this multi-threaded, or at least process in batches. */ const unsigned char *in_buffer = (unsigned char *)ibuf->rect; const bool use_premultiply = IMB_alpha_affects_rgb(ibuf) && store_premultiplied; @@ -2235,20 +2228,7 @@ void IMB_colormanagement_imbuf_to_byte_texture(unsigned char *out_buffer, const unsigned char *in = in_buffer + in_offset * 4; unsigned char *out = out_buffer + out_offset * 4; - if (processor != NULL) { - /* Convert to scene linear, to sRGB and premultiply. */ - for (int x = 0; x < width; x++, in += 4, out += 4) { - float pixel[4]; - rgba_uchar_to_float(pixel, in); - OCIO_cpuProcessorApplyRGB(processor, pixel); - linearrgb_to_srgb_v3_v3(pixel, pixel); - if (use_premultiply) { - mul_v3_fl(pixel, pixel[3]); - } - rgba_float_to_uchar(out, pixel); - } - } - else if (use_premultiply) { + if (use_premultiply) { /* Premultiply only. */ for (int x = 0; x < width; x++, in += 4, out += 4) { out[0] = (in[0] * in[3]) >> 8; @@ -2279,43 +2259,80 @@ void IMB_colormanagement_imbuf_to_float_texture(float *out_buffer, { /* Float texture are stored in scene linear color space, with premultiplied * alpha depending on the image alpha mode. */ - const float *in_buffer = ibuf->rect_float; - const int in_channels = ibuf->channels; - const bool use_unpremultiply = IMB_alpha_affects_rgb(ibuf) && !store_premultiplied; - - for (int y = 0; y < height; y++) { - const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; - const size_t out_offset = y * width; - const float *in = in_buffer + in_offset * in_channels; - float *out = out_buffer + out_offset * 4; - - if (in_channels == 1) { - /* Copy single channel. */ - for (int x = 0; x < width; x++, in += 1, out += 4) { - out[0] = in[0]; - out[1] = in[0]; - out[2] = in[0]; - out[3] = in[0]; + if (ibuf->rect_float) { + /* Float source buffer. */ + const float *in_buffer = ibuf->rect_float; + const int in_channels = ibuf->channels; + const bool use_unpremultiply = IMB_alpha_affects_rgb(ibuf) && !store_premultiplied; + + for (int y = 0; y < height; y++) { + const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; + const size_t out_offset = y * width; + const float *in = in_buffer + in_offset * in_channels; + float *out = out_buffer + out_offset * 4; + + if (in_channels == 1) { + /* Copy single channel. */ + for (int x = 0; x < width; x++, in += 1, out += 4) { + out[0] = in[0]; + out[1] = in[0]; + out[2] = in[0]; + out[3] = in[0]; + } } - } - else if (in_channels == 3) { - /* Copy RGB. */ - for (int x = 0; x < width; x++, in += 3, out += 4) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = 1.0f; + else if (in_channels == 3) { + /* Copy RGB. */ + for (int x = 0; x < width; x++, in += 3, out += 4) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = 1.0f; + } } - } - else if (in_channels == 4) { - /* Copy or convert RGBA. */ - if (use_unpremultiply) { - for (int x = 0; x < width; x++, in += 4, out += 4) { - premul_to_straight_v4_v4(out, in); + else if (in_channels == 4) { + /* Copy or convert RGBA. */ + if (use_unpremultiply) { + for (int x = 0; x < width; x++, in += 4, out += 4) { + premul_to_straight_v4_v4(out, in); + } + } + else { + memcpy(out, in, sizeof(float[4]) * width); } } - else { - memcpy(out, in, sizeof(float[4]) * width); + } + } + else { + /* Byte source buffer. */ + const unsigned char *in_buffer = (unsigned char *)ibuf->rect; + const bool use_premultiply = IMB_alpha_affects_rgb(ibuf) && store_premultiplied; + + /* TODO(brecht): make this multi-threaded, or at least process in batches. */ + OCIO_ConstCPUProcessorRcPtr *processor = (ibuf->rect_colorspace) ? + colorspace_to_scene_linear_cpu_processor( + ibuf->rect_colorspace) : + NULL; + + for (int y = 0; y < height; y++) { + const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; + const size_t out_offset = y * width; + const unsigned char *in = in_buffer + in_offset * 4; + float *out = out_buffer + out_offset * 4; + + /* Convert to scene linear, to sRGB and premultiply. */ + for (int x = 0; x < width; x++, in += 4, out += 4) { + float pixel[4]; + rgba_uchar_to_float(pixel, in); + if (processor) { + OCIO_cpuProcessorApplyRGB(processor, pixel); + } + else { + srgb_to_linearrgb_v3_v3(pixel, pixel); + } + if (use_premultiply) { + mul_v3_fl(pixel, pixel[3]); + } + copy_v4_v4(out, pixel); } } } |