diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-05-18 21:52:20 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-05-19 15:36:42 +0300 |
commit | 7aaa7aa9dd79b8c6e37f351fd67a93ba07fbb883 (patch) | |
tree | 6d64084b9b104ad3d9f2bbff2b3d0404ec356862 /source/blender/imbuf/intern/colormanagement.c | |
parent | 3b23b5c638feae0ad6319440771b83a64a1f9ebe (diff) |
Images: change alpha settings to support channel packing
This also replaces the Use Alpha setting. We now have these alpha modes:
* Straight: store RGB and alpha channels separately with alpha acting as a
mask, also known as unassociated alpha.
* Premultiplied: transparent RGB pixels are multiplied by the alpha channel.
The natural format for renders.
* Channel Packed: different images are packed in the RGB and alpha channels,
and they should not influence each other. Channel packing is commonly used
by game engines to save memory.
* None: ignore alpha channel from the file and make image fully opaque.
Cycles OSL does not correctly support Channel Packed and None yet, we are
missing fine control over the OpenImageIO texture cache to do that.
Fixes T53672
Diffstat (limited to 'source/blender/imbuf/intern/colormanagement.c')
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index ba0f10446a1..8a10af7e184 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1057,13 +1057,19 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) if (ibuf->rect_float) { const char *to_colorspace = global_role_scene_linear; + const bool predivide = IMB_alpha_affects_rgb(ibuf); if (ibuf->rect) { imb_freerectImBuf(ibuf); } - IMB_colormanagement_transform( - ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, true); + IMB_colormanagement_transform(ibuf->rect_float, + ibuf->x, + ibuf->y, + ibuf->channels, + from_colorspace, + to_colorspace, + predivide); } } @@ -1405,6 +1411,7 @@ typedef struct DisplayBufferThread { int channels; float dither; bool is_data; + bool predivide; const char *byte_colorspace; const char *float_colorspace; @@ -1469,6 +1476,7 @@ static void display_buffer_init_handle(void *handle_v, handle->channels = channels; handle->dither = dither; handle->is_data = is_data; + handle->predivide = IMB_alpha_affects_rgb(ibuf); handle->byte_colorspace = init_data->byte_colorspace; handle->float_colorspace = init_data->float_colorspace; @@ -1486,6 +1494,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, bool is_data = handle->is_data; bool is_data_display = handle->cm_processor->is_data_result; + bool predivide = handle->predivide; if (!handle->buffer) { unsigned char *byte_buffer = handle->byte_buffer; @@ -1534,7 +1543,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, if (!is_data && !is_data_display) { IMB_colormanagement_transform( - linear_buffer, width, height, channels, from_colorspace, to_colorspace, true); + linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide); } *is_straight_alpha = false; @@ -1590,13 +1599,13 @@ static void *do_display_buffer_apply_thread(void *handle_v) } } else { - bool is_straight_alpha, predivide; + bool is_straight_alpha; float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), "color conversion linear buffer"); display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); - predivide = is_straight_alpha == false; + bool predivide = handle->predivide && (is_straight_alpha == false); if (is_data) { /* special case for data buffers - no color space conversions, @@ -2178,6 +2187,7 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, /* TODO(brecht): make this multithreaded, or at least process in batches. */ const unsigned char *in_buffer = (unsigned char *)ibuf->rect; + const bool use_premultiply = IMB_alpha_affects_rgb(ibuf); for (int y = 0; y < height; y++) { const size_t in_offset = (offset_y + y) * ibuf->x + offset_x; @@ -2192,11 +2202,13 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, rgba_uchar_to_float(pixel, in); OCIO_processorApplyRGB(processor, pixel); linearrgb_to_srgb_v3_v3(pixel, pixel); - mul_v3_fl(pixel, pixel[3]); + if (use_premultiply) { + mul_v3_fl(pixel, pixel[3]); + } rgba_float_to_uchar(out, pixel); } } - else { + else if (use_premultiply) { /* Premultiply only. */ for (int x = 0; x < width; x++, in += 4, out += 4) { out[0] = (in[0] * in[3]) >> 8; @@ -2205,6 +2217,15 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer, out[3] = in[3]; } } + else { + /* Copy only. */ + for (int x = 0; x < width; x++, in += 4, out += 4) { + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + } + } } } |