From 78e7b20c0f8dd2e76148f351ef1104375a4a1c94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 7 May 2022 19:11:34 +0200 Subject: Fix T96683: Mipmaps are inaccurate for UDIM textures For some reasons the mipmap count was not set to max during creation. Probably it was mistaken with the UDIM tilemap texture which is only 1D and has only one mipmap. --- source/blender/imbuf/intern/util_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 5abbc84b0ea..8da9eb9ccf7 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -154,7 +154,7 @@ GPUTexture *IMB_touch_gpu_texture( GPUTexture *tex; if (layers > 0) { - tex = GPU_texture_create_2d_array(name, w, h, layers, 1, tex_format, NULL); + tex = GPU_texture_create_2d_array(name, w, h, layers, 9999, tex_format, NULL); } else { tex = GPU_texture_create_2d(name, w, h, 9999, tex_format, NULL); -- cgit v1.2.3 From 78f61bf8c13460f8065eaa8eabaa2ac5a4c66a5e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 9 May 2022 17:17:03 +0200 Subject: Fix T97906: OpenEXR files with lower case xyz channel names not read correctly Adds some utility functions to avoid using toupper() which depends on the locale and should not be used for this type of parsing. --- .../blender/imbuf/intern/openexr/openexr_api.cpp | 31 +++++++++++----------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 9948aaac5da..2281d8d85b3 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1394,12 +1394,10 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa const char *name = echan->m->name.c_str(); const char *end = name + strlen(name); const char *token; - char tokenbuf[EXR_TOT_MAXNAME]; - int len; /* some multilayers have the combined buffer with names A B G R saved */ if (name[1] == 0) { - echan->chan_id = name[0]; + echan->chan_id = BLI_toupper_ascii(name[0]); layname[0] = '\0'; if (ELEM(name[0], 'R', 'G', 'B', 'A')) { @@ -1416,13 +1414,17 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa } /* last token is channel identifier */ - len = imb_exr_split_token(name, end, &token); + size_t len = imb_exr_split_token(name, end, &token); if (len == 0) { printf("multilayer read: bad channel name: %s\n", name); return 0; } + + char channelname[EXR_TOT_MAXNAME]; + BLI_strncpy(channelname, token, std::min(len + 1, sizeof(channelname))); + if (len == 1) { - echan->chan_id = token[0]; + echan->chan_id = BLI_toupper_ascii(channelname[0]); } else if (len > 1) { bool ok = false; @@ -1436,36 +1438,35 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa * * Here we do some magic to distinguish such cases. */ - if (ELEM(token[1], 'X', 'Y', 'Z') || ELEM(token[1], 'R', 'G', 'B') || - ELEM(token[1], 'U', 'V', 'A')) { - echan->chan_id = token[1]; + const char chan_id = BLI_toupper_ascii(channelname[1]); + if (ELEM(chan_id, 'X', 'Y', 'Z', 'R', 'G', 'B', 'U', 'V', 'A')) { + echan->chan_id = chan_id; ok = true; } } - else if (BLI_strcaseeq(token, "red")) { + else if (BLI_strcaseeq(channelname, "red")) { echan->chan_id = 'R'; ok = true; } - else if (BLI_strcaseeq(token, "green")) { + else if (BLI_strcaseeq(channelname, "green")) { echan->chan_id = 'G'; ok = true; } - else if (BLI_strcaseeq(token, "blue")) { + else if (BLI_strcaseeq(channelname, "blue")) { echan->chan_id = 'B'; ok = true; } - else if (BLI_strcaseeq(token, "alpha")) { + else if (BLI_strcaseeq(channelname, "alpha")) { echan->chan_id = 'A'; ok = true; } - else if (BLI_strcaseeq(token, "depth")) { + else if (BLI_strcaseeq(channelname, "depth")) { echan->chan_id = 'Z'; ok = true; } if (ok == false) { - BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME)); - printf("multilayer read: unknown channel token: %s\n", tokenbuf); + printf("multilayer read: unknown channel token: %s\n", channelname); return 0; } } -- cgit v1.2.3 From 17ab0342acfd36a15812011311d8be88cf782192 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 11 May 2022 10:03:17 +1000 Subject: Cleanup: spelling in comments Revert change from [0] that assumed UNORM was a mis-spelling of UNIFORM. [0]: 2c75857f9fc0dc5d524e4a0407e0a68856e5906e --- source/blender/imbuf/intern/jpeg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 80fcceb0aa7..cffa61977f7 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -286,8 +286,8 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, } if (max_size > 0) { - /* libjpeg can more quickly decompress while scaling down to 1/2, 1/4, 1/8, - * while libjpeg-turbo can also do 3/8, 5/8, etc. But max is 1/8. */ + /* `libjpeg` can more quickly decompress while scaling down to 1/2, 1/4, 1/8, + * while `libjpeg-turbo` can also do 3/8, 5/8, etc. But max is 1/8. */ float scale = (float)max_size / MAX2(cinfo->image_width, cinfo->image_height); cinfo->scale_denom = 8; cinfo->scale_num = max_uu(1, min_uu(8, ceill(scale * (float)cinfo->scale_denom))); @@ -520,9 +520,9 @@ struct ImBuf *imb_thumbnail_jpeg(const char *filepath, if ((fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_SOI) && (fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_APP1)) { - /* This is a JPEG in Exif format (SOI + APP1), not JFIF (SOI + APP0). */ + /* This is a JPEG in EXIF format (SOI + APP1), not JFIF (SOI + APP0). */ unsigned int i = JPEG_APP1_MAX; - /* All Exif data is within this 64K header segment. Skip ahead until next SOI for thumbnail. */ + /* All EXIF data is within this 64K header segment. Skip ahead until next SOI for thumbnail. */ while (!((fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_SOI)) && !feof(infile) && i--) ; -- cgit v1.2.3 From b30cb05c14a9061f53367e9a4ad76d39dc62d7ee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 11 May 2022 17:01:06 +1000 Subject: Cleanup: spelling in comments/strings D14918 from @linux_dr with some other changes included. --- source/blender/imbuf/intern/anim_movie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 096089d4c41..0052ce19aa1 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -423,7 +423,7 @@ static int startavi(struct anim *anim) anim->cur_position = 0; # if 0 - printf("x:%d y:%d size:%d interl:%d dur:%d\n", + printf("x:%d y:%d size:%d interlace:%d dur:%d\n", anim->x, anim->y, anim->framesize, -- cgit v1.2.3 From 906b9f55afbf132218a3dc815da2652fbc502352 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 12 May 2022 22:46:15 +0200 Subject: Cleanup: remove redundant float to byte conversion for stereo image saving For non-stereo cases this is automatically handled by IMB_saveiff, no reason for stereo to do this separately. Ref D14899 --- source/blender/imbuf/intern/util.c | 11 ---------- source/blender/imbuf/intern/writeimage.c | 37 +++++++++----------------------- 2 files changed, 10 insertions(+), 38 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 45b50c866fe..ffa989a29b4 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -390,14 +390,3 @@ bool IMB_isanim(const char *filepath) return (type && type != ANIM_SEQUENCE); } - -bool IMB_isfloat(const ImBuf *ibuf) -{ - const ImFileType *type = IMB_file_type_from_ibuf(ibuf); - if (type != NULL) { - if (type->flag & IM_FTYPE_FLOAT) { - return true; - } - } - return false; -} diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c index 56c9384a330..d2c0b61c1c5 100644 --- a/source/blender/imbuf/intern/writeimage.c +++ b/source/blender/imbuf/intern/writeimage.c @@ -19,11 +19,6 @@ #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" -static bool prepare_write_imbuf(const ImFileType *type, ImBuf *ibuf) -{ - return IMB_prepare_write_ImBuf((type->flag & IM_FTYPE_FLOAT), ibuf); -} - bool IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags) { errno = 0; @@ -36,34 +31,22 @@ bool IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags) ibuf->flags = flags; const ImFileType *type = IMB_file_type_from_ibuf(ibuf); - if (type != NULL) { - if (type->save != NULL) { - prepare_write_imbuf(type, ibuf); - return type->save(ibuf, filepath, flags); - } + if (type == NULL || type->save == NULL) { + fprintf(stderr, "Couldn't save picture.\n"); + return false; } - fprintf(stderr, "Couldn't save picture.\n"); - - return false; -} - -bool IMB_prepare_write_ImBuf(const bool isfloat, ImBuf *ibuf) -{ - bool changed = false; - - if (isfloat) { - /* pass */ - } - else { + /* If writing byte image from float buffer, create a byte buffer for writing. + * + * For color managed image writing, IMB_colormanagement_imbuf_for_write should + * have already created this byte buffer. This is a basic fallback for other + * cases where we do not have a specific desired output colorspace. */ + if (!(type->flag & IM_FTYPE_FLOAT)) { if (ibuf->rect == NULL && ibuf->rect_float) { ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE); IMB_rect_from_float(ibuf); - if (ibuf->rect != NULL) { - changed = true; - } } } - return changed; + return type->save(ibuf, filepath, flags); } -- cgit v1.2.3 From 427a2c920a249c066e324e4a5e40dd141a4968aa Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 13 May 2022 09:24:28 +1000 Subject: Cleanup: spelling in comments, capitalize tags Also add missing task-ID reference & remove colon after \note as it doesn't render properly in doxygen. --- source/blender/imbuf/intern/dds/Stream.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp index 34f3654aa3f..566891dac8b 100644 --- a/source/blender/imbuf/intern/dds/Stream.cpp +++ b/source/blender/imbuf/intern/dds/Stream.cpp @@ -45,7 +45,7 @@ unsigned int mem_read(Stream &mem, unsigned long long &i) mem.set_failed(msg_error_seek); return 0; } - memcpy(&i, mem.mem + mem.pos, 8); /* @@ todo: make sure little endian */ + memcpy(&i, mem.mem + mem.pos, 8); /* TODO: make sure little endian. */ mem.pos += 8; return 8; } @@ -56,7 +56,7 @@ unsigned int mem_read(Stream &mem, unsigned int &i) mem.set_failed(msg_error_read); return 0; } - memcpy(&i, mem.mem + mem.pos, 4); /* @@ todo: make sure little endian */ + memcpy(&i, mem.mem + mem.pos, 4); /* TODO: make sure little endian. */ mem.pos += 4; return 4; } @@ -67,7 +67,7 @@ unsigned int mem_read(Stream &mem, unsigned short &i) mem.set_failed(msg_error_read); return 0; } - memcpy(&i, mem.mem + mem.pos, 2); /* @@ todo: make sure little endian */ + memcpy(&i, mem.mem + mem.pos, 2); /* TODO: make sure little endian. */ mem.pos += 2; return 2; } -- cgit v1.2.3 From 5baa3ecda66337c0584f0bc6c6e7af0a6c0f6320 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 13 May 2022 16:03:26 +0200 Subject: Color Management: various improvements and fixes for image saving * Respect the image file color space setitng for saving in various cases where it was previously ignored. Previously it would often use the sRGB or Linear color space even when not selected. * For the Save As operator, add a Color Space option in the file browser to choose the color space of the file. Previously this was chosen automatically, now it's possible to e.g. resave a Linear image as Linear ACES. * When changing the file format, the colorspace is automatically changed to an appropriate color space for the file format. This already happened before, but there was no visibility or control in the operator settings for this. * Don't change color space when using the Save operator to save over the same file. * Fix missing color space conversion for 16 bit PNGs, where it assumed wrongly assumed ibuf->rect would be used for saving. Add BKE_image_format_is_byte to more accurately test this. Fixes T74610 Ref T68926 Differential Revision: https://developer.blender.org/D14899 --- source/blender/imbuf/intern/colormanagement.c | 209 +++++++++++++++----------- 1 file changed, 122 insertions(+), 87 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 53aa74edc61..1613595148b 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -2445,68 +2445,77 @@ void IMB_colormanagement_imbuf_make_display_space( colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, false); } +static ImBuf *imbuf_ensure_editable(ImBuf *ibuf, ImBuf *colormanaged_ibuf, bool allocate_result) +{ + if (colormanaged_ibuf != ibuf) { + /* Is already an editable copy. */ + return colormanaged_ibuf; + } + + if (allocate_result) { + /* Copy full image buffer. */ + colormanaged_ibuf = IMB_dupImBuf(ibuf); + IMB_metadata_copy(colormanaged_ibuf, ibuf); + return colormanaged_ibuf; + } + else { + /* Render pipeline is constructing image buffer itself, + * but it's re-using byte and float buffers from render result make copy of this buffers + * here sine this buffers would be transformed to other color space here. */ + if (ibuf->rect && (ibuf->mall & IB_rect) == 0) { + ibuf->rect = MEM_dupallocN(ibuf->rect); + ibuf->mall |= IB_rect; + } + + if (ibuf->rect_float && (ibuf->mall & IB_rectfloat) == 0) { + ibuf->rect_float = MEM_dupallocN(ibuf->rect_float); + ibuf->mall |= IB_rectfloat; + } + + return ibuf; + } +} + ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, bool allocate_result, const ImageFormatData *image_format) { ImBuf *colormanaged_ibuf = ibuf; - const bool is_movie = BKE_imtype_is_movie(image_format->imtype); - const bool requires_linear_float = BKE_imtype_requires_linear_float(image_format->imtype); - const bool do_alpha_under = image_format->planes != R_IMF_PLANES_RGBA; + /* Update byte buffer if exists but invalid. */ if (ibuf->rect_float && ibuf->rect && (ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)) != 0) { IMB_rect_from_float(ibuf); ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID); } - const bool do_colormanagement_display = save_as_render && (is_movie || !requires_linear_float); - const bool do_colormanagement_linear = save_as_render && requires_linear_float && - image_format->linear_colorspace_settings.name[0] && - !IMB_colormanagement_space_name_is_scene_linear( - image_format->linear_colorspace_settings.name); - - if (do_colormanagement_display || do_colormanagement_linear || do_alpha_under) { - if (allocate_result) { - colormanaged_ibuf = IMB_dupImBuf(ibuf); - } - else { - /* Render pipeline is constructing image buffer itself, - * but it's re-using byte and float buffers from render result make copy of this buffers - * here sine this buffers would be transformed to other color space here. - */ + /* Detect if we are writing to a file format that needs a linear float buffer. */ + const bool linear_float_output = BKE_imtype_requires_linear_float(image_format->imtype); - if (ibuf->rect && (ibuf->mall & IB_rect) == 0) { - ibuf->rect = MEM_dupallocN(ibuf->rect); - ibuf->mall |= IB_rect; - } + /* Detect if we are writing output a byte buffer, which we would need to create + * with color management conversions applied. This may be for either applying the + * display transform for renders, or a user specified color space for the file. */ + const bool byte_output = BKE_image_format_is_byte(image_format); - if (ibuf->rect_float && (ibuf->mall & IB_rectfloat) == 0) { - ibuf->rect_float = MEM_dupallocN(ibuf->rect_float); - ibuf->mall |= IB_rectfloat; - } - } - } + BLI_assert(!(byte_output && linear_float_output)); - /* If we're saving from RGBA to RGB buffer then it's not - * so much useful to just ignore alpha -- it leads to bad - * artifacts especially when saving byte images. - * - * What we do here is we're overlaying our image on top of - * background color (which is currently black). + /* If we're saving from RGBA to RGB buffer then it's not so much useful to just ignore alpha -- + * it leads to bad artifacts especially when saving byte images. * - * This is quite much the same as what Gimp does and it - * seems to be what artists expects from saving. + * What we do here is we're overlaying our image on top of background color (which is currently + * black). This is quite much the same as what Gimp does and it seems to be what artists expects + * from saving. * - * Do a conversion here, so image format writers could - * happily assume all the alpha tricks were made already. - * helps keep things locally here, not spreading it to - * all possible image writers we've got. + * Do a conversion here, so image format writers could happily assume all the alpha tricks were + * made already. helps keep things locally here, not spreading it to all possible image writers + * we've got. */ - if (do_alpha_under) { + if (image_format->planes != R_IMF_PLANES_RGBA) { float color[3] = {0, 0, 0}; + colormanaged_ibuf = imbuf_ensure_editable(ibuf, colormanaged_ibuf, allocate_result); + if (colormanaged_ibuf->rect_float && colormanaged_ibuf->channels == 4) { IMB_alpha_under_color_float( colormanaged_ibuf->rect_float, colormanaged_ibuf->x, colormanaged_ibuf->y, color); @@ -2520,69 +2529,95 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, } } - if (do_colormanagement_display) { - /* Color management with display and view transform. */ - bool make_byte = false; + if (save_as_render && !linear_float_output) { + /* Render output: perform conversion to display space using view transform. */ + colormanaged_ibuf = imbuf_ensure_editable(ibuf, colormanaged_ibuf, allocate_result); - /* for proper check whether byte buffer is required by a format or not - * should be pretty safe since this image buffer is supposed to be used for - * saving only and ftype would be overwritten a bit later by BKE_imbuf_write - */ - colormanaged_ibuf->ftype = BKE_imtype_to_ftype(image_format->imtype, - &colormanaged_ibuf->foptions); - - /* if file format isn't able to handle float buffer itself, - * we need to allocate byte buffer and store color managed - * image there - */ - const ImFileType *type = IMB_file_type_from_ibuf(colormanaged_ibuf); - if (type != NULL) { - if ((type->save != NULL) && (type->flag & IM_FTYPE_FLOAT) == 0) { - make_byte = true; - } - } - - /* perform color space conversions */ colormanagement_imbuf_make_display_space(colormanaged_ibuf, &image_format->view_settings, &image_format->display_settings, - make_byte); + byte_output); if (colormanaged_ibuf->rect_float) { - /* float buffer isn't linear anymore, + /* Float buffer isn't linear anymore, * image format write callback should check for this flag and assume - * no space conversion should happen if ibuf->float_colorspace != NULL - */ + * no space conversion should happen if ibuf->float_colorspace != NULL. */ colormanaged_ibuf->float_colorspace = display_transform_get_colorspace( &image_format->view_settings, &image_format->display_settings); + if (byte_output) { + colormanaged_ibuf->rect_colorspace = colormanaged_ibuf->float_colorspace; + } } } - else if (do_colormanagement_linear) { - /* Color management transform to another linear color space. */ - if (!colormanaged_ibuf->rect_float) { - IMB_float_from_rect(colormanaged_ibuf); - imb_freerectImBuf(colormanaged_ibuf); + else { + /* Linear render or regular file output: conversion between two color spaces. */ + + /* Detect which color space we need to convert between. */ + const char *from_colorspace = (ibuf->rect_float && !(byte_output && ibuf->rect)) ? + /* From float buffer. */ + (ibuf->float_colorspace) ? ibuf->float_colorspace->name : + global_role_scene_linear : + /* From byte buffer. */ + (ibuf->rect_colorspace) ? ibuf->rect_colorspace->name : + global_role_default_byte; + + const char *to_colorspace = image_format->linear_colorspace_settings.name; + + /* TODO: can we check with OCIO if color spaces are the same but have different names? */ + if (to_colorspace[0] == '\0' || STREQ(from_colorspace, to_colorspace)) { + /* No conversion needed, but may still need to allocate byte buffer for output. */ + if (byte_output && !ibuf->rect) { + ibuf->rect_colorspace = ibuf->float_colorspace; + IMB_rect_from_float(ibuf); + } } + else { + /* Color space conversion needed. */ + colormanaged_ibuf = imbuf_ensure_editable(ibuf, colormanaged_ibuf, allocate_result); + + if (byte_output) { + colormanaged_ibuf->rect_colorspace = colormanage_colorspace_get_named(to_colorspace); + + if (colormanaged_ibuf->rect) { + /* Byte to byte. */ + IMB_colormanagement_transform_byte_threaded((unsigned char *)colormanaged_ibuf->rect, + colormanaged_ibuf->x, + colormanaged_ibuf->y, + colormanaged_ibuf->channels, + from_colorspace, + to_colorspace); + } + else { + /* Float to byte. */ + IMB_rect_from_float(colormanaged_ibuf); + } + } + else { + if (!colormanaged_ibuf->rect_float) { + /* Byte to float. */ + IMB_float_from_rect(colormanaged_ibuf); + imb_freerectImBuf(colormanaged_ibuf); - if (colormanaged_ibuf->rect_float) { - const char *from_colorspace = (ibuf->float_colorspace) ? ibuf->float_colorspace->name : - global_role_scene_linear; - const char *to_colorspace = image_format->linear_colorspace_settings.name; + /* This conversion always goes to scene linear. */ + from_colorspace = global_role_scene_linear; + } - IMB_colormanagement_transform(colormanaged_ibuf->rect_float, - colormanaged_ibuf->x, - colormanaged_ibuf->y, - colormanaged_ibuf->channels, - from_colorspace, - to_colorspace, - false); + if (colormanaged_ibuf->rect_float) { + /* Float to float. */ + IMB_colormanagement_transform(colormanaged_ibuf->rect_float, + colormanaged_ibuf->x, + colormanaged_ibuf->y, + colormanaged_ibuf->channels, + from_colorspace, + to_colorspace, + false); + + colormanaged_ibuf->float_colorspace = colormanage_colorspace_get_named(to_colorspace); + } + } } } - if (colormanaged_ibuf != ibuf) { - IMB_metadata_copy(colormanaged_ibuf, ibuf); - } - return colormanaged_ibuf; } -- cgit v1.2.3 From 7bbf1010825106629b1619852d463b5949d0f160 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2022 10:24:26 +1000 Subject: Cleanup: better doc-string for iris, order args & use const variables --- source/blender/imbuf/intern/iris.c | 47 ++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index eb0a2c4a47f..c3d940d85be 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -105,7 +105,7 @@ static int expandrow2( float *optr, const float *optr_end, const uchar *iptr, const uchar *iptr_end, int z); static void interleaverow(uchar *lptr, const uchar *cptr, int z, int n); static void interleaverow2(float *lptr, const uchar *cptr, int z, int n); -static int compressrow(uchar *lbuf, uchar *rlebuf, int z, int row_len); +static int compressrow(const uchar *lbuf, uchar *rlebuf, int z, int row_len); static void lumrow(const uchar *rgbptr, uchar *lumptr, int n); /* @@ -779,18 +779,24 @@ fail: } /** - * Copy an array of ints to an iris image file. - * Each int represents one pixel. xsize and ysize specify the dimensions of - * the pixel array. zsize specifies what kind of image file to - * write out. if zsize is 1, the luminance of the pixels are - * calculated, and a single channel black and white image is saved. - * If zsize is 3, an RGB image file is saved. If zsize is 4, an - * RGBA image file is saved. - * - * Added: zbuf write + * \param filepath: The file path to write to. + * \param lptr: an array of integers to an iris image file (each int represents one pixel). + * \param zptr: depth-buffer (optional, may be NULL). + * \param xsize: with width of the pixel-array. + * \param ysize: height of the pixel-array. + * \param zsize: specifies what kind of image file to write out. + * - 1: the luminance of the pixels are calculated, + * and a single channel black and white image is saved. + * - 3: an RGB image file is saved. + * - 4: an RGBA image file is saved. + * - 8: an RGBA image and a Z-buffer (non-null `zptr`). */ - -static bool output_iris(uint *lptr, int xsize, int ysize, int zsize, const char *name, int *zptr) +static bool output_iris(const char *filepath, + const uint *lptr, + const int *zptr, + const int xsize, + const int ysize, + const int zsize) { FILE *outf; IMAGE *image; @@ -801,7 +807,7 @@ static bool output_iris(uint *lptr, int xsize, int ysize, int zsize, const char int rlebuflen, goodwrite; goodwrite = 1; - outf = BLI_fopen(name, "wb"); + outf = BLI_fopen(filepath, "wb"); if (!outf) { return 0; } @@ -837,15 +843,15 @@ static bool output_iris(uint *lptr, int xsize, int ysize, int zsize, const char for (z = 0; z < zsize; z++) { if (zsize == 1) { - lumrow((uchar *)lptr, (uchar *)lumbuf, xsize); - len = compressrow((uchar *)lumbuf, rlebuf, CHANOFFSET(z), xsize); + lumrow((const uchar *)lptr, (uchar *)lumbuf, xsize); + len = compressrow((const uchar *)lumbuf, rlebuf, CHANOFFSET(z), xsize); } else { if (z < 4) { - len = compressrow((uchar *)lptr, rlebuf, CHANOFFSET(z), xsize); + len = compressrow((const uchar *)lptr, rlebuf, CHANOFFSET(z), xsize); } else if (z < 8 && zptr) { - len = compressrow((uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize); + len = compressrow((const uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize); } } if (len > rlebuflen) { @@ -892,9 +898,10 @@ static void lumrow(const uchar *rgbptr, uchar *lumptr, int n) } } -static int compressrow(uchar *lbuf, uchar *rlebuf, int z, int row_len) +static int compressrow(const uchar *lbuf, uchar *rlebuf, const int z, const int row_len) { - uchar *iptr, *ibufend, *sptr, *optr; + const uchar *iptr, *ibufend, *sptr; + uchar *optr; short todo, cc; int count; @@ -964,7 +971,7 @@ bool imb_saveiris(struct ImBuf *ibuf, const char *filepath, int flags) IMB_convert_rgba_to_abgr(ibuf); test_endian_zbuf(ibuf); - const bool ok = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, filepath, ibuf->zbuf); + const bool ok = output_iris(filepath, ibuf->rect, ibuf->zbuf, ibuf->x, ibuf->y, zsize); /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */ IMB_convert_rgba_to_abgr(ibuf); -- cgit v1.2.3 From 77ddcc471721194531834786c010b9e603cb18d8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2022 10:50:21 +1000 Subject: ImBuf: replace exit(1) with assert when writing IRIS images In this case memory past the buffer bounds would have been written, potentially crashing. Replace the check with an assert since this should never happen. Also don't call exit as failing to write a file shouldn't exit Blender. --- source/blender/imbuf/intern/iris.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index c3d940d85be..a8150fd1648 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -854,10 +854,9 @@ static bool output_iris(const char *filepath, len = compressrow((const uchar *)zptr, rlebuf, CHANOFFSET(z - 4), xsize); } } - if (len > rlebuflen) { - fprintf(stderr, "output_iris: rlebuf is too small - bad poop\n"); - exit(1); - } + + BLI_assert_msg(len <= rlebuflen, "The length calculated for 'rlebuflen' was too small!"); + goodwrite *= fwrite(rlebuf, len, 1, outf); starttab[y + z * ysize] = pos; lengthtab[y + z * ysize] = len; -- cgit v1.2.3 From 5c9ab3e003d2cdca46c078c33c946ec1d7ab7626 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2022 11:38:05 +1000 Subject: Cleanup: use term 'filepath' for full file paths --- source/blender/imbuf/intern/cineon/cineon_dpx.c | 6 +- source/blender/imbuf/intern/cineon/cineonlib.c | 22 +++--- source/blender/imbuf/intern/cineon/cineonlib.h | 2 +- source/blender/imbuf/intern/cineon/dpxlib.c | 18 ++--- source/blender/imbuf/intern/cineon/dpxlib.h | 2 +- source/blender/imbuf/intern/cineon/logImageCore.c | 14 ++-- source/blender/imbuf/intern/cineon/logImageCore.h | 4 +- source/blender/imbuf/intern/indexer.c | 96 +++++++++++------------ source/blender/imbuf/intern/readimage.c | 10 +-- source/blender/imbuf/intern/thumbs.c | 16 ++-- source/blender/imbuf/intern/thumbs_font.c | 4 +- 11 files changed, 97 insertions(+), 97 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index d1cd30cfe84..6448d6cd76a 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -69,7 +69,7 @@ static struct ImBuf *imb_load_dpx_cineon(const unsigned char *mem, return ibuf; } -static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon, int flags) +static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filepath, int use_cineon, int flags) { LogImageFile *logImage; float *fbuf; @@ -86,7 +86,7 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon depth = (ibuf->planes + 7) >> 3; if (depth > 4 || depth < 3) { - printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filename); + printf("DPX/Cineon: unsupported depth: %d for file: '%s'\n", depth, filepath); return 0; } @@ -103,7 +103,7 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon bitspersample = 8; } - logImage = logImageCreate(filename, + logImage = logImageCreate(filepath, use_cineon, ibuf->x, ibuf->y, diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 3bdfcb60292..2f00a64a2cf 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -35,7 +35,7 @@ void cineonSetVerbose(int verbosity) static void fillCineonMainHeader(LogImageFile *cineon, CineonMainHeader *header, - const char *filename, + const char *filepath, const char *creator) { time_t fileClock; @@ -57,7 +57,7 @@ static void fillCineonMainHeader(LogImageFile *cineon, getRowLength(cineon->width, cineon->element[0]), cineon->isMSB); strcpy(header->fileHeader.version, "v4.5"); - strncpy(header->fileHeader.file_name, filename, 99); + strncpy(header->fileHeader.file_name, filepath, 99); header->fileHeader.file_name[99] = 0; fileClock = time(NULL); fileTime = localtime(&fileClock); @@ -126,7 +126,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t { CineonMainHeader header; LogImageFile *cineon = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - const char *filename = (const char *)byteStuff; + const char *filepath = (const char *)byteStuff; int i; unsigned int dataOffset; @@ -144,11 +144,11 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t cineon->file = NULL; if (fromMemory == 0) { - /* byteStuff is then the filename */ - cineon->file = BLI_fopen(filename, "rb"); + /* byteStuff is then the filepath */ + cineon->file = BLI_fopen(filepath, "rb"); if (cineon->file == NULL) { if (verbose) { - printf("Cineon: Failed to open file \"%s\".\n", filename); + printf("Cineon: Failed to open file \"%s\".\n", filepath); } logImageClose(cineon); return NULL; @@ -350,7 +350,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t } LogImageFile *cineonCreate( - const char *filename, int width, int height, int bitsPerSample, const char *creator) + const char *filepath, int width, int height, int bitsPerSample, const char *creator) { CineonMainHeader header; const char *shortFilename = NULL; @@ -393,18 +393,18 @@ LogImageFile *cineonCreate( cineon->referenceBlack = 95.0f; cineon->gamma = 1.7f; - shortFilename = strrchr(filename, '/'); + shortFilename = strrchr(filepath, '/'); if (shortFilename == NULL) { - shortFilename = filename; + shortFilename = filepath; } else { shortFilename++; } - cineon->file = BLI_fopen(filename, "wb"); + cineon->file = BLI_fopen(filepath, "wb"); if (cineon->file == NULL) { if (verbose) { - printf("cineon: Couldn't open file %s\n", filename); + printf("cineon: Couldn't open file %s\n", filepath); } logImageClose(cineon); return NULL; diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index 37b27d19539..13d40461728 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -114,7 +114,7 @@ typedef struct { void cineonSetVerbose(int); LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); LogImageFile *cineonCreate( - const char *filename, int width, int height, int bitsPerSample, const char *creator); + const char *filepath, int width, int height, int bitsPerSample, const char *creator); #ifdef __cplusplus } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 2d28a477c8a..9fbc118913d 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -124,7 +124,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf { DpxMainHeader header; LogImageFile *dpx = (LogImageFile *)MEM_mallocN(sizeof(LogImageFile), __func__); - const char *filename = (const char *)byteStuff; + const char *filepath = (const char *)byteStuff; int i; if (dpx == NULL) { @@ -141,11 +141,11 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf dpx->file = NULL; if (fromMemory == 0) { - /* byteStuff is then the filename */ - dpx->file = BLI_fopen(filename, "rb"); + /* byteStuff is then the filepath */ + dpx->file = BLI_fopen(filepath, "rb"); if (dpx->file == NULL) { if (verbose) { - printf("DPX: Failed to open file \"%s\".\n", filename); + printf("DPX: Failed to open file \"%s\".\n", filepath); } logImageClose(dpx); return NULL; @@ -406,7 +406,7 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf return dpx; } -LogImageFile *dpxCreate(const char *filename, +LogImageFile *dpxCreate(const char *filepath, int width, int height, int bitsPerSample, @@ -502,19 +502,19 @@ LogImageFile *dpxCreate(const char *filename, dpx->gamma = 1.7f; } - shortFilename = strrchr(filename, '/'); + shortFilename = strrchr(filepath, '/'); if (shortFilename == NULL) { - shortFilename = filename; + shortFilename = filepath; } else { shortFilename++; } - dpx->file = BLI_fopen(filename, "wb"); + dpx->file = BLI_fopen(filepath, "wb"); if (dpx->file == NULL) { if (verbose) { - printf("DPX: Couldn't open file %s\n", filename); + printf("DPX: Couldn't open file %s\n", filepath); } logImageClose(dpx); return NULL; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index d8ed5dc6f67..aac424d52d6 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -133,7 +133,7 @@ typedef struct { void dpxSetVerbose(int verbosity); LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t bufferSize); -LogImageFile *dpxCreate(const char *filename, +LogImageFile *dpxCreate(const char *filepath, int width, int height, int bitsPerSample, diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index 36e12e07316..e693aa6f891 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -101,10 +101,10 @@ int logImageIsCineon(const void *buffer, const unsigned int size) return (magicNum == CINEON_FILE_MAGIC || magicNum == swap_uint(CINEON_FILE_MAGIC, 1)); } -LogImageFile *logImageOpenFromFile(const char *filename, int cineon) +LogImageFile *logImageOpenFromFile(const char *filepath, int cineon) { unsigned int magicNum; - FILE *f = BLI_fopen(filename, "rb"); + FILE *f = BLI_fopen(filepath, "rb"); (void)cineon; @@ -120,10 +120,10 @@ LogImageFile *logImageOpenFromFile(const char *filename, int cineon) fclose(f); if (logImageIsDpx(&magicNum, sizeof(magicNum))) { - return dpxOpen((const unsigned char *)filename, 0, 0); + return dpxOpen((const unsigned char *)filepath, 0, 0); } if (logImageIsCineon(&magicNum, sizeof(magicNum))) { - return cineonOpen((const unsigned char *)filename, 0, 0); + return cineonOpen((const unsigned char *)filepath, 0, 0); } return NULL; @@ -141,7 +141,7 @@ LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int s return NULL; } -LogImageFile *logImageCreate(const char *filename, +LogImageFile *logImageCreate(const char *filepath, int cineon, int width, int height, @@ -155,10 +155,10 @@ LogImageFile *logImageCreate(const char *filename, { /* referenceWhite, referenceBlack and gamma values are only supported for DPX file */ if (cineon) { - return cineonCreate(filename, width, height, bitsPerSample, creator); + return cineonCreate(filepath, width, height, bitsPerSample, creator); } - return dpxCreate(filename, + return dpxCreate(filepath, width, height, bitsPerSample, diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h index 6875dba3f87..8366927a95b 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -169,9 +169,9 @@ void logImageSetVerbose(int verbosity); int logImageIsDpx(const void *buffer, unsigned int size); int logImageIsCineon(const void *buffer, unsigned int size); LogImageFile *logImageOpenFromMemory(const unsigned char *buffer, unsigned int size); -LogImageFile *logImageOpenFromFile(const char *filename, int cineon); +LogImageFile *logImageOpenFromFile(const char *filepath, int cineon); void logImageGetSize(LogImageFile *logImage, int *width, int *height, int *depth); -LogImageFile *logImageCreate(const char *filename, +LogImageFile *logImageCreate(const char *filepath, int cineon, int width, int height, diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 1cc91d25d2a..cbc5d984755 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -376,10 +376,10 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc) static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_len) { if (!anim->index_dir[0]) { - char fname[FILE_MAXFILE]; - BLI_split_dirfile(anim->name, index_dir, fname, index_dir_len, sizeof(fname)); + char filename[FILE_MAXFILE]; + BLI_split_dirfile(anim->name, index_dir, filename, index_dir_len, sizeof(filename)); BLI_path_append(index_dir, index_dir_len, "BL_proxy"); - BLI_path_append(index_dir, index_dir_len, fname); + BLI_path_append(index_dir, index_dir_len, filename); } else { BLI_strncpy(index_dir, anim->index_dir, index_dir_len); @@ -388,14 +388,14 @@ static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_l void IMB_anim_get_fname(struct anim *anim, char *file, int size) { - char fname[FILE_MAXFILE]; - BLI_split_dirfile(anim->name, file, fname, size, sizeof(fname)); - BLI_strncpy(file, fname, size); + char filename[FILE_MAXFILE]; + BLI_split_dirfile(anim->name, file, filename, size, sizeof(filename)); + BLI_strncpy(file, filename, size); } -static bool get_proxy_filename(struct anim *anim, +static bool get_proxy_filepath(struct anim *anim, IMB_Proxy_Size preview_size, - char *fname, + char *filepath, bool temp) { char index_dir[FILE_MAXDIR]; @@ -426,11 +426,11 @@ static bool get_proxy_filename(struct anim *anim, return false; } - BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); + BLI_join_dirfile(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, proxy_name); return true; } -static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *fname) +static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *filepath) { char index_dir[FILE_MAXDIR]; int i = IMB_timecode_to_array_index(tc); @@ -457,7 +457,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, char *fname get_index_dir(anim, index_dir, sizeof(index_dir)); - BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); + BLI_join_dirfile(filepath, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); } /* ---------------------------------------------------------------------- @@ -492,18 +492,18 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( { struct proxy_output_ctx *rv = MEM_callocN(sizeof(struct proxy_output_ctx), "alloc_proxy_output"); - char fname[FILE_MAX]; + char filepath[FILE_MAX]; rv->proxy_size = proxy_size; rv->anim = anim; - get_proxy_filename(rv->anim, rv->proxy_size, fname, true); - BLI_make_existing_file(fname); + get_proxy_filepath(rv->anim, rv->proxy_size, filepath, true); + BLI_make_existing_file(filepath); rv->of = avformat_alloc_context(); rv->of->oformat = av_guess_format("avi", NULL, NULL); - rv->of->url = av_strdup(fname); + rv->of->url = av_strdup(filepath); fprintf(stderr, "Starting work on proxy: %s\n", rv->of->url); @@ -577,7 +577,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( avcodec_parameters_from_context(rv->st->codecpar, rv->c); - int ret = avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE); + int ret = avio_open(&rv->of->pb, filepath, AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, @@ -723,8 +723,8 @@ static void add_to_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, AVFrame *fr static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback) { - char fname[FILE_MAX]; - char fname_tmp[FILE_MAX]; + char filepath[FILE_MAX]; + char filepath_tmp[FILE_MAX]; if (!ctx) { return; @@ -755,15 +755,15 @@ static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx, int rollback) av_free(ctx->frame); } - get_proxy_filename(ctx->anim, ctx->proxy_size, fname_tmp, true); + get_proxy_filepath(ctx->anim, ctx->proxy_size, filepath_tmp, true); if (rollback) { - unlink(fname_tmp); + unlink(filepath_tmp); } else { - get_proxy_filename(ctx->anim, ctx->proxy_size, fname, false); - unlink(fname); - BLI_rename(fname_tmp, fname); + get_proxy_filepath(ctx->anim, ctx->proxy_size, filepath, false); + unlink(filepath); + BLI_rename(filepath_tmp, filepath); } MEM_freeN(ctx); @@ -907,11 +907,11 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, for (i = 0; i < num_indexers; i++) { if (tcs_in_use & tc_types[i]) { - char fname[FILE_MAX]; + char filepath[FILE_MAX]; - get_tc_filename(anim, tc_types[i], fname); + get_tc_filename(anim, tc_types[i], filepath); - context->indexer[i] = IMB_index_builder_create(fname); + context->indexer[i] = IMB_index_builder_create(filepath); if (!context->indexer[i]) { tcs_in_use &= ~tc_types[i]; } @@ -1212,7 +1212,7 @@ typedef struct FallbackIndexBuilderContext { } FallbackIndexBuilderContext; static AviMovie *alloc_proxy_output_avi( - struct anim *anim, char *filename, int width, int height, int quality) + struct anim *anim, char *filepath, int width, int height, int quality) { int x, y; AviFormat format; @@ -1233,7 +1233,7 @@ static AviMovie *alloc_proxy_output_avi( format = AVI_FORMAT_MJPEG; - if (AVI_open_compress(filename, avi, 1, format) != AVI_ERROR_NONE) { + if (AVI_open_compress(filepath, avi, 1, format) != AVI_ERROR_NONE) { MEM_freeN(avi); return NULL; } @@ -1275,13 +1275,13 @@ static IndexBuildContext *index_fallback_create_context(struct anim *anim, for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { if (context->proxy_sizes_in_use & proxy_sizes[i]) { - char fname[FILE_MAX]; + char filepath[FILE_MAX]; - get_proxy_filename(anim, proxy_sizes[i], fname, true); - BLI_make_existing_file(fname); + get_proxy_filepath(anim, proxy_sizes[i], filepath, true); + BLI_make_existing_file(filepath); context->proxy_ctx[i] = alloc_proxy_output_avi( - anim, fname, anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality); + anim, filepath, anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality); } } @@ -1291,8 +1291,8 @@ static IndexBuildContext *index_fallback_create_context(struct anim *anim, static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, int stop) { struct anim *anim = context->anim; - char fname[FILE_MAX]; - char fname_tmp[FILE_MAX]; + char filepath[FILE_MAX]; + char filepath_tmp[FILE_MAX]; int i; for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) { @@ -1300,15 +1300,15 @@ static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, AVI_close_compress(context->proxy_ctx[i]); MEM_freeN(context->proxy_ctx[i]); - get_proxy_filename(anim, proxy_sizes[i], fname_tmp, true); - get_proxy_filename(anim, proxy_sizes[i], fname, false); + get_proxy_filepath(anim, proxy_sizes[i], filepath_tmp, true); + get_proxy_filepath(anim, proxy_sizes[i], filepath, false); if (stop) { - unlink(fname_tmp); + unlink(filepath_tmp); } else { - unlink(fname); - rename(fname_tmp, fname); + unlink(filepath); + rename(filepath_tmp, filepath); } } } @@ -1388,7 +1388,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Proxy_Size proxy_size = proxy_sizes[i]; if (proxy_size & proxy_sizes_to_build) { char filename[FILE_MAX]; - if (get_proxy_filename(anim, proxy_size, filename, false) == false) { + if (get_proxy_filepath(anim, proxy_size, filename, false) == false) { return NULL; } void **filename_key_p; @@ -1411,7 +1411,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Proxy_Size proxy_size = proxy_sizes[i]; if (proxy_size & built_proxies) { char filename[FILE_MAX]; - if (get_proxy_filename(anim, proxy_size, filename, false) == false) { + if (get_proxy_filepath(anim, proxy_size, filename, false) == false) { return NULL; } printf("Skipping proxy: %s\n", filename); @@ -1532,7 +1532,7 @@ void IMB_anim_set_index_dir(struct anim *anim, const char *dir) struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size) { - char fname[FILE_MAX]; + char filepath[FILE_MAX]; int i = IMB_proxy_size_to_array_index(preview_size); if (i < 0) { @@ -1547,10 +1547,10 @@ struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size) return NULL; } - get_proxy_filename(anim, preview_size, fname, false); + get_proxy_filepath(anim, preview_size, filepath, false); /* proxies are generated in the same color space as animation itself */ - anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, anim->colorspace); + anim->proxy_anim[i] = IMB_open_anim(filepath, 0, 0, anim->colorspace); anim->proxies_tried |= preview_size; @@ -1559,7 +1559,7 @@ struct anim *IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size) struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc) { - char fname[FILE_MAX]; + char filepath[FILE_MAX]; int i = IMB_timecode_to_array_index(tc); if (i < 0) { @@ -1574,9 +1574,9 @@ struct anim_index *IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc) return NULL; } - get_tc_filename(anim, tc, fname); + get_tc_filename(anim, tc, filepath); - anim->curr_idx[i] = IMB_indexer_open(fname); + anim->curr_idx[i] = IMB_indexer_open(filepath); anim->indices_tried |= tc; @@ -1602,7 +1602,7 @@ IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim) for (i = 0; i < num_proxy_sizes; i++) { IMB_Proxy_Size proxy_size = proxy_sizes[i]; char filename[FILE_MAX]; - get_proxy_filename(anim, proxy_size, filename, false); + get_proxy_filepath(anim, proxy_size, filename, false); if (BLI_exists(filename)) { existing |= proxy_size; } diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 805a7e8d687..4b433836767 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -189,21 +189,21 @@ ImBuf *IMB_loadifffile( return ibuf; } -static void imb_cache_filename(char *filename, const char *name, int flags) +static void imb_cache_filename(char *filepath, const char *name, int flags) { /* read .tx instead if it exists and is not older */ if (flags & IB_tilecache) { - BLI_strncpy(filename, name, IMB_FILENAME_SIZE); - if (!BLI_path_extension_replace(filename, IMB_FILENAME_SIZE, ".tx")) { + BLI_strncpy(filepath, name, IMB_FILENAME_SIZE); + if (!BLI_path_extension_replace(filepath, IMB_FILENAME_SIZE, ".tx")) { return; } - if (BLI_file_older(name, filename)) { + if (BLI_file_older(name, filepath)) { return; } } - BLI_strncpy(filename, name, IMB_FILENAME_SIZE); + BLI_strncpy(filepath, name, IMB_FILENAME_SIZE); } ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]) diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 51951aa9605..f2c9c82fa66 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -466,27 +466,27 @@ static ImBuf *thumb_create_or_fail(const char *file_path, return img; } -ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, ImBuf *img) +ImBuf *IMB_thumb_create(const char *filepath, ThumbSize size, ThumbSource source, ImBuf *img) { char uri[URI_MAX] = ""; char thumb_name[40]; - if (!uri_from_filename(path, uri)) { + if (!uri_from_filename(filepath, uri)) { return NULL; } thumbname_from_uri(uri, thumb_name, sizeof(thumb_name)); return thumb_create_ex( - path, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img); + filepath, uri, thumb_name, false, THUMB_DEFAULT_HASH, NULL, NULL, size, source, img); } -ImBuf *IMB_thumb_read(const char *path, ThumbSize size) +ImBuf *IMB_thumb_read(const char *filepath, ThumbSize size) { char thumb[FILE_MAX]; char uri[URI_MAX]; ImBuf *img = NULL; - if (!uri_from_filename(path, uri)) { + if (!uri_from_filename(filepath, uri)) { return NULL; } if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { @@ -496,16 +496,16 @@ ImBuf *IMB_thumb_read(const char *path, ThumbSize size) return img; } -void IMB_thumb_delete(const char *path, ThumbSize size) +void IMB_thumb_delete(const char *filepath, ThumbSize size) { char thumb[FILE_MAX]; char uri[URI_MAX]; - if (!uri_from_filename(path, uri)) { + if (!uri_from_filename(filepath, uri)) { return; } if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) { - if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) { + if (BLI_path_ncmp(filepath, thumb, sizeof(thumb)) == 0) { return; } if (BLI_exists(thumb)) { diff --git a/source/blender/imbuf/intern/thumbs_font.c b/source/blender/imbuf/intern/thumbs_font.c index 7a1c4947c99..c0a33f608a5 100644 --- a/source/blender/imbuf/intern/thumbs_font.c +++ b/source/blender/imbuf/intern/thumbs_font.c @@ -41,7 +41,7 @@ void IMB_thumb_ensure_translations(void) } } -struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned int y) +struct ImBuf *IMB_thumb_load_font(const char *filepath, unsigned int x, unsigned int y) { const int font_size = y / 4; @@ -60,7 +60,7 @@ struct ImBuf *IMB_thumb_load_font(const char *filename, unsigned int x, unsigned /* draw with full alpha */ font_color[3] = 1.0f; - BLF_thumb_preview(filename, + BLF_thumb_preview(filepath, thumb_str, i18n_thumb_str, ARRAY_SIZE(thumb_str), -- cgit v1.2.3 From 48c4c409b83c6ab8c00b64efb087cf0eb9bb8597 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2022 12:33:20 +1000 Subject: Fix DPX/CINEON writing full file paths into image headers on WIN32 Use back-slashes to find the file-name component on windows. --- source/blender/imbuf/intern/cineon/cineonlib.c | 2 +- source/blender/imbuf/intern/cineon/dpxlib.c | 2 +- source/blender/imbuf/intern/cineon/logImageCore.h | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 2f00a64a2cf..8312476bda0 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -393,7 +393,7 @@ LogImageFile *cineonCreate( cineon->referenceBlack = 95.0f; cineon->gamma = 1.7f; - shortFilename = strrchr(filepath, '/'); + shortFilename = strrchr(filepath, PATHSEP_CHAR); if (shortFilename == NULL) { shortFilename = filepath; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index 9fbc118913d..28c19116361 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -502,7 +502,7 @@ LogImageFile *dpxCreate(const char *filepath, dpx->gamma = 1.7f; } - shortFilename = strrchr(filepath, '/'); + shortFilename = strrchr(filepath, PATHSEP_CHAR); if (shortFilename == NULL) { shortFilename = filepath; } diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h index 8366927a95b..35540497828 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -19,6 +19,12 @@ #include "BLI_sys_types.h" #include "BLI_utildefines.h" +#ifdef _WIN32 +# define PATHSEP_CHAR '\\' +#else +# define PATHSEP_CHAR '/' +#endif + #ifdef __cplusplus extern "C" { #endif -- cgit v1.2.3 From a820ba0d36a05453af4e49b402dd6e893d28ecca Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 18 May 2022 09:51:11 +0200 Subject: Fix T98216: OpenEXR: No difference in file size between ZIP, DWAA, DWAB. Check in code would not expect major version of OpenEXR > 2. Investigated by Jesse Yurkovich (@deadpin), thanks! --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 2281d8d85b3..66ee3cf2c26 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -363,7 +363,7 @@ static void openexr_header_compression(Header *header, int compression) case R_IMF_EXR_CODEC_B44A: header->compression() = B44A_COMPRESSION; break; -#if OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2 +#if OPENEXR_VERSION_MAJOR > 2 || (OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2) case R_IMF_EXR_CODEC_DWAA: header->compression() = DWAA_COMPRESSION; break; -- cgit v1.2.3 From 6730c11dd9f084512bab03e8668de3be0bce42e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 19 May 2022 10:04:18 +1000 Subject: Cleanup: quiet deprecated-copy warning with GCC --- source/blender/imbuf/intern/dds/Color.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h index 3918ef31052..5b00333ad77 100644 --- a/source/blender/imbuf/intern/dds/Color.h +++ b/source/blender/imbuf/intern/dds/Color.h @@ -21,9 +21,8 @@ class Color32 { Color32() { } - Color32(const Color32 &c) : u(c.u) - { - } + Color32(const Color32 &) = default; + Color32(unsigned char R, unsigned char G, unsigned char B) { setRGBA(R, G, B, 0xFF); -- cgit v1.2.3 From f600a2aa6df1dd85f9d00be57031c9e1dcbfbd08 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Thu, 19 May 2022 14:55:04 -0700 Subject: IMBUF: Thumbnails of all EXR files using less RAM Specialized thumbnailing function to create previews of all EXR image files, regardless of type, size, or dimensions. Uses less RAM by only loading a single row of pixels at a time. See D14663 for more details and examples. Differential Revision: https://developer.blender.org/D14663 Reviewed by Brecht Van Lommel --- source/blender/imbuf/intern/filetype.c | 2 +- .../blender/imbuf/intern/openexr/openexr_api.cpp | 185 ++++++++++++++++++++- source/blender/imbuf/intern/openexr/openexr_api.h | 7 + 3 files changed, 186 insertions(+), 8 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c index 74042ef75be..92fa980cd7f 100644 --- a/source/blender/imbuf/intern/filetype.c +++ b/source/blender/imbuf/intern/filetype.c @@ -157,7 +157,7 @@ const ImFileType IMB_FILE_TYPES[] = { .is_a = imb_is_a_openexr, .load = imb_load_openexr, .load_filepath = NULL, - .load_filepath_thumbnail = NULL, + .load_filepath_thumbnail = imb_load_filepath_thumbnail_openexr, .save = imb_save_openexr, .load_tile = NULL, .flag = IM_FTYPE_FLOAT, diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 66ee3cf2c26..104be9008a4 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,8 @@ #include #include #include +#include +#include #include #include #include @@ -63,6 +66,9 @@ #if defined(WIN32) # include "utfconv.h" +# include +#else +# include #endif #include "MEM_guardedalloc.h" @@ -77,7 +83,9 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #endif } #include "BLI_blenlib.h" +#include "BLI_fileops.h" #include "BLI_math_color.h" +#include "BLI_mmap.h" #include "BLI_string_utils.h" #include "BLI_threads.h" @@ -151,6 +159,66 @@ class IMemStream : public Imf::IStream { unsigned char *_exrbuf; }; +/* Memory-Mapped Input Stream */ + +class IMMapStream : public Imf::IStream { + public: + IMMapStream(const char *filepath) : IStream(filepath) + { + int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0); + if (file < 0) { + throw IEX_NAMESPACE::InputExc("file not found"); + } + _exrpos = 0; + _exrsize = BLI_file_descriptor_size(file); + imb_mmap_lock(); + _mmap_file = BLI_mmap_open(file); + imb_mmap_unlock(); + if (_mmap_file == NULL) { + throw IEX_NAMESPACE::InputExc("BLI_mmap_open failed"); + } + close(file); + _exrbuf = (unsigned char *)BLI_mmap_get_pointer(_mmap_file); + } + + ~IMMapStream() + { + imb_mmap_lock(); + BLI_mmap_free(_mmap_file); + imb_mmap_unlock(); + } + + /* This is implementing regular `read`, not `readMemoryMapped`, because DWAA and DWAB + * decompressors load on unaligned offsets. Therefore we can't avoid the memory copy. */ + + bool read(char c[], int n) override + { + if (_exrpos + n > _exrsize) { + throw Iex::InputExc("Unexpected end of file."); + } + memcpy(c, _exrbuf + _exrpos, n); + _exrpos += n; + + return _exrpos < _exrsize; + } + + exr_file_offset_t tellg() override + { + return _exrpos; + } + + void seekg(exr_file_offset_t pos) override + { + _exrpos = pos; + } + + private: + BLI_mmap_file *_mmap_file; + exr_file_offset_t _exrpos; + exr_file_offset_t _exrsize; + unsigned char *_exrbuf; +}; + /* File Input Stream */ class IFileStream : public Imf::IStream { @@ -2099,19 +2167,122 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem, } } -void imb_initopenexr(void) +struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, + const int flags, + const size_t max_thumb_size, + char colorspace[], + size_t *r_width, + size_t *r_height) { - int num_threads = BLI_system_thread_count(); + IStream *stream = nullptr; + Imf::RgbaInputFile *file = nullptr; + + /* OpenExr uses exceptions for error-handling. */ + try { + + /* The memory-mapped stream is faster, but don't use for huge files as it requires contiguous + * address space and we are processing multiple files at once (typically one per processor + * core). The 100 MB limit here is arbitrary, but seems reasonable and conservative. */ + if (BLI_file_size(filepath) < 100 * 1024 * 1024) { + stream = new IMMapStream(filepath); + } + else { + stream = new IFileStream(filepath); + } + + /* imb_initopenexr() creates a global pool of worker threads. But we thumbnail multiple images + * at once, and by default each file will attempt to use the entire pool for itself, stalling + * the others. So each thumbnail should use a single thread of the pool. */ + file = new RgbaInputFile(*stream, 1); + + if (!file->isComplete()) { + return nullptr; + } + + Imath::Box2i dw = file->dataWindow(); + int source_w = dw.max.x - dw.min.x + 1; + int source_h = dw.max.y - dw.min.y + 1; + *r_width = source_w; + *r_height = source_h; + + /* If there is an embedded thumbnail, return that instead of making a new one. */ + if (file->header().hasPreviewImage()) { + const Imf::PreviewImage &preview = file->header().previewImage(); + ImBuf *ibuf = IMB_allocFromBuffer( + (unsigned int *)preview.pixels(), NULL, preview.width(), preview.height(), 4); + delete file; + delete stream; + IMB_flipy(ibuf); + return ibuf; + } + + /* Create a new thumbnail. */ + + if (colorspace && colorspace[0]) { + colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT); + } + + float scale_factor = MIN2((float)max_thumb_size / (float)source_w, + (float)max_thumb_size / (float)source_h); + int dest_w = (int)(source_w * scale_factor); + int dest_h = (int)(source_h * scale_factor); + + struct ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rectfloat); + + /* A single row of source pixels. */ + Imf::Array pixels(source_w); + + /* Loop through destination thumbnail rows. */ + for (int h = 0; h < dest_h; h++) { + + /* Load the single source row that corresponds with destination row. */ + int source_y = (int)((float)h / scale_factor) + dw.min.y; + file->setFrameBuffer(&pixels[0] - dw.min.x - source_y * source_w, 1, source_w); + file->readPixels(source_y); + + for (int w = 0; w < dest_w; w++) { + /* For each destination pixel find single corresponding source pixel. */ + int source_x = (int)(MIN2((w / scale_factor), dw.max.x - 1)); + float *dest_px = &ibuf->rect_float[(h * dest_w + w) * 4]; + dest_px[0] = pixels[source_x].r; + dest_px[1] = pixels[source_x].g; + dest_px[2] = pixels[source_x].b; + dest_px[3] = pixels[source_x].a; + } + } - setGlobalThreadCount(num_threads); + if (file->lineOrder() == INCREASING_Y) { + IMB_flipy(ibuf); + } + + delete file; + delete stream; + + return ibuf; + } + + catch (const std::exception &exc) { + std::cerr << exc.what() << std::endl; + delete file; + delete stream; + return nullptr; + } + + return nullptr; +} + +void imb_initopenexr(void) +{ + /* In a multithreaded program, staticInitialize() must be called once during startup, before the + * program accesses any other functions or classes in the IlmImf library. */ + Imf::staticInitialize(); + Imf::setGlobalThreadCount(BLI_system_thread_count()); } void imb_exitopenexr(void) { - /* Tells OpenEXR to free thread pool, also ensures there is no running - * tasks. - */ - setGlobalThreadCount(0); + /* Tells OpenEXR to free thread pool, also ensures there is no running tasks. */ + Imf::setGlobalThreadCount(0); } } /* export "C" */ diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index c02b03dbe6c..a62c87428b6 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -26,6 +26,13 @@ bool imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags); struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char *colorspace); +struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, + const int flags, + const size_t max_thumb_size, + char colorspace[], + size_t *r_width, + size_t *r_height); + #ifdef __cplusplus } #endif -- cgit v1.2.3 From a42307eb652ae5484438efab12284ad1344ad323 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 May 2022 09:59:46 +1000 Subject: Fix building with OpenEXR on Linux --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 104be9008a4..6fcd106c3d4 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 930e526cae6204658e70fe7f19c61cf3291949f4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 May 2022 11:24:34 +1000 Subject: Cleanup: warnings, spelling, formatting Avoid multiple `sound.bl_rna.properties["channels"].enum_items` in the same line. Note we might want a way to avoid having to do this. --- source/blender/imbuf/intern/openexr/openexr_api.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 6fcd106c3d4..54ef5438c23 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -2168,7 +2168,7 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem, } struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, - const int flags, + const int UNUSED(flags), const size_t max_thumb_size, char colorspace[], size_t *r_width, -- cgit v1.2.3 From bf352df27a6f85d73bc0d6417f50fd62958cfb6e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 20 May 2022 16:41:51 +0200 Subject: Fix wrong USD image color space export with non-default OpenColorIO config The names of color spaces in OpenColorIO configs can be arbitrary, so don't use hardcoded names from our default config. --- source/blender/imbuf/intern/colormanagement.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 53aa74edc61..95e2d36891a 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1412,6 +1412,12 @@ bool IMB_colormanagement_space_name_is_scene_linear(const char *name) return (colorspace && IMB_colormanagement_space_is_scene_linear(colorspace)); } +bool IMB_colormanagement_space_name_is_srgb(const char *name) +{ + ColorSpace *colorspace = colormanage_colorspace_get_named(name); + return (colorspace && IMB_colormanagement_space_is_srgb(colorspace)); +} + const float *IMB_colormanagement_get_xyz_to_rgb() { return &imbuf_xyz_to_rgb[0][0]; -- cgit v1.2.3 From 469ee7ff1529a1b28ce0b300835ebc42d5c5362f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 19 May 2022 20:31:58 +0200 Subject: Python API: add mathutils.Color functions to convert color spaces Between scene linear and sRGB, XYZ, linear Rec.709 and ACES2065-1. And add some clarifications about color spaces in the docs. Fixes T98267 Ref T68926 Differential Revision: https://developer.blender.org/D14989 --- .../imbuf/intern/IMB_colormanagement_intern.h | 4 ++++ source/blender/imbuf/intern/colormanagement.c | 18 ++++++++++------ .../blender/imbuf/intern/colormanagement_inline.c | 24 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index c89b15480a2..fd70c633f83 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -20,6 +20,10 @@ struct OCIO_ConstCPUProcessorRcPtr; extern float imbuf_luma_coefficients[3]; extern float imbuf_xyz_to_rgb[3][3]; extern float imbuf_rgb_to_xyz[3][3]; +extern float imbuf_xyz_to_aces[3][3]; +extern float imbuf_aces_to_xyz[3][3]; +extern float imbuf_xyz_to_rec709[3][3]; +extern float imbuf_rec709_to_xyz[3][3]; #define MAX_COLORSPACE_NAME 64 #define MAX_COLORSPACE_DESCRIPTION 512 diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 95e2d36891a..f189614e61c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -75,8 +75,10 @@ static int global_tot_looks = 0; float imbuf_luma_coefficients[3] = {0.0f}; float imbuf_xyz_to_rgb[3][3] = {{0.0f}}; float imbuf_rgb_to_xyz[3][3] = {{0.0f}}; -static float imbuf_xyz_to_linear_srgb[3][3] = {{0.0f}}; -static float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_rec709[3][3] = {{0.0f}}; +float imbuf_rec709_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_aces[3][3] = {{0.0f}}; +float imbuf_aces_to_xyz[3][3] = {{0.0f}}; /* lock used by pre-cached processors getters, so processor wouldn't * be created several times @@ -573,10 +575,14 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) /* Load luminance coefficients. */ OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); + + /* Load standard color spaces. */ OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); - copy_m3_m3(imbuf_xyz_to_linear_srgb, OCIO_XYZ_TO_LINEAR_SRGB); - invert_m3_m3(imbuf_linear_srgb_to_xyz, imbuf_xyz_to_linear_srgb); + copy_m3_m3(imbuf_xyz_to_rec709, OCIO_XYZ_TO_REC709); + invert_m3_m3(imbuf_rec709_to_xyz, imbuf_xyz_to_rec709); + copy_m3_m3(imbuf_aces_to_xyz, OCIO_ACES_TO_XYZ); + invert_m3_m3(imbuf_xyz_to_aces, imbuf_aces_to_xyz); } static void colormanage_free_config(void) @@ -2370,14 +2376,14 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]) { mul_m3_v3(imbuf_rgb_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_linear_srgb, pixel); + mul_m3_v3(imbuf_xyz_to_rec709, pixel); linearrgb_to_srgb_v3_v3(pixel, pixel); } void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) { srgb_to_linearrgb_v3_v3(pixel, pixel); - mul_m3_v3(imbuf_linear_srgb_to_xyz, pixel); + mul_m3_v3(imbuf_rec709_to_xyz, pixel); mul_m3_v3(imbuf_xyz_to_rgb, pixel); } diff --git a/source/blender/imbuf/intern/colormanagement_inline.c b/source/blender/imbuf/intern/colormanagement_inline.c index 411cf9af802..4c632da1520 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.c +++ b/source/blender/imbuf/intern/colormanagement_inline.c @@ -37,4 +37,28 @@ void IMB_colormanagement_rgb_to_xyz(float xyz[3], const float rgb[3]) mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); } +void IMB_colormanagement_rec709_to_rgb(float rgb[3], const float rec709[3]) +{ + mul_v3_m3v3(rgb, imbuf_rec709_to_xyz, rec709); + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); +} + +void IMB_colormanagement_rgb_to_rec709(float rec709[3], const float rgb[3]) +{ + mul_v3_m3v3(rec709, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(rec709, imbuf_xyz_to_rec709, rec709); +} + +void IMB_colormanagement_aces_to_rgb(float rgb[3], const float aces[3]) +{ + mul_v3_m3v3(rgb, imbuf_aces_to_xyz, aces); + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); +} + +void IMB_colormanagement_rgb_to_aces(float aces[3], const float rgb[3]) +{ + mul_v3_m3v3(aces, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(aces, imbuf_xyz_to_aces, aces); +} + #endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ -- cgit v1.2.3 From eb5e7d0a31eed698909c23ab0ca89c8fd4929365 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 20 May 2022 17:54:43 +0200 Subject: Cleanup: clarify what is scene linear color space in conversion conversion * Rename ambiguous rgb to scene_linear in some places * Precompute matrices to directly go to scene instead of through XYZ * Make function signatures more consistent --- .../imbuf/intern/IMB_colormanagement_intern.h | 12 ++--- source/blender/imbuf/intern/colormanagement.c | 58 ++++++++++------------ .../blender/imbuf/intern/colormanagement_inline.c | 40 +++++++++------ 3 files changed, 56 insertions(+), 54 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index fd70c633f83..23b3f0191b7 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -18,12 +18,12 @@ struct ImBuf; struct OCIO_ConstCPUProcessorRcPtr; extern float imbuf_luma_coefficients[3]; -extern float imbuf_xyz_to_rgb[3][3]; -extern float imbuf_rgb_to_xyz[3][3]; -extern float imbuf_xyz_to_aces[3][3]; -extern float imbuf_aces_to_xyz[3][3]; -extern float imbuf_xyz_to_rec709[3][3]; -extern float imbuf_rec709_to_xyz[3][3]; +extern float imbuf_scene_linear_to_xyz[3][3]; +extern float imbuf_xyz_to_scene_linear[3][3]; +extern float imbuf_scene_linear_to_aces[3][3]; +extern float imbuf_aces_to_scene_linear[3][3]; +extern float imbuf_scene_linear_to_rec709[3][3]; +extern float imbuf_rec709_to_scene_linear[3][3]; #define MAX_COLORSPACE_NAME 64 #define MAX_COLORSPACE_DESCRIPTION 512 diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index f189614e61c..35601abab6e 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -73,12 +73,12 @@ static int global_tot_looks = 0; /* Luma coefficients and XYZ to RGB to be initialized by OCIO. */ float imbuf_luma_coefficients[3] = {0.0f}; -float imbuf_xyz_to_rgb[3][3] = {{0.0f}}; -float imbuf_rgb_to_xyz[3][3] = {{0.0f}}; -float imbuf_xyz_to_rec709[3][3] = {{0.0f}}; -float imbuf_rec709_to_xyz[3][3] = {{0.0f}}; -float imbuf_xyz_to_aces[3][3] = {{0.0f}}; -float imbuf_aces_to_xyz[3][3] = {{0.0f}}; +float imbuf_scene_linear_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_scene_linear[3][3] = {{0.0f}}; +float imbuf_scene_linear_to_rec709[3][3] = {{0.0f}}; +float imbuf_rec709_to_scene_linear[3][3] = {{0.0f}}; +float imbuf_scene_linear_to_aces[3][3] = {{0.0f}}; +float imbuf_aces_to_scene_linear[3][3] = {{0.0f}}; /* lock used by pre-cached processors getters, so processor wouldn't * be created several times @@ -577,12 +577,14 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); /* Load standard color spaces. */ - OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); - invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); - copy_m3_m3(imbuf_xyz_to_rec709, OCIO_XYZ_TO_REC709); - invert_m3_m3(imbuf_rec709_to_xyz, imbuf_xyz_to_rec709); - copy_m3_m3(imbuf_aces_to_xyz, OCIO_ACES_TO_XYZ); - invert_m3_m3(imbuf_xyz_to_aces, imbuf_aces_to_xyz); + OCIO_configGetXYZtoSceneLinear(config, imbuf_xyz_to_scene_linear); + invert_m3_m3(imbuf_scene_linear_to_xyz, imbuf_xyz_to_scene_linear); + + mul_m3_m3m3(imbuf_scene_linear_to_rec709, OCIO_XYZ_TO_REC709, imbuf_scene_linear_to_xyz); + invert_m3_m3(imbuf_rec709_to_scene_linear, imbuf_scene_linear_to_rec709); + + mul_m3_m3m3(imbuf_aces_to_scene_linear, imbuf_xyz_to_scene_linear, OCIO_ACES_TO_XYZ); + invert_m3_m3(imbuf_scene_linear_to_aces, imbuf_aces_to_scene_linear); } static void colormanage_free_config(void) @@ -1424,9 +1426,9 @@ bool IMB_colormanagement_space_name_is_srgb(const char *name) return (colorspace && IMB_colormanagement_space_is_srgb(colorspace)); } -const float *IMB_colormanagement_get_xyz_to_rgb() +const float *IMB_colormanagement_get_xyz_to_scene_linear() { - return &imbuf_xyz_to_rgb[0][0]; + return &imbuf_xyz_to_scene_linear[0][0]; } /** \} */ @@ -2319,7 +2321,8 @@ void IMB_colormanagement_imbuf_to_float_texture(float *out_buffer, } } -void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) +void IMB_colormanagement_scene_linear_to_color_picking_v3(float color_picking[3], + const float scene_linear[3]) { if (!global_color_picking_state.cpu_processor_to && !global_color_picking_state.failed) { /* Create processor if none exists. */ @@ -2341,12 +2344,15 @@ void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]) BLI_mutex_unlock(&processor_lock); } + copy_v3_v3(color_picking, scene_linear); + if (global_color_picking_state.cpu_processor_to) { - OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_to, pixel); + OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_to, color_picking); } } -void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) +void IMB_colormanagement_color_picking_to_scene_linear_v3(float scene_linear[3], + const float color_picking[3]) { if (!global_color_picking_state.cpu_processor_from && !global_color_picking_state.failed) { /* Create processor if none exists. */ @@ -2368,25 +2374,13 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) BLI_mutex_unlock(&processor_lock); } + copy_v3_v3(scene_linear, color_picking); + if (global_color_picking_state.cpu_processor_from) { - OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_from, pixel); + OCIO_cpuProcessorApplyRGB(global_color_picking_state.cpu_processor_from, scene_linear); } } -void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]) -{ - mul_m3_v3(imbuf_rgb_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_rec709, pixel); - linearrgb_to_srgb_v3_v3(pixel, pixel); -} - -void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) -{ - srgb_to_linearrgb_v3_v3(pixel, pixel); - mul_m3_v3(imbuf_rec709_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_rgb, pixel); -} - void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display) { OCIO_ConstCPUProcessorRcPtr *processor = display_from_scene_linear_processor(display); diff --git a/source/blender/imbuf/intern/colormanagement_inline.c b/source/blender/imbuf/intern/colormanagement_inline.c index 4c632da1520..668307ec802 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.c +++ b/source/blender/imbuf/intern/colormanagement_inline.c @@ -27,38 +27,46 @@ unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char rgb[3]) return unit_float_to_uchar_clamp(val); } -void IMB_colormanagement_xyz_to_rgb(float rgb[3], const float xyz[3]) +void IMB_colormanagement_xyz_to_scene_linear(float scene_linear[3], const float xyz[3]) { - mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, xyz); + mul_v3_m3v3(scene_linear, imbuf_xyz_to_scene_linear, xyz); } -void IMB_colormanagement_rgb_to_xyz(float xyz[3], const float rgb[3]) +void IMB_colormanagement_scene_linear_to_xyz(float xyz[3], const float scene_linear[3]) { - mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(xyz, imbuf_scene_linear_to_xyz, scene_linear); } -void IMB_colormanagement_rec709_to_rgb(float rgb[3], const float rec709[3]) +void IMB_colormanagement_rec709_to_scene_linear(float scene_linear[3], const float rec709[3]) { - mul_v3_m3v3(rgb, imbuf_rec709_to_xyz, rec709); - mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); + mul_v3_m3v3(scene_linear, imbuf_rec709_to_scene_linear, rec709); } -void IMB_colormanagement_rgb_to_rec709(float rec709[3], const float rgb[3]) +void IMB_colormanagement_scene_linear_to_rec709(float rec709[3], const float scene_linear[3]) { - mul_v3_m3v3(rec709, imbuf_rgb_to_xyz, rgb); - mul_v3_m3v3(rec709, imbuf_xyz_to_rec709, rec709); + mul_v3_m3v3(rec709, imbuf_scene_linear_to_rec709, scene_linear); } -void IMB_colormanagement_aces_to_rgb(float rgb[3], const float aces[3]) +void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[3]) { - mul_v3_m3v3(rgb, imbuf_aces_to_xyz, aces); - mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); + mul_v3_m3v3(srgb, imbuf_scene_linear_to_rec709, scene_linear); + linearrgb_to_srgb_v3_v3(srgb, srgb); } -void IMB_colormanagement_rgb_to_aces(float aces[3], const float rgb[3]) +void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3]) { - mul_v3_m3v3(aces, imbuf_rgb_to_xyz, rgb); - mul_v3_m3v3(aces, imbuf_xyz_to_aces, aces); + srgb_to_linearrgb_v3_v3(scene_linear, srgb); + mul_m3_v3(imbuf_rec709_to_scene_linear, scene_linear); +} + +void IMB_colormanagement_aces_to_scene_linear(float scene_linear[3], const float aces[3]) +{ + mul_v3_m3v3(scene_linear, imbuf_aces_to_scene_linear, aces); +} + +void IMB_colormanagement_scene_linear_to_aces(float aces[3], const float scene_linear[3]) +{ + mul_v3_m3v3(aces, imbuf_scene_linear_to_aces, scene_linear); } #endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ -- cgit v1.2.3 From bdab538b3019406cfbd53d99bc40c4dbae27393c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 23 May 2022 20:54:09 +0200 Subject: Fix Eevee blackbody wrong with non-default scene linear color space * Port over new code tables from Cycles * Convert Rec.709 to scene linear for lookup table. * Move code for wavelength and blackbody to IMB so they can access the required transforms, which are not in blenlib. * Remove clamping from blackbody shader to bypass the texture read. Since it's variable now easiest to just always read from the texture than pass additional parameters. * Fold XYZ to RGB conversion into the wavelength table. Ref T68926 --- source/blender/imbuf/intern/colormanagement.c | 167 ++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 35601abab6e..670394e1a1a 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -4082,3 +4082,170 @@ void IMB_colormanagement_finish_glsl_draw(void) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Rendering Tables + * \{ */ + +/* Calculate color in range 800..12000 using an approximation + * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B + * + * The result of this can be negative to support gamut wider than + * than rec.709, just needs to be clamped. */ + +static const float blackbody_table_r[7][3] = {{1.61919106e+03f, -2.05010916e-03f, 5.02995757e+00f}, + {2.48845471e+03f, -1.11330907e-03f, 3.22621544e+00f}, + {3.34143193e+03f, -4.86551192e-04f, 1.76486769e+00f}, + {4.09461742e+03f, -1.27446582e-04f, 7.25731635e-01f}, + {4.67028036e+03f, 2.91258199e-05f, 1.26703442e-01f}, + {4.59509185e+03f, 2.87495649e-05f, 1.50345020e-01f}, + {3.78717450e+03f, 9.35907826e-06f, 3.99075871e-01f}}; + +static const float blackbody_table_g[7][3] = { + {-4.88999748e+02f, 6.04330754e-04f, -7.55807526e-02f}, + {-7.55994277e+02f, 3.16730098e-04f, 4.78306139e-01f}, + {-1.02363977e+03f, 1.20223470e-04f, 9.36662319e-01f}, + {-1.26571316e+03f, 4.87340896e-06f, 1.27054498e+00f}, + {-1.42529332e+03f, -4.01150431e-05f, 1.43972784e+00f}, + {-1.17554822e+03f, -2.16378048e-05f, 1.30408023e+00f}, + {-5.00799571e+02f, -4.59832026e-06f, 1.09098763e+00f}}; + +static const float blackbody_table_b[7][4] = { + {5.96945309e-11f, -4.85742887e-08f, -9.70622247e-05f, -4.07936148e-03f}, + {2.40430366e-11f, 5.55021075e-08f, -1.98503712e-04f, 2.89312858e-02f}, + {-1.40949732e-11f, 1.89878968e-07f, -3.56632824e-04f, 9.10767778e-02f}, + {-3.61460868e-11f, 2.84822009e-07f, -4.93211319e-04f, 1.56723440e-01f}, + {-1.97075738e-11f, 1.75359352e-07f, -2.50542825e-04f, -2.22783266e-02f}, + {-1.61997957e-13f, -1.64216008e-08f, 3.86216271e-04f, -7.38077418e-01f}, + {6.72650283e-13f, -2.73078809e-08f, 4.24098264e-04f, -7.52335691e-01f}}; + +static void blackbody_temperature_to_rec709(float rec709[3], float t) +{ + if (t >= 12000.0f) { + rec709[0] = 0.8262954810464208f; + rec709[1] = 0.9945080501520986f; + rec709[2] = 1.566307710274283f; + } + else if (t < 800.0f) { + rec709[0] = 5.413294490189271f; + rec709[1] = -0.20319390035873933f; + rec709[2] = -0.0822535242887164f; + } + else { + int i = (t >= 6365.0f) ? 6 : + (t >= 3315.0f) ? 5 : + (t >= 1902.0f) ? 4 : + (t >= 1449.0f) ? 3 : + (t >= 1167.0f) ? 2 : + (t >= 965.0f) ? 1 : + 0; + + const float *r = blackbody_table_r[i]; + const float *g = blackbody_table_g[i]; + const float *b = blackbody_table_b[i]; + + const float t_inv = 1.0f / t; + rec709[0] = r[0] * t_inv + r[1] * t + r[2]; + rec709[1] = g[0] * t_inv + g[1] * t + g[2]; + rec709[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3]; + } +} + +void IMB_colormanagement_blackbody_temperature_to_rgb_table(float *r_table, + const int width, + const float min, + const float max) +{ + for (int i = 0; i < width; i++) { + float temperature = min + (max - min) / (float)width * (float)i; + + float rec709[3]; + blackbody_temperature_to_rec709(rec709, temperature); + + float rgb[3]; + IMB_colormanagement_rec709_to_scene_linear(rgb, rec709); + clamp_v3(rgb, 0.0f, FLT_MAX); + + copy_v3_v3(&r_table[i * 4], rgb); + r_table[i * 4 + 3] = 0.0f; + } +} + +/** + * CIE color matching functions `xBar`, `yBar`, and `zBar` for + * wavelengths from 380 through 780 nanometers, every 5 nanometers. + * + * For a wavelength lambda in this range: + * \code{.txt} + * cie_color_match[(lambda - 380) / 5][0] = xBar + * cie_color_match[(lambda - 380) / 5][1] = yBar + * cie_color_match[(lambda - 380) / 5][2] = zBar + * \endcode + */ + +static float cie_colour_match[81][3] = { + {0.0014f, 0.0000f, 0.0065f}, {0.0022f, 0.0001f, 0.0105f}, {0.0042f, 0.0001f, 0.0201f}, + {0.0076f, 0.0002f, 0.0362f}, {0.0143f, 0.0004f, 0.0679f}, {0.0232f, 0.0006f, 0.1102f}, + {0.0435f, 0.0012f, 0.2074f}, {0.0776f, 0.0022f, 0.3713f}, {0.1344f, 0.0040f, 0.6456f}, + {0.2148f, 0.0073f, 1.0391f}, {0.2839f, 0.0116f, 1.3856f}, {0.3285f, 0.0168f, 1.6230f}, + {0.3483f, 0.0230f, 1.7471f}, {0.3481f, 0.0298f, 1.7826f}, {0.3362f, 0.0380f, 1.7721f}, + {0.3187f, 0.0480f, 1.7441f}, {0.2908f, 0.0600f, 1.6692f}, {0.2511f, 0.0739f, 1.5281f}, + {0.1954f, 0.0910f, 1.2876f}, {0.1421f, 0.1126f, 1.0419f}, {0.0956f, 0.1390f, 0.8130f}, + {0.0580f, 0.1693f, 0.6162f}, {0.0320f, 0.2080f, 0.4652f}, {0.0147f, 0.2586f, 0.3533f}, + {0.0049f, 0.3230f, 0.2720f}, {0.0024f, 0.4073f, 0.2123f}, {0.0093f, 0.5030f, 0.1582f}, + {0.0291f, 0.6082f, 0.1117f}, {0.0633f, 0.7100f, 0.0782f}, {0.1096f, 0.7932f, 0.0573f}, + {0.1655f, 0.8620f, 0.0422f}, {0.2257f, 0.9149f, 0.0298f}, {0.2904f, 0.9540f, 0.0203f}, + {0.3597f, 0.9803f, 0.0134f}, {0.4334f, 0.9950f, 0.0087f}, {0.5121f, 1.0000f, 0.0057f}, + {0.5945f, 0.9950f, 0.0039f}, {0.6784f, 0.9786f, 0.0027f}, {0.7621f, 0.9520f, 0.0021f}, + {0.8425f, 0.9154f, 0.0018f}, {0.9163f, 0.8700f, 0.0017f}, {0.9786f, 0.8163f, 0.0014f}, + {1.0263f, 0.7570f, 0.0011f}, {1.0567f, 0.6949f, 0.0010f}, {1.0622f, 0.6310f, 0.0008f}, + {1.0456f, 0.5668f, 0.0006f}, {1.0026f, 0.5030f, 0.0003f}, {0.9384f, 0.4412f, 0.0002f}, + {0.8544f, 0.3810f, 0.0002f}, {0.7514f, 0.3210f, 0.0001f}, {0.6424f, 0.2650f, 0.0000f}, + {0.5419f, 0.2170f, 0.0000f}, {0.4479f, 0.1750f, 0.0000f}, {0.3608f, 0.1382f, 0.0000f}, + {0.2835f, 0.1070f, 0.0000f}, {0.2187f, 0.0816f, 0.0000f}, {0.1649f, 0.0610f, 0.0000f}, + {0.1212f, 0.0446f, 0.0000f}, {0.0874f, 0.0320f, 0.0000f}, {0.0636f, 0.0232f, 0.0000f}, + {0.0468f, 0.0170f, 0.0000f}, {0.0329f, 0.0119f, 0.0000f}, {0.0227f, 0.0082f, 0.0000f}, + {0.0158f, 0.0057f, 0.0000f}, {0.0114f, 0.0041f, 0.0000f}, {0.0081f, 0.0029f, 0.0000f}, + {0.0058f, 0.0021f, 0.0000f}, {0.0041f, 0.0015f, 0.0000f}, {0.0029f, 0.0010f, 0.0000f}, + {0.0020f, 0.0007f, 0.0000f}, {0.0014f, 0.0005f, 0.0000f}, {0.0010f, 0.0004f, 0.0000f}, + {0.0007f, 0.0002f, 0.0000f}, {0.0005f, 0.0002f, 0.0000f}, {0.0003f, 0.0001f, 0.0000f}, + {0.0002f, 0.0001f, 0.0000f}, {0.0002f, 0.0001f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, + {0.0001f, 0.0000f, 0.0000f}, {0.0001f, 0.0000f, 0.0000f}, {0.0000f, 0.0000f, 0.0000f}}; + +static void wavelength_to_xyz(float xyz[3], float lambda_nm) +{ + float ii = (lambda_nm - 380.0f) * (1.0f / 5.0f); /* Scaled 0..80. */ + int i = (int)ii; + + if (i < 0 || i >= 80) { + xyz[0] = 0.0f; + xyz[1] = 0.0f; + xyz[2] = 0.0f; + } + else { + ii -= (float)i; + const float *c = cie_colour_match[i]; + xyz[0] = c[0] + ii * (c[3] - c[0]); + xyz[1] = c[1] + ii * (c[4] - c[1]); + xyz[2] = c[2] + ii * (c[5] - c[2]); + } +} + +void IMB_colormanagement_wavelength_to_rgb_table(float *r_table, const int width) +{ + for (int i = 0; i < width; i++) { + float temperature = 380 + 400 / (float)width * (float)i; + + float xyz[3]; + wavelength_to_xyz(xyz, temperature); + + float rgb[3]; + IMB_colormanagement_xyz_to_scene_linear(rgb, xyz); + clamp_v3(rgb, 0.0f, FLT_MAX); + + copy_v3_v3(&r_table[i * 4], rgb); + r_table[i * 4 + 3] = 0.0f; + } +} + +/** \} */ -- cgit v1.2.3 From f41c7723c93bc9e784634887da8b682787729538 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 27 May 2022 10:52:49 +0200 Subject: GPU: Remove cached full/scaled image texture. full scaled image isn't used anymore. It was added to use a different scale when displaying an image in the image editor. This was replaced by the image engine redesign. This change will reduce complexity of {T98375}. --- source/blender/imbuf/intern/util_gpu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 8da9eb9ccf7..8e004938a89 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -197,12 +197,10 @@ void IMB_update_gpu_texture_sub(GPUTexture *tex, GPUTexture *IMB_create_gpu_texture(const char *name, ImBuf *ibuf, bool use_high_bitdepth, - bool use_premult, - bool limit_gl_texture_size) + bool use_premult) { GPUTexture *tex = NULL; - int size[2] = {GPU_texture_size_with_limit(ibuf->x, limit_gl_texture_size), - GPU_texture_size_with_limit(ibuf->y, limit_gl_texture_size)}; + int size[2] = {GPU_texture_size_with_limit(ibuf->x), GPU_texture_size_with_limit(ibuf->y)}; bool do_rescale = (ibuf->x != size[0]) || (ibuf->y != size[1]); #ifdef WITH_DDS -- cgit v1.2.3 From 0f29f2c3e630a9f092bf02fd4669d27aef4b5921 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 1 Jun 2022 15:06:21 +1000 Subject: Cleanup: remove redundant const qualifiers for scalar & enum types --- source/blender/imbuf/intern/IMB_filetype.h | 8 ++++---- source/blender/imbuf/intern/openexr/openexr_api.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 67d1aefeacb..6e505746643 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -42,8 +42,8 @@ typedef struct ImFileType { * dimensions of the full-size image in r_width & r_height. */ struct ImBuf *(*load_filepath_thumbnail)(const char *filepath, - const int flags, - const size_t max_thumb_size, + int flags, + size_t max_thumb_size, char colorspace[IM_MAX_SPACE], size_t *r_width, size_t *r_height); @@ -155,8 +155,8 @@ struct ImBuf *imb_load_jpeg(const unsigned char *buffer, int flags, char colorspace[IM_MAX_SPACE]); struct ImBuf *imb_thumbnail_jpeg(const char *filepath, - const int flags, - const size_t max_thumb_size, + int flags, + size_t max_thumb_size, char colorspace[IM_MAX_SPACE], size_t *r_width, size_t *r_height); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index a62c87428b6..40a724c9f42 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -27,8 +27,8 @@ bool imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags); struct ImBuf *imb_load_openexr(const unsigned char *mem, size_t size, int flags, char *colorspace); struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, - const int flags, - const size_t max_thumb_size, + int flags, + size_t max_thumb_size, char colorspace[], size_t *r_width, size_t *r_height); -- cgit v1.2.3 From e87082d8a70a0252ca76ce93b08c5bd65e29928b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 3 Jun 2022 13:39:37 +1000 Subject: Cleanup: spelling in comments --- source/blender/imbuf/intern/cineon/cineon_dpx.c | 4 ++-- source/blender/imbuf/intern/colormanagement.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 6448d6cd76a..1a99d2a34d9 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -121,8 +121,8 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filepath, int use_cineon } if (ibuf->rect_float != NULL && bitspersample != 8) { - /* don't use the float buffer to save 8 bpp picture to prevent color banding - * (there's no dithering algorithm behind the logImageSetDataRGBA function) */ + /* Don't use the float buffer to save 8 BPP picture to prevent color banding + * (there's no dithering algorithm behind the #logImageSetDataRGBA function). */ fbuf = (float *)MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, "fbuf in imb_save_dpx_cineon"); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index d4c9e78a299..0a85b31ef7b 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -597,7 +597,7 @@ static void colormanage_free_config(void) while (colorspace) { ColorSpace *colorspace_next = colorspace->next; - /* free precomputer processors */ + /* Free precomputed processors. */ if (colorspace->to_scene_linear) { OCIO_cpuProcessorRelease((OCIO_ConstCPUProcessorRcPtr *)colorspace->to_scene_linear); } @@ -673,7 +673,7 @@ void colormanagement_init(void) #ifdef WIN32 { - /* quite a hack to support loading configuration from path with non-acii symbols */ + /* Quite a hack to support loading configuration from path with non-ACII symbols. */ char short_name[256]; BLI_get_short_name(short_name, configfile); -- cgit v1.2.3 From 9d8fb80f218f05f743943a289e2aad579e709058 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 3 Jun 2022 14:13:10 +0200 Subject: Eevee/Workbench: store 8 bit image textures as half float for some color spaces Same as in Cycles, this is needed for some color space conversions that don't compress well to byte sRGB, like for example Filmic sRGB. Ref T68926 --- source/blender/imbuf/intern/colormanagement.c | 133 +++++++++++++++----------- source/blender/imbuf/intern/util_gpu.c | 65 +++++++++---- 2 files changed, 122 insertions(+), 76 deletions(-) (limited to 'source/blender/imbuf/intern') 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); } } } diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c index 8e004938a89..5feb0ceb515 100644 --- a/source/blender/imbuf/intern/util_gpu.c +++ b/source/blender/imbuf/intern/util_gpu.c @@ -28,17 +28,30 @@ static void imb_gpu_get_format(const ImBuf *ibuf, eGPUTextureFormat *r_texture_format) { const bool float_rect = (ibuf->rect_float != NULL); - const bool use_srgb = (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace) && - !IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace)); - high_bitdepth = (!(ibuf->flags & IB_halffloat) && high_bitdepth); - - *r_data_format = (float_rect) ? GPU_DATA_FLOAT : GPU_DATA_UBYTE; if (float_rect) { - *r_texture_format = high_bitdepth ? GPU_RGBA32F : GPU_RGBA16F; + /* Float. */ + const bool use_high_bitdepth = (!(ibuf->flags & IB_halffloat) && high_bitdepth); + *r_data_format = GPU_DATA_FLOAT; + *r_texture_format = use_high_bitdepth ? GPU_RGBA32F : GPU_RGBA16F; } else { - *r_texture_format = use_srgb ? GPU_SRGB8_A8 : GPU_RGBA8; + if (IMB_colormanagement_space_is_data(ibuf->rect_colorspace) || + IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace)) { + /* Non-color data or scene linear, just store buffer as is. */ + *r_data_format = GPU_DATA_UBYTE; + *r_texture_format = GPU_RGBA8; + } + else if (IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) { + /* sRGB, store as byte texture that the GPU can decode directly. */ + *r_data_format = GPU_DATA_UBYTE; + *r_texture_format = GPU_SRGB8_A8; + } + else { + /* Other colorspace, store as half float texture to avoid precision loss. */ + *r_data_format = GPU_DATA_FLOAT; + *r_texture_format = GPU_RGBA16F; + } } } @@ -74,7 +87,6 @@ static bool IMB_gpu_get_compressed_format(const ImBuf *ibuf, eGPUTextureFormat * static void *imb_gpu_get_data(const ImBuf *ibuf, const bool do_rescale, const int rescale_size[2], - const bool compress_as_srgb, const bool store_premultiplied, bool *r_freedata) { @@ -99,14 +111,16 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, } } else { - /* Byte image is in original colorspace from the file. If the file is sRGB - * scene linear, or non-color data no conversion is needed. Otherwise we - * compress as scene linear + sRGB transfer function to avoid precision loss - * in common cases. + /* Byte image is in original colorspace from the file, and may need conversion. * * We must also convert to premultiplied for correct texture interpolation * and consistency with float images. */ - if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { + if (IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) { + /* Non-color data, just store buffer as is. */ + } + else if (IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace) || + IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace)) { + /* sRGB or scene linear, store as byte texture that the GPU can decode directly. */ data_rect = MEM_mallocN(sizeof(uchar[4]) * ibuf->x * ibuf->y, __func__); *r_freedata = freedata = true; @@ -120,7 +134,24 @@ static void *imb_gpu_get_data(const ImBuf *ibuf, * zero alpha areas, and appears generally closer to what game engines that we * want to be compatible with do. */ IMB_colormanagement_imbuf_to_byte_texture( - (uchar *)data_rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb, store_premultiplied); + (uchar *)data_rect, 0, 0, ibuf->x, ibuf->y, ibuf, store_premultiplied); + } + else { + /* Other colorspace, store as float texture to avoid precision loss. */ + data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__); + *r_freedata = freedata = true; + + if (data_rect == NULL) { + return NULL; + } + + /* Texture storage of images is defined by the alpha mode of the image. The + * downside of this is that there can be artifacts near alpha edges. However, + * this allows us to use sRGB texture formats and preserves color values in + * zero alpha areas, and appears generally closer to what game engines that we + * want to be compatible with do. */ + IMB_colormanagement_imbuf_to_float_texture( + (float *)data_rect, 0, 0, ibuf->x, ibuf->y, ibuf, store_premultiplied); } } @@ -181,10 +212,9 @@ void IMB_update_gpu_texture_sub(GPUTexture *tex, eGPUTextureFormat tex_format; imb_gpu_get_format(ibuf, use_high_bitdepth, &data_format, &tex_format); - const bool compress_as_srgb = (tex_format == GPU_SRGB8_A8); bool freebuf = false; - void *data = imb_gpu_get_data(ibuf, do_rescale, size, compress_as_srgb, use_premult, &freebuf); + void *data = imb_gpu_get_data(ibuf, do_rescale, size, use_premult, &freebuf); /* Update Texture. */ GPU_texture_update_sub(tex, data_format, data, x, y, z, w, h, 1); @@ -238,7 +268,6 @@ GPUTexture *IMB_create_gpu_texture(const char *name, eGPUTextureFormat tex_format; imb_gpu_get_format(ibuf, use_high_bitdepth, &data_format, &tex_format); - const bool compress_as_srgb = (tex_format == GPU_SRGB8_A8); bool freebuf = false; /* Create Texture. */ @@ -250,7 +279,7 @@ GPUTexture *IMB_create_gpu_texture(const char *name, do_rescale = true; } BLI_assert(tex != NULL); - void *data = imb_gpu_get_data(ibuf, do_rescale, size, compress_as_srgb, use_premult, &freebuf); + void *data = imb_gpu_get_data(ibuf, do_rescale, size, use_premult, &freebuf); GPU_texture_update(tex, data_format, data); GPU_texture_anisotropic_filter(tex, true); -- cgit v1.2.3 From 263371dc4e217ab38ee30fcb210e3c342c6c60ec Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 7 Jun 2022 14:53:20 +1000 Subject: Cleanup: spelling in comments, additional white space --- source/blender/imbuf/intern/IMB_filetype.h | 9 ++++----- source/blender/imbuf/intern/tiff.c | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 6e505746643..9a0a6998fab 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -240,11 +240,10 @@ void imb_loadtiletiff( /** * Saves a TIFF file. * - * #ImBuf structures with 1, 3 or 4 bytes per pixel (GRAY, RGB, RGBA - * respectively) are accepted, and interpreted correctly. Note that the TIFF - * convention is to use pre-multiplied alpha, which can be achieved within - * Blender by setting "Premul" alpha handling. Other alpha conventions are - * not strictly correct, but are permitted anyhow. + * #ImBuf structures with 1, 3 or 4 bytes per pixel (GRAY, RGB, RGBA respectively) + * are accepted, and interpreted correctly. Note that the TIFF convention is to use + * pre-multiplied alpha, which can be achieved within Blender by setting `premul` alpha handling. + * Other alpha conventions are not strictly correct, but are permitted anyhow. * * \param ibuf: Image buffer. * \param filepath: Name of the TIFF file to create. diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 1372aa31713..2f13ef409e3 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -8,15 +8,15 @@ * Provides TIFF file loading and saving for Blender, via libtiff. * * The task of loading is complicated somewhat by the fact that Blender has - * already loaded the file into a memory buffer. libtiff is not well + * already loaded the file into a memory buffer. libtiff is not well * configured to handle files in memory, so a client wrapper is written to - * surround the memory and turn it into a virtual file. Currently, reading - * of TIFF files is done using libtiff's RGBAImage support. This is a + * surround the memory and turn it into a virtual file. Currently, reading + * of TIFF files is done using libtiff's RGBAImage support. This is a * high-level routine that loads all images as 32-bit RGBA, handling all the * required conversions between many different TIFF types internally. * * Saving supports RGB, RGBA and BW (gray-scale) images correctly, with - * 8 bits per channel in all cases. The "deflate" compression algorithm is + * 8 bits per channel in all cases. The "deflate" compression algorithm is * used to compress images. */ @@ -151,8 +151,8 @@ static tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n) /** * Writes data to an in-memory TIFF file. * - * NOTE: The current Blender implementation should not need this function. It - * is simply a stub. + * NOTE: The current Blender implementation should not need this function. + * It is simply a stub. */ static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n) { @@ -176,7 +176,7 @@ static tsize_t imb_tiff_WriteProc(thandle_t handle, tdata_t data, tsize_t n) * error). * * \return Resulting offset location within the file, measured in bytes from - * the beginning of the file. (-1) indicates an error. + * the beginning of the file. (-1) indicates an error. */ static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence) { @@ -215,8 +215,8 @@ static toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence) * Closes (virtually) an in-memory TIFF file. * * NOTE: All this function actually does is sets the data pointer within the - * TIFF file to NULL. That should trigger assertion errors if attempts - * are made to access the file after that point. However, no such + * TIFF file to NULL. That should trigger assertion errors if attempts + * are made to access the file after that point. However, no such * attempts should ever be made (in theory). * * \param handle: Handle of the TIFF file (pointer to #ImbTIFFMemFile). @@ -734,7 +734,7 @@ bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags) int x, y, from_i, to_i, i; int compress_mode = COMPRESSION_NONE; - /* check for a valid number of bytes per pixel. Like the PNG writer, + /* check for a valid number of bytes per pixel. Like the PNG writer, * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding * to gray, RGB, RGBA respectively. */ samplesperpixel = (uint16_t)((ibuf->planes + 7) >> 3); @@ -838,7 +838,7 @@ bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags) TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); } - /* copy pixel data. While copying, we flip the image vertically. */ + /* copy pixel data. While copying, we flip the image vertically. */ const int channels_in_float = ibuf->channels ? ibuf->channels : 4; for (x = 0; x < ibuf->x; x++) { for (y = 0; y < ibuf->y; y++) { -- cgit v1.2.3 From 6a11cd036cefd99689866ddd8f63861f9383766a Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 10 Jun 2022 10:29:35 +0200 Subject: Cleanup: Clang tidy --- .../blender/imbuf/intern/openexr/openexr_api.cpp | 10 +++++----- source/blender/imbuf/intern/thumbs.c | 5 ++--- source/blender/imbuf/intern/transform.cc | 23 ++++++++++++++-------- 3 files changed, 22 insertions(+), 16 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 54ef5438c23..0414fa1268d 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -174,14 +174,14 @@ class IMMapStream : public Imf::IStream { imb_mmap_lock(); _mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - if (_mmap_file == NULL) { + if (_mmap_file == nullptr) { throw IEX_NAMESPACE::InputExc("BLI_mmap_open failed"); } close(file); _exrbuf = (unsigned char *)BLI_mmap_get_pointer(_mmap_file); } - ~IMMapStream() + ~IMMapStream() override { imb_mmap_lock(); BLI_mmap_free(_mmap_file); @@ -512,7 +512,7 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags /* we store first everything in half array */ std::vector pixels(height * width); - RGBAZ *to = &pixels[0]; + RGBAZ *to = pixels.data(); int xstride = sizeof(RGBAZ); int ystride = xstride * width; @@ -1010,7 +1010,7 @@ void IMB_exrtile_begin_write( /* manually create ofstream, so we can handle utf-8 filepaths on windows */ try { data->ofile_stream = new OFileStream(filepath); - data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), &headers[0], headers.size()); + data->mpofile = new MultiPartOutputFile(*(data->ofile_stream), headers.data(), headers.size()); } catch (const std::exception &) { delete data->mpofile; @@ -2209,7 +2209,7 @@ struct ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath, if (file->header().hasPreviewImage()) { const Imf::PreviewImage &preview = file->header().previewImage(); ImBuf *ibuf = IMB_allocFromBuffer( - (unsigned int *)preview.pixels(), NULL, preview.width(), preview.height(), 4); + (unsigned int *)preview.pixels(), nullptr, preview.width(), preview.height(), 4); delete file; delete stream; IMB_flipy(ibuf); diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index f2c9c82fa66..6f39009d38d 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -30,7 +30,6 @@ #include "IMB_thumbs.h" #include -#include #include #include #include @@ -514,7 +513,7 @@ void IMB_thumb_delete(const char *filepath, ThumbSize size) } } -ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source) +ImBuf *IMB_thumb_manage(const char *filepath, ThumbSize size, ThumbSource source) { char thumb_path[FILE_MAX]; char thumb_name[40]; @@ -526,7 +525,7 @@ ImBuf *IMB_thumb_manage(const char *org_path, ThumbSize size, ThumbSource source ImBuf *img = NULL; char *blen_group = NULL, *blen_id = NULL; - path = file_path = org_path; + path = file_path = filepath; if (source == THB_SOURCE_BLEND) { if (BLO_library_path_explode(path, path_buff, &blen_group, &blen_id)) { if (blen_group) { diff --git a/source/blender/imbuf/intern/transform.cc b/source/blender/imbuf/intern/transform.cc index edb47c8c7ce..1499c1071e3 100644 --- a/source/blender/imbuf/intern/transform.cc +++ b/source/blender/imbuf/intern/transform.cc @@ -293,30 +293,37 @@ class Sampler { NumChannels == 4) { const float wrapped_u = uv_wrapper.modify_u(source, u); const float wrapped_v = uv_wrapper.modify_v(source, v); - bilinear_interpolation_color_fl(source, nullptr, &r_sample[0], wrapped_u, wrapped_v); + bilinear_interpolation_color_fl(source, nullptr, r_sample.data(), wrapped_u, wrapped_v); } else if constexpr (Filter == IMB_FILTER_NEAREST && std::is_same_v && NumChannels == 4) { const float wrapped_u = uv_wrapper.modify_u(source, u); const float wrapped_v = uv_wrapper.modify_v(source, v); - nearest_interpolation_color_char(source, &r_sample[0], nullptr, wrapped_u, wrapped_v); + nearest_interpolation_color_char(source, r_sample.data(), nullptr, wrapped_u, wrapped_v); } else if constexpr (Filter == IMB_FILTER_BILINEAR && std::is_same_v && NumChannels == 4) { const float wrapped_u = uv_wrapper.modify_u(source, u); const float wrapped_v = uv_wrapper.modify_v(source, v); - bilinear_interpolation_color_char(source, &r_sample[0], nullptr, wrapped_u, wrapped_v); + bilinear_interpolation_color_char(source, r_sample.data(), nullptr, wrapped_u, wrapped_v); } else if constexpr (Filter == IMB_FILTER_BILINEAR && std::is_same_v) { if constexpr (std::is_same_v) { - BLI_bilinear_interpolation_wrap_fl( - source->rect_float, &r_sample[0], source->x, source->y, NumChannels, u, v, true, true); + BLI_bilinear_interpolation_wrap_fl(source->rect_float, + r_sample.data(), + source->x, + source->y, + NumChannels, + u, + v, + true, + true); } else { const float wrapped_u = uv_wrapper.modify_u(source, u); const float wrapped_v = uv_wrapper.modify_v(source, v); BLI_bilinear_interpolation_fl(source->rect_float, - &r_sample[0], + r_sample.data(), source->x, source->y, NumChannels, @@ -390,11 +397,11 @@ class ChannelConverter { BLI_STATIC_ASSERT(SourceNumChannels == 4, "Unsigned chars always have 4 channels."); BLI_STATIC_ASSERT(DestinationNumChannels == 4, "Unsigned chars always have 4 channels."); - copy_v4_v4_uchar(pixel_pointer.get_pointer(), &sample[0]); + copy_v4_v4_uchar(pixel_pointer.get_pointer(), sample.data()); } else if constexpr (std::is_same_v && SourceNumChannels == 4 && DestinationNumChannels == 4) { - copy_v4_v4(pixel_pointer.get_pointer(), &sample[0]); + copy_v4_v4(pixel_pointer.get_pointer(), sample.data()); } else if constexpr (std::is_same_v && SourceNumChannels == 3 && DestinationNumChannels == 4) { -- cgit v1.2.3 From 1152a437e097a80618cce23056af74dacc192c52 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 17 Jun 2022 17:13:59 +1000 Subject: Cleanup: remove `r_` prefix for non-return values --- source/blender/imbuf/intern/stereoimbuf.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'source/blender/imbuf/intern') diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c index 52756891f21..2a0baaf6172 100644 --- a/source/blender/imbuf/intern/stereoimbuf.c +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -702,21 +702,21 @@ int *IMB_stereo3d_from_rect(const ImageFormatData *im_format, int *rect_left, int *rect_right) { - int *r_rect; + int *rect_result; Stereo3DData s3d_data = {{NULL}}; size_t width, height; const bool is_float = im_format->depth > 8; IMB_stereo3d_write_dimensions( im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rect = MEM_mallocN(channels * sizeof(int) * width * height, __func__); + rect_result = MEM_mallocN(channels * sizeof(int) * width * height, __func__); imb_stereo3d_data_init( - &s3d_data, is_float, x, y, channels, rect_left, rect_right, r_rect, NULL, NULL, NULL); + &s3d_data, is_float, x, y, channels, rect_left, rect_right, rect_result, NULL, NULL, NULL); imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rect(r_rect, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_squeeze_rect(rect_result, &im_format->stereo3d_format, x, y, channels); - return r_rect; + return rect_result; } float *IMB_stereo3d_from_rectf(const ImageFormatData *im_format, @@ -726,21 +726,30 @@ float *IMB_stereo3d_from_rectf(const ImageFormatData *im_format, float *rectf_left, float *rectf_right) { - float *r_rectf; + float *rectf_result; Stereo3DData s3d_data = {{NULL}}; size_t width, height; const bool is_float = im_format->depth > 8; IMB_stereo3d_write_dimensions( im_format->stereo3d_format.display_mode, false, x, y, &width, &height); - r_rectf = MEM_mallocN(channels * sizeof(float) * width * height, __func__); + rectf_result = MEM_mallocN(channels * sizeof(float) * width * height, __func__); - imb_stereo3d_data_init( - &s3d_data, is_float, x, y, channels, NULL, NULL, NULL, rectf_left, rectf_right, r_rectf); + imb_stereo3d_data_init(&s3d_data, + is_float, + x, + y, + channels, + NULL, + NULL, + NULL, + rectf_left, + rectf_right, + rectf_result); imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); - imb_stereo3d_squeeze_rectf(r_rectf, &im_format->stereo3d_format, x, y, channels); + imb_stereo3d_squeeze_rectf(rectf_result, &im_format->stereo3d_format, x, y, channels); - return r_rectf; + return rectf_result; } ImBuf *IMB_stereo3d_ImBuf(const ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *ibuf_right) -- cgit v1.2.3