diff options
Diffstat (limited to 'source/blender/imbuf/intern/colormanagement.c')
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 130 |
1 files changed, 89 insertions, 41 deletions
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 86f47fe07c4..23804291a65 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1353,6 +1353,23 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c display_buffer_init_handle, do_display_buffer_apply_thread); } +static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) +{ + if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && + view_settings->exposure == 0.0f && + view_settings->gamma == 1.0f) + { + const char *from_colorspace = ibuf->rect_colorspace->name; + const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings); + + if (to_colorspace && !strcmp(from_colorspace, to_colorspace)) + return TRUE; + } + + return FALSE; +} + static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) @@ -1366,16 +1383,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu * computation noticeable faster */ if (ibuf->rect_float == NULL && ibuf->rect_colorspace) { - if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && - view_settings->exposure == 0.0f && - view_settings->gamma == 1.0f) - { - const char *from_colorspace = ibuf->rect_colorspace->name; - const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings); - - if (to_colorspace && !strcmp(from_colorspace, to_colorspace)) - skip_transform = TRUE; - } + skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); } if (skip_transform == FALSE) @@ -2110,7 +2118,7 @@ static void colormanage_description_strip(char *description) { int i, n; - for (i = strlen(description) - 1; i >= 0; i--) { + for (i = (int)strlen(description) - 1; i >= 0; i--) { if (ELEM(description[i], '\r', '\n')) { description[i] = '\0'; } @@ -2332,37 +2340,67 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; if (dither != 0.0f) { + /* cm_processor is NULL in cases byte_buffer's space matches display + * buffer's space + * in this case we could skip extra transform and only apply dither + * use 4 channels for easier byte->float->byte conversion here so + * (this is only needed to apply dither, in other cases we'll convert + * byte buffer to display directly) + */ + if (!cm_processor) + channels = 4; + display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither"); } - for (y = ymin; y < ymax; y++) { - for (x = xmin; x < xmax; x++) { - int display_index = (y * display_stride + x) * channels; - int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; - float pixel[4]; - - if (linear_buffer) { - copy_v4_v4(pixel, (float *) linear_buffer + linear_index); - } - else if (byte_buffer) { - rgba_uchar_to_float(pixel, byte_buffer + linear_index); - IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); - straight_to_premul_v4(pixel); - } - - if (!is_data) { - IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel); + if (cm_processor) { + for (y = ymin; y < ymax; y++) { + for (x = xmin; x < xmax; x++) { + int display_index = (y * display_stride + x) * channels; + int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels; + float pixel[4]; + + if (linear_buffer) { + copy_v4_v4(pixel, (float *) linear_buffer + linear_index); + } + else if (byte_buffer) { + rgba_uchar_to_float(pixel, byte_buffer + linear_index); + IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); + straight_to_premul_v4(pixel); + } + + if (!is_data) { + IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel); + } + + if (display_buffer_float) { + int index = ((y - ymin) * width + (x - xmin)) * channels; + + copy_v4_v4(display_buffer_float + index, pixel); + } + else { + float pixel_straight[4]; + premul_to_straight_v4_v4(pixel_straight, pixel); + rgba_float_to_uchar(display_buffer + display_index, pixel_straight); + } } + } + } + else { + if (display_buffer_float) { + /* huh, for dither we need float buffer first, no cheaper way. currently */ + IMB_buffer_float_from_byte(display_buffer_float, byte_buffer, + IB_PROFILE_SRGB, IB_PROFILE_SRGB, TRUE, + width, height, width, display_stride); + } + else { + int i, width = xmax - xmin; - if (display_buffer_float) { - int index = ((y - ymin) * width + (x - xmin)) * channels; + for (i = ymin; i < ymax; i++) { + int byte_offset = (linear_stride * i + xmin) * 4; + int display_offset = (display_stride * i + xmin) * 4; - copy_v4_v4(display_buffer_float + index, pixel); - } - else { - float pixel_straight[4]; - premul_to_straight_v4_v4(pixel_straight, pixel); - rgba_float_to_uchar(display_buffer + display_index, pixel_straight); + memcpy(display_buffer + display_offset, byte_buffer + byte_offset, 4 * sizeof(char) * width); } } } @@ -2371,7 +2409,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe int display_index = (ymin * display_stride + xmin) * channels; IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither, - IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, width, height, display_stride, width); + IB_PROFILE_SRGB, IB_PROFILE_SRGB, TRUE, width, height, display_stride, width); MEM_freeN(display_buffer_float); } @@ -2426,14 +2464,24 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, BLI_unlock_thread(LOCK_COLORMANAGE); if (display_buffer) { - ColormanageProcessor *cm_processor; + ColormanageProcessor *cm_processor = NULL; + int skip_transform = 0; + + /* byte buffer is assumed to be in imbuf's rect space, so if byte buffer + * is known we could skip display->linear->display conversion in case + * display color space matches imbuf's rect space + */ + if (byte_buffer != NULL) + skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); - cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); + if (!skip_transform) + cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); partial_buffer_update_rect(ibuf, display_buffer, linear_buffer, byte_buffer, buffer_width, stride, - offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax); + offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax); - IMB_colormanagement_processor_free(cm_processor); + if (cm_processor) + IMB_colormanagement_processor_free(cm_processor); IMB_display_buffer_release(cache_handle); } |