diff options
Diffstat (limited to 'source/blender/imbuf/intern/colormanagement.c')
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 173 |
1 files changed, 146 insertions, 27 deletions
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a45346279d9..48cba3e0800 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1555,21 +1555,25 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ typedef struct ProcessorTransformThread { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int start_line; int tot_line; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformThread; typedef struct ProcessorTransformInit { ColormanageProcessor *cm_processor; - float *buffer; + unsigned char *byte_buffer; + float *float_buffer; int width; int height; int channels; bool predivide; + bool float_from_byte; } ProcessorTransformInitData; static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -1577,17 +1581,24 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v; - int channels = init_data->channels; - int width = init_data->width; - bool predivide = init_data->predivide; + const int channels = init_data->channels; + const int width = init_data->width; + const bool predivide = init_data->predivide; + const bool float_from_byte = init_data->float_from_byte; - size_t offset = ((size_t)channels) * start_line * width; + const size_t offset = ((size_t)channels) * start_line * width; memset(handle, 0, sizeof(ProcessorTransformThread)); handle->cm_processor = init_data->cm_processor; - handle->buffer = init_data->buffer + offset; + if (init_data->byte_buffer != NULL) { + /* TODO(serge): Offset might be different for byte and float buffers. */ + handle->byte_buffer = init_data->byte_buffer + offset; + } + if (init_data->float_buffer != NULL) { + handle->float_buffer = init_data->float_buffer + offset; + } handle->width = width; @@ -1596,33 +1607,62 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int handle->channels = channels; handle->predivide = predivide; + handle->float_from_byte = float_from_byte; } static void *do_processor_transform_thread(void *handle_v) { ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v; - float *buffer = handle->buffer; - int channels = handle->channels; - int width = handle->width; - int height = handle->tot_line; - bool predivide = handle->predivide; - - IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide); + unsigned char *byte_buffer = handle->byte_buffer; + float *float_buffer = handle->float_buffer; + const int channels = handle->channels; + const int width = handle->width; + const int height = handle->tot_line; + const bool predivide = handle->predivide; + const bool float_from_byte = handle->float_from_byte; + + if (float_from_byte) { + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(handle->cm_processor, + byte_buffer, + width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(handle->cm_processor, + float_buffer, + width, height, channels, + predivide); + } + } return NULL; } -static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels, - ColormanageProcessor *cm_processor, bool predivide) +static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer, + const int width, const int height, const int channels, + ColormanageProcessor *cm_processor, + const bool predivide, const bool float_from_byte) { ProcessorTransformInitData init_data; init_data.cm_processor = cm_processor; - init_data.buffer = buffer; + init_data.byte_buffer = byte_buffer; + init_data.float_buffer = float_buffer; init_data.width = width; init_data.height = height; init_data.channels = channels; init_data.predivide = predivide; + init_data.float_from_byte = float_from_byte; IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data, processor_transform_init_handle, do_processor_transform_thread); @@ -1631,8 +1671,10 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei /*********************** Color space transformation functions *************************/ /* convert the whole buffer from specified by name color space to another - internal implementation */ -static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace, - const char *to_colorspace, bool predivide, bool do_threaded) +static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace, + bool predivide, bool do_threaded) { ColormanageProcessor *cm_processor; @@ -1649,10 +1691,19 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); - if (do_threaded) - processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide); - else - IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide); + if (do_threaded) { + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, predivide, false); + } + else { + if (byte_buffer != NULL) { + IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels); + } + if (float_buffer != NULL) { + IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide); + } + } IMB_colormanagement_processor_free(cm_processor); } @@ -1661,7 +1712,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); } /* convert the whole buffer from specified by name color space to another @@ -1670,7 +1721,54 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); + colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); +} + +/* Similar to functions above, but operates on byte buffer. */ +void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false); +} +void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true); +} + +/* Similar to above, but gets float buffer from display one. */ +void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + IMB_buffer_float_from_byte(float_buffer, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, + true, + width, height, width, width); + IMB_colormanagement_transform(float_buffer, + width, height, channels, + from_colorspace, to_colorspace, + true); +} +void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer, + int width, int height, int channels, + const char *from_colorspace, const char *to_colorspace) +{ + ColormanageProcessor *cm_processor; + if (from_colorspace == NULL || from_colorspace[0] == '\0') { + return; + } + if (STREQ(from_colorspace, to_colorspace)) { + /* If source and destination color spaces are identical, skip + * threading overhead and simply do nothing + */ + return; + } + cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace); + processor_transform_apply_threaded(byte_buffer, float_buffer, + width, height, channels, + cm_processor, true, true); + IMB_colormanagement_processor_free(cm_processor); } void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) @@ -1974,12 +2072,14 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float); float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space"); + /* TODO(sergey): Convert float directly to byte buffer. */ + memcpy(display_buffer_float, buffer, float_buffer_size); cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); - processor_transform_apply_threaded(display_buffer_float, width, height, channels, - cm_processor, true); + processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels, + cm_processor, true, false); IMB_buffer_byte_from_float(display_buffer, display_buffer_float, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, @@ -3100,6 +3200,25 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo } } +void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor, + unsigned char *buffer, + int width, int height, int channels) +{ + /* TODO(sergey): Would be nice to support arbitrary channels configurations, + * but for now it's not so important. + */ + BLI_assert(channels == 4); + float pixel[4]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + size_t offset = channels * (((size_t)y) * width + x); + rgba_uchar_to_float(pixel, buffer + offset); + IMB_colormanagement_processor_apply_v4(cm_processor, pixel); + rgba_float_to_uchar(buffer + offset, pixel); + } + } +} + void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) { if (cm_processor->curve_mapping) |