Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py26
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py2
-rw-r--r--source/blender/blenfont/BLF_api.h3
-rw-r--r--source/blender/blenfont/CMakeLists.txt1
-rw-r--r--source/blender/blenfont/SConscript2
-rw-r--r--source/blender/blenfont/intern/blf.c5
-rw-r--r--source/blender/blenfont/intern/blf_font.c9
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h4
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_colortools.h23
-rw-r--r--source/blender/blenkernel/BKE_image.h5
-rw-r--r--source/blender/blenkernel/BKE_node.h5
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h12
-rw-r--r--source/blender/blenkernel/SConscript7
-rw-r--r--source/blender/blenkernel/intern/blender.c8
-rw-r--r--source/blender/blenkernel/intern/colortools.c92
-rw-r--r--source/blender/blenkernel/intern/image.c80
-rw-r--r--source/blender/blenkernel/intern/image_gen.c6
-rw-r--r--source/blender/blenkernel/intern/movieclip.c15
-rw-r--r--source/blender/blenkernel/intern/ocean.c9
-rw-r--r--source/blender/blenkernel/intern/scene.c40
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c9
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c9
-rw-r--r--source/blender/blenkernel/intern/sequencer.c135
-rw-r--r--source/blender/blenkernel/intern/tracking.c3
-rw-r--r--source/blender/blenlib/BLI_threads.h1
-rw-r--r--source/blender/blenlib/intern/threads.c5
-rw-r--r--source/blender/blenloader/intern/readfile.c58
-rw-r--r--source/blender/blenloader/intern/writefile.c11
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/compositor/COM_compositor.h15
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.cpp12
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h26
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.cpp6
-rw-r--r--source/blender/compositor/intern/COM_ExecutionSystem.h4
-rw-r--r--source/blender/compositor/intern/COM_Node.cpp8
-rw-r--r--source/blender/compositor/intern/COM_Node.h4
-rw-r--r--source/blender/compositor/intern/COM_compositor.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_BlurNode.cpp8
-rw-r--r--source/blender/compositor/nodes/COM_BokehImageNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ChannelMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ChromaMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ColorMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_CompositorNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DespeckleNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DilateErodeNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_DistanceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_FilterNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp4
-rw-r--r--source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MovieClipNode.cpp22
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cpp7
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.cpp62
-rw-r--r--source/blender/compositor/nodes/COM_RenderLayersNode.h2
-rw-r--r--source/blender/compositor/nodes/COM_SplitViewerNode.cpp7
-rw-r--r--source/blender/compositor/nodes/COM_TextureNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_ViewerNode.cpp7
-rw-r--r--source/blender/compositor/operations/COM_ImageOperation.cpp1
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h7
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.cpp13
-rw-r--r--source/blender/compositor/operations/COM_PreviewOperation.h5
-rw-r--r--source/blender/compositor/operations/COM_SplitViewerOperation.cpp18
-rw-r--r--source/blender/compositor/operations/COM_ViewerBaseOperation.cpp31
-rw-r--r--source/blender/compositor/operations/COM_ViewerBaseOperation.h13
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp16
-rw-r--r--source/blender/editors/include/ED_clip.h2
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_view3d.h8
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/interface/interface.c30
-rw-r--r--source/blender/editors/interface/interface_draw.c13
-rw-r--r--source/blender/editors/interface/interface_handlers.c30
-rw-r--r--source/blender/editors/interface/interface_icons.c6
-rw-r--r--source/blender/editors/interface/interface_intern.h9
-rw-r--r--source/blender/editors/interface/interface_ops.c20
-rw-r--r--source/blender/editors/interface/interface_regions.c31
-rw-r--r--source/blender/editors/interface/interface_templates.c53
-rw-r--r--source/blender/editors/interface/interface_widgets.c26
-rw-r--r--source/blender/editors/object/object_bake.c10
-rw-r--r--source/blender/editors/render/render_internal.c18
-rw-r--r--source/blender/editors/render/render_opengl.c90
-rw-r--r--source/blender/editors/render/render_preview.c38
-rw-r--r--source/blender/editors/screen/screendump.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c47
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c5
-rw-r--r--source/blender/editors/space_clip/clip_draw.c25
-rw-r--r--source/blender/editors/space_clip/clip_editor.c35
-rw-r--r--source/blender/editors/space_file/filelist.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c81
-rw-r--r--source/blender/editors/space_image/image_draw.c127
-rw-r--r--source/blender/editors/space_image/image_intern.h2
-rw-r--r--source/blender/editors/space_image/image_ops.c126
-rw-r--r--source/blender/editors/space_image/space_image.c13
-rw-r--r--source/blender/editors/space_node/drawnode.c29
-rw-r--r--source/blender/editors/space_node/node_draw.c4
-rw-r--r--source/blender/editors/space_node/node_edit.c5
-rw-r--r--source/blender/editors/space_node/node_intern.h2
-rw-r--r--source/blender/editors/space_node/node_view.c19
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c133
-rw-r--r--source/blender/editors/space_sequencer/sequencer_scopes.c50
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c13
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c52
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c10
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c57
-rw-r--r--source/blender/gpu/intern/gpu_draw.c15
-rw-r--r--source/blender/gpu/intern/gpu_material.c8
-rw-r--r--source/blender/imbuf/CMakeLists.txt7
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h155
-rw-r--r--source/blender/imbuf/IMB_imbuf.h20
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h16
-rw-r--r--source/blender/imbuf/SConscript4
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h1
-rw-r--r--source/blender/imbuf/intern/IMB_colormanagement_intern.h92
-rw-r--r--source/blender/imbuf/intern/IMB_filetype.h25
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c16
-rw-r--r--source/blender/imbuf/intern/anim_movie.c37
-rw-r--r--source/blender/imbuf/intern/bmp.c8
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c15
-rw-r--r--source/blender/imbuf/intern/colormanagement.c2337
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp12
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.h4
-rw-r--r--source/blender/imbuf/intern/divers.c137
-rw-r--r--source/blender/imbuf/intern/filetype.c30
-rw-r--r--source/blender/imbuf/intern/indexer.c3
-rw-r--r--source/blender/imbuf/intern/iris.c9
-rw-r--r--source/blender/imbuf/intern/jp2.c155
-rw-r--r--source/blender/imbuf/intern/jpeg.c10
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp41
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.h2
-rw-r--r--source/blender/imbuf/intern/png.c41
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c8
-rw-r--r--source/blender/imbuf/intern/readimage.c38
-rw-r--r--source/blender/imbuf/intern/rectop.c16
-rw-r--r--source/blender/imbuf/intern/targa.c9
-rw-r--r--source/blender/imbuf/intern/thumbs.c11
-rw-r--r--source/blender/imbuf/intern/tiff.c15
-rw-r--r--source/blender/imbuf/intern/writeimage.c36
-rw-r--r--source/blender/makesdna/DNA_color_types.h22
-rw-r--r--source/blender/makesdna/DNA_image_types.h5
-rw-r--r--source/blender/makesdna/DNA_movieclip_types.h4
-rw-r--r--source/blender/makesdna/DNA_scene_types.h11
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h13
-rw-r--r--source/blender/makesdna/DNA_space_types.h8
-rw-r--r--source/blender/makesrna/RNA_access.h3
-rw-r--r--source/blender/makesrna/intern/rna_color.c242
-rw-r--r--source/blender/makesrna/intern/rna_image.c10
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c20
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c6
-rw-r--r--source/blender/makesrna/intern/rna_scene.c60
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c5
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_space.c21
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c12
-rw-r--r--source/blender/nodes/composite/node_composite_tree.c8
-rw-r--r--source/blender/nodes/composite/node_composite_util.c3
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c29
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c3
-rw-r--r--source/blender/quicktime/apple/qtkit_import.m1
-rw-r--r--source/blender/quicktime/apple/quicktime_import.c2
-rw-r--r--source/blender/render/intern/include/render_result.h6
-rw-r--r--source/blender/render/intern/source/envmap.c3
-rw-r--r--source/blender/render/intern/source/pipeline.c60
-rw-r--r--source/blender/render/intern/source/render_result.c41
-rw-r--r--source/blender/render/intern/source/render_texture.c21
-rw-r--r--source/blender/render/intern/source/rendercore.c14
-rw-r--r--source/blender/render/intern/source/shadeinput.c9
-rw-r--r--source/blender/windowmanager/intern/wm_files.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c9
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c2
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c20
-rw-r--r--source/blenderplayer/CMakeLists.txt1
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c2
-rw-r--r--source/creator/CMakeLists.txt21
178 files changed, 5024 insertions, 1186 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 74bb720b618..b777fcddcf2 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -316,10 +316,7 @@ class RENDER_PT_shading(RenderButtonsPanel, Panel):
col = split.column()
col.prop(rd, "use_raytrace", text="Ray Tracing")
- col.prop(rd, "use_color_management")
- sub = col.row()
- sub.active = rd.use_color_management == True
- sub.prop(rd, "use_color_unpremultiply")
+ col.prop(rd, "use_color_unpremultiply")
col.prop(rd, "alpha_mode", text="Alpha")
@@ -467,7 +464,7 @@ class RENDER_PT_output(RenderButtonsPanel, Panel):
flow.prop(rd, "use_placeholder")
flow.prop(rd, "use_file_extension")
- layout.template_image_settings(image_settings)
+ layout.template_image_settings(image_settings, color_management=False)
if file_format == 'QUICKTIME_CARBON':
layout.operator("scene.render_data_set_quicktime_codec")
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 8449d26f6e6..2ccdb9cee26 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -231,6 +231,32 @@ class SCENE_PT_simplify(SceneButtonsPanel, Panel):
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
+class SCENE_PT_color_management(Panel):
+ bl_label = "Color Management"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "scene"
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+
+ col = layout.column()
+ col.label(text="Display:")
+ col.prop(scene.display_settings, "display_device")
+
+ col = layout.column()
+ col.separator()
+ col.label(text="Render:")
+ col.template_colormanaged_view_settings(scene, "view_settings")
+
+ col = layout.column()
+ col.separator()
+ col.label(text="Sequencer:")
+ col.prop(scene.sequencer_colorspace_settings, "name")
+
+
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "scene"
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index dd13b8a9b51..39c892930f4 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -884,6 +884,8 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel):
strip = act_strip(context)
sequencer = context.scene.sequence_editor
+ layout.prop(strip, "use_linear_modifiers")
+
layout.operator_menu_enum("sequencer.strip_modifier_add", "type")
for mod in strip.modifiers:
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 0732e02b5fc..ce10951d6ff 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -33,6 +33,7 @@
#define __BLF_API_H__
struct rctf;
+struct ColorManagedDisplay;
int BLF_init(int points, int dpi);
void BLF_exit(void);
@@ -151,7 +152,7 @@ void BLF_shadow_offset(int fontid, int x, int y);
*
* BLF_buffer(NULL, NULL, 0, 0, 0, FALSE);
*/
-void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, int do_color_management);
+void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display);
/* Set the color to be used for text. */
void BLF_buffer_col(int fontid, float r, float g, float b, float a);
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index ebf9ff4db39..da60710a137 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -27,6 +27,7 @@ set(INC
../blenlib
../editors/include
../makesdna
+ ../imbuf
../../../intern/guardedalloc
)
diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript
index c46960d2311..d3c7b1c2fcc 100644
--- a/source/blender/blenfont/SConscript
+++ b/source/blender/blenfont/SConscript
@@ -4,7 +4,7 @@ Import ('env')
sources = env.Glob('intern/*.c')
-incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ../editors/include'
+incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../makesdna ../imbuf ../editors/include'
incs += ' #/extern/glew/include'
incs += ' ' + env['BF_FREETYPE_INC']
incs += ' ' + env['BF_GETTEXT_INC']
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index d4739b37f93..92fcb576e7d 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -50,7 +50,6 @@
#include "blf_internal_types.h"
#include "blf_internal.h"
-
/* Max number of font in memory.
* Take care that now every font have a glyph cache per size/dpi,
* so we don't need load the same font with different size, just
@@ -746,7 +745,7 @@ void BLF_shadow_offset(int fontid, int x, int y)
}
}
-void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, int do_color_management)
+void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
{
FontBLF *font = BLF_get(fontid);
@@ -756,7 +755,7 @@ void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int
font->buf_info.w = w;
font->buf_info.h = h;
font->buf_info.ch = nch;
- font->buf_info.do_color_management = do_color_management;
+ font->buf_info.display = display;
}
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index cb05c89921e..02b66993c0a 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -53,6 +53,8 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "IMB_colormanagement.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -245,11 +247,12 @@ void blf_font_buffer(FontBLF *font, const char *str)
blf_font_ensure_ascii_table(font);
/* another buffer specific call for color conversion */
- if (buf_info->do_color_management) {
- srgb_to_linearrgb_v4(b_col_float, buf_info->col);
+ if (buf_info->display) {
+ copy_v4_v4(b_col_float, buf_info->col);
+ IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display);
}
else {
- copy_v4_v4(b_col_float, buf_info->col);
+ srgb_to_linearrgb_v4(b_col_float, buf_info->col);
}
while (str[i]) {
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index 4c617da7583..1acc3dad4cf 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -145,8 +145,8 @@ typedef struct FontBufInfoBLF {
/* number of channels. */
int ch;
- /* is the float buffer linear */
- int do_color_management;
+ /* display device used for color management */
+ struct ColorManagedDisplay *display;
/* and the color, the alphas is get from the glyph!
* color is srgb space */
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index 1e67027ae8c..fed82d7e93d 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 263
-#define BLENDER_SUBVERSION 18
+#define BLENDER_SUBVERSION 19
/* 262 was the last editmesh release but its has compatibility code for bmesh data,
* so set the minversion to 2.61 */
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index 9b7fc1fddad..cd67059ea8c 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -31,6 +31,9 @@
* \ingroup bke
*/
+struct ColorManagedColorspaceSettings;
+struct ColorManagedDisplaySettings;
+struct ColorManagedViewSettings;
struct CurveMapping;
struct CurveMap;
struct CurveMapPoint;
@@ -89,9 +92,25 @@ void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBu
void curvemapping_premultiply(struct CurveMapping *cumap, int restore);
-void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf, const short use_color_management);
-void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int use_color_management);
+void BKE_histogram_update_sample_line(struct Histogram *hist, struct ImBuf *ibuf,
+ const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
void scopes_free(struct Scopes *scopes);
void scopes_new(struct Scopes *scopes);
+void BKE_color_managed_display_settings_init(struct ColorManagedDisplaySettings *settings);
+void BKE_color_managed_display_settings_copy(struct ColorManagedDisplaySettings *new_settings,
+ const struct ColorManagedDisplaySettings *settings);
+
+void BKE_color_managed_view_settings_init(struct ColorManagedViewSettings *settings);
+void BKE_color_managed_view_settings_copy(struct ColorManagedViewSettings *new_settings,
+ const struct ColorManagedViewSettings *settings);
+void BKE_color_managed_view_settings_free(struct ColorManagedViewSettings *settings);
+
+void BKE_color_managed_colorspace_settings_init(struct ColorManagedColorspaceSettings *colorspace_settings);
+void BKE_color_managed_colorspace_settings_copy(struct ColorManagedColorspaceSettings *colorspace_settings,
+ const struct ColorManagedColorspaceSettings *settings);
+
#endif
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 67461281674..ac324b2af00 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -46,6 +46,8 @@ struct Object;
struct ImageFormatData;
struct Main;
+#define IMA_MAX_SPACE 64
+
/* call from library */
void BKE_image_free(struct Image *me);
@@ -64,6 +66,7 @@ int BKE_imtype_is_movie(const char imtype);
int BKE_imtype_supports_zbuf(const char imtype);
int BKE_imtype_supports_compress(const char imtype);
int BKE_imtype_supports_quality(const char imtype);
+int BKE_imtype_supports_float(const char imtype);
char BKE_imtype_valid_channels(const char imtype);
char BKE_imtype_valid_depths(const char imtype);
@@ -72,7 +75,7 @@ char BKE_imtype_from_arg(const char *arg);
void BKE_imformat_defaults(struct ImageFormatData *im_format);
void BKE_imbuf_to_image_format(struct ImageFormatData *im_format, const struct ImBuf *imbuf);
-struct anim *openanim(const char *name, int flags, int streamindex);
+struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]);
void BKE_image_de_interlace(struct Image *ima, int odd);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 438d5110666..6ad2ad924e2 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -64,6 +64,8 @@ struct Tex;
struct SpaceNode;
struct ARegion;
struct Object;
+struct ColorManagedViewSettings;
+struct ColorManagedDisplaySettings;
/* ************** NODE TYPE DEFINITIONS ***** */
@@ -725,7 +727,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria
struct CompBuf;
struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data);
void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data);
-void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews);
+void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews,
+ const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings);
void ntreeCompositTagRender(struct Scene *sce);
int ntreeCompositTagAnimated(struct bNodeTree *ntree);
void ntreeCompositTagGenerators(struct bNodeTree *ntree);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index bce4243190a..023b7e85c40 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -108,6 +108,8 @@ float get_render_aosss_error(struct RenderData *r, float error);
int BKE_scene_use_new_shading_nodes(struct Scene *scene);
+void BKE_scene_disable_color_management(struct Scene *scene);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 51a64c97ca6..0c571f62f0e 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -177,6 +177,16 @@ struct ImBuf *BKE_sequencer_give_ibuf_seqbase(SeqRenderData context, float cfra,
void BKE_sequencer_give_ibuf_prefetch_request(SeqRenderData context, float cfra, int chan_shown);
/* **********************************************************************
+ * sequencer.c
+ *
+ * sequencer color space functions
+ * ********************************************************************** */
+
+void BKE_sequencer_imbuf_to_sequencer_space(struct Scene *scene, struct ImBuf *ibuf, int make_float);
+void BKE_sequencer_imbuf_from_sequencer_space(struct Scene *scene, struct ImBuf *ibuf);
+void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4]);
+
+/* **********************************************************************
* sequencer scene functions
* ********************************************************************** */
struct Editing *BKE_sequencer_editing_get(struct Scene *scene, int alloc);
@@ -350,7 +360,7 @@ struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seq
struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
/* view3d draw callback, run when not in background view */
-typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, char[256]);
+typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, int, int, char[256]);
extern SequencerDrawView sequencer_view3d_cb;
/* copy/paste */
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 68ca3170bd8..d1a35b122e8 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -3,6 +3,10 @@ Import ('env')
import os
sources = env.Glob('intern/*.c')
+sources.remove('intern' + os.sep + 'mask_rasterize.c')
+sources.remove('intern' + os.sep + 'mask.c')
+
+sources_mask = env.Glob('intern/mask*.c')
incs = '. #/intern/guardedalloc #/intern/memutil'
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
@@ -118,7 +122,10 @@ if env['WITH_BF_INTERNATIONAL']:
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
incs += ' ' + env['BF_PTHREADS_INC']
+
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') )
else:
env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player', 'player2'], priority = [166,25,0] )
+
+env.BlenderLib ( libname = 'bf_blenkernel_mask', sources = sources_mask, includes = Split(incs), defines = defs, libtype=['core','player', 'player2'], priority = [200,25,0] )
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 45e2167af2f..99b788e80ce 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -89,6 +89,8 @@
#include "WM_api.h" // XXXXX BAD, very BAD dependency (bad level call) - remove asap, elubie
+#include "IMB_colormanagement.h"
+
#ifdef WITH_PYTHON
# include "BPY_extern.h"
#endif
@@ -320,7 +322,11 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, const char *filepath
/* baseflags, groups, make depsgraph, etc */
BKE_scene_set_background(G.main, CTX_data_scene(C));
-
+
+ if (mode != 'u') {
+ IMB_colormanagement_check_file_config(G.main);
+ }
+
MEM_freeN(bfd);
(void)curscene; /* quiet warning */
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index d65c81b4f9b..19c8c2cd632 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -49,6 +49,7 @@
#include "BKE_fcurve.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -174,6 +175,7 @@ void curvemapping_set_black_white(CurveMapping *cumap, const float black[3], con
}
curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul);
+ cumap->changed_timestamp++;
}
/* ***************** operations on single curve ************* */
@@ -996,7 +998,8 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons
}
}
-void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short use_color_management)
+void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
{
int i, x, y;
float *fp;
@@ -1008,6 +1011,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short
int y1 = 0.5f + hist->co[0][1] * ibuf->y;
int y2 = 0.5f + hist->co[1][1] * ibuf->y;
+ struct ColormanageProcessor *cm_processor = NULL;
+
hist->channels = 3;
hist->x_resolution = 256;
hist->xmax = 1.0f;
@@ -1015,6 +1020,9 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short
if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;
+ if (ibuf->rect_float)
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+
/* persistent draw */
hist->flag |= HISTO_FLAG_SAMPLELINE; /* keep drawing the flag after */
@@ -1029,10 +1037,8 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- if (use_color_management)
- linearrgb_to_srgb_v3_v3(rgb, fp);
- else
- copy_v3_v3(rgb, fp);
+ copy_v3_v3(rgb, fp);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgb);
hist->data_luma[i] = rgb_to_luma(rgb);
hist->data_r[i] = rgb[0];
@@ -1050,9 +1056,13 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const short
}
}
}
+
+ if (cm_processor)
+ IMB_colormanagement_processor_free(cm_processor);
}
-void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
+void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
{
int x, y, c;
unsigned int n, nl;
@@ -1065,6 +1075,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
int ycc_mode = -1;
const short is_float = (ibuf->rect_float != NULL);
+ struct ColormanageProcessor *cm_processor = NULL;
+
if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;
if (scopes->ok == 1) return;
@@ -1134,6 +1146,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
else
rc = (unsigned char *)ibuf->rect;
+ if (ibuf->rect_float)
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+
for (y = 0; y < ibuf->y; y++) {
if (savedlines < scopes->sample_lines && y >= ((savedlines) * ibuf->y) / (scopes->sample_lines + 1)) {
saveline = 1;
@@ -1144,11 +1159,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
for (x = 0; x < ibuf->x; x++) {
if (is_float) {
- if (use_color_management)
- linearrgb_to_srgb_v3_v3(rgba, rf);
- else
- copy_v3_v3(rgba, rf);
- rgba[3] = rf[3];
+ copy_v4_v4(rgba, rf);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
}
else {
for (c = 0; c < 4; c++)
@@ -1219,6 +1231,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, int use_color_management)
MEM_freeN(bin_b);
MEM_freeN(bin_a);
+ if (cm_processor)
+ IMB_colormanagement_processor_free(cm_processor);
+
scopes->ok = 1;
}
@@ -1257,3 +1272,58 @@ void scopes_new(Scopes *scopes)
scopes->waveform_3 = NULL;
scopes->vecscope = NULL;
}
+
+void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settings)
+{
+ const char *display_name = IMB_colormanagement_display_get_default_name();
+
+ BLI_strncpy(settings->display_device, display_name, sizeof(settings->display_device));
+}
+
+void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings,
+ const ColorManagedDisplaySettings *settings)
+{
+ BLI_strncpy(new_settings->display_device, settings->display_device, sizeof(new_settings->display_device));
+}
+
+void BKE_color_managed_view_settings_init(ColorManagedViewSettings *settings)
+{
+ /* OCIO_TODO: use default view transform here when OCIO is completely integrated
+ * and proper versioning stuff is added.
+ * for now use NONE to be compatible with all current files
+ */
+ BLI_strncpy(settings->view_transform, "Default", sizeof(settings->view_transform));
+
+ settings->gamma = 1.0f;
+ settings->exposure = 0.0f;
+}
+
+void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings,
+ const ColorManagedViewSettings *settings)
+{
+ BLI_strncpy(new_settings->view_transform, settings->view_transform, sizeof(new_settings->view_transform));
+
+ new_settings->flag = settings->flag;
+ new_settings->exposure = settings->exposure;
+ new_settings->gamma = settings->gamma;
+
+ if (settings->curve_mapping)
+ new_settings->curve_mapping = curvemapping_copy(settings->curve_mapping);
+}
+
+void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings)
+{
+ if (settings->curve_mapping)
+ curvemapping_free(settings->curve_mapping);
+}
+
+void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings)
+{
+ BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name));
+}
+
+void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings,
+ const ColorManagedColorspaceSettings *settings)
+{
+ BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name));
+}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 3f756e74b26..d514a0a7dd0 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -47,6 +47,7 @@
#include "MEM_guardedalloc.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -70,6 +71,7 @@
#include "BLI_bpath.h"
#include "BKE_bmfont.h"
+#include "BKE_colortools.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_image.h"
@@ -243,6 +245,11 @@ static Image *image_alloc(const char *name, short source, short type)
ima->source = source;
ima->type = type;
+
+ if (source == IMA_SRC_VIEWER)
+ ima->flag |= IMA_VIEW_AS_RENDER;
+
+ BKE_color_managed_colorspace_settings_init(&ima->colorspace_settings);
}
return ima;
}
@@ -325,6 +332,8 @@ Image *BKE_image_copy(Image *ima)
nima->aspx = ima->aspx;
nima->aspy = ima->aspy;
+ BKE_color_managed_colorspace_settings_copy(&nima->colorspace_settings, &ima->colorspace_settings);
+
return nima;
}
@@ -603,12 +612,10 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (floatbuf) {
ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat);
rect_float = ibuf->rect_float;
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
}
else {
ibuf = IMB_allocImBuf(width, height, depth, IB_rect);
rect = (unsigned char *)ibuf->rect;
- ibuf->profile = IB_PROFILE_SRGB;
}
BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
@@ -1009,6 +1016,19 @@ int BKE_imtype_supports_quality(const char imtype)
return 0;
}
+int BKE_imtype_supports_float(const char imtype)
+{
+ switch (imtype) {
+ case R_IMF_IMTYPE_CINEON:
+ case R_IMF_IMTYPE_DPX:
+ case R_IMF_IMTYPE_RADHDR:
+ case R_IMF_IMTYPE_OPENEXR:
+ case R_IMF_IMTYPE_MULTILAYER:
+ return TRUE;
+ }
+ return 0;
+}
+
char BKE_imtype_valid_channels(const char imtype)
{
char chan_flag = IMA_CHAN_FLAG_RGB; /* assume all support rgb */
@@ -1477,10 +1497,11 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
int x, y, y_ofs;
float h_fixed;
const int mono = blf_mono_font_render; // XXX
+ struct ColorManagedDisplay *display;
+ const char *display_device;
/* this could be an argument if we want to operate on non linear float imbuf's
* for now though this is only used for renders which use scene settings */
- const int do_color_management = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0;
#define BUFF_MARGIN_X 2
#define BUFF_MARGIN_Y 1
@@ -1488,6 +1509,9 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
if (!rect && !rectf)
return;
+ display_device = scene->display_settings.display_device;
+ display = IMB_colormanagement_display_get_named(display_device);
+
stampdata(scene, camera, &stamp_data, 1);
/* TODO, do_versions */
@@ -1497,7 +1521,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
/* set before return */
BLF_size(mono, scene->r.stamp_font_id, 72);
- BLF_buffer(mono, rectf, rect, width, height, channels, do_color_management);
+ BLF_buffer(mono, rectf, rect, width, height, channels, display);
BLF_buffer_col(mono, scene->r.fg_stamp[0], scene->r.fg_stamp[1], scene->r.fg_stamp[2], 1.0);
pad = BLF_width_max(mono);
@@ -1514,7 +1538,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y -= h;
/* also a little of space to the background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and draw the text. */
@@ -1531,7 +1555,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y -= h;
/* and space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1547,7 +1571,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y -= h;
/* and space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1563,7 +1587,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y -= h;
/* and space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1578,7 +1602,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_width_and_height(mono, stamp_data.marker, &w, &h); h = h_fixed;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
@@ -1594,7 +1618,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_width_and_height(mono, stamp_data.time, &w, &h); h = h_fixed;
/* extra space for background */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
@@ -1609,7 +1633,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_width_and_height(mono, stamp_data.frame, &w, &h); h = h_fixed;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
@@ -1624,7 +1648,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_width_and_height(mono, stamp_data.camera, &w, &h); h = h_fixed;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.camera);
@@ -1637,7 +1661,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
BLF_width_and_height(mono, stamp_data.cameralens, &w, &h); h = h_fixed;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
BLF_draw_buffer(mono, stamp_data.cameralens);
@@ -1650,7 +1674,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
x = width - w - 2;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
/* and pad the text. */
@@ -1666,7 +1690,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec
y = height - h;
/* extra space for background. */
- buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, do_color_management,
+ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display,
x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y);
BLF_position(mono, x, y + y_ofs, 0.0);
@@ -1878,12 +1902,12 @@ void BKE_makepicstring(char *string, const char *base, const char *relbase, int
}
/* used by sequencer too */
-struct anim *openanim(const char *name, int flags, int streamindex)
+struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
{
struct anim *anim;
struct ImBuf *ibuf;
- anim = IMB_open_anim(name, flags, streamindex);
+ anim = IMB_open_anim(name, flags, streamindex, colorspace);
if (anim == NULL) return NULL;
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
@@ -2226,7 +2250,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
flag |= IB_premul;
/* read ibuf */
- ibuf = IMB_loadiffname(name, flag);
+ ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
#if 0
if (ibuf) {
@@ -2304,7 +2328,6 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f
ibuf->flags |= IB_rectfloat;
ibuf->mall = IB_rectfloat;
ibuf->channels = rpass->channels;
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
image_initialize_after_load(ima, ibuf);
image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, frame);
@@ -2334,7 +2357,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
BKE_image_user_file_path(iuser, ima, str);
/* FIXME: make several stream accessible in image editor, too*/
- ima->anim = openanim(str, IB_rect, 0);
+ ima->anim = openanim(str, IB_rect, 0, ima->colorspace_settings.name);
/* let's initialize this user */
if (ima->anim && iuser && iuser->frames == 0)
@@ -2385,8 +2408,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
flag = IB_rect | IB_multilayer;
if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul;
- ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data,
- ima->packedfile->size, flag, "<packed data>");
+ ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag,
+ ima->colorspace_settings.name, "<packed data>");
}
else {
flag = IB_rect | IB_multilayer | IB_metadata;
@@ -2398,7 +2421,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
BKE_image_user_file_path(iuser, ima, str);
/* read ibuf */
- ibuf = IMB_loadiffname(str, flag);
+ ibuf = IMB_loadiffname(str, flag, ima->colorspace_settings.name);
}
if (ibuf) {
@@ -2455,7 +2478,6 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
ibuf->rect_float = rpass->rect;
ibuf->flags |= IB_rectfloat;
ibuf->channels = rpass->channels;
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : IMA_NO_INDEX, 0);
}
@@ -2561,6 +2583,12 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
}
+ /* invalidate color managed buffers if render result changed */
+ BLI_lock_thread(LOCK_COLORMANAGE);
+ if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) {
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ }
+
ibuf->x = rres.rectx;
ibuf->y = rres.recty;
@@ -2592,8 +2620,8 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
ibuf->flags &= ~IB_zbuffloat;
}
- /* since its possible to access the buffer from the image directly, set the profile [#25073] */
- ibuf->profile = (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_NONE;
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+
ibuf->dither = dither;
if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) {
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index 4d7013b9f73..37572eebed6 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -289,7 +289,11 @@ static void checker_board_text(unsigned char *rect, float *rect_float, int width
BLF_size(mono, 54, 72); /* hard coded size! */
- BLF_buffer(mono, rect_float, rect, width, height, 4, TRUE);
+ /* OCIO_TODO: using NULL as display will assume using sRGB display
+ * this is correct since currently generated images are assumed to be in sRGB space,
+ * but this would probably needed to be fixed in some way
+ */
+ BLF_buffer(mono, rect_float, rect, width, height, 4, NULL);
for (y = 0; y < height; y += step) {
text[1] = '1';
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 1a6a9503887..97d4c150b84 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -66,6 +66,7 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
+#include "BKE_colortools.h"
#include "BKE_library.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -73,6 +74,7 @@
#include "BKE_image.h" /* openanim */
#include "BKE_tracking.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
@@ -197,19 +199,25 @@ static ImBuf *movieclip_load_sequence_file(MovieClip *clip, MovieClipUser *user,
struct ImBuf *ibuf;
char name[FILE_MAX];
int loadflag, use_proxy = FALSE;
+ char *colorspace;
use_proxy = (flag & MCLIP_USE_PROXY) && user->render_size != MCLIP_PROXY_RENDER_SIZE_FULL;
if (use_proxy) {
int undistort = user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
get_proxy_fname(clip, user->render_size, undistort, framenr, name);
+
+ /* proxies were built using default color space settings */
+ colorspace = NULL;
}
- else
+ else {
get_sequence_fname(clip, framenr, name);
+ colorspace = clip->colorspace_settings.name;
+ }
loadflag = IB_rect | IB_multilayer;
/* read ibuf */
- ibuf = IMB_loadiffname(name, loadflag);
+ ibuf = IMB_loadiffname(name, loadflag, colorspace);
return ibuf;
}
@@ -223,7 +231,7 @@ static void movieclip_open_anim_file(MovieClip *clip)
BLI_path_abs(str, ID_BLEND_PATH(G.main, &clip->id));
/* FIXME: make several stream accessible in image editor, too */
- clip->anim = openanim(str, IB_rect, 0);
+ clip->anim = openanim(str, IB_rect, 0, clip->colorspace_settings.name);
if (clip->anim) {
if (clip->flag & MCLIP_USE_PROXY_CUSTOM_DIR) {
@@ -478,6 +486,7 @@ static MovieClip *movieclip_alloc(const char *name)
clip->aspx = clip->aspy = 1.0f;
BKE_tracking_settings_init(&clip->tracking);
+ BKE_color_managed_colorspace_settings_init(&clip->colorspace_settings);
clip->proxy.build_size_flag = IMB_PROXY_25;
clip->proxy.build_tc_flag = IMB_TC_RECORD_RUN |
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index b862a824d50..4f3921936e8 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -1117,19 +1117,20 @@ void BKE_simulate_ocean_cache(struct OceanCache *och, int frame)
/* if image is already loaded in mem, return */
if (och->ibufs_disp[f] != NULL) return;
+ /* use default color spaces since we know for sure cache files were saved with default settings too */
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_DISPLACE);
- och->ibufs_disp[f] = IMB_loadiffname(string, 0);
+ och->ibufs_disp[f] = IMB_loadiffname(string, 0, NULL);
//if (och->ibufs_disp[f] == NULL) printf("error loading %s\n", string);
//else printf("loaded cache %s\n", string);
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_FOAM);
- och->ibufs_foam[f] = IMB_loadiffname(string, 0);
+ och->ibufs_foam[f] = IMB_loadiffname(string, 0, NULL);
//if (och->ibufs_foam[f] == NULL) printf("error loading %s\n", string);
//else printf("loaded cache %s\n", string);
cache_filename(string, och->bakepath, och->relbase, frame, CACHE_TYPE_NORMAL);
- och->ibufs_norm[f] = IMB_loadiffname(string, 0);
+ och->ibufs_norm[f] = IMB_loadiffname(string, 0, NULL);
//if (och->ibufs_norm[f] == NULL) printf("error loading %s\n", string);
//else printf("loaded cache %s\n", string);
}
@@ -1172,8 +1173,6 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
ibuf_disp = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
ibuf_normal = IMB_allocImBuf(res_x, res_y, 32, IB_rectfloat);
- ibuf_disp->profile = ibuf_foam->profile = ibuf_normal->profile = IB_PROFILE_LINEAR_RGB;
-
BKE_simulate_ocean(o, och->time[i], och->wave_scale, och->chop_amount);
/* add new foam */
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 145bd6a88e5..2dec72560a2 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -57,6 +57,7 @@
#include "BKE_anim.h"
#include "BKE_animsys.h"
+#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
@@ -76,6 +77,8 @@
#include "RE_engine.h"
+#include "IMB_colormanagement.h"
+
//XXX #include "BIF_previewrender.h"
//XXX #include "BIF_editseq.h"
@@ -132,6 +135,8 @@ Scene *BKE_scene_copy(Scene *sce, int type)
MEM_freeN(scen->toolsettings);
}
else {
+ ImageFormatData *im_format, *im_formatn;
+
scen = BKE_libblock_copy(&sce->id);
BLI_duplicatelist(&(scen->base), &(sce->base));
@@ -167,6 +172,13 @@ Scene *BKE_scene_copy(Scene *sce, int type)
obase = obase->next;
base = base->next;
}
+
+ /* copy color management settings */
+ im_format = &sce->r.im_format;
+ im_formatn = &scen->r.im_format;
+
+ BKE_color_managed_display_settings_copy(&scen->display_settings, &sce->display_settings);
+ BKE_color_managed_view_settings_copy(&scen->view_settings, &sce->view_settings);
}
/* tool settings */
@@ -332,6 +344,8 @@ void BKE_scene_free(Scene *sce)
MEM_freeN(sce->fps_info);
sound_destroy_scene(sce);
+
+ BKE_color_managed_view_settings_free(&sce->view_settings);
}
Scene *BKE_scene_add(const char *name)
@@ -372,7 +386,14 @@ Scene *BKE_scene_add(const char *name)
sce->r.frs_sec_base = 1;
sce->r.edgeint = 10;
sce->r.ocres = 128;
+
+ /* OCIO_TODO: for forwards compatibiliy only, so if no tonecurve are used,
+ * images would look in the same way as in current blender
+ *
+ * perhaps at some point should be completely deprecated?
+ */
sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT;
+
sce->r.gauss = 1.0;
/* deprecated but keep for upwards compat */
@@ -546,6 +567,9 @@ Scene *BKE_scene_add(const char *name)
sound_create_scene(sce);
+ BKE_color_managed_display_settings_init(&sce->display_settings);
+ BKE_color_managed_view_settings_init(&sce->view_settings);
+
return sce;
}
@@ -1240,3 +1264,19 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene)
base = base->next;
}
}
+
+void BKE_scene_disable_color_management(Scene *scene)
+{
+ ColorManagedDisplaySettings *display_settings = &scene->display_settings;
+ ColorManagedViewSettings *view_settings = &scene->view_settings;
+ const char *view;
+
+ /* NOTE: None display with Default view should always exist in OCIO configuration, otherwise it wouldn't work as expected */
+ BLI_strncpy(display_settings->display_device, "None", sizeof(display_settings->display_device));
+
+ view = IMB_colormanagement_view_get_default_name(display_settings->display_device);
+
+ if (view) {
+ BLI_strncpy(view_settings->view_transform, view, sizeof(view_settings->view_transform));
+ }
+}
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 4dbe0b6290c..eaf3ec384c8 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "RNA_access.h"
@@ -119,13 +120,13 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf *
}
if (ibuf1 && !ibuf1->rect_float && out->rect_float) {
- IMB_float_from_rect_simple(ibuf1);
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf1, TRUE);
}
if (ibuf2 && !ibuf2->rect_float && out->rect_float) {
- IMB_float_from_rect_simple(ibuf2);
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf2, TRUE);
}
if (ibuf3 && !ibuf3->rect_float && out->rect_float) {
- IMB_float_from_rect_simple(ibuf3);
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf3, TRUE);
}
if (ibuf1 && !ibuf1->rect && !out->rect_float) {
@@ -137,7 +138,7 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf *
if (ibuf3 && !ibuf3->rect && !out->rect_float) {
IMB_rect_from_float(ibuf3);
}
-
+
return out;
}
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index 65fcd0d85d6..b0dcad64722 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -581,6 +581,11 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I
SequenceModifierData *smd;
ImBuf *processed_ibuf = ibuf;
+ if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
+ processed_ibuf = IMB_dupImBuf(ibuf);
+ BKE_sequencer_imbuf_from_sequencer_space(context.scene, processed_ibuf);
+ }
+
for (smd = seq->modifiers.first; smd; smd = smd->next) {
SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
@@ -605,6 +610,10 @@ ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, I
}
}
+ if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, processed_ibuf, FALSE);
+ }
+
return processed_ibuf;
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 2596bf57f05..8d7ca94ed48 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -71,6 +71,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "BKE_context.h"
#include "BKE_sound.h"
@@ -308,6 +309,81 @@ void BKE_sequencer_editing_free(Scene *scene)
scene->ed = NULL;
}
+/*********************** Sequencer color space functions *************************/
+
+static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
+{
+ IMB_colormanagement_imbuf_assign_float_space(ibuf, &scene->sequencer_colorspace_settings);
+}
+
+void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float)
+{
+ const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ const char *to_colorspace = scene->sequencer_colorspace_settings.name;
+ int predivide = ibuf->flags & IB_cm_predivide;
+
+ if (!ibuf->rect_float) {
+ if (make_float && ibuf->rect) {
+ /* when converting byte buffer to float in sequencer we need to make float
+ * buffer be in sequencer's working space, which is currently only doable
+ * from linear space.
+ *
+ */
+
+ /*
+ * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
+ */
+
+ IMB_float_from_rect(ibuf);
+ }
+ else {
+ /* if there's only byte buffer in image it's already in compositor's working space,
+ * nothing to do here
+ */
+
+ return;
+ }
+ }
+
+ if (from_colorspace && from_colorspace[0] != '\0') {
+ if (ibuf->rect)
+ imb_freerectImBuf(ibuf);
+
+ IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace, predivide);
+ }
+}
+
+void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
+{
+ const char *from_colorspace = scene->sequencer_colorspace_settings.name;
+ const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
+ if (!ibuf->rect_float)
+ return;
+
+ if (to_colorspace && to_colorspace[0] != '\0') {
+ int predivide = ibuf->flags & IB_cm_predivide;
+
+ IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace, predivide);
+ }
+}
+
+void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4])
+{
+ const char *from_colorspace = scene->sequencer_colorspace_settings.name;
+ const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+
+ if (to_colorspace && to_colorspace[0] != '\0') {
+ IMB_colormanagement_transform_v4(pixel, from_colorspace, to_colorspace);
+ }
+ else {
+ /* if no color management enables fallback to legacy conversion */
+ srgb_to_linearrgb_v4(pixel, pixel);
+ }
+}
+
/*********************** sequencer pipeline functions *************************/
SeqRenderData BKE_sequencer_new_render_data(Main *bmain, Scene *scene, int rectx, int recty, int preview_render_size)
@@ -597,7 +673,9 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, int lock_range)
BLI_path_abs(str, G.main->name);
if (seq->anim) IMB_free_anim(seq->anim);
- seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex);
+
+ /* OCIO_TODO: support configurable input space for strips */
+ seq->anim = openanim(str, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL);
if (!seq->anim) {
return;
@@ -1094,7 +1172,8 @@ static void seq_open_anim_file(Sequence *seq)
seq->strip->dir, seq->strip->stripdata->name);
BLI_path_abs(name, G.main->name);
- seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex);
+ /* OCIO_TODO: support configurable input space for strips */
+ seq->anim = openanim(name, IB_rect | ((seq->flag & SEQ_FILTERY) ? IB_animdeinterlace : 0), seq->streamindex, NULL);
if (seq->anim == NULL) {
return;
@@ -1200,8 +1279,9 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra)
if (seq_proxy_get_fname(seq, cfra, render_size, name) == 0) {
return NULL;
}
-
- seq->strip->proxy->anim = openanim(name, IB_rect, 0);
+
+ /* proxies are generated in default color space */
+ seq->strip->proxy->anim = openanim(name, IB_rect, 0, NULL);
}
if (seq->strip->proxy->anim == NULL) {
return NULL;
@@ -1219,7 +1299,13 @@ static ImBuf *seq_proxy_fetch(SeqRenderData context, Sequence *seq, int cfra)
}
if (BLI_exists(name)) {
- return IMB_loadiffname(name, IB_rect);
+ /* OCIO_TODO: support configurable spaces for strips */
+ ImBuf *ibuf = IMB_loadiffname(name, IB_rect, NULL);
+
+ if (ibuf)
+ sequencer_imbuf_assign_spaces(context.scene, ibuf);
+
+ return ibuf;
}
else {
return NULL;
@@ -1257,7 +1343,8 @@ static void seq_proxy_build_frame(SeqRenderData context, Sequence *seq, int cfra
ibuf->planes = 24;
BLI_make_existing_file(name);
-
+
+ /* OCIO_TODO: support per-strip color space settings */
ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
if (ok == 0) {
perror(name);
@@ -1706,7 +1793,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
{
float mul;
- if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL)) {
+ if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) {
return TRUE;
}
@@ -1826,8 +1913,9 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
}
if (seq->flag & SEQ_MAKE_FLOAT) {
- if (!ibuf->rect_float)
- IMB_float_from_rect_simple(ibuf);
+ if (!ibuf->rect_float) {
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, TRUE);
+ }
if (ibuf->rect) {
imb_freerectImBuf(ibuf);
@@ -1893,6 +1981,8 @@ static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, I
* changing the cached image... */
ibuf = IMB_dupImBuf(ibuf);
+ sequencer_imbuf_assign_spaces(context.scene, ibuf);
+
if (nr == 0) {
BKE_sequencer_cache_put(context, seq, seq->start, SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
}
@@ -2307,7 +2397,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
/* opengl offscreen render */
BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty,
- IB_rect, context.scene->r.seq_prev_type, TRUE, err_out);
+ IB_rect, context.scene->r.seq_prev_type, TRUE, FALSE, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -2338,11 +2428,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
}
/* float buffers in the sequencer are not linear */
- if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
- else
- ibuf->profile = IB_PROFILE_NONE;
- IMB_convert_profile(ibuf, IB_PROFILE_SRGB);
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE);
}
else if (rres.rect32) {
ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect);
@@ -2442,14 +2528,14 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
BLI_path_abs(name, G.main->name);
}
- if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
+ /* OCIO_TODO: support configurable space for image strips */
+ if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, NULL))) {
/* we don't need both (speed reasons)! */
if (ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
- IMB_convert_profile(ibuf, IB_PROFILE_NONE);
+ BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE);
copy_to_ibuf_still(context, seq, nr, ibuf);
@@ -2497,6 +2583,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
case SEQ_TYPE_MOVIECLIP:
{
ibuf = seq_render_movieclip_strip(context, seq, nr);
+ sequencer_imbuf_assign_spaces(context.scene, ibuf);
if (ibuf && use_preprocess) {
ImBuf *i = IMB_dupImBuf(ibuf);
@@ -2520,6 +2607,9 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
}
}
+ if (ibuf)
+ sequencer_imbuf_assign_spaces(context.scene, ibuf);
+
return ibuf;
}
@@ -2561,8 +2651,10 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
}
}
- if (ibuf == NULL)
+ if (ibuf == NULL) {
ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect);
+ sequencer_imbuf_assign_spaces(context.scene, ibuf);
+ }
if (ibuf->x != context.rectx || ibuf->y != context.recty)
use_preprocess = TRUE;
@@ -2641,12 +2733,12 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep,
if (count == 1) {
out = seq_render_strip(context, seq_arr[0], cfra);
+
BKE_sequencer_cache_put(context, seq_arr[0], cfra, SEQ_STRIPELEM_IBUF_COMP, out);
return out;
}
-
for (i = count - 1; i >= 0; i--) {
int early_out;
Sequence *seq = seq_arr[i];
@@ -3946,7 +4038,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
BLI_strncpy(path, seq_load->path, sizeof(path));
BLI_path_abs(path, G.main->name);
- an = openanim(path, IB_rect, 0);
+ /* OCIO_TODO: support configurable input space for strips */
+ an = openanim(path, IB_rect, 0, NULL);
if (an == NULL)
return NULL;
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index ff48f5db9aa..97ebc3a90ba 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -1627,7 +1627,6 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea
float *mask = NULL;
pattern_ibuf = IMB_allocImBuf(num_samples_x, num_samples_y, 32, IB_rectfloat);
- pattern_ibuf->profile = IB_PROFILE_LINEAR_RGB;
if (!search_ibuf->rect_float) {
IMB_float_from_rect(search_ibuf);
@@ -1722,7 +1721,6 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov
h = (marker->search_max[1] - marker->search_min[1]) * ibuf->y;
searchibuf = IMB_allocImBuf(w, h, 32, ibuf->rect_float ? IB_rectfloat : IB_rect);
- searchibuf->profile = ibuf->profile;
IMB_rectcpy(searchibuf, ibuf, 0, 0, x, y, w, h);
@@ -3317,7 +3315,6 @@ static ImBuf *stabilization_allocate_ibuf(ImBuf *cacheibuf, ImBuf *srcibuf, int
}
else {
cacheibuf = IMB_allocImBuf(srcibuf->x, srcibuf->y, srcibuf->planes, flags);
- cacheibuf->profile = srcibuf->profile;
}
return cacheibuf;
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index 902373bcd6b..9cd801f819d 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -77,6 +77,7 @@ int BLI_system_thread_count(void); /* gets the number of threads the system
#define LOCK_OPENGL 5
#define LOCK_NODES 6
#define LOCK_MOVIECLIP 7
+#define LOCK_COLORMANAGE 8
void BLI_lock_thread(int type);
void BLI_unlock_thread(int type);
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 9994f89acd5..66527b9b92a 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -113,6 +113,7 @@ static pthread_mutex_t _rcache_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
static int thread_levels = 0; /* threads can be invoked inside threads */
@@ -351,6 +352,8 @@ void BLI_lock_thread(int type)
pthread_mutex_lock(&_nodes_lock);
else if (type == LOCK_MOVIECLIP)
pthread_mutex_lock(&_movieclip_lock);
+ else if (type == LOCK_COLORMANAGE)
+ pthread_mutex_lock(&_colormanage_lock);
}
void BLI_unlock_thread(int type)
@@ -371,6 +374,8 @@ void BLI_unlock_thread(int type)
pthread_mutex_unlock(&_nodes_lock);
else if (type == LOCK_MOVIECLIP)
pthread_mutex_unlock(&_movieclip_lock);
+ else if (type == LOCK_COLORMANAGE)
+ pthread_mutex_unlock(&_colormanage_lock);
}
/* Mutex Locks */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index a7f8026ad5d..c6483442b00 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4900,6 +4900,14 @@ static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb)
}
}
+static void direct_link_view_settings(FileData *fd, ColorManagedViewSettings *view_settings)
+{
+ view_settings->curve_mapping = newdataadr(fd, view_settings->curve_mapping);
+
+ if (view_settings->curve_mapping)
+ direct_link_curvemapping(fd, view_settings->curve_mapping);
+}
+
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
@@ -5077,6 +5085,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->nodetree = newdataadr(fd, sce->nodetree);
if (sce->nodetree)
direct_link_nodetree(fd, sce->nodetree);
+
+ direct_link_view_settings(fd, &sce->view_settings);
}
/* ************ READ WM ***************** */
@@ -5290,6 +5300,13 @@ static void lib_link_screen(FileData *fd, Main *main)
* so fingers crossed this works fine!
*/
sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
+
+ sseq->scopes.reference_ibuf = NULL;
+ sseq->scopes.zebra_ibuf = NULL;
+ sseq->scopes.waveform_ibuf = NULL;
+ sseq->scopes.sep_waveform_ibuf = NULL;
+ sseq->scopes.vector_ibuf = NULL;
+ sseq->scopes.histogram_ibuf = NULL;
}
else if (sl->spacetype == SPACE_NLA) {
SpaceNla *snla= (SpaceNla *)sl;
@@ -7902,6 +7919,47 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
+ /* color management pipeline changes compatibility code */
+ if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 19)) {
+ Scene *scene;
+ Image *ima;
+ int colormanagement_disabled = FALSE;
+
+ /* make scenes which are not using color management have got None as display device,
+ * so they wouldn't perform linear-to-sRGB conversion on display
+ */
+ for (scene = main->scene.first; scene; scene = scene->id.next) {
+ if ((scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) == 0) {
+ ColorManagedDisplaySettings *display_settings = &scene->display_settings;
+
+ if (display_settings->display_device[0] == 0) {
+ BKE_scene_disable_color_management(scene);
+
+ }
+
+ colormanagement_disabled = TRUE;
+ }
+ }
+
+ for (ima = main->image.first; ima; ima = ima->id.next) {
+ if (ima->source == IMA_SRC_VIEWER) {
+ ima->flag |= IMA_VIEW_AS_RENDER;
+ }
+ else if (colormanagement_disabled) {
+ /* if colormanagement not used, set image's color space to raw, so no sRGB->linear conversion
+ * would happen on display and render
+ * there's no clear way to check whether color management is enabled or not in render engine
+ * so set all images to raw if there's at least one scene with color management disabled
+ * this would still behave incorrect in cases when color management was used for only some
+ * of scenes, but such a setup is crazy anyway and think it's fair enough to break compatibility
+ * in that cases
+ */
+
+ BLI_strncpy(ima->colorspace_settings.name, "Raw", sizeof(ima->colorspace_settings.name));
+ }
+ }
+ }
+
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 109a844352f..b8d63b3c5d5 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2119,6 +2119,13 @@ static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
}
}
+static void write_view_settings(WriteData *wd, ColorManagedViewSettings *view_settings)
+{
+ if (view_settings->curve_mapping) {
+ write_curvemapping(wd, view_settings->curve_mapping);
+ }
+}
+
static void write_scenes(WriteData *wd, ListBase *scebase)
{
Scene *sce;
@@ -2261,7 +2268,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
write_nodetree(wd, sce->nodetree);
}
-
+
+ write_view_settings(wd, &sce->view_settings);
+
sce= sce->id.next;
}
/* flush helps the compression for undo-save */
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index a15dadda8cf..f1f1efdbd33 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -103,7 +103,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// So we have to export it. The export will keep the image state intact,
// so the exported file will not be associated with the image.
- if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, true) == 0) {
+ if (BKE_imbuf_write_as(imbuf, export_path, &imageFormat, image->colorspace_settings.name, true) == 0) {
fprintf(stderr, "Collada export: Cannot export image to:\n%s\n", export_path);
return;
}
diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h
index f35bf71392c..a64583b68ff 100644
--- a/source/blender/compositor/COM_compositor.h
+++ b/source/blender/compositor/COM_compositor.h
@@ -24,6 +24,7 @@
extern "C" {
#endif
+#include "DNA_color_types.h"
#include "DNA_node_types.h"
/**
@@ -299,8 +300,20 @@ extern "C" {
*
* - output nodes can have different priorities in the WorkScheduler.
* This is implemented in the COM_execute function.
+ *
+ * @param viewSettings
+ * reference to view settings used for color management
+ *
+ * @param displaySettings
+ * reference to display settings used for color management
+ *
+ * OCIO_TODO: this options only used in rare cases, namely in output file node,
+ * so probably this settings could be passed in a nicer way.
+ * should be checked further, probably it'll be also needed for preview
+ * generation in display space
*/
-void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering);
+void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
/**
* @brief Deinitialize the compositor caches and allocated memory.
diff --git a/source/blender/compositor/intern/COM_CompositorContext.cpp b/source/blender/compositor/intern/COM_CompositorContext.cpp
index fbdb4cd6b28..e1cc25d028a 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.cpp
+++ b/source/blender/compositor/intern/COM_CompositorContext.cpp
@@ -31,6 +31,8 @@ CompositorContext::CompositorContext()
this->m_hasActiveOpenCLDevices = false;
this->m_activegNode = NULL;
this->m_fastCalculation = false;
+ this->m_viewSettings = NULL;
+ this->m_displaySettings = NULL;
}
const int CompositorContext::getFramenumber() const
@@ -42,13 +44,3 @@ const int CompositorContext::getFramenumber() const
return -1; /* this should never happen */
}
}
-
-const int CompositorContext::isColorManaged() const
-{
- if (this->m_rd) {
- return this->m_rd->color_mgt_flag & R_COLOR_MANAGEMENT;
- }
- else {
- return 0; /* this should never happen */
- }
-}
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index 2f6abf39985..2f5e8c0648d 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -27,6 +27,7 @@
#include "BKE_text.h"
#include <string>
#include "DNA_node_types.h"
+#include "DNA_color_types.h"
#include "BLI_rect.h"
#include "DNA_scene_types.h"
#include "COM_defines.h"
@@ -79,6 +80,9 @@ private:
*/
bool m_fastCalculation;
+ /* @brief color management settings */
+ const ColorManagedViewSettings *m_viewSettings;
+ const ColorManagedDisplaySettings *m_displaySettings;
public:
/**
* @brief constructor initializes the context with default values.
@@ -126,6 +130,26 @@ public:
const RenderData *getRenderData() const { return this->m_rd; }
/**
+ * @brief set view settings of color color management
+ */
+ void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; }
+
+ /**
+ * @brief get view settings of color color management
+ */
+ const ColorManagedViewSettings *getViewSettings() const { return this->m_viewSettings; }
+
+ /**
+ * @brief set display settings of color color management
+ */
+ void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; }
+
+ /**
+ * @brief get display settings of color color management
+ */
+ const ColorManagedDisplaySettings *getDisplaySettings() const { return this->m_displaySettings; }
+
+ /**
* @brief set the quality
*/
void setQuality(CompositorQuality quality) { this->m_quality = quality; }
@@ -152,8 +176,6 @@ public:
int getChunksize() { return this->getbNodeTree()->chunksize; }
- const int isColorManaged() const;
-
void setFastCalculation(bool fastCalculation) {this->m_fastCalculation = fastCalculation;}
bool isFastCalculation() {return this->m_fastCalculation;}
};
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
index 801505e9d39..a13717c9d86 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp
@@ -44,7 +44,8 @@
#include "MEM_guardedalloc.h"
#endif
-ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation)
+ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
{
this->m_context.setbNodeTree(editingtree);
this->m_context.setFastCalculation(fastcalculation);
@@ -69,6 +70,9 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re
ExecutionSystemHelper::addbNodeTree(*this, 0, editingtree, NULL);
this->m_context.setRenderData(rd);
+ this->m_context.setViewSettings(viewSettings);
+ this->m_context.setDisplaySettings(displaySettings);
+
this->convertToOperations();
this->groupOperations(); /* group operations in ExecutionGroups */
unsigned int index;
diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.h b/source/blender/compositor/intern/COM_ExecutionSystem.h
index 39e7bc80279..56a60bf7a03 100644
--- a/source/blender/compositor/intern/COM_ExecutionSystem.h
+++ b/source/blender/compositor/intern/COM_ExecutionSystem.h
@@ -25,6 +25,7 @@ class ExecutionGroup;
#ifndef _COM_ExecutionSystem_h
#define _COM_ExecutionSystem_h
+#include "DNA_color_types.h"
#include "DNA_node_types.h"
#include <vector>
#include "COM_Node.h"
@@ -156,7 +157,8 @@ public:
* @param editingtree [bNodeTree *]
* @param rendering [true false]
*/
- ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation);
+ ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool rendering, bool fastcalculation,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
/**
* Destructor
diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp
index 50393d14f35..5922b0e6b08 100644
--- a/source/blender/compositor/intern/COM_Node.cpp
+++ b/source/blender/compositor/intern/COM_Node.cpp
@@ -75,12 +75,12 @@ void Node::addSetValueOperation(ExecutionSystem *graph, InputSocket *inputsocket
graph->addOperation(operation);
}
-void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket)
+void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket)
{
if (this->isInActiveGroup()) {
if (!(this->getbNode()->flag & NODE_HIDDEN)) { // do not calculate previews of hidden nodes.
if (this->getbNode()->flag & NODE_PREVIEW) {
- PreviewOperation *operation = new PreviewOperation();
+ PreviewOperation *operation = new PreviewOperation(context->getViewSettings(), context->getDisplaySettings());
system->addOperation(operation);
operation->setbNode(this->getbNode());
operation->setbNodeTree(system->getContext().getbNodeTree());
@@ -90,11 +90,11 @@ void Node::addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSock
}
}
-void Node::addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket)
+void Node::addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket)
{
if (inputSocket->isConnected() && this->isInActiveGroup()) {
OutputSocket *outputsocket = inputSocket->getConnection()->getFromSocket();
- this->addPreviewOperation(system, outputsocket);
+ this->addPreviewOperation(system, context, outputsocket);
}
}
diff --git a/source/blender/compositor/intern/COM_Node.h b/source/blender/compositor/intern/COM_Node.h
index 7ce40e3cb34..bfccd069ad1 100644
--- a/source/blender/compositor/intern/COM_Node.h
+++ b/source/blender/compositor/intern/COM_Node.h
@@ -135,8 +135,8 @@ public:
*/
OutputSocket *findOutputSocketBybNodeSocket(bNodeSocket *socket);
protected:
- void addPreviewOperation(ExecutionSystem *system, InputSocket *inputSocket);
- void addPreviewOperation(ExecutionSystem *system, OutputSocket *outputSocket);
+ void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, InputSocket *inputSocket);
+ void addPreviewOperation(ExecutionSystem *system, CompositorContext *context, OutputSocket *outputSocket);
bNodeSocket *getEditorInputSocket(int editorNodeInputSocketIndex);
bNodeSocket *getEditorOutputSocket(int editorNodeOutputSocketIndex);
diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp
index cb9166c929d..5cfcd83f8f1 100644
--- a/source/blender/compositor/intern/COM_compositor.cpp
+++ b/source/blender/compositor/intern/COM_compositor.cpp
@@ -42,7 +42,9 @@ void intern_freeCompositorCaches()
deintializeDistortionCache();
}
-void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering)
+void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering,
+ const ColorManagedViewSettings *viewSettings,
+ const ColorManagedDisplaySettings *displaySettings)
{
/* initialize mutex, TODO this mutex init is actually not thread safe and
* should be done somewhere as part of blender startup, all the other
@@ -71,7 +73,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering)
bool twopass = (editingtree->flag & NTREE_TWO_PASS) > 0 && !rendering;
/* initialize execution system */
if (twopass) {
- ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, twopass);
+ ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, twopass, viewSettings, displaySettings);
system->execute();
delete system;
@@ -84,7 +86,7 @@ void COM_execute(RenderData *rd, bNodeTree *editingtree, int rendering)
}
- ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false);
+ ExecutionSystem *system = new ExecutionSystem(rd, editingtree, rendering, false, viewSettings, displaySettings);
system->execute();
delete system;
diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp
index e39ef2b3f23..4f120ea5a6e 100644
--- a/source/blender/compositor/nodes/COM_BlurNode.cpp
+++ b/source/blender/compositor/nodes/COM_BlurNode.cpp
@@ -57,7 +57,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph);
this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0));
graph->addOperation(operationfgb);
- addPreviewOperation(graph, operationfgb->getOutputSocket());
+ addPreviewOperation(graph, context, operationfgb->getOutputSocket());
}
else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) {
MathAddOperation *clamp = new MathAddOperation();
@@ -97,7 +97,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1));
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
}
else if (!data->bokeh) {
GaussianXBlurOperation *operationx = new GaussianXBlurOperation();
@@ -115,7 +115,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
graph->addOperation(operationy);
addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0));
addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1));
- addPreviewOperation(graph, operationy->getOutputSocket());
+ addPreviewOperation(graph, context, operationy->getOutputSocket());
if (!connectedSizeSocket) {
operationx->setSize(size);
@@ -131,7 +131,7 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co
operation->setQuality(quality);
graph->addOperation(operation);
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
if (!connectedSizeSocket) {
operation->setSize(size);
diff --git a/source/blender/compositor/nodes/COM_BokehImageNode.cpp b/source/blender/compositor/nodes/COM_BokehImageNode.cpp
index f6abbbb9a9a..a89ed9e0c64 100644
--- a/source/blender/compositor/nodes/COM_BokehImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_BokehImageNode.cpp
@@ -35,5 +35,5 @@ void BokehImageNode::convertToOperations(ExecutionSystem *graph, CompositorConte
this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0));
graph->addOperation(operation);
operation->setData((NodeBokehImage *)this->getbNode()->storage);
- addPreviewOperation(graph, operation->getOutputSocket(0));
+ addPreviewOperation(graph, context, operation->getOutputSocket(0));
}
diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
index eab921863e9..c1511ee611b 100644
--- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
@@ -84,7 +84,7 @@ void ChannelMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCon
graph->addOperation(operationAlpha);
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
- addPreviewOperation(graph, operationAlpha->getOutputSocket());
+ addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
index 0fb09157351..4c4b77ba6cc 100644
--- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
@@ -65,7 +65,7 @@ void ChromaMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCont
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
graph->addOperation(operationAlpha);
- addPreviewOperation(graph, operationAlpha->getOutputSocket());
+ addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
index 38ab6ba8da2..54e6762961b 100644
--- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp
@@ -62,7 +62,7 @@ void ColorMatteNode::convertToOperations(ExecutionSystem *graph, CompositorConte
addLink(graph, operationRGBToHSV_Image->getInputSocket(0)->getConnection()->getFromSocket(), operationAlpha->getInputSocket(0));
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
graph->addOperation(operationAlpha);
- addPreviewOperation(graph, operationAlpha->getOutputSocket());
+ addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp
index d0d66a81c77..e3313750e66 100644
--- a/source/blender/compositor/nodes/COM_CompositorNode.cpp
+++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp
@@ -45,5 +45,5 @@ void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorConte
alphaSocket->relinkConnections(compositorOperation->getInputSocket(1));
depthSocket->relinkConnections(compositorOperation->getInputSocket(2));
graph->addOperation(compositorOperation);
- addPreviewOperation(graph, compositorOperation->getInputSocket(0));
+ addPreviewOperation(graph, context, compositorOperation->getInputSocket(0));
}
diff --git a/source/blender/compositor/nodes/COM_DespeckleNode.cpp b/source/blender/compositor/nodes/COM_DespeckleNode.cpp
index 603ddcd1389..a97714c870e 100644
--- a/source/blender/compositor/nodes/COM_DespeckleNode.cpp
+++ b/source/blender/compositor/nodes/COM_DespeckleNode.cpp
@@ -44,7 +44,7 @@ void DespeckleNode::convertToOperations(ExecutionSystem *graph, CompositorContex
inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph);
inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph);
outputSocket->relinkConnections(operation->getOutputSocket());
- addPreviewOperation(graph, operation->getOutputSocket(0));
+ addPreviewOperation(graph, context, operation->getOutputSocket(0));
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
index 6dca049a6ae..b5ad07be319 100644
--- a/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
@@ -51,5 +51,5 @@ void DifferenceMatteNode::convertToOperations(ExecutionSystem *graph, Compositor
addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1));
outputSocketImage->relinkConnections(operation->getOutputSocket());
graph->addOperation(operation);
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
}
diff --git a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp
index cecc3bf6e86..5bd2f78d8a6 100644
--- a/source/blender/compositor/nodes/COM_DilateErodeNode.cpp
+++ b/source/blender/compositor/nodes/COM_DilateErodeNode.cpp
@@ -106,7 +106,7 @@ void DilateErodeNode::convertToOperations(ExecutionSystem *graph, CompositorCont
graph->addOperation(operationy);
addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0));
// addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); // no size input yet
- addPreviewOperation(graph, operationy->getOutputSocket());
+ addPreviewOperation(graph, context, operationy->getOutputSocket());
/* TODO? */
/* see gaussian blue node for original usage */
diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
index 87e7b9d0788..782c897f6fb 100644
--- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
@@ -77,7 +77,7 @@ void DistanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorCo
addLink(graph, operation->getOutputSocket(), operationAlpha->getInputSocket(1));
graph->addOperation(operationAlpha);
- addPreviewOperation(graph, operationAlpha->getOutputSocket());
+ addPreviewOperation(graph, context, operationAlpha->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operationAlpha->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp
index 021ec6c2508..990cdb480ca 100644
--- a/source/blender/compositor/nodes/COM_FilterNode.cpp
+++ b/source/blender/compositor/nodes/COM_FilterNode.cpp
@@ -77,7 +77,7 @@ void FilterNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
inputImageSocket->relinkConnections(operation->getInputSocket(0), 1, graph);
inputSocket->relinkConnections(operation->getInputSocket(1), 0, graph);
outputSocket->relinkConnections(operation->getOutputSocket());
- addPreviewOperation(graph, operation->getOutputSocket(0));
+ addPreviewOperation(graph, context, operation->getOutputSocket(0));
graph->addOperation(operation);
}
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index 2d13ffb82b6..4ebd28d710a 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -111,7 +111,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
break;
}
if (index == 0 && operation) {
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
}
}
}
@@ -134,7 +134,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
operation->setImageUser(imageuser);
operation->setFramenumber(framenumber);
graph->addOperation(operation);
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
}
if (numberOfOutputs > 1) {
diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
index be949e2cacb..4656e00b006 100644
--- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
+++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
@@ -55,7 +55,7 @@ void LuminanceMatteNode::convertToOperations(ExecutionSystem *graph, CompositorC
addLink(graph, rgbToYUV->getInputSocket(0)->getConnection()->getFromSocket(), operation->getInputSocket(0));
addLink(graph, operationSet->getOutputSocket(), operation->getInputSocket(1));
graph->addOperation(operation);
- addPreviewOperation(graph, operation->getOutputSocket());
+ addPreviewOperation(graph, context, operation->getOutputSocket());
if (outputSocketImage->isConnected()) {
outputSocketImage->relinkConnections(operation->getOutputSocket());
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index 7aeaaf56c98..ab4e464327d 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -128,7 +128,7 @@ void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext *con
color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph);
color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph);
outputSocket->relinkConnections(convertProg->getOutputSocket(0));
- addPreviewOperation(graph, convertProg->getOutputSocket(0));
+ addPreviewOperation(graph, context, convertProg->getOutputSocket(0));
convertProg->getInputSocket(2)->setResizeMode(color2Socket->getResizeMode());
diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp
index 6d5b9bba8aa..5d5e68fba37 100644
--- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp
+++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp
@@ -62,25 +62,9 @@ void MovieClipNode::convertToOperations(ExecutionSystem *graph, CompositorContex
// always connect the output image
MovieClipOperation *operation = new MovieClipOperation();
- if (ibuf && context->isColorManaged() && ibuf->profile == IB_PROFILE_NONE) {
- ConvertColorProfileOperation *converter = new ConvertColorProfileOperation();
- converter->setFromColorProfile(IB_PROFILE_LINEAR_RGB);
- converter->setToColorProfile(IB_PROFILE_SRGB);
- addLink(graph, operation->getOutputSocket(), converter->getInputSocket(0));
- addPreviewOperation(graph, converter->getOutputSocket());
- if (outputMovieClip->isConnected()) {
- outputMovieClip->relinkConnections(converter->getOutputSocket());
- }
- graph->addOperation(converter);
- if (ibuf) {
- converter->setPredivided(ibuf->flags & IB_cm_predivide);
- }
- }
- else {
- addPreviewOperation(graph, operation->getOutputSocket());
- if (outputMovieClip->isConnected()) {
- outputMovieClip->relinkConnections(operation->getOutputSocket());
- }
+ addPreviewOperation(graph, context, operation->getOutputSocket());
+ if (outputMovieClip->isConnected()) {
+ outputMovieClip->relinkConnections(operation->getOutputSocket());
}
operation->setMovieClip(movieClip);
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
index b8cee29fee6..921b9e63a73 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
@@ -62,7 +62,7 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte
input->relinkConnections(outputOperation->getInputSocket(i));
}
}
- if (hasConnections) addPreviewOperation(graph, outputOperation->getInputSocket(0));
+ if (hasConnections) addPreviewOperation(graph, context, outputOperation->getInputSocket(0));
graph->addOperation(outputOperation);
}
@@ -80,11 +80,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte
BLI_join_dirfile(path, FILE_MAX, storage->base_path, sockdata->path);
OutputSingleLayerOperation *outputOperation = new OutputSingleLayerOperation(
- context->getRenderData(), context->getbNodeTree(), input->getDataType(), format, path);
+ context->getRenderData(), context->getbNodeTree(), input->getDataType(), format, path,
+ context->getViewSettings(), context->getDisplaySettings());
input->relinkConnections(outputOperation->getInputSocket(0));
graph->addOperation(outputOperation);
if (!previewAdded) {
- addPreviewOperation(graph, outputOperation->getInputSocket(0));
+ addPreviewOperation(graph, context, outputOperation->getInputSocket(0));
previewAdded = true;
}
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
index dfb46af841c..b57e99754d6 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp
@@ -52,7 +52,7 @@ RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
/* pass */
}
-void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputSocketNumber, RenderLayersBaseProg *operation)
+void RenderLayersNode::testSocketConnection(ExecutionSystem *system, CompositorContext *context, int outputSocketNumber, RenderLayersBaseProg *operation)
{
OutputSocket *outputSocket = this->getOutputSocket(outputSocketNumber);
Scene *scene = (Scene *)this->getbNode()->id;
@@ -64,7 +64,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS
outputSocket->relinkConnections(operation->getOutputSocket());
system->addOperation(operation);
if (outputSocketNumber == 0) { // only do for image socket if connected
- addPreviewOperation(system, operation->getOutputSocket());
+ addPreviewOperation(system, context, operation->getOutputSocket());
}
}
else {
@@ -72,7 +72,7 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS
system->addOperation(operation);
operation->setScene(scene);
operation->setLayerId(layerId);
- addPreviewOperation(system, operation->getOutputSocket());
+ addPreviewOperation(system, context, operation->getOutputSocket());
}
else {
delete operation;
@@ -82,34 +82,34 @@ void RenderLayersNode::testSocketConnection(ExecutionSystem *system, int outputS
void RenderLayersNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
- testSocketConnection(graph, 0, new RenderLayersColorProg());
- testSocketConnection(graph, 1, new RenderLayersAlphaProg());
- testSocketConnection(graph, 2, new RenderLayersDepthProg());
- testSocketConnection(graph, 3, new RenderLayersNormalOperation());
- testSocketConnection(graph, 4, new RenderLayersUVOperation());
- testSocketConnection(graph, 5, new RenderLayersSpeedOperation());
- testSocketConnection(graph, 6, new RenderLayersColorOperation());
- testSocketConnection(graph, 7, new RenderLayersDiffuseOperation());
- testSocketConnection(graph, 8, new RenderLayersSpecularOperation());
- testSocketConnection(graph, 9, new RenderLayersShadowOperation());
- testSocketConnection(graph, 10, new RenderLayersAOOperation());
- testSocketConnection(graph, 11, new RenderLayersReflectionOperation());
- testSocketConnection(graph, 12, new RenderLayersRefractionOperation());
- testSocketConnection(graph, 13, new RenderLayersIndirectOperation());
- testSocketConnection(graph, 14, new RenderLayersObjectIndexOperation());
- testSocketConnection(graph, 15, new RenderLayersMaterialIndexOperation());
- testSocketConnection(graph, 16, new RenderLayersMistOperation());
- testSocketConnection(graph, 17, new RenderLayersEmitOperation());
- testSocketConnection(graph, 18, new RenderLayersEnvironmentOperation());
+ testSocketConnection(graph, context, 0, new RenderLayersColorProg());
+ testSocketConnection(graph, context, 1, new RenderLayersAlphaProg());
+ testSocketConnection(graph, context, 2, new RenderLayersDepthProg());
+ testSocketConnection(graph, context, 3, new RenderLayersNormalOperation());
+ testSocketConnection(graph, context, 4, new RenderLayersUVOperation());
+ testSocketConnection(graph, context, 5, new RenderLayersSpeedOperation());
+ testSocketConnection(graph, context, 6, new RenderLayersColorOperation());
+ testSocketConnection(graph, context, 7, new RenderLayersDiffuseOperation());
+ testSocketConnection(graph, context, 8, new RenderLayersSpecularOperation());
+ testSocketConnection(graph, context, 9, new RenderLayersShadowOperation());
+ testSocketConnection(graph, context, 10, new RenderLayersAOOperation());
+ testSocketConnection(graph, context, 11, new RenderLayersReflectionOperation());
+ testSocketConnection(graph, context, 12, new RenderLayersRefractionOperation());
+ testSocketConnection(graph, context, 13, new RenderLayersIndirectOperation());
+ testSocketConnection(graph, context, 14, new RenderLayersObjectIndexOperation());
+ testSocketConnection(graph, context, 15, new RenderLayersMaterialIndexOperation());
+ testSocketConnection(graph, context, 16, new RenderLayersMistOperation());
+ testSocketConnection(graph, context, 17, new RenderLayersEmitOperation());
+ testSocketConnection(graph, context, 18, new RenderLayersEnvironmentOperation());
// cycles passes
- testSocketConnection(graph, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT));
- testSocketConnection(graph, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT));
- testSocketConnection(graph, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR));
- testSocketConnection(graph, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT));
- testSocketConnection(graph, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT));
- testSocketConnection(graph, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR));
- testSocketConnection(graph, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT));
- testSocketConnection(graph, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT));
- testSocketConnection(graph, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR));
+ testSocketConnection(graph, context, 19, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_DIRECT));
+ testSocketConnection(graph, context, 20, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_INDIRECT));
+ testSocketConnection(graph, context, 21, new RenderLayersCyclesOperation(SCE_PASS_DIFFUSE_COLOR));
+ testSocketConnection(graph, context, 22, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_DIRECT));
+ testSocketConnection(graph, context, 23, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_INDIRECT));
+ testSocketConnection(graph, context, 24, new RenderLayersCyclesOperation(SCE_PASS_GLOSSY_COLOR));
+ testSocketConnection(graph, context, 25, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_DIRECT));
+ testSocketConnection(graph, context, 26, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_INDIRECT));
+ testSocketConnection(graph, context, 27, new RenderLayersCyclesOperation(SCE_PASS_TRANSM_COLOR));
}
diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h
index 32672c8ba2d..9bd74624b0c 100644
--- a/source/blender/compositor/nodes/COM_RenderLayersNode.h
+++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h
@@ -33,5 +33,5 @@ public:
RenderLayersNode(bNode *editorNode);
void convertToOperations(ExecutionSystem *graph, CompositorContext *context);
private:
- void testSocketConnection(ExecutionSystem *graph, int outputSocketNumber, RenderLayersBaseProg *operation);
+ void testSocketConnection(ExecutionSystem *graph, CompositorContext *context, int outputSocketNumber, RenderLayersBaseProg *operation);
};
diff --git a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
index 388466cee3c..37b888becca 100644
--- a/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_SplitViewerNode.cpp
@@ -39,13 +39,14 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont
ImageUser *imageUser = (ImageUser *) this->getbNode()->storage;
if (image1Socket->isConnected() && image2Socket->isConnected()) {
SplitViewerOperation *splitViewerOperation = new SplitViewerOperation();
- splitViewerOperation->setColorManagement(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT);
- splitViewerOperation->setColorPredivide(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
splitViewerOperation->setImage(image);
splitViewerOperation->setImageUser(imageUser);
splitViewerOperation->setActive((this->getbNode()->flag & NODE_DO_OUTPUT) && this->isInActiveGroup());
splitViewerOperation->setSplitPercentage(this->getbNode()->custom1);
+ splitViewerOperation->setViewSettings(context->getViewSettings());
+ splitViewerOperation->setDisplaySettings(context->getDisplaySettings());
+
/* defaults - the viewer node has these options but not exposed for split view
* we could use the split to define an area of interest on one axis at least */
splitViewerOperation->setChunkOrder(COM_ORDER_OF_CHUNKS_DEFAULT);
@@ -55,7 +56,7 @@ void SplitViewerNode::convertToOperations(ExecutionSystem *graph, CompositorCont
splitViewerOperation->setXSplit(!this->getbNode()->custom2);
image1Socket->relinkConnections(splitViewerOperation->getInputSocket(0), 0, graph);
image2Socket->relinkConnections(splitViewerOperation->getInputSocket(1), 1, graph);
- addPreviewOperation(graph, splitViewerOperation->getInputSocket(0));
+ addPreviewOperation(graph, context, splitViewerOperation->getInputSocket(0));
graph->addOperation(splitViewerOperation);
}
}
diff --git a/source/blender/compositor/nodes/COM_TextureNode.cpp b/source/blender/compositor/nodes/COM_TextureNode.cpp
index b035e0a392c..5b386a504e4 100644
--- a/source/blender/compositor/nodes/COM_TextureNode.cpp
+++ b/source/blender/compositor/nodes/COM_TextureNode.cpp
@@ -40,7 +40,7 @@ void TextureNode::convertToOperations(ExecutionSystem *system, CompositorContext
operation->setTexture(texture);
operation->setRenderData(context->getRenderData());
system->addOperation(operation);
- addPreviewOperation(system, operation->getOutputSocket());
+ addPreviewOperation(system, context, operation->getOutputSocket());
if (this->getOutputSocket(0)->isConnected()) {
TextureAlphaOperation *alphaOperation = new TextureAlphaOperation();
diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp
index 88ce0ff2016..d67e9e274b0 100644
--- a/source/blender/compositor/nodes/COM_ViewerNode.cpp
+++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp
@@ -40,8 +40,6 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
ImageUser *imageUser = (ImageUser *) this->getbNode()->storage;
bNode *editorNode = this->getbNode();
ViewerOperation *viewerOperation = new ViewerOperation();
- viewerOperation->setColorManagement(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT);
- viewerOperation->setColorPredivide(context->getRenderData()->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
viewerOperation->setbNodeTree(context->getbNodeTree());
viewerOperation->setImage(image);
viewerOperation->setImageUser(imageUser);
@@ -50,6 +48,9 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
viewerOperation->setCenterX(editorNode->custom3);
viewerOperation->setCenterY(editorNode->custom4);
+ viewerOperation->setViewSettings(context->getViewSettings());
+ viewerOperation->setDisplaySettings(context->getDisplaySettings());
+
viewerOperation->setResolutionInputSocketIndex(0);
if (!imageSocket->isConnected())
{
@@ -62,5 +63,5 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext *
alphaSocket->relinkConnections(viewerOperation->getInputSocket(1));
depthSocket->relinkConnections(viewerOperation->getInputSocket(2));
graph->addOperation(viewerOperation);
- addPreviewOperation(graph, viewerOperation->getInputSocket(0));
+ addPreviewOperation(graph, context, viewerOperation->getInputSocket(0));
}
diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp
index 4ec5643c0bb..fb3efbb67ed 100644
--- a/source/blender/compositor/operations/COM_ImageOperation.cpp
+++ b/source/blender/compositor/operations/COM_ImageOperation.cpp
@@ -33,6 +33,7 @@ extern "C" {
#include "RE_render_ext.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+ #include "IMB_colormanagement.h"
}
BaseImageOperation::BaseImageOperation() : NodeOperation()
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index b72875ab2f9..21ecfdb5272 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -31,9 +31,12 @@
#include "BKE_global.h"
#include "BKE_main.h"
+#include "DNA_color_types.h"
+
extern "C" {
#include "MEM_guardedalloc.h"
#include "IMB_imbuf.h"
+ #include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
}
@@ -91,7 +94,8 @@ static void write_buffer_rect(rcti *rect, const bNodeTree *tree,
OutputSingleLayerOperation::OutputSingleLayerOperation(
- const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path)
+ const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings)
{
this->m_rd = rd;
this->m_tree = tree;
@@ -104,6 +108,9 @@ OutputSingleLayerOperation::OutputSingleLayerOperation(
this->m_format = format;
BLI_strncpy(this->m_path, path, sizeof(this->m_path));
+
+ this->m_viewSettings = viewSettings;
+ this->m_displaySettings = displaySettings;
}
void OutputSingleLayerOperation::initExecution()
@@ -131,8 +138,7 @@ void OutputSingleLayerOperation::deinitExecution()
ibuf->mall |= IB_rectfloat;
ibuf->dither = this->m_rd->dither_intensity;
- if (this->m_rd->color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
+ IMB_display_buffer_to_imbuf_rect(ibuf, m_viewSettings, m_displaySettings);
BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format->imtype,
(this->m_rd->scemode & R_EXTENSION), true);
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index 532242c97ce..69d1ad48ced 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -28,6 +28,8 @@
#include "BLI_rect.h"
#include "BLI_path_util.h"
+#include "DNA_color_types.h"
+
#include "intern/openexr/openexr_multi.h"
/* Writes the image to a single-layer file. */
@@ -43,8 +45,11 @@ private:
DataType m_datatype;
SocketReader *m_imageInput;
+ const ColorManagedViewSettings *m_viewSettings;
+ const ColorManagedDisplaySettings *m_displaySettings;
public:
- OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path);
+ OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path,
+ const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
void executeRegion(rcti *rect, unsigned int tileNumber);
bool isOutputOperation(bool rendering) const { return true; }
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp
index aff374cdded..6e58b277f66 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.cpp
+++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp
@@ -35,16 +35,19 @@ extern "C" {
#include "MEM_guardedalloc.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+ #include "IMB_colormanagement.h"
}
-PreviewOperation::PreviewOperation() : NodeOperation()
+PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) : NodeOperation()
{
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
this->m_outputBuffer = NULL;
this->m_input = NULL;
this->m_divider = 1.0f;
this->m_node = NULL;
+ this->m_viewSettings = viewSettings;
+ this->m_displaySettings = displaySettings;
}
void PreviewOperation::initExecution()
@@ -82,6 +85,10 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber)
{
int offset;
float color[4];
+ struct ColormanageProcessor *cm_processor;
+
+ cm_processor = IMB_colormanagement_display_processor_new(this->m_viewSettings, this->m_displaySettings);
+
for (int y = rect->ymin; y < rect->ymax; y++) {
offset = (y * getWidth() + rect->xmin) * 4;
for (int x = rect->xmin; x < rect->xmax; x++) {
@@ -93,11 +100,13 @@ void PreviewOperation::executeRegion(rcti *rect, unsigned int tileNumber)
color[2] = 0.0f;
color[3] = 1.0f;
this->m_input->read(color, rx, ry, COM_PS_NEAREST);
- linearrgb_to_srgb_v4(color, color);
+ IMB_colormanagement_processor_apply_v4(cm_processor, color);
F4TOCHAR4(color, this->m_outputBuffer + offset);
offset += 4;
}
}
+
+ IMB_colormanagement_processor_free(cm_processor);
}
bool PreviewOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h
index ffd80ff27af..9e774d0e41b 100644
--- a/source/blender/compositor/operations/COM_PreviewOperation.h
+++ b/source/blender/compositor/operations/COM_PreviewOperation.h
@@ -24,6 +24,7 @@
#define _COM_PreviewOperation_h
#include "COM_NodeOperation.h"
#include "DNA_image_types.h"
+#include "DNA_color_types.h"
#include "BLI_rect.h"
class PreviewOperation : public NodeOperation {
@@ -37,8 +38,10 @@ protected:
SocketReader *m_input;
float m_divider;
+ const ColorManagedViewSettings *m_viewSettings;
+ const ColorManagedDisplaySettings *m_displaySettings;
public:
- PreviewOperation();
+ PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings);
bool isOutputOperation(bool rendering) const { return true; }
void initExecution();
void deinitExecution();
diff --git a/source/blender/compositor/operations/COM_SplitViewerOperation.cpp b/source/blender/compositor/operations/COM_SplitViewerOperation.cpp
index d59d1f9f10d..7325e32a863 100644
--- a/source/blender/compositor/operations/COM_SplitViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_SplitViewerOperation.cpp
@@ -62,7 +62,6 @@ void SplitViewerOperation::deinitExecution()
void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
{
float *buffer = this->m_outputBuffer;
- unsigned char *bufferDisplay = this->m_outputBufferDisplay;
if (!buffer) return;
int x1 = rect->xmin;
@@ -76,7 +75,6 @@ void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
for (y = y1; y < y2; y++) {
for (x = x1; x < x2; x++) {
bool image1;
- float srgb[4];
image1 = this->m_xSplit ? x > perc : y > perc;
if (image1) {
this->m_image1Input->read(&(buffer[offset]), x, y, COM_PS_NEAREST);
@@ -84,21 +82,7 @@ void SplitViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
else {
this->m_image2Input->read(&(buffer[offset]), x, y, COM_PS_NEAREST);
}
- /// @todo: linear conversion only when scene color management is selected, also check predivide.
- if (this->m_doColorManagement) {
- if (this->m_doColorPredivide) {
- linearrgb_to_srgb_predivide_v4(srgb, buffer + offset);
- }
- else {
- linearrgb_to_srgb_v4(srgb, buffer + offset);
- }
- }
- else {
- copy_v4_v4(srgb, buffer + offset);
- }
-
- rgba_float_to_uchar(bufferDisplay + offset, srgb);
-
+
offset += 4;
}
offset += (this->getWidth() - (x2 - x1)) * 4;
diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
index f443c33cd54..d9ca131721f 100644
--- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
@@ -34,6 +34,7 @@ extern "C" {
#include "MEM_guardedalloc.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+ #include "IMB_colormanagement.h"
}
@@ -43,10 +44,10 @@ ViewerBaseOperation::ViewerBaseOperation() : NodeOperation()
this->setImageUser(NULL);
this->m_outputBuffer = NULL;
this->m_depthBuffer = NULL;
- this->m_outputBufferDisplay = NULL;
this->m_active = false;
- this->m_doColorManagement = true;
this->m_doDepthBuffer = false;
+ this->m_viewSettings = NULL;
+ this->m_displaySettings = NULL;
}
void ViewerBaseOperation::initExecution()
@@ -60,7 +61,7 @@ void ViewerBaseOperation::initImage()
{
Image *anImage = this->m_image;
ImBuf *ibuf = BKE_image_acquire_ibuf(anImage, this->m_imageUser, &this->m_lock);
-
+
if (!ibuf) return;
BLI_lock_thread(LOCK_DRAW_IMAGE);
if (ibuf->x != (int)getWidth() || ibuf->y != (int)getHeight()) {
@@ -70,30 +71,44 @@ void ViewerBaseOperation::initImage()
IMB_freezbuffloatImBuf(ibuf);
ibuf->x = getWidth();
ibuf->y = getHeight();
- imb_addrectImBuf(ibuf);
imb_addrectfloatImBuf(ibuf);
anImage->ok = IMA_OK_LOADED;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+
+ BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
+
if (m_doDepthBuffer)
{
addzbuffloatImBuf(ibuf);
}
BLI_unlock_thread(LOCK_DRAW_IMAGE);
-
-
+
/* now we combine the input with ibuf */
this->m_outputBuffer = ibuf->rect_float;
- this->m_outputBufferDisplay = (unsigned char *)ibuf->rect;
+
+ /* needed for display buffer update
+ *
+ * no need to lock / reference the image buffer because it's seems
+ * to be the single place which changes buffers of viewer image
+ * which is this node
+ */
+ this->m_ibuf = ibuf;
+
if (m_doDepthBuffer)
{
this->m_depthBuffer = ibuf->zbuf_float;
}
-
+
BKE_image_release_ibuf(this->m_image, this->m_lock);
}
void ViewerBaseOperation:: updateImage(rcti *rect)
{
+ IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0,
+ this->m_viewSettings, this->m_displaySettings,
+ rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
WM_main_add_notifier(NC_WINDOW | ND_DRAW, NULL);
}
diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h
index d90eb343f6c..f7d479eb3b8 100644
--- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h
+++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h
@@ -30,7 +30,6 @@ class ViewerBaseOperation : public NodeOperation {
protected:
float *m_outputBuffer;
float *m_depthBuffer;
- unsigned char *m_outputBufferDisplay;
Image *m_image;
ImageUser *m_imageUser;
void *m_lock;
@@ -38,9 +37,11 @@ protected:
float m_centerX;
float m_centerY;
OrderOfChunks m_chunkOrder;
- bool m_doColorManagement;
- bool m_doColorPredivide;
bool m_doDepthBuffer;
+ ImBuf *m_ibuf;
+
+ const ColorManagedViewSettings *m_viewSettings;
+ const ColorManagedDisplaySettings *m_displaySettings;
public:
bool isOutputOperation(bool rendering) const { return isActiveViewerOutput(); }
@@ -57,10 +58,10 @@ public:
float getCenterY() { return this->m_centerY; }
OrderOfChunks getChunkOrder() { return this->m_chunkOrder; }
const CompositorPriority getRenderPriority() const;
- void setColorManagement(bool doColorManagement) { this->m_doColorManagement = doColorManagement; }
- void setColorPredivide(bool doColorPredivide) { this->m_doColorPredivide = doColorPredivide; }
bool isViewerOperation() { return true; }
-
+
+ void setViewSettings(const ColorManagedViewSettings *viewSettings) { this->m_viewSettings = viewSettings; }
+ void setDisplaySettings(const ColorManagedDisplaySettings *displaySettings) { this->m_displaySettings = displaySettings; }
protected:
ViewerBaseOperation();
void updateImage(rcti *rect);
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index b85b86bddc3..576d5da4d74 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -72,7 +72,6 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
{
float *buffer = this->m_outputBuffer;
float *depthbuffer = this->m_depthBuffer;
- unsigned char *bufferDisplay = this->m_outputBufferDisplay;
if (!buffer) return;
const int x1 = rect->xmin;
const int y1 = rect->ymin;
@@ -82,7 +81,7 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
const int offsetadd4 = offsetadd * 4;
int offset = (y1 * this->getWidth() + x1);
int offset4 = offset * 4;
- float alpha[4], srgb[4], depth[4];
+ float alpha[4], depth[4];
int x;
int y;
bool breaked = false;
@@ -98,19 +97,6 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int tileNumber)
this->m_depthInput->read(depth, x, y, COM_PS_NEAREST);
depthbuffer[offset] = depth[0];
}
- if (this->m_doColorManagement) {
- if (this->m_doColorPredivide) {
- linearrgb_to_srgb_predivide_v4(srgb, buffer + offset4);
- }
- else {
- linearrgb_to_srgb_v4(srgb, buffer + offset4);
- }
- }
- else {
- copy_v4_v4(srgb, buffer + offset4);
- }
-
- rgba_float_to_uchar(bufferDisplay + offset4, srgb);
offset ++;
offset4 += 4;
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 13c3b180230..28727c913cb 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -83,7 +83,7 @@ void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mas
/* textures buffer */
int ED_space_clip_texture_buffer_supported(struct SpaceClip *sc);
-int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf);
+int ED_space_clip_load_movieclip_buffer(struct SpaceClip *sc, struct ImBuf *ibuf, const unsigned char *display_buffer);
void ED_space_clip_unload_movieclip_buffer(struct SpaceClip *sc);
void ED_space_clip_free_texture_buffer(struct SpaceClip *sc);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 87f12b8ac9c..a50b33966c6 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -39,6 +39,7 @@ struct ToolSettings;
struct uiBlock;
struct wmWindowManager;
struct ARegion;
+struct Scene;
/* image_edit.c, exported for transform */
struct Image *ED_space_image(struct SpaceImage *sima);
@@ -77,7 +78,7 @@ int ED_space_image_maskedit_mask_poll(struct bContext *C);
/* UI level image (texture) updating... render calls own stuff (too) */
void ED_image_update_frame(const struct Main *mainp, int cfra);
-void ED_image_draw_info(struct ARegion *ar, int color_manage, int channels, int x, int y,
+void ED_image_draw_info(struct Scene *scene, struct ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
const unsigned char cp[4], const float fp[4], int *zp, float *zpf);
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 7f40024a056..b1bccfa32c5 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -282,10 +282,12 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
int ED_view3d_context_activate(struct bContext *C);
void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar,
- int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic);
+ int winx, int winy, float viewmat[][4], float winmat[][4], int do_bgpic, int colormanage_background);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256]);
-struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, int draw_background, char err_out[256]);
+struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag,
+ int draw_background, int colormanage_background, char err_out[256]);
+struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype,
+ int draw_background, int colormanage_background, char err_out[256]);
struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c6f58fdd70b..917153c9199 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -811,7 +811,7 @@ void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *
void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname,
PointerRNA *used_ptr, const char *used_propname, int active_layer);
void uiTemplateImage(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr, int compact);
-void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr);
+void uiTemplateImageSettings(uiLayout *layout, struct PointerRNA *imfptr, int color_management);
void uiTemplateImageLayers(uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser);
void uiTemplateRunningJobs(uiLayout *layout, struct bContext *C);
void uiTemplateOperatorSearch(uiLayout *layout);
@@ -831,6 +831,9 @@ void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct Poi
void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int cmpact);
+void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname);
+void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
+
/* items */
void uiItemO(uiLayout *layout, const char *name, int icon, const char *opname);
void uiItemEnumO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, const char *propname, int value);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 823f8d7be39..742aed4fbb1 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -75,6 +75,8 @@
#include "BPY_extern.h"
+#include "IMB_colormanagement.h"
+
#include "interface_intern.h"
#define MENU_WIDTH 120
@@ -2138,7 +2140,14 @@ uiBlock *uiBeginBlock(const bContext *C, ARegion *region, const char *name, shor
block->evil_C = (void *)C; /* XXX */
if (scn) {
- block->color_profile = (scn->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+ block->color_profile = TRUE;
+
+ /* store display device name, don't lookup for transformations yet
+ * block could be used for non-color displays where looking up for transformation
+ * would slow down redraw, so only lookup for actual transform when it's indeed
+ * needed
+ */
+ block->display_device = scn->display_settings.display_device;
/* copy to avoid crash when scene gets deleted with ui still open */
block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings");
@@ -2575,6 +2584,25 @@ void ui_block_do_align(uiBlock *block)
}
}
+struct ColorManagedDisplay *ui_block_display_get(uiBlock *block)
+{
+ return IMB_colormanagement_display_get_named(block->display_device);
+}
+
+void ui_block_to_display_space_v3(uiBlock *block, float pixel[3])
+{
+ struct ColorManagedDisplay *display = ui_block_display_get(block);
+
+ IMB_colormanagement_scene_linear_to_display_v3(pixel, display);
+}
+
+void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3])
+{
+ struct ColorManagedDisplay *display = ui_block_display_get(block);
+
+ IMB_colormanagement_display_to_scene_linear_v3(pixel, display);
+}
+
/**
* \brief ui_def_but is the function that draws many button types
*
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 77dbbc878a7..f535c3c3e2a 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -48,6 +48,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -1110,10 +1111,14 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
float v3[2], v1[2], v2[2], v1a[2], v2a[2];
int a;
float pos, colf[4] = {0, 0, 0, 0}; /* initialize in case the colorband isn't valid */
-
+ struct ColorManagedDisplay *display = NULL;
+
coba = (ColorBand *)(but->editcoba ? but->editcoba : but->poin);
if (coba == NULL) return;
-
+
+ if (but->block->color_profile)
+ display = ui_block_display_get(but->block);
+
x1 = rect->xmin;
y1 = rect->ymin;
sizex = rect->xmax - x1;
@@ -1146,8 +1151,8 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect)
for (a = 1; a <= sizex; a++) {
pos = ((float)a) / (sizex - 1);
do_colorband(coba, pos, colf);
- if (but->block->color_profile != BLI_PR_NONE)
- linearrgb_to_srgb_v3_v3(colf, colf);
+ if (display)
+ IMB_colormanagement_scene_linear_to_display_v3(colf, display);
v1[0] = v2[0] = x1 + a;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index b8a84e1638a..f7b22098835 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -3162,13 +3162,15 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
if (but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- color_profile = BLI_PR_NONE;
+ color_profile = FALSE;
}
ui_get_but_vectorf(but, rgb);
- rgb_to_hsv_compat_v(rgb, hsv);
+ if (color_profile && (int)but->a1)
+ ui_block_to_display_space_v3(but->block, rgb);
+ rgb_to_hsv_compat_v(rgb, hsv);
/* relative position within box */
x = ((float)mx_fl - but->rect.xmin) / BLI_RCT_SIZE_X(&but->rect);
@@ -3204,17 +3206,16 @@ static int ui_numedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, int mx,
/* exception only for value strip - use the range set in but->min/max */
hsv[2] = y * (but->softmax - but->softmin) + but->softmin;
- if (color_profile)
- hsv[2] = srgb_to_linearrgb(hsv[2]);
-
- if (hsv[2] > but->softmax)
- hsv[2] = but->softmax;
break;
default:
assert(!"invalid hsv type");
}
hsv_to_rgb_v(hsv, rgb);
+
+ if (color_profile && (int)but->a1)
+ ui_block_to_scene_linear_v3(but->block, rgb);
+
copy_v3_v3(data->vec, rgb);
data->draglastx = mx;
@@ -3233,10 +3234,14 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF
if (but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- color_profile = BLI_PR_NONE;
+ color_profile = FALSE;
}
ui_get_but_vectorf(but, rgb);
+
+ if (color_profile && (int)but->a1)
+ ui_block_to_display_space_v3(but->block, rgb);
+
rgb_to_hsv_compat_v(rgb, hsv);
switch ((int)but->a1) {
@@ -3267,15 +3272,16 @@ static void ui_ndofedit_but_HSVCUBE(uiBut *but, uiHandleButtonData *data, wmNDOF
/* exception only for value strip - use the range set in but->min/max */
hsv[2] += ndof->rx * sensitivity;
- if (color_profile)
- hsv[2] = srgb_to_linearrgb(hsv[2]);
-
CLAMP(hsv[2], but->softmin, but->softmax);
default:
assert(!"invalid hsv type");
}
-
+
hsv_to_rgb_v(hsv, rgb);
+
+ if (color_profile && (int)but->a1)
+ ui_block_to_scene_linear_v3(but->block, rgb);
+
copy_v3_v3(data->vec, rgb);
ui_set_but_vectorf(but, data->vec);
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index f6f12f98181..0921107b8e6 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -466,7 +466,7 @@ static void init_brush_icons(void)
{ \
bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \
datatoc_ ##name## _png_size, \
- IB_rect, "<brush icon>"); \
+ IB_rect, NULL, "<brush icon>"); \
def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \
IMB_freeImBuf(bbuf); \
} (void)0
@@ -520,7 +520,7 @@ static void init_internal_icons(void)
char *icondir = BLI_get_folder(BLENDER_DATAFILES, "icons");
if (icondir) {
BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
- bbuf = IMB_loadiffname(iconfilestr, IB_rect); /* if the image is missing bbuf will just be NULL */
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL); /* if the image is missing bbuf will just be NULL */
if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
printf("\n***WARNING***\nIcons file %s too small.\nUsing built-in Icons instead\n", iconfilestr);
IMB_freeImBuf(bbuf);
@@ -533,7 +533,7 @@ static void init_internal_icons(void)
}
if (bbuf == NULL)
bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_blender_icons_png,
- datatoc_blender_icons_png_size, IB_rect, "<blender icons>");
+ datatoc_blender_icons_png_size, IB_rect, NULL, "<blender icons>");
if (bbuf) {
/* free existing texture if any */
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 73e6427d1cb..928e1671cee 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -342,7 +342,12 @@ struct uiBlock {
struct UnitSettings *unit; /* unit system, used a lot for numeric buttons so include here rather then fetching through the scene every time. */
float _hsv[3]; /* XXX, only access via ui_block_hsv_get() */
+
char color_profile; /* color profile for correcting linear colors for display */
+
+ char *display_device; /* display devide name used to display this block,
+ * used by color widgets to transform colors from/to scene linear
+ */
};
typedef struct uiSafetyRct {
@@ -392,6 +397,10 @@ extern void ui_bounds_block(uiBlock *block);
extern void ui_block_translate(uiBlock *block, int x, int y);
extern void ui_block_do_align(uiBlock *block);
+extern struct ColorManagedDisplay *ui_block_display_get(uiBlock *block);
+void ui_block_to_display_space_v3(uiBlock *block, float pixel[3]);
+void ui_block_to_scene_linear_v3(uiBlock *block, float pixel[3]);
+
/* interface_regions.c */
struct uiPopupBlockHandle {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index bf77e605d6e..ded5887f7f2 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -58,6 +58,8 @@
#include "UI_interface.h"
+#include "IMB_colormanagement.h"
+
#include "interface_intern.h"
#include "WM_api.h"
@@ -75,7 +77,7 @@
/* ********************************************************** */
typedef struct Eyedropper {
- short do_color_management;
+ struct ColorManagedDisplay *display;
PointerRNA ptr;
PropertyRNA *prop;
@@ -89,8 +91,6 @@ typedef struct Eyedropper {
static int eyedropper_init(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- const int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
-
Eyedropper *eye;
op->customdata = eye = MEM_callocN(sizeof(Eyedropper), "Eyedropper");
@@ -106,7 +106,12 @@ static int eyedropper_init(bContext *C, wmOperator *op)
return FALSE;
}
- eye->do_color_management = (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR);
+ if (RNA_property_subtype(eye->prop) == PROP_COLOR) {
+ const char *display_device;
+
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+ }
return TRUE;
}
@@ -194,9 +199,10 @@ static void eyedropper_color_set(bContext *C, Eyedropper *eye, const float col[3
/* to maintain alpha */
RNA_property_float_get_array(&eye->ptr, eye->prop, col_conv);
- /* convert from screen (srgb) space to linear rgb space */
- if (eye->do_color_management) {
- srgb_to_linearrgb_v3_v3(col_conv, col);
+ /* convert from display space to linear rgb space */
+ if (eye->display) {
+ copy_v3_v3(col_conv, col);
+ IMB_colormanagement_display_to_scene_linear_v3(col_conv, eye->display);
}
else {
copy_v3_v3(col_conv, col);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 59fa66b12af..dc9347b3852 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -66,6 +66,8 @@
#include "ED_screen.h"
+#include "IMB_colormanagement.h"
+
#include "interface_intern.h"
#define MENU_SEPR_HEIGHT 6
@@ -1893,11 +1895,15 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3])
{
uiBut *bt;
float *hsv = ui_block_hsv_get(block);
+ struct ColorManagedDisplay *display = NULL;
/* this is to keep the H and S value when V is equal to zero
* and we are working in HSV mode, of course!
*/
rgb_to_hsv_compat_v(rgb, hsv);
+
+ if (block->color_profile)
+ display = ui_block_display_get(block);
/* this updates button strings, is hackish... but button pointers are on stack of caller function */
for (bt = block->buttons.first; bt; bt = bt->next) {
@@ -1913,12 +1919,11 @@ static void ui_update_block_buts_rgb(uiBlock *block, const float rgb[3])
/* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
- if (block->color_profile == BLI_PR_NONE) {
- copy_v3_v3(rgb_gamma, rgb);
- }
- else {
- /* make an sRGB version, for Hex code */
- linearrgb_to_srgb_v3_v3(rgb_gamma, rgb);
+ copy_v3_v3(rgb_gamma, rgb);
+
+ if (display) {
+ /* make a display version, for Hex code */
+ IMB_colormanagement_scene_linear_to_display_v3(rgb_gamma, display);
}
if (rgb_gamma[0] > 1.0f) rgb_gamma[0] = modf(rgb_gamma[0], &intpart);
@@ -1997,9 +2002,9 @@ static void do_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexcl)
hex_to_rgb(hexcol, rgb, rgb + 1, rgb + 2);
/* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
- if (but->block->color_profile != BLI_PR_NONE) {
+ if (but->block->color_profile) {
/* so we need to linearise it for Blender */
- srgb_to_linearrgb_v3_v3(rgb, rgb);
+ ui_block_to_scene_linear_v3(but->block, rgb);
}
ui_update_block_buts_rgb(but->block, rgb);
@@ -2107,14 +2112,16 @@ static void uiBlockPicker(uiBlock *block, float rgba[4], PointerRNA *ptr, Proper
/* existence of profile means storage is in linear color space, with display correction */
/* XXX That tip message is not use anywhere! */
- if (block->color_profile == BLI_PR_NONE) {
+ if (!block->color_profile) {
BLI_strncpy(tip, N_("Value in Display Color Space"), sizeof(tip));
copy_v3_v3(rgb_gamma, rgba);
}
else {
BLI_strncpy(tip, N_("Value in Linear RGB Color Space"), sizeof(tip));
- /* make an sRGB version, for Hex code */
- linearrgb_to_srgb_v3_v3(rgb_gamma, rgba);
+
+ /* make a display version, for Hex code */
+ copy_v3_v3(rgb_gamma, rgba);
+ ui_block_to_display_space_v3(block, rgb_gamma);
}
/* sneaky way to check for alpha */
@@ -2239,7 +2246,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_
if (but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
- block->color_profile = BLI_PR_NONE;
+ block->color_profile = FALSE;
}
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 6a63e2b571f..79b9d313775 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2801,3 +2801,56 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
}
}
+/********************************* Color management *************************************/
+
+void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname)
+{
+ PropertyRNA *prop;
+ PointerRNA colorspace_settings_ptr;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ printf("%s: property not found: %s.%s\n",
+ __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ colorspace_settings_ptr = RNA_property_pointer_get(ptr, prop);
+
+ uiItemL(layout, "Color Space:", ICON_NONE);
+ uiItemR(layout, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
+}
+
+void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr, const char *propname)
+{
+ PropertyRNA *prop;
+ PointerRNA view_transform_ptr;
+ uiLayout *col, *row;
+ ColorManagedViewSettings *view_settings;
+
+ prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ printf("%s: property not found: %s.%s\n",
+ __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ view_transform_ptr = RNA_property_pointer_get(ptr, prop);
+ view_settings = view_transform_ptr.data;
+
+ col = uiLayoutColumn(layout, FALSE);
+
+ row = uiLayoutRow(col, FALSE);
+ uiItemR(row, &view_transform_ptr, "view_transform", UI_ITEM_R_EXPAND, IFACE_("View"), ICON_NONE);
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemR(col, &view_transform_ptr, "exposure", 0, NULL, ICON_NONE);
+ uiItemR(col, &view_transform_ptr, "gamma", 0, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemR(col, &view_transform_ptr, "use_curve_mapping", 0, NULL, ICON_NONE);
+ if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
+ uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0);
+}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 026f02d1089..8a7f2d9ca47 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1874,7 +1874,7 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
int color_profile = but->block->color_profile;
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- color_profile = BLI_PR_NONE;
+ color_profile = FALSE;
radstep = 2.0f * (float)M_PI / (float)tot;
centx = BLI_RCT_CENTER_X_FL(rect);
@@ -1887,17 +1887,20 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, rcti *rect)
/* color */
ui_get_but_vectorf(but, rgb);
- copy_v3_v3(hsv, ui_block_hsv_get(but->block));
+ /* copy_v3_v3(hsv, ui_block_hsv_get(but->block)); */ /* UNUSED */
+
+ rgb_to_hsv_compat_v(rgb, hsvo);
+
+ if (color_profile)
+ ui_block_to_display_space_v3(but->block, rgb);
+
rgb_to_hsv_compat_v(rgb, hsv);
- copy_v3_v3(hsvo, hsv);
/* exception: if 'lock' is set
* lock the value of the color wheel to 1.
* Useful for color correction tools where you're only interested in hue. */
if (but->flag & UI_BUT_COLOR_LOCK)
hsv[2] = 1.f;
- else if (color_profile)
- hsv[2] = linearrgb_to_srgb(hsv[2]);
hsv_to_rgb(0.f, 0.f, hsv[2], colcent, colcent + 1, colcent + 2);
@@ -2139,15 +2142,16 @@ static void ui_draw_but_HSV_v(uiBut *but, rcti *rect)
int color_profile = but->block->color_profile;
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- color_profile = BLI_PR_NONE;
+ color_profile = FALSE;
ui_get_but_vectorf(but, rgb);
+
+ if (color_profile)
+ ui_block_to_display_space_v3(but->block, rgb);
+
rgb_to_hsv_v(rgb, hsv);
v = hsv[2];
- if (color_profile)
- v = linearrgb_to_srgb(v);
-
/* map v from property range to [0,1] */
range = but->softmax - but->softmin;
v = (v - but->softmin) / range;
@@ -2531,7 +2535,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
if (but->rnaprop) {
if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA)
- color_profile = BLI_PR_NONE;
+ color_profile = FALSE;
if (RNA_property_array_length(&but->rnapoin, but->rnaprop) == 4) {
col[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
@@ -2559,7 +2563,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
}
if (color_profile)
- linearrgb_to_srgb_v3_v3(col, col);
+ ui_block_to_display_space_v3(but->block, col);
rgba_float_to_uchar((unsigned char *)wcol->inner, col);
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index f9b73a56403..f03cb312e3e 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -69,6 +69,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "GPU_draw.h" /* GPU_free_image */
@@ -685,7 +686,7 @@ static void apply_heights_data(void *bake_data)
}
}
- ibuf->userflags = IB_RECT_INVALID;
+ ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID;
}
static void free_heights_data(void *bake_data)
@@ -769,6 +770,8 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
char *rrgb = (char *)ibuf->rect + pixel * 4;
rrgb[3] = 255;
}
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
/* MultiresBake callback for normals' baking
@@ -826,6 +829,8 @@ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm,
rgb_float_to_uchar(rrgb, vec);
rrgb[3] = 255;
}
+
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
static void count_images(MultiresBakeRender *bkr)
@@ -895,7 +900,7 @@ static void finish_images(MultiresBakeRender *bkr)
RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter);
- ibuf->userflags |= IB_BITMAPDIRTY;
+ ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;;
if (ibuf->rect_float)
ibuf->userflags |= IB_RECT_INVALID;
@@ -1369,6 +1374,7 @@ static void finish_bake_internal(BakeRender *bkr)
if (ima->ok == IMA_OK_LOADED) {
if (ibuf) {
if (ibuf->userflags & IB_BITMAPDIRTY) {
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
GPU_free_image(ima);
imb_freemipmapImBuf(ibuf);
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index b236b555850..ebacac917e8 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -61,6 +61,7 @@
#include "ED_object.h"
#include "RE_pipeline.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -78,7 +79,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
{
float *rectf = NULL;
int ymin, ymax, xmin, xmax;
- int rymin, rxmin, predivide, profile_from;
+ int rymin, rxmin;
unsigned char *rectc;
/* if renrect argument, we only refresh scanlines */
@@ -138,18 +139,9 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat
rectf += 4 * (rr->rectx * ymin + xmin);
rectc = (unsigned char *)(ibuf->rect + ibuf->x * rymin + rxmin);
- if (scene && (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
- profile_from = IB_PROFILE_LINEAR_RGB;
- predivide = (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
- }
- else {
- profile_from = IB_PROFILE_SRGB;
- predivide = 0;
- }
-
- IMB_buffer_byte_from_float(rectc, rectf,
- 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
- xmax, ymax, ibuf->x, rr->rectx);
+ IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin,
+ &scene->view_settings, &scene->display_settings,
+ rxmin, rymin, rxmin + xmax, rymin + ymax);
}
/* ****************************** render invoking ***************** */
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 55df1caf3eb..d9618e89b68 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -63,6 +63,7 @@
#include "RE_pipeline.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -143,22 +144,30 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown);
if (ibuf) {
+ ImBuf *linear_ibuf;
+
BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
- if (ibuf->rect_float == NULL) {
- /* internally sequencer working in sRGB space and stores both bytes and float
- * buffers in sRGB space, but if byte->float onversion doesn't happen in sequencer
- * (e.g. when adding image sequence/movie into sequencer) there'll be only
- * byte buffer and profile will still indicate sRGB->linear space conversion is needed
- * here we're ensure there'll be no conversion happen and float buffer would store
- * linear frame (sergey) */
- ibuf->profile = IB_PROFILE_NONE;
- IMB_float_from_rect(ibuf);
+ linear_ibuf = IMB_dupImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
+
+ if (linear_ibuf->rect_float == NULL) {
+ /* internally sequencer working in display space and stores both bytes and float buffers in that space.
+ * It is possible that byte->float onversion didn't happen in sequencer (e.g. when adding image sequence/movie
+ * into sequencer) there'll be only byte buffer. Create float buffer from existing byte buffer, making it linear
+ */
+
+ IMB_float_from_rect(linear_ibuf);
+ }
+ else {
+ /* ensure float buffer is in linear space, not in display space */
+ BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf);
}
- memcpy(rr->rectf, ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
- IMB_freeImBuf(ibuf);
+ memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey);
+
+ IMB_freeImBuf(linear_ibuf);
}
}
else if (view_context) {
@@ -181,7 +190,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
}
if ((scene->r.mode & R_OSA) == 0) {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf);
}
else {
@@ -195,7 +204,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
BLI_jitter_init(jit_ofs[0], scene->r.osa);
/* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE, FALSE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer);
/* skip the first sample */
@@ -205,7 +214,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
(jit_ofs[j][0] * 2.0f) / sizex,
(jit_ofs[j][1] * 2.0f) / sizey);
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE, FALSE);
GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp);
add_vn_vn(accum_buffer, accum_tmp, sizex * sizey * sizeof(float));
}
@@ -221,7 +230,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
else {
/* shouldnt suddenly give errors mid-render but possible */
char err_out[256] = "unknown";
- ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, err_out);
+ ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, IB_rectfloat, OB_SOLID, TRUE, FALSE, err_out);
camera = scene->camera;
if (ibuf_view) {
@@ -233,27 +242,27 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
}
}
- /* rr->rectf is now filled with image data */
-
- if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
- BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4);
-
/* note on color management:
*
* OpenGL renders into sRGB colors, but render buffers are expected to be
- * linear if color management is enabled. So we convert to linear here, so
- * the conversion back to bytes using the color management flag can make it
- * sRGB again, and so that e.g. openexr saving also saves the correct linear
- * float buffer. */
+ * linear So we convert to linear here, so the conversion back to bytes can make it
+ * sRGB (or other display space) again, and so that e.g. openexr saving also saves the
+ * correct linear float buffer.
+ */
- if (oglrender->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) {
- int predivide = 0; /* no alpha */
+ if (!oglrender->is_sequencer) {
+ /* sequencer has got tricker ocnversion happened above */
IMB_buffer_float_from_float(rr->rectf, rr->rectf,
- 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
+ 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, FALSE,
oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex);
}
+ /* rr->rectf is now filled with image data */
+
+ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW))
+ BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4);
+
RE_ReleaseResult(oglrender->re);
/* update byte from float buffer */
@@ -536,12 +545,28 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
if (ibuf) {
+ int needs_free = FALSE;
+
+ if (is_movie || !BKE_imtype_supports_float(scene->r.im_format.imtype)) {
+ ImBuf *colormanage_ibuf = IMB_dupImBuf(ibuf);
+
+ IMB_display_buffer_to_imbuf_rect(colormanage_ibuf, &scene->view_settings, &scene->display_settings);
+ imb_freerectfloatImBuf(colormanage_ibuf);
+
+ // IMB_freeImBuf(ibuf); /* owned by the image */
+ ibuf = colormanage_ibuf;
+ needs_free = TRUE;
+ }
+
/* color -> grayscale */
/* editing directly would alter the render view */
if (scene->r.im_format.planes == R_IMF_PLANES_BW) {
- ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
+ ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
IMB_color_to_bw(ibuf_bw);
- // IMB_freeImBuf(ibuf); /* owned by the image */
+
+ if (needs_free)
+ IMB_freeImBuf(ibuf);
+
ibuf = ibuf_bw;
}
else {
@@ -551,6 +576,13 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
ibuf_cpy->rect = ibuf->rect;
ibuf_cpy->rect_float = ibuf->rect_float;
ibuf_cpy->zbuf_float = ibuf->zbuf_float;
+
+ if (needs_free) {
+ ibuf_cpy->mall = ibuf->mall;
+ ibuf->mall = 0;
+ IMB_freeImBuf(ibuf);
+ }
+
ibuf = ibuf_cpy;
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 068a7aaa50a..a829ef57b85 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -64,6 +64,7 @@
#include "BKE_brush.h"
#include "BKE_context.h"
+#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -75,11 +76,13 @@
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_scene.h"
#include "BKE_texture.h"
#include "BKE_world.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -115,7 +118,8 @@ ImBuf *get_brush_icon(Brush *brush)
BLI_strncpy(path, brush->icon_filepath, sizeof(brush->icon_filepath));
BLI_path_abs(path, G.main->name);
- brush->icon_imbuf = IMB_loadiffname(path, flags);
+ /* use default colorspaces for brushes */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
// otherwise lets try to find it in other directories
if (!(brush->icon_imbuf)) {
@@ -123,8 +127,10 @@ ImBuf *get_brush_icon(Brush *brush)
BLI_make_file_string(G.main->name, path, folder, brush->icon_filepath);
- if (path[0])
- brush->icon_imbuf = IMB_loadiffname(path, flags);
+ if (path[0]) {
+ /* use fefault color spaces */
+ brush->icon_imbuf = IMB_loadiffname(path, flags, NULL);
+ }
}
if (brush->icon_imbuf)
@@ -254,6 +260,10 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
}
sce->r.color_mgt_flag = scene->r.color_mgt_flag;
+ BKE_color_managed_display_settings_copy(&sce->display_settings, &scene->display_settings);
+
+ BKE_color_managed_view_settings_free(&sce->view_settings);
+ BKE_color_managed_view_settings_copy(&sce->view_settings, &scene->view_settings);
/* prevent overhead for small renders and icons (32) */
if (id && sp->sizex < 40)
@@ -263,7 +273,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
/* exception: don't color manage texture previews or icons */
if ((id && sp->pr_method == PR_ICON_RENDER) || id_type == ID_TE)
- sce->r.color_mgt_flag &= ~R_COLOR_MANAGEMENT;
+ BKE_scene_disable_color_management(sce);
if ((id && sp->pr_method == PR_ICON_RENDER) && id_type != ID_WO)
sce->r.alphamode = R_ALPHAPREMUL;
@@ -481,7 +491,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
if (id && GS(id->name) != ID_TE) {
/* exception: don't color manage texture previews - show the raw values */
if (sce) {
- do_gamma_correct = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT;
+ do_gamma_correct = TRUE;
do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
}
}
@@ -514,15 +524,25 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
/* temporary conversion to byte for drawing */
float fx = rect->xmin + offx;
float fy = rect->ymin;
- int profile_from = (do_gamma_correct) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
int dither = 0;
unsigned char *rect_byte;
rect_byte = MEM_mallocN(rres.rectx * rres.recty * sizeof(int), "ed_preview_draw_rect");
- IMB_buffer_byte_from_float(rect_byte, rres.rectf,
- 4, dither, IB_PROFILE_SRGB, profile_from, do_predivide,
- rres.rectx, rres.recty, rres.rectx, rres.rectx);
+ if (do_gamma_correct) {
+ IMB_display_buffer_transform_apply(rect_byte, rres.rectf, rres.rectx, rres.recty, 4,
+ &sce->view_settings, &sce->display_settings, do_predivide);
+
+ }
+ else {
+ /* OCIO_TODO: currently seems an exception for textures (came fro mlegacish time),
+ * but is it indeed expected behavior, or textures should be
+ * color managed as well?
+ */
+ IMB_buffer_byte_from_float(rect_byte, rres.rectf,
+ 4, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, do_predivide,
+ rres.rectx, rres.recty, rres.rectx, rres.rectx);
+ }
glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 4e71c49465f..5e54119118a 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -245,7 +245,7 @@ static void screenshot_draw(bContext *UNUSED(C), wmOperator *op)
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &scd->im_format, &ptr);
- uiTemplateImageSettings(layout, &ptr);
+ uiTemplateImageSettings(layout, &ptr, TRUE);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 101235e9c99..64430a263f0 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -104,6 +104,8 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "IMB_colormanagement.h"
+
#include "paint_intern.h"
/* Defines and Structs */
@@ -139,7 +141,7 @@
#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS)
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
+static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint);
typedef struct ImagePaintState {
@@ -153,7 +155,6 @@ typedef struct ImagePaintState {
Image *image;
ImBuf *canvas;
ImBuf *clonecanvas;
- short clonefreefloat;
char *warnpackedfile;
char *warnmultifile;
@@ -510,7 +511,7 @@ static void image_undo_restore(bContext *C, ListBase *lb)
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
if (ibuf->mipmap[0])
ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */
-
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
IMB_freeImBuf(tmpibuf);
@@ -3615,7 +3616,7 @@ static int project_image_refresh_tagged(ProjPaintState *ps)
pr = &(projIma->partRedrawRect[i]);
if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
imapaintpartial = *pr;
- imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/
+ imapaint_image_update(NULL, NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/
redraw = 1;
}
}
@@ -3945,7 +3946,7 @@ static void *do_projectpaint_thread(void *ph_v)
last_projIma->touch = 1;
is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
- use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0;
+ use_color_correction = TRUE;
}
/* end copy */
@@ -4028,7 +4029,7 @@ static void *do_projectpaint_thread(void *ph_v)
last_projIma->touch = 1;
is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0;
- use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0;
+ use_color_correction = TRUE;
}
/* end copy */
@@ -4244,10 +4245,17 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w,
IMB_freeImBuf(tmpibuf);
}
-static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
+static void imapaint_image_update(Scene *scene, SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
{
- if (ibuf->rect_float)
- ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+ if (scene) {
+ IMB_partial_display_buffer_update(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, ibuf->x, 0, 0,
+ &scene->view_settings, &scene->display_settings,
+ imapaintpartial.x1, imapaintpartial.y1,
+ imapaintpartial.x2, imapaintpartial.y2);
+ }
+ else {
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ }
if (ibuf->mipmap[0])
ibuf->userflags |= IB_MIPMAP_INVALID;
@@ -4571,15 +4579,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
/* temporarily add float rect for cloning */
if (s->canvas->rect_float && !s->clonecanvas->rect_float) {
- short profile = IB_PROFILE_NONE;
-
- /* Don't want to color manage, but don't disturb existing profiles */
- SWAP(short, s->clonecanvas->profile, profile);
-
IMB_float_from_rect(s->clonecanvas);
- s->clonefreefloat = 1;
-
- SWAP(short, s->clonecanvas->profile, profile);
}
else if (!s->canvas->rect_float && !s->clonecanvas->rect)
IMB_rect_from_float(s->clonecanvas);
@@ -4588,10 +4588,8 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima)
return 1;
}
-static void imapaint_canvas_free(ImagePaintState *s)
+static void imapaint_canvas_free(ImagePaintState *UNUSED(s))
{
- if (s->clonefreefloat)
- imb_freerectfloatImBuf(s->clonecanvas);
}
static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure)
@@ -4607,9 +4605,12 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter,
BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0);
- if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) {
+ /* OCIO_TODO: float buffers are now always linear, so always use color correction
+ * this should probably be changed when texture painting color space is supported
+ */
+ if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, TRUE)) {
if (update)
- imapaint_image_update(s->sima, image, ibuf, texpaint);
+ imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint);
return 1;
}
else return 0;
@@ -5884,7 +5885,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (w > maxsize) w = maxsize;
if (h > maxsize) h = maxsize;
- ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, err_out);
+ ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, FALSE, err_out);
if (!ibuf) {
/* Mostly happens when OpenGL offscreen buffer was failed to create, */
/* but could be other reasons. Should be handled in the future. nazgul */
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index e66faa88b93..0a1e1d75098 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -119,6 +119,8 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiTemplateID(layout, C, ptr, propname, NULL, "CLIP_OT_open", NULL);
if (clip) {
+ uiLayout *col;
+
row = uiLayoutRow(layout, FALSE);
block = uiLayoutGetBlock(row);
uiDefBut(block, LABEL, 0, "File Path:", 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
@@ -129,6 +131,9 @@ void uiTemplateMovieClip(uiLayout *layout, bContext *C, PointerRNA *ptr, const c
uiItemR(row, &clipptr, "filepath", 0, "", ICON_NONE);
uiItemO(row, "", ICON_FILE_REFRESH, "clip.reload");
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiTemplateColorspaceSettings(col, &clipptr, "colorspace_settings");
}
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 2353f8f8c12..d486caeacc2 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -42,6 +42,7 @@
#include "BKE_tracking.h"
#include "BKE_mask.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -246,14 +247,7 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar)
ED_region_info_draw(ar, str, block, 0.6f);
}
-static void verify_buffer_float(ImBuf *ibuf)
-{
- if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) {
- IMB_rect_from_float(ibuf);
- }
-}
-
-static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
+static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
int width, int height, float zoomx, float zoomy)
{
int x, y;
@@ -267,13 +261,16 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
glRectf(x, y, x + zoomx * width, y + zoomy * height);
}
else {
- verify_buffer_float(ibuf);
+ unsigned char *display_buffer;
+ void *cache_handle;
+
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
- if (ibuf->rect) {
+ if (display_buffer) {
int need_fallback = 1;
if (ED_space_clip_texture_buffer_supported(sc)) {
- if (ED_space_clip_load_movieclip_buffer(sc, ibuf)) {
+ if (ED_space_clip_load_movieclip_buffer(sc, ibuf, display_buffer)) {
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(zoomx, zoomy, 1.0f);
@@ -299,12 +296,14 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
/* set zoom */
glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
/* reset zoom */
glPixelZoom(1.0f, 1.0f);
}
}
+
+ IMB_display_buffer_release(cache_handle);
}
/* draw boundary border for frame if stabilization is enabled */
@@ -1461,7 +1460,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
}
if (ibuf) {
- draw_movieclip_buffer(sc, ar, ibuf, width, height, zoomx, zoomy);
+ draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
}
else {
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 08ad6aac970..f2a48f299cf 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -277,13 +277,7 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
- /* IB_PROFILE_NONE is default but infact its linear */
- if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) {
- linearrgb_to_srgb_v3_v3(r_col, fp);
- }
- else {
- copy_v3_v3(r_col, fp);
- }
+ linearrgb_to_srgb_v3_v3(r_col, fp);
ret = TRUE;
}
else if (ibuf->rect) {
@@ -583,12 +577,15 @@ typedef struct SpaceClipDrawContext {
GLuint texture; /* OGL texture ID */
short texture_allocated; /* flag if texture was allocated by glGenTextures */
struct ImBuf *texture_ibuf; /* image buffer for which texture was created */
+ const unsigned char *display_buffer; /* display buffer for which texture was created */
int image_width, image_height; /* image width and height for which texture was created */
unsigned last_texture; /* ID of previously used texture, so it'll be restored after clip drawing */
/* fields to check if cache is still valid */
int framenr, start_frame, frame_offset;
short render_size, render_flag;
+
+ char colorspace[64];
} SpaceClipDrawContext;
int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
@@ -613,7 +610,7 @@ int ED_space_clip_texture_buffer_supported(SpaceClip *sc)
return context->buffers_supported;
}
-int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
+int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf, const unsigned char *display_buffer)
{
SpaceClipDrawContext *context = sc->draw_context;
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -625,12 +622,22 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
* assuming displaying happens of footage frames only on which painting doesn't heppen.
* so not changed image buffer pointer means unchanged image content */
need_rebind |= context->texture_ibuf != ibuf;
+ need_rebind |= context->display_buffer != display_buffer;
need_rebind |= context->framenr != sc->user.framenr;
need_rebind |= context->render_size != sc->user.render_size;
need_rebind |= context->render_flag != sc->user.render_flag;
need_rebind |= context->start_frame != clip->start_frame;
need_rebind |= context->frame_offset != clip->frame_offset;
+ if (!need_rebind) {
+ /* OCIO_TODO: not entirely nice, but currently it seems to be easiest way
+ * to deal with changing input color space settings
+ * pointer-based check could fail due to new buffers could be
+ * be allocated on on old memory
+ */
+ need_rebind = strcmp(context->colorspace, clip->colorspace_settings.name) != 0;
+ }
+
if (need_rebind) {
int width = ibuf->x, height = ibuf->y;
int need_recreate = 0;
@@ -670,16 +677,12 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
glBindTexture(GL_TEXTURE_2D, context->texture);
}
- if (ibuf->rect_float) {
- if (ibuf->rect == NULL)
- IMB_rect_from_float(ibuf);
- }
-
- if (ibuf->rect)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (display_buffer)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
/* store settings */
context->texture_allocated = 1;
+ context->display_buffer = display_buffer;
context->texture_ibuf = ibuf;
context->image_width = ibuf->x;
context->image_height = ibuf->y;
@@ -688,6 +691,8 @@ int ED_space_clip_load_movieclip_buffer(SpaceClip *sc, ImBuf *ibuf)
context->render_flag = sc->user.render_flag;
context->start_frame = clip->start_frame;
context->frame_offset = clip->frame_offset;
+
+ strcpy(context->colorspace, clip->colorspace_settings.name);
}
else {
/* displaying exactly the same image which was loaded t oa texture,
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 337e13f7785..d3b4df05aa9 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -389,7 +389,7 @@ void filelist_init_icons(void)
#ifdef WITH_HEADLESS
bbuf = NULL;
#else
- bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, "<splash>");
+ bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_prvicons_png, datatoc_prvicons_png_size, IB_rect, NULL, "<splash>");
#endif
if (bbuf) {
for (y = 0; y < SPECIAL_IMG_ROWS; y++) {
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 40f0683a852..c372973b7b0 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -169,47 +169,6 @@ struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
/* ************ panel stuff ************* */
-/* is used for both read and write... */
-
-static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- ImBuf *ibuf;
- void *lock;
- int result;
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
- result = ibuf && ibuf->rect_float;
- ED_space_image_release_buffer(sima, lock);
-
- return result;
-}
-
-static void image_panel_curves(const bContext *C, Panel *pa)
-{
- bScreen *sc = CTX_wm_screen(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- ImBuf *ibuf;
- PointerRNA simaptr;
- int levels;
- void *lock;
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
-
- if (ibuf) {
- if (sima->cumap == NULL)
- sima->cumap = curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
-
- /* curvemap black/white levels only works for RGBA */
- levels = (ibuf->channels == 4);
-
- RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr);
- uiTemplateCurveMapping(pa->layout, &simaptr, "curve", 'c', levels, 0);
- }
-
- ED_space_image_release_buffer(sima, lock);
-}
-
#if 0
/* 0: disable preview
* otherwise refresh preview
@@ -234,6 +193,7 @@ void image_preview_event(int event)
}
if (exec && G.scene->nodetree) {
+ Scene *scene = G.scene;
/* should work when no node editor in screen..., so we execute right away */
ntreeCompositTagGenerators(G.scene->nodetree);
@@ -244,7 +204,7 @@ void image_preview_event(int event)
BIF_store_spare();
- ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1); /* 1 is do_previews */
+ ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */
G.scene->nodetree->timecursor = NULL;
G.scene->nodetree->test_break = NULL;
@@ -611,6 +571,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiLayout *row, *split, *col;
uiBlock *block;
char str[128];
+
void *lock;
if (!ptr->data)
@@ -728,7 +689,11 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
uiItemL(layout, str, ICON_NONE);
}
}
-
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
+ uiItemR(col, &imaptr, "view_as_render", 0, NULL, ICON_NONE);
+
if (ima->source != IMA_SRC_GENERATED) {
if (compact == 0) { /* background image view doesnt need these */
uiItemS(layout);
@@ -794,15 +759,18 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
MEM_freeN(cb);
}
-void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr)
+void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management)
{
ImageFormatData *imf = imfptr->data;
ID *id = imfptr->id.data;
+ PointerRNA display_settings_ptr;
+ PropertyRNA *prop;
const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
/* some settings depend on this being a scene thats rendered */
const short is_render_out = (id && GS(id->name) == ID_SCE);
uiLayout *col, *row, *split, *sub;
+ int show_preview = FALSE;
col = uiLayoutColumn(layout, FALSE);
@@ -843,6 +811,7 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr)
}
if (is_render_out && (imf->imtype == R_IMF_IMTYPE_OPENEXR)) {
+ show_preview = TRUE;
uiItemR(row, imfptr, "use_preview", 0, NULL, ICON_NONE);
}
@@ -864,6 +833,22 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
#endif
}
+
+ /* color management */
+ if (color_management &&
+ (!BKE_imtype_supports_float(imf->imtype) ||
+ (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG)))
+ {
+ prop = RNA_struct_find_property(imfptr, "display_settings");
+ display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
+
+ col = uiLayoutColumn(layout, FALSE);
+ uiItemL(col, IFACE_("Color Management"), ICON_NONE);
+
+ uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
+
+ uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
+ }
}
void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
@@ -886,14 +871,6 @@ void image_buttons_register(ARegionType *art)
{
PanelType *pt;
- pt = MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
- strcpy(pt->idname, "IMAGE_PT_curves");
- strcpy(pt->label, "Curves");
- pt->draw = image_panel_curves;
- pt->poll = image_panel_poll;
- pt->flag |= PNL_DEFAULT_CLOSED;
- BLI_addtail(&art->paneltypes, pt);
-
pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
strcpy(pt->idname, "IMAGE_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index e293264c021..638a2ac6681 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -51,6 +51,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -70,6 +71,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "WM_api.h"
+#include "WM_types.h"
#include "RE_pipeline.h"
@@ -77,27 +80,6 @@
#define HEADER_HEIGHT 18
-static void image_verify_buffer_float(Image *ima, ImBuf *ibuf, int color_manage)
-{
- /* detect if we need to redo the curve map.
- * ibuf->rect is zero for compositor and render results after change
- * convert to 32 bits always... drawing float rects isn't supported well (atis)
- *
- * NOTE: if float buffer changes, we have to manually remove the rect
- */
-
- if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID)) ) {
- if (color_manage) {
- if (ima && ima->source == IMA_SRC_VIEWER)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
- }
- else
- ibuf->profile = IB_PROFILE_NONE;
-
- IMB_rect_from_float(ibuf);
- }
-}
-
static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
{
RenderResult *rr;
@@ -112,7 +94,7 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar)
}
/* used by node view too */
-void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int y,
+void ED_image_draw_info(Scene *scene, ARegion *ar, int color_manage, int use_default_view, int channels, int x, int y,
const unsigned char cp[4], const float fp[4], int *zp, float *zpf)
{
char str[256];
@@ -209,6 +191,20 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str);
}
+
+ if (color_manage && channels == 4) {
+ float pixel[4];
+
+ if (use_default_view)
+ IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, NULL, &scene->display_settings);
+ else
+ IMB_colormanagement_pixel_to_display_space_v4(pixel, fp, &scene->view_settings, &scene->display_settings);
+
+ BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", pixel[0], pixel[1], pixel[2]);
+ BLF_position(blf_mono_font, dx, 6, 0);
+ BLF_draw_ascii(blf_mono_font, str, sizeof(str));
+ dx += BLF_width(blf_mono_font, str);
+ }
}
/* color rectangle */
@@ -252,11 +248,15 @@ void ED_image_draw_info(ARegion *ar, int color_manage, int channels, int x, int
}
if (color_manage) {
- linearrgb_to_srgb_v4(finalcol, col);
+ if (use_default_view)
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
+ else
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
}
else {
copy_v4_v4(finalcol, col);
}
+
glDisable(GL_BLEND);
glColor3fv(finalcol);
dx += 5;
@@ -418,10 +418,9 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
MEM_freeN(rectf);
}
-static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
+static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
{
int x, y;
- int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
/* set zoom */
glPixelZoom(zoomx, zoomy);
@@ -445,6 +444,9 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
}
else {
+ unsigned char *display_buffer;
+ void *cache_handle;
+
if (sima->flag & SI_USE_ALPHA) {
fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
@@ -452,17 +454,17 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- /* we don't draw floats buffers directly but
- * convert them, and optionally apply curves */
- image_verify_buffer_float(ima, ibuf, color_manage);
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
- if (ibuf->rect)
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ if (display_buffer)
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
#if 0
else
glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
#endif
-
+
+ IMB_display_buffer_release(cache_handle);
+
if (sima->flag & SI_USE_ALPHA)
glDisable(GL_BLEND);
}
@@ -471,14 +473,14 @@ static void draw_image_buffer(SpaceImage *sima, ARegion *ar, Scene *scene, Image
glPixelZoom(1.0f, 1.0f);
}
-static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty, short endx, short endy)
+static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy)
{
unsigned int *rt, *rp, *rectmain;
short y, heigth, len;
/* the right offset in rectot */
- rt = ibuf->rect + (starty * ibuf->x + startx);
+ rt = buffer + (starty * width + startx);
len = (endx - startx);
heigth = (endy - starty);
@@ -487,7 +489,7 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty,
for (y = 0; y < heigth; y++) {
memcpy(rp, rt, len * 4);
- rt += ibuf->x;
+ rt += width;
rp += len;
}
return rectmain;
@@ -495,28 +497,34 @@ static unsigned int *get_part_from_ibuf(ImBuf *ibuf, short startx, short starty,
static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
{
+ unsigned char *display_buffer;
unsigned int *rect;
int dx, dy, sx, sy, x, y;
- int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
+ void *cache_handle;
/* verify valid values, just leave this a while */
if (ima->xrep < 1) return;
if (ima->yrep < 1) return;
-
+
+ if (ima->flag & IMA_VIEW_AS_RENDER)
+ display_buffer = IMB_display_buffer_acquire(ibuf, &scene->view_settings, &scene->display_settings, &cache_handle);
+ else
+ display_buffer = IMB_display_buffer_acquire(ibuf, NULL, &scene->display_settings, &cache_handle);
+
+ if (!display_buffer)
+ return;
+
glPixelZoom(zoomx, zoomy);
if (sima->curtile >= ima->xrep * ima->yrep)
sima->curtile = ima->xrep * ima->yrep - 1;
- /* create char buffer from float if needed */
- image_verify_buffer_float(ima, ibuf, color_manage);
-
/* retrieve part of image buffer */
dx = ibuf->x / ima->xrep;
dy = ibuf->y / ima->yrep;
sx = (sima->curtile % ima->xrep) * dx;
sy = (sima->curtile / ima->xrep) * dy;
- rect = get_part_from_ibuf(ibuf, sx, sy, sx + dx, sy + dy);
+ rect = get_part_from_buffer((unsigned int*)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
/* draw repeated */
for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
@@ -529,10 +537,12 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
glPixelZoom(1.0f, 1.0f);
+ IMB_display_buffer_release(cache_handle);
+
MEM_freeN(rect);
}
-static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
+static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, Image *ima, ImBuf *ibuf, float zoomx, float zoomy)
{
const double time_current = PIL_check_seconds_timer();
@@ -549,7 +559,7 @@ static void draw_image_buffer_repeated(SpaceImage *sima, ARegion *ar, Scene *sce
if (ima && (ima->tpageflag & IMA_TILES))
draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy);
else
- draw_image_buffer(sima, ar, scene, ima, ibuf, x, y, zoomx, zoomy);
+ draw_image_buffer(C, sima, ar, scene, ibuf, x, y, zoomx, zoomy);
/* only draw until running out of time */
if ((PIL_check_seconds_timer() - time_current) > 0.25)
@@ -632,22 +642,35 @@ static void draw_image_view_tool(Scene *scene)
}
#endif
-static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *height)
+static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height)
{
Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint);
ImBuf *ibuf;
unsigned int size, alpha;
+ unsigned char *display_buffer;
unsigned char *rect, *cp;
+ void *cache_handle;
if (!brush || !brush->clone.image)
return NULL;
ibuf = BKE_image_get_ibuf(brush->clone.image, NULL);
- if (!ibuf || !ibuf->rect)
+ if (!ibuf)
return NULL;
- rect = MEM_dupallocN(ibuf->rect);
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (!display_buffer) {
+ IMB_display_buffer_release(cache_handle);
+
+ return NULL;
+ }
+
+ rect = MEM_dupallocN(display_buffer);
+
+ IMB_display_buffer_release(cache_handle);
+
if (!rect)
return NULL;
@@ -666,7 +689,7 @@ static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *heigh
return rect;
}
-static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, float zoomy)
+static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
{
Brush *brush;
int x, y, w, h;
@@ -677,7 +700,7 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo
if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
/* this is not very efficient, but glDrawPixels doesn't allow
* drawing with alpha */
- clonerect = get_alpha_clone_image(scene, &w, &h);
+ clonerect = get_alpha_clone_image(C, scene, &w, &h);
if (clonerect) {
UI_view2d_to_region_no_clip(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
@@ -698,8 +721,10 @@ static void draw_image_paint_helpers(ARegion *ar, Scene *scene, float zoomx, flo
/* draw main image area */
-void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
+void draw_image_main(const bContext *C, ARegion *ar)
{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Scene *scene = CTX_data_scene(C);
Image *ima;
ImBuf *ibuf;
float zoomx, zoomy;
@@ -748,15 +773,15 @@ void draw_image_main(SpaceImage *sima, ARegion *ar, Scene *scene)
if (ibuf == NULL)
ED_region_grid_draw(ar, zoomx, zoomy);
else if (sima->flag & SI_DRAW_TILE)
- draw_image_buffer_repeated(sima, ar, scene, ima, ibuf, zoomx, zoomy);
+ draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy);
else if (ima && (ima->tpageflag & IMA_TILES))
draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy);
else
- draw_image_buffer(sima, ar, scene, ima, ibuf, 0.0f, 0.0f, zoomx, zoomy);
+ draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
/* paint helpers */
if (sima->mode == SI_MODE_PAINT)
- draw_image_paint_helpers(ar, scene, zoomx, zoomy);
+ draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
/* XXX integrate this code */
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 0d3a7614f10..f86e59c41a8 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -52,7 +52,7 @@ struct ARegion *image_has_scope_region(struct ScrArea *sa);
extern const char *image_context_dir[]; /* doc access */
/* image_draw.c */
-void draw_image_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene);
+void draw_image_main(const struct bContext *C, struct ARegion *ar);
void draw_image_grease_pencil(struct bContext *C, short onlyv2d);
void draw_image_sample_line(struct SpaceImage *sima);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 52a2bf22d4b..16804c5a1c6 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -55,6 +55,7 @@
#include "BKE_report.h"
#include "BKE_screen.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -1168,6 +1169,10 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
}
BLI_path_abs(simopts->filepath, G.main->name);
}
+
+ /* color management */
+ BKE_color_managed_display_settings_copy(&simopts->im_format.display_settings, &scene->display_settings);
+ BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings);
}
ED_space_image_release_buffer(sima, lock);
@@ -1178,6 +1183,8 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima,
static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op)
{
if (op->customdata) {
+ BKE_color_managed_view_settings_free(&simopts->im_format.view_settings);
+
simopts->im_format = *(ImageFormatData *)op->customdata;
}
@@ -1190,12 +1197,47 @@ static void save_image_options_from_op(SaveImageOptions *simopts, wmOperator *op
static void save_image_options_to_op(SaveImageOptions *simopts, wmOperator *op)
{
if (op->customdata) {
+ BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings);
+
*(ImageFormatData *)op->customdata = simopts->im_format;
}
RNA_string_set(op->ptr, "filepath", simopts->filepath);
}
+static ImBuf *save_image_colormanaged_imbuf_acquire(ImBuf *ibuf, SaveImageOptions *simopts, int save_as_render, void **cache_handle)
+{
+ ImageFormatData *imf = &simopts->im_format;
+ ImBuf *colormanaged_ibuf;
+ int do_colormanagement;
+
+ *cache_handle = NULL;
+ do_colormanagement = save_as_render && !BKE_imtype_supports_float(imf->imtype);
+
+ if (do_colormanagement) {
+ unsigned char *display_buffer;
+
+ display_buffer = IMB_display_buffer_acquire(ibuf, &imf->view_settings, &imf->display_settings, cache_handle);
+
+ if (*cache_handle) {
+ colormanaged_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
+ colormanaged_ibuf->rect = (unsigned int *) display_buffer;
+ }
+ else {
+ /* no cache handle means color management didn't run transformation
+ * or performed transformation to image's byte buffer which doesn't
+ * require allocating new image buffer
+ */
+ colormanaged_ibuf = ibuf;
+ }
+ }
+ else {
+ colormanaged_ibuf = ibuf;
+ }
+
+ return colormanaged_ibuf;
+}
+
/* assumes name is FILE_MAX */
/* ima->name and ibuf->name should end up the same */
static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, int do_newpath)
@@ -1205,9 +1247,12 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
+ void *cache_handle;
+ ImBuf *colormanaged_ibuf;
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path"));
const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy"));
+ const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render"));
short ok = FALSE;
/* old global to ensure a 2nd save goes to same dir */
@@ -1231,7 +1276,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
ibuf->planes = BKE_imbuf_alpha_test(ibuf) ? 32 : 24;
}
}
-
+
+ colormanaged_ibuf = save_image_colormanaged_imbuf_acquire(ibuf, simopts, save_as_render, &cache_handle);
+
if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
Scene *scene = CTX_data_scene(C);
RenderResult *rr = BKE_image_acquire_renderresult(scene, ima);
@@ -1245,7 +1292,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
BKE_image_release_renderresult(scene, ima);
}
else {
- if (BKE_imbuf_write_as(ibuf, simopts->filepath, &simopts->im_format, save_copy)) {
+ if (BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, &simopts->im_format, save_copy))
+ {
ok = TRUE;
}
}
@@ -1284,6 +1332,8 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
if (relative) {
BLI_path_rel(ima->name, relbase); /* only after saving */
}
+
+ IMB_colormanagment_colorspace_from_ibuf_ftype(&ima->colorspace_settings, ibuf);
}
}
else {
@@ -1294,6 +1344,13 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
WM_cursor_wait(0);
+
+ if (cache_handle) {
+ colormanaged_ibuf->rect = NULL;
+ IMB_freeImBuf(colormanaged_ibuf);
+
+ IMB_display_buffer_release(cache_handle);
+ }
}
ED_space_image_release_buffer(sima, lock);
@@ -1302,6 +1359,9 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI
static void image_save_as_free(wmOperator *op)
{
if (op->customdata) {
+ ImageFormatData *im_format = (ImageFormatData *)op->customdata;
+ BKE_color_managed_view_settings_free(&im_format->view_settings);
+
MEM_freeN(op->customdata);
op->customdata = NULL;
}
@@ -1354,6 +1414,11 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve
RNA_boolean_set(op->ptr, "copy", TRUE);
}
+ if (ima->source == IMA_SRC_VIEWER)
+ RNA_boolean_set(op->ptr, "save_as_render", TRUE);
+ else
+ RNA_boolean_set(op->ptr, "save_as_render", FALSE);
+
op->customdata = MEM_mallocN(sizeof(simopts.im_format), __func__);
memcpy(op->customdata, &simopts.im_format, sizeof(simopts.im_format));
@@ -1389,7 +1454,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
/* image template */
RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &ptr);
- uiTemplateImageSettings(layout, &ptr);
+ uiTemplateImageSettings(layout, &ptr, FALSE);
/* main draw call */
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
@@ -1417,6 +1482,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
+ RNA_def_boolean(ot->srna, "save_as_render", 0, "Save As Render", "Apply render part of display transform when saving byte image");
RNA_def_boolean(ot->srna, "copy", 0, "Copy", "Create a new image file without modifying the current image in blender");
WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_SAVE,
@@ -1601,8 +1667,10 @@ static int image_new_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
- if (!floatbuf && scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
+ if (!floatbuf) {
+ /* OCIO_TODO: perhaps we need to convert to display space, not just to sRGB */
linearrgb_to_srgb_v3_v3(color, color);
+ }
if (!alpha)
color[3] = 1.0f;
@@ -1938,14 +2006,18 @@ typedef struct ImageSampleInfo {
float *zfp;
int draw;
+ int color_manage;
+ int use_default_view;
} ImageSampleInfo;
-static void image_sample_draw(const bContext *UNUSED(C), ARegion *ar, void *arg_info)
+static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
{
ImageSampleInfo *info = arg_info;
if (info->draw) {
- /* no color management needed for images (color_manage=0) */
- ED_image_draw_info(ar, 0, info->channels, info->x, info->y, info->colp, info->colfp, info->zp, info->zfp);
+ Scene *scene = CTX_data_scene(C);
+
+ ED_image_draw_info(scene, ar, info->color_manage, info->use_default_view, info->channels,
+ info->x, info->y, info->colp, info->colfp, info->zp, info->zfp);
}
}
@@ -1975,13 +2047,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
-
- if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) {
- linearrgb_to_srgb_v3_v3(r_col, fp);
- }
- else {
- copy_v3_v3(r_col, fp);
- }
+ linearrgb_to_srgb_v3_v3(r_col, fp);
ret = TRUE;
}
else if (ibuf->rect) {
@@ -2003,7 +2069,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
ImageSampleInfo *info = op->customdata;
float fx, fy;
-
+ Scene *scene = CTX_data_scene(C);
+ CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
+
if (ibuf == NULL) {
ED_space_image_release_buffer(sima, lock);
info->draw = 0;
@@ -2016,6 +2084,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
float *fp;
unsigned char *cp;
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+ Image *image = ED_space_image(sima);
CLAMP(x, 0, ibuf->x - 1);
CLAMP(y, 0, ibuf->y - 1);
@@ -2029,7 +2098,9 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colfp = NULL;
info->zp = NULL;
info->zfp = NULL;
-
+
+ info->use_default_view = (image->flag & IMA_VIEW_AS_RENDER) ? FALSE : TRUE;
+
if (ibuf->rect) {
cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
@@ -2044,6 +2115,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[2] = (float)cp[2] / 255.0f;
info->colf[3] = (float)cp[3] / 255.0f;
info->colfp = info->colf;
+
+ info->color_manage = FALSE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -2053,6 +2126,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[2] = fp[2];
info->colf[3] = fp[3];
info->colfp = info->colf;
+
+ info->color_manage = TRUE;
}
if (ibuf->zbuf) {
@@ -2063,25 +2138,21 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->zf = ibuf->zbuf_float[y * ibuf->x + x];
info->zfp = &info->zf;
}
-
- if (sima->cumap && ibuf->channels == 4) {
+
+ if (curve_mapping && ibuf->channels == 4) {
/* we reuse this callback for set curves point operators */
if (RNA_struct_find_property(op->ptr, "point")) {
int point = RNA_enum_get(op->ptr, "point");
if (point == 1) {
- curvemapping_set_black_white(sima->cumap, NULL, info->colfp);
- if (ibuf->rect_float)
- curvemapping_do_ibuf(sima->cumap, ibuf);
+ curvemapping_set_black_white(curve_mapping, NULL, info->colfp);
}
else if (point == 0) {
- curvemapping_set_black_white(sima->cumap, info->colfp, NULL);
- if (ibuf->rect_float)
- curvemapping_do_ibuf(sima->cumap, ibuf);
+ curvemapping_set_black_white(curve_mapping, info->colfp, NULL);
}
}
}
-
+
// XXX node curve integration ..
#if 0
{
@@ -2211,7 +2282,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
hist->co[1][0] = x2f;
hist->co[1][1] = y2f;
- BKE_histogram_update_sample_line(hist, ibuf, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0);
+ BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
/* reset y zoom */
hist->ymax = 1.0f;
@@ -2306,7 +2377,8 @@ static int image_record_composite_apply(bContext *C, wmOperator *op)
BKE_image_all_free_anim_ibufs(scene->r.cfra);
ntreeCompositTagAnimated(scene->nodetree);
- ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra); /* 1 is no previews */
+ ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra,
+ &scene->view_settings, &scene->display_settings); /* 1 is no previews */
ED_area_tag_redraw(CTX_wm_area(C));
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 91a0cba2555..5b288bd6149 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -195,9 +195,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
static void image_free(SpaceLink *sl)
{
SpaceImage *simage = (SpaceImage *) sl;
-
- if (simage->cumap)
- curvemapping_free(simage->cumap);
+
scopes_free(&simage->scopes);
}
@@ -217,8 +215,6 @@ static SpaceLink *image_duplicate(SpaceLink *sl)
SpaceImage *simagen = MEM_dupallocN(sl);
/* clear or remove stuff from old */
- if (simagen->cumap)
- simagen->cumap = curvemapping_copy(simagen->cumap);
scopes_new(&simagen->scopes);
@@ -443,6 +439,7 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn)
break;
case ND_MODE:
case ND_RENDER_RESULT:
+ case ND_RENDER_OPTIONS:
case ND_COMPO_RESULT:
if (ED_space_image_show_render(sima))
image_scopes_tag_refresh(sa);
@@ -652,7 +649,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar)
image_main_area_set_view2d(sima, ar);
/* we draw image in pixelspace */
- draw_image_main(sima, ar, scene);
+ draw_image_main(C, ar);
/* and uvs in 0.0-1.0 space */
UI_view2d_view_ortho(v2d);
@@ -776,9 +773,9 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar)
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
if (!sima->scopes.ok) {
- BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+ BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings);
}
- scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+ scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
}
ED_space_image_release_buffer(sima, lock);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 4c46f5c4c62..1f266c98020 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -63,6 +63,7 @@
#include "UI_resources.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -2023,7 +2024,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
node_composit_buts_file_output(layout, C, ptr);
- uiTemplateImageSettings(layout, &imfptr);
+ uiTemplateImageSettings(layout, &imfptr, TRUE);
uiItemS(layout);
@@ -2082,7 +2083,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
col = uiLayoutColumn(layout, FALSE);
uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE);
- uiTemplateImageSettings(col, &imfptr);
+ uiTemplateImageSettings(col, &imfptr, TRUE);
}
}
}
@@ -3051,7 +3052,7 @@ void ED_node_init_butfuncs(void)
/* ************** Generic drawing ************** */
-void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
+void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
{
if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) {
@@ -3059,7 +3060,10 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
+ SpaceNode *snode = CTX_wm_space_node(C);
float x, y;
+ unsigned char *display_buffer;
+ void *cache_handle;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@@ -3078,15 +3082,10 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
- if (!ibuf->rect) {
- if (color_manage)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
- else
- ibuf->profile = IB_PROFILE_NONE;
- IMB_rect_from_float(ibuf);
- }
- if (ibuf->rect) {
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (display_buffer) {
if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) {
int ofs;
@@ -3114,7 +3113,7 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
#ifdef __BIG_ENDIAN__
glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
#endif
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, ibuf->rect);
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer);
#ifdef __BIG_ENDIAN__
glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
@@ -3126,7 +3125,7 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelZoom(snode->zoom, snode->zoom);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
@@ -3134,12 +3133,14 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
else {
glPixelZoom(snode->zoom, snode->zoom);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
glPixelZoom(1.0f, 1.0f);
}
}
+ IMB_display_buffer_release(cache_handle);
+
/** @note draw selected info on backdrop */
if (snode->edittree) {
bNode *node = snode->edittree->nodes.first;
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index f1a91df6f53..7d35f566140 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -1091,8 +1091,6 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
{
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
- Scene *scene = CTX_data_scene(C);
- int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
bNodeLinkDrag *nldrag;
LinkData *linkdata;
@@ -1118,7 +1116,7 @@ void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
UI_view2d_multi_grid_draw(v2d, 25.0f, 5, 2);
/* backdrop */
- draw_nodespace_back_pix(ar, snode, color_manage);
+ draw_nodespace_back_pix(C, ar, snode);
/* nodes */
snode_set_context(snode, CTX_data_scene(C));
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 9e04bd36a1f..cc386da2e93 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -148,8 +148,9 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
{
CompoJob *cj = cjv;
bNodeTree *ntree = cj->localtree;
+ Scene *scene = cj->scene;
- if (cj->scene->use_nodes == FALSE)
+ if (scene->use_nodes == FALSE)
return;
cj->stop = stop;
@@ -165,7 +166,7 @@ static void compo_startjob(void *cjv, short *stop, short *do_update, float *prog
// XXX BIF_store_spare();
- ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1); /* 1 is do_previews */
+ ntreeCompositExecTree(ntree, &cj->scene->r, 0, 1, &scene->view_settings, &scene->display_settings); /* 1 is do_previews */
ntree->test_break = NULL;
ntree->stats_draw = NULL;
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index 2bb550d1a63..36ebddc8d22 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -125,7 +125,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link);
void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3);
int node_link_bezier_points(View2D * v2d, SpaceNode * snode, bNodeLink * link, float coord_array[][2], int resol);
// void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 );
-void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage);
+void draw_nodespace_back_pix(const struct bContext *C, ARegion *ar, SpaceNode *snode);
/* node_add.c */
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index e89e798a6fa..8e38247348f 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -327,12 +327,12 @@ typedef struct ImageSampleInfo {
void *draw_handle;
int x, y;
int channels;
- int color_manage;
unsigned char col[4];
float colf[4];
int draw;
+ int color_manage;
} ImageSampleInfo;
static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
@@ -341,7 +341,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
ImageSampleInfo *info = arg_info;
if (info->draw) {
- ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
+ ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
info->x, info->y, info->col, info->colf,
NULL, NULL /* zbuf - unused for nodes */
);
@@ -381,12 +381,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
/* IB_PROFILE_NONE is default but infact its linear */
- if (ELEM(ibuf->profile, IB_PROFILE_LINEAR_RGB, IB_PROFILE_NONE)) {
- linearrgb_to_srgb_v3_v3(r_col, fp);
- }
- else {
- copy_v3_v3(r_col, fp);
- }
+ linearrgb_to_srgb_v3_v3(r_col, fp);
ret = TRUE;
}
else if (ibuf->rect) {
@@ -419,10 +414,6 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
}
if (!ibuf->rect) {
- if (info->color_manage)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
- else
- ibuf->profile = IB_PROFILE_NONE;
IMB_rect_from_float(ibuf);
}
@@ -457,6 +448,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[1] = (float)cp[1] / 255.0f;
info->colf[2] = (float)cp[2] / 255.0f;
info->colf[3] = (float)cp[3] / 255.0f;
+
+ info->color_manage = FALSE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -465,6 +458,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[1] = fp[1];
info->colf[2] = fp[2];
info->colf[3] = fp[3];
+
+ info->color_manage = TRUE;
}
ED_node_sample_set(info->colf);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 0c316450c29..7363bf2fbd8 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -52,6 +52,7 @@
#include "BKE_sound.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "BIF_gl.h"
@@ -68,6 +69,9 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
/* own include */
#include "sequencer_intern.h"
@@ -846,6 +850,50 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
return ibuf;
}
+static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf)
+{
+ if (scopes->reference_ibuf != ibuf) {
+ if (scopes->zebra_ibuf) {
+ IMB_freeImBuf(scopes->zebra_ibuf);
+ scopes->zebra_ibuf = NULL;
+ }
+
+ if (scopes->waveform_ibuf) {
+ IMB_freeImBuf(scopes->waveform_ibuf);
+ scopes->waveform_ibuf = NULL;
+ }
+
+ if (scopes->sep_waveform_ibuf) {
+ IMB_freeImBuf(scopes->sep_waveform_ibuf);
+ scopes->sep_waveform_ibuf = NULL;
+ }
+
+ if (scopes->vector_ibuf) {
+ IMB_freeImBuf(scopes->vector_ibuf);
+ scopes->vector_ibuf = NULL;
+ }
+
+ if (scopes->histogram_ibuf) {
+ IMB_freeImBuf(scopes->histogram_ibuf);
+ scopes->histogram_ibuf = NULL;
+ }
+ }
+}
+
+static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_cb) (ImBuf *ibuf))
+{
+ ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
+ ImBuf *scope;
+
+ IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings);
+
+ scope = make_scope_cb(display_ibuf);
+
+ IMB_freeImBuf(display_ibuf);
+
+ return scope;
+}
+
void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, int draw_overlay)
{
struct Main *bmain = CTX_data_main(C);
@@ -859,6 +907,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
float col[3];
GLuint texid;
GLuint last_texid;
+ unsigned char *display_buffer;
+ void *cache_handle = NULL;
render_size = sseq->render_size;
if (render_size == 0) {
@@ -906,38 +956,64 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (ibuf->rect == NULL && ibuf->rect_float == NULL)
return;
-
- switch (sseq->mainb) {
- case SEQ_DRAW_IMG_IMBUF:
- if (sseq->zebra != 0) {
- scope = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
- }
- break;
- case SEQ_DRAW_IMG_WAVEFORM:
- if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
- scope = make_sep_waveform_view_from_ibuf(ibuf);
- }
- else {
- scope = make_waveform_view_from_ibuf(ibuf);
- }
- break;
- case SEQ_DRAW_IMG_VECTORSCOPE:
- scope = make_vectorscope_view_from_ibuf(ibuf);
- break;
- case SEQ_DRAW_IMG_HISTOGRAM:
- scope = make_histogram_view_from_ibuf(ibuf);
- break;
+
+ if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) {
+ SequencerScopes *scopes = &sseq->scopes;
+
+ sequencer_check_scopes(scopes, ibuf);
+
+ switch (sseq->mainb) {
+ case SEQ_DRAW_IMG_IMBUF:
+ if (!scopes->zebra_ibuf) {
+ ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
+
+ IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings);
+ scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
+ IMB_freeImBuf(display_ibuf);
+ }
+ scope = scopes->zebra_ibuf;
+ break;
+ case SEQ_DRAW_IMG_WAVEFORM:
+ if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
+ if (!scopes->sep_waveform_ibuf)
+ scopes->sep_waveform_ibuf = sequencer_make_scope(scene, ibuf, make_sep_waveform_view_from_ibuf);
+ scope = scopes->sep_waveform_ibuf;
+ }
+ else {
+ if (!scopes->waveform_ibuf)
+ scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
+ scope = scopes->waveform_ibuf;
+ }
+ break;
+ case SEQ_DRAW_IMG_VECTORSCOPE:
+ if (!scopes->vector_ibuf)
+ scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
+ scope = scopes->vector_ibuf;
+ break;
+ case SEQ_DRAW_IMG_HISTOGRAM:
+ if (!scopes->histogram_ibuf)
+ scopes->histogram_ibuf = sequencer_make_scope(scene, ibuf, make_histogram_view_from_ibuf);
+ scope = scopes->histogram_ibuf;
+ break;
+ }
+
+ scopes->reference_ibuf = ibuf;
}
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
- }
- if (ibuf->rect_float && ibuf->rect == NULL) {
- IMB_rect_from_float(ibuf);
+ if (ibuf->rect_float && ibuf->rect == NULL) {
+ IMB_rect_from_float(ibuf);
+ }
+
+ display_buffer = (unsigned char *)ibuf->rect;
}
-
+ else {
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ }
+
/* setting up the view - actual drawing starts here */
UI_view2d_view_ortho(v2d);
@@ -950,7 +1026,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
glBegin(GL_QUADS);
if (draw_overlay) {
@@ -1030,7 +1106,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
/* draw grease-pencil (image aligned) */
draw_gpencil_2dimage(C);
- IMB_freeImBuf(ibuf);
+ if (!scope)
+ IMB_freeImBuf(ibuf);
/* ortho at pixel level */
UI_view2d_view_restore(C);
@@ -1065,6 +1142,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
+ if (cache_handle)
+ IMB_display_buffer_release(cache_handle);
}
#if 0
diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c
index 1655b3ec7bc..d09d6a29c10 100644
--- a/source/blender/editors/space_sequencer/sequencer_scopes.c
+++ b/source/blender/editors/space_sequencer/sequencer_scopes.c
@@ -460,12 +460,28 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
memset(bins, 0, sizeof(bins));
+ #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256)
for (y = 0; y < ibuf->y; y++) {
+ unsigned int cur_bins[3][512];
+
+ memset(cur_bins, 0, sizeof(cur_bins));
+
for (x = 0; x < ibuf->x; x++) {
- bins[0][*src++]++;
- bins[1][*src++]++;
- bins[2][*src++]++;
- src++;
+ unsigned char *pixel = src + (y * ibuf->x + x) * 4;
+
+ cur_bins[0][pixel[0]]++;
+ cur_bins[1][pixel[1]]++;
+ cur_bins[2][pixel[2]]++;
+ }
+
+ #pragma omp critical
+ {
+ int i;
+ for (i = 0; i < 512; i++) {
+ bins[0][i] += cur_bins[0][i];
+ bins[1][i] += cur_bins[1][i];
+ bins[2][i] += cur_bins[2][i];
+ }
}
}
@@ -490,7 +506,7 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf)
return rval;
}
-static int get_bin_float(float f)
+BLI_INLINE int get_bin_float(float f)
{
if (f < -0.25f) {
return 0;
@@ -512,12 +528,28 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf)
memset(bins, 0, sizeof(bins));
+ #pragma omp parallel for shared(bins, src, ibuf) private(x, y) if (ibuf->y >= 256)
for (y = 0; y < ibuf->y; y++) {
+ unsigned int cur_bins[3][512];
+
+ memset(cur_bins, 0, sizeof(cur_bins));
+
for (x = 0; x < ibuf->x; x++) {
- bins[0][get_bin_float(*src++)]++;
- bins[1][get_bin_float(*src++)]++;
- bins[2][get_bin_float(*src++)]++;
- src++;
+ float *pixel = src + (y * ibuf->x + x) * 4;
+
+ cur_bins[0][get_bin_float(pixel[0])]++;
+ cur_bins[1][get_bin_float(pixel[1])]++;
+ cur_bins[2][get_bin_float(pixel[2])]++;
+ }
+
+ #pragma omp critical
+ {
+ int i;
+ for (i = 0; i < 512; i++) {
+ bins[0][i] += cur_bins[0][i];
+ bins[1][i] += cur_bins[1][i];
+ bins[2][i] += cur_bins[2][i];
+ }
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index f5a13e4efb7..3c3489115a4 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -49,6 +49,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "UI_view2d.h"
@@ -70,6 +71,7 @@ typedef struct ImageSampleInfo {
float *colfp;
int draw;
+int color_manage;
} ImageSampleInfo;
static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
@@ -78,8 +80,8 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info)
ImageSampleInfo *info = arg_info;
if (info->draw) {
- ED_image_draw_info(ar, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT), info->channels,
- info->x, info->y, info->col, info->colf, NULL, NULL);
+ ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels,
+ info->x, info->y, info->colp, info->colfp, NULL, NULL);
}
}
@@ -131,6 +133,8 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[2] = (float)cp[2] / 255.0f;
info->colf[3] = (float)cp[3] / 255.0f;
info->colfp = info->colf;
+
+ info->color_manage = FALSE;
}
if (ibuf->rect_float) {
fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -140,6 +144,11 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event)
info->colf[2] = fp[2];
info->colf[3] = fp[3];
info->colfp = info->colf;
+
+ /* sequencer's image buffers are in non-linear space, need to make them linear */
+ BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf);
+
+ info->color_manage = TRUE;
}
}
else {
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index f7362aab7aa..8ac50a57b10 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -57,8 +57,19 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "IMB_imbuf.h"
+
#include "sequencer_intern.h" // own include
+/**************************** common state *****************************/
+
+static void sequencer_scopes_tag_refresh(ScrArea *sa)
+{
+ SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
+
+ sseq->scopes.reference_ibuf = NULL;
+}
+
/* ******************** manage regions ********************* */
ARegion *sequencer_has_buttons_region(ScrArea *sa)
@@ -183,12 +194,27 @@ static SpaceLink *sequencer_new(const bContext *C)
}
/* not spacelink itself */
-static void sequencer_free(SpaceLink *UNUSED(sl))
+static void sequencer_free(SpaceLink *sl)
{
-// SpaceSeq *sseq= (SpaceSequencer*) sl;
-
+ SpaceSeq *sseq= (SpaceSeq *) sl;
+ SequencerScopes *scopes = &sseq->scopes;
+
// XXX if (sseq->gpd) BKE_gpencil_free(sseq->gpd);
+ if (scopes->zebra_ibuf)
+ IMB_freeImBuf(scopes->zebra_ibuf);
+
+ if (scopes->waveform_ibuf)
+ IMB_freeImBuf(scopes->waveform_ibuf);
+
+ if (scopes->sep_waveform_ibuf)
+ IMB_freeImBuf(scopes->sep_waveform_ibuf);
+
+ if (scopes->vector_ibuf)
+ IMB_freeImBuf(scopes->vector_ibuf);
+
+ if (scopes->histogram_ibuf)
+ IMB_freeImBuf(scopes->histogram_ibuf);
}
@@ -290,7 +316,24 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl)
return (SpaceLink *)sseqn;
}
-
+static void sequencer_listener(ScrArea *sa, wmNotifier *wmn)
+{
+ /* context changes */
+ switch (wmn->category) {
+ case NC_SCENE:
+ switch (wmn->data) {
+ case ND_FRAME:
+ case ND_SEQUENCER:
+ sequencer_scopes_tag_refresh(sa);
+ break;
+ }
+ break;
+ case NC_SPACE:
+ if (wmn->data == ND_SPACE_SEQUENCER)
+ sequencer_scopes_tag_refresh(sa);
+ break;
+ }
+}
/* *********************** sequencer (main) region ************************ */
/* add handlers, stuff you only do once or on area/region changes */
@@ -610,6 +653,7 @@ void ED_spacetype_sequencer(void)
st->context = sequencer_context;
st->dropboxes = sequencer_dropboxes;
st->refresh = sequencer_refresh;
+ st->listener = sequencer_listener;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 895b256ab84..ca4f00be2d5 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -372,7 +372,15 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O
Gtexdraw.ob = ob;
Gtexdraw.is_tex = is_tex;
- Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
+
+ /* OCIO_TODO: for now assume OpenGL is always doing color management and working in sRGB space
+ * supporting for real display conversion could be nice here, but it's a bit challenging
+ * since all the shaders should be aware of such a transform
+ * perhaps this flag could be completely removed before release in separated commit and
+ * be re-implemented if real display transform would be needed
+ */
+ Gtexdraw.color_profile = TRUE;
+
memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
glShadeModel(GL_SMOOTH);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 8a334423ab0..5fbf1971349 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -69,6 +69,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -2375,7 +2376,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
- ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE);
+ ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE, FALSE);
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
v3d->drawtype = drawtype;
@@ -2514,7 +2515,7 @@ static void view3d_main_area_setup_view(Scene *scene, View3D *v3d, ARegion *ar,
void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
int winx, int winy, float viewmat[][4], float winmat[][4],
- int do_bgpic)
+ int do_bgpic, int colormanage_background)
{
RegionView3D *rv3d = ar->regiondata;
Base *base;
@@ -2553,10 +2554,25 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
/* set background color, fallback on the view background color
* (if active clip is set but frame is failed to load fallback to horizon color as background) */
if (scene->world) {
- if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
+ /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not
+ * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc)
+ * but due to compatibility issues background is being affected display transform, so we can
+ * emulate behavior of disabled colro management
+ * but this function is also used for sequencer's scene strips which shouldn't be affected by
+ * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background
+ * we can drop this flag in cost of some compatibility loss -- background wouldn't be
+ * color managed in 3d viewport
+ * same goes to opengl rendering, where color profile should be applied as very final step
+ */
+
+ if (colormanage_background) {
+ IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+ }
+ else {
linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
- else
- copy_v3_v3(backcol, &scene->world->horr);
+ }
+
glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
}
else {
@@ -2661,7 +2677,8 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
/* utility func for ED_view3d_draw_offscreen */
ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
- int sizex, int sizey, unsigned int flag, int draw_background, char err_out[256])
+ int sizex, int sizey, unsigned int flag, int draw_background,
+ int colormanage_background, char err_out[256])
{
RegionView3D *rv3d = ar->regiondata;
ImBuf *ibuf;
@@ -2686,10 +2703,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, colormanage_background);
}
else {
- ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background);
+ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, colormanage_background);
}
/* read in pixels & stamp */
@@ -2714,7 +2731,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar,
/* creates own 3d views, used by the sequencer */
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height,
- unsigned int flag, int drawtype, int draw_background, char err_out[256])
+ unsigned int flag, int drawtype, int draw_background,
+ int colormanage_background, char err_out[256])
{
View3D v3d = {NULL};
ARegion ar = {NULL};
@@ -2753,7 +2771,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w
mult_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat);
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
- return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, draw_background, err_out);
+ return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag,
+ draw_background, colormanage_background, err_out);
// seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty);
}
@@ -2936,10 +2955,9 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const
/* clear background */
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) && scene->world) {
- if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
- linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr);
- else
- copy_v3_v3(backcol, &scene->world->horr);
+ IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings,
+ &scene->display_settings);
+
glClearColor(backcol[0], backcol[1], backcol[2], 0.0);
}
else
@@ -3163,6 +3181,17 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar)
const char *grid_unit = NULL;
int draw_border = (rv3d->persp == RV3D_CAMOB && (scene->r.mode & R_BORDER));
+ /* --- until we get a clue and make viewport threadsafe (temp mango change for stability) */
+ if (G.is_rendering) {
+ ED_region_pixelspace(ar);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ UI_ThemeClearColor(TH_BACK);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ BLF_draw_default(10,10,0, "do do da da.. da da.. da da.. can't touch this! it's render time", 512);
+ return;
+ }
+ /* --- end temp mango change */
+
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) {
view3d_main_area_draw_objects(C, ar, &grid_unit);
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index ab3ab0a133e..9b027f7906d 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -492,7 +492,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
}
/* TODO unneeded when float images are correctly treated as linear always */
- if (!ncd && ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ if (!ncd)
do_color_management = TRUE;
if (ibuf->rect==NULL)
@@ -535,7 +535,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
- ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0,
+ ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
@@ -560,7 +560,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
if (do_color_management) {
frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
- ibuf->channels, IB_PROFILE_SRGB, ibuf->profile, 0,
+ ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
@@ -901,7 +901,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap)
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
/* if color correction is needed, we must update the part that needs updating. */
- if (ibuf->rect_float && (!U.use_16bit_textures || (ibuf->profile == IB_PROFILE_LINEAR_RGB))) {
+ if (ibuf->rect_float) {
float *buffer = MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf");
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h);
@@ -1197,7 +1197,12 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GPUMaterial *gpumat;
GPUBlendMode alphablend;
int a;
- int gamma = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
+
+ /* OCIO_TODO: assume color management is always enabled. could be nice to support real display transform here,
+ * but that's not so important and could be done later
+ */
+ int gamma = TRUE;
+
int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
/* initialize state */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 61be4057843..dd92b561235 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -389,8 +389,12 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
int GPU_material_do_color_management(GPUMaterial *mat)
{
- return ((mat->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) &&
- !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT)));
+ /* OCIO_TODO: for now assume scene always does color management. probably could be
+ * improved in the future to support real display transform
+ * also probably we'll need to get rid ofgame engine's color management flag
+ */
+
+ return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT));
}
static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist)
diff --git a/source/blender/imbuf/CMakeLists.txt b/source/blender/imbuf/CMakeLists.txt
index aa4454562b4..8849265679a 100644
--- a/source/blender/imbuf/CMakeLists.txt
+++ b/source/blender/imbuf/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenlib
../blenloader
../makesdna
+ ../makesrna
../../../intern/guardedalloc
../../../intern/memutil
)
@@ -45,6 +46,7 @@ set(SRC
intern/anim_movie.c
intern/bmp.c
intern/cache.c
+ intern/colormanagement.c
intern/divers.c
intern/filetype.c
intern/filter.c
@@ -67,6 +69,7 @@ set(SRC
intern/util.c
intern/writeimage.c
+ IMB_colormanagement.h
IMB_imbuf.h
IMB_imbuf_types.h
IMB_moviecache.h
@@ -180,6 +183,10 @@ if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+list(APPEND INC
+ ../../../intern/opencolorio
+)
+
if(WIN32)
list(APPEND INC
../../../intern/utfconv
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
new file mode 100644
index 00000000000..d09007985b0
--- /dev/null
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -0,0 +1,155 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Xavier Thomas,
+ * Lukas Toenne,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef IMB_COLORMANAGEMENT_H
+#define IMB_COLORMANAGEMENT_H
+
+#define BCM_CONFIG_FILE "config.ocio"
+
+struct bContext;
+struct ColorManagedColorspaceSettings;
+struct ColorManagedDisplaySettings;
+struct ColorManagedViewSettings;
+struct ColormanageProcessor;
+struct EnumPropertyItem;
+struct ImBuf;
+struct Main;
+struct rcti;
+struct PartialBufferUpdateContext;
+struct wmWindow;
+struct Scene;
+
+struct ColorSpace;
+struct ColorManagedDisplay;
+
+/* ** Initialization / De-initialization ** */
+
+void IMB_colormanagement_init(void);
+void IMB_colormanagement_exit(void);
+
+/* ** Generic functions ** */
+
+void IMB_colormanagement_check_file_config(struct Main *bmain);
+
+void IMB_colormanagement_validate_settings(struct ColorManagedDisplaySettings *display_settings,
+ struct ColorManagedViewSettings *view_settings);
+
+const char *IMB_colormanagement_role_colorspace_name_get(int role);
+
+/* ** Color space transformation functions ** */
+void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace, int predivide);
+void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace, int predivide);
+void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace);
+
+void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace);
+void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace);
+
+void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide);
+
+void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display);
+void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display);
+
+void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4], const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+
+void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3], const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+
+void IMB_colormanagement_imbuf_assign_float_space(struct ImBuf *ibuf, struct ColorManagedColorspaceSettings *colorspace_settings);
+
+void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+
+/* ** Public display buffers interfaces ** */
+
+unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings, void **cache_handle);
+unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct ImBuf *ibuf, void **cache_handle);
+
+void IMB_display_buffer_to_imbuf_rect(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+
+void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height,
+ int channels, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings, int predivide);
+
+void IMB_display_buffer_release(void *cache_handle);
+
+/* ** Display funcrions ** */
+int IMB_colormanagement_display_get_named_index(const char *name);
+const char *IMB_colormanagement_display_get_indexed_name(int index);
+const char *IMB_colormanagement_display_get_default_name(void);
+struct ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name);
+
+/* ** View funcrions ** */
+int IMB_colormanagement_view_get_named_index(const char *name);
+const char *IMB_colormanagement_view_get_indexed_name(int index);
+
+/* ** Color space functions ** */
+int IMB_colormanagement_colorspace_get_named_index(const char *name);
+const char *IMB_colormanagement_colorspace_get_indexed_name(int index);
+const char *IMB_colormanagement_view_get_default_name(const char *display_name);
+
+void IMB_colormanagment_colorspace_from_ibuf_ftype(struct ColorManagedColorspaceSettings *colorspace_settings, struct ImBuf *ibuf);
+
+/* ** RNA helper functions ** */
+void IMB_colormanagement_display_items_add(struct EnumPropertyItem **items, int *totitem);
+void IMB_colormanagement_view_items_add(struct EnumPropertyItem **items, int *totitem, const char *display_name);
+void IMB_colormanagement_colorspace_items_add(struct EnumPropertyItem **items, int *totitem);
+
+/* ** Tile-based buffer management ** */
+void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_buffer, const unsigned char *buffer_byte,
+ int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings,
+ int xmin, int ymin, int xmax, int ymax);
+
+/* ** Pixel processor functions ** */
+struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
+struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]);
+void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]);
+void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
+ int channels, int predivide);
+void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor);
+
+/* Roles */
+enum {
+ COLOR_ROLE_SCENE_LINEAR = 0,
+ COLOR_ROLE_COLOR_PICKING,
+ COLOR_ROLE_TEXTURE_PAINTING,
+ COLOR_ROLE_DEFAULT_SEQUENCER,
+ COLOR_ROLE_DEFAULT_BYTE,
+ COLOR_ROLE_DEFAULT_FLOAT,
+};
+
+#endif /* IMB_COLORMANAGEMENT_H */
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index d23d42ddd0c..1503b9f6f67 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -70,6 +70,8 @@
#ifndef __IMB_IMBUF_H__
#define __IMB_IMBUF_H__
+#define IM_MAX_SPACE 64
+
/**
*
* \attention defined in ???
@@ -82,6 +84,8 @@ struct ImBuf;
*/
struct anim;
+struct ColorManagedDisplay;
+
/**
*
* \attention Defined in allocimbuf.c
@@ -93,20 +97,19 @@ void IMB_exit(void);
*
* \attention Defined in readimage.c
*/
-struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size,
- int flags, const char *descr);
+struct ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
/**
*
* \attention Defined in readimage.c
*/
-struct ImBuf *IMB_testiffname(const char *filepath, int flags);
+struct ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]);
/**
*
* \attention Defined in readimage.c
*/
-struct ImBuf *IMB_loadiffname(const char *filepath, int flags);
+struct ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE]);
/**
*
@@ -245,7 +248,7 @@ int IMB_anim_get_fps(struct anim * anim,
*
* \attention Defined in anim_movie.c
*/
-struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex);
+struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE]);
void IMB_close_anim(struct anim *anim);
void IMB_close_anim_proxies(struct anim *anim);
@@ -372,7 +375,6 @@ void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y
void IMB_float_from_rect(struct ImBuf *ibuf);
void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
/* note, check that the conversion exists, only some are supported */
-void IMB_convert_profile(struct ImBuf *ibuf, int profile);
float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
void IMB_color_to_bw(struct ImBuf *ibuf);
void IMB_saturation(struct ImBuf *ibuf, float sat);
@@ -417,7 +419,7 @@ void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char *col, flo
*
* \attention defined in readimage.c
*/
-struct ImBuf *IMB_loadifffile(int file, int flags, const char *descr);
+struct ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr);
/**
*
@@ -478,12 +480,12 @@ void IMB_freezbuffloatImBuf(struct ImBuf *ibuf);
* \attention Defined in rectop.c
*/
void IMB_rectfill(struct ImBuf *drect, const float col[4]);
-void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2);
+void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display);
void IMB_rectfill_alpha(struct ImBuf *ibuf, const float value);
/* this should not be here, really, we needed it for operating on render data, IMB_rectfill_area calls it */
void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
- const float col[4], const int do_color_management,
+ const float col[4], struct ColorManagedDisplay *display,
int x1, int y1, int x2, int y2);
/* defined in metadata.c */
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index be93d51d7d7..93e213dc486 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -101,7 +101,6 @@ typedef struct ImBuf {
/* parameters used by conversion between byte and float */
float dither; /* random dither value, for conversion from float -> byte rect */
- short profile; /* color space/profile preset that the byte rect buffer represents */
/* mipmapping */
struct ImBuf *mipmap[IB_MIPMAP_LEVELS]; /* MipMap levels, a series of halved images */
@@ -127,6 +126,12 @@ typedef struct ImBuf {
unsigned int encodedsize; /* Size of data written to encodedbuffer */
unsigned int encodedbuffersize; /* Size of encodedbuffer */
+ /* color management */
+ struct ColorSpace *rect_colorspace; /* color space of byte buffer */
+ struct ColorSpace *float_colorspace; /* color space of float buffer, used by sequencer only */
+ unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
+ struct ColormanageCache *colormanage_cache; /* cache used by color management */
+
/* information for compressed textures */
struct DDSData dds_data;
} ImBuf;
@@ -136,10 +141,11 @@ typedef struct ImBuf {
* \brief userflags: Flags used internally by blender for imagebuffers
*/
-#define IB_BITMAPFONT (1 << 0) /* this image is a font */
-#define IB_BITMAPDIRTY (1 << 1) /* image needs to be saved is not the same as filename */
-#define IB_MIPMAP_INVALID (1 << 2) /* image mipmaps are invalid, need recreate */
-#define IB_RECT_INVALID (1 << 3) /* float buffer changed, needs recreation of byte rect */
+#define IB_BITMAPFONT (1 << 0) /* this image is a font */
+#define IB_BITMAPDIRTY (1 << 1) /* image needs to be saved is not the same as filename */
+#define IB_MIPMAP_INVALID (1 << 2) /* image mipmaps are invalid, need recreate */
+#define IB_RECT_INVALID (1 << 3) /* float buffer changed, needs recreation of byte rect */
+#define IB_DISPLAY_BUFFER_INVALID (1 << 4) /* either float or byte buffer changed, need to re-calculate display buffers */
/**
* \name Imbuf Component flags
diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript
index a1030112f4b..976108cd84e 100644
--- a/source/blender/imbuf/SConscript
+++ b/source/blender/imbuf/SConscript
@@ -4,9 +4,9 @@ Import ('env')
sources = env.Glob('intern/*.c')
-incs = '. ../makesdna #/intern/guardedalloc #/intern/memutil ../blenlib'
+incs = '. ../makesdna ../makesrna #/intern/guardedalloc #/intern/memutil ../blenlib'
incs += ' ../avi ../blenkernel ../blenloader'
-incs += ' #/intern/ffmpeg'
+incs += ' #/intern/ffmpeg #intern/opencolorio'
incs += ' ' + env['BF_JPEG_INC']
incs += ' ' + env['BF_PNG_INC']
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 571c54b9cb3..d5cc4929aed 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -191,6 +191,7 @@ struct anim {
struct anim *proxy_anim[IMB_PROXY_MAX_SLOT];
struct anim_index *curr_idx[IMB_TC_MAX_SLOT];
+ char colorspace[64];
};
#endif
diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
new file mode 100644
index 00000000000..0c002b78848
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -0,0 +1,92 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Xavier Thomas,
+ * Lukas Toenne,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef IMB_COLORMANAGEMENT_INTERN_H
+#define IMB_COLORMANAGEMENT_INTERN_H
+
+#include "DNA_listBase.h"
+
+#define BCM_CONFIG_FILE "config.ocio"
+
+struct ConstProcessorRcPtr;
+struct ImBuf;
+
+typedef struct ColorSpace {
+ struct ColorSpace *next, *prev;
+ int index;
+ char name[64];
+ char description[64];
+
+ struct ConstProcessorRcPtr *to_scene_linear;
+ struct ConstProcessorRcPtr *from_scene_linear;
+
+ int is_invertible;
+} ColorSpace;
+
+typedef struct ColorManagedDisplay {
+ struct ColorManagedDisplay *next, *prev;
+ int index;
+ char name[64];
+ ListBase views;
+
+ struct ConstProcessorRcPtr *to_scene_linear;
+ struct ConstProcessorRcPtr *from_scene_linear;
+} ColorManagedDisplay;
+
+typedef struct ColorManagedView {
+ struct ColorManagedView *next, *prev;
+ int index;
+ char name[64];
+} ColorManagedView;
+
+void colormanage_cache_free(struct ImBuf *ibuf);
+
+struct ColorManagedDisplay *colormanage_display_get_default(void);
+struct ColorManagedDisplay *colormanage_display_add(const char *name);
+struct ColorManagedDisplay *colormanage_display_get_named(const char *name);
+struct ColorManagedDisplay *colormanage_display_get_indexed(int index);
+
+const char *colormanage_view_get_default_name(const ColorManagedDisplay *display);
+struct ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display);
+struct ColorManagedView *colormanage_view_add(const char *name);
+struct ColorManagedView *colormanage_view_get_indexed(int index);
+struct ColorManagedView *colormanage_view_get_named(const char *name);
+
+struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible);
+struct ColorSpace *colormanage_colorspace_get_named(const char *name);
+struct ColorSpace *colormanage_colorspace_get_roled(int role);
+struct ColorSpace *colormanage_colorspace_get_indexed(int index);
+
+void colorspace_set_default_role(char *colorspace, int size, int role);
+
+void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf);
+void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace);
+
+#endif /* IMB_COLORMANAGEMENT_INTERN_H */
diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h
index 74d0a92f26b..56a03121409 100644
--- a/source/blender/imbuf/intern/IMB_filetype.h
+++ b/source/blender/imbuf/intern/IMB_filetype.h
@@ -40,12 +40,13 @@ typedef struct ImFileType {
int (*is_a)(unsigned char *buf);
int (*ftype)(struct ImFileType *type, struct ImBuf *ibuf);
- struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags);
+ struct ImBuf *(*load)(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int (*save)(struct ImBuf *ibuf, const char *name, int flags);
void (*load_tile)(struct ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect);
int flag;
int filetype;
+ int default_save_role;
} ImFileType;
extern ImFileType IMB_FILE_TYPES[];
@@ -63,57 +64,57 @@ void imb_tile_cache_tile_free(struct ImBuf *ibuf, int tx, int ty);
/* png */
int imb_is_a_png(unsigned char *buf);
-struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savepng(struct ImBuf *ibuf, const char *name, int flags);
/* targa */
int imb_is_a_targa(unsigned char *buf);
-struct ImBuf *imb_loadtarga(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadtarga(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savetarga(struct ImBuf * ibuf, const char *name, int flags);
/* iris */
int imb_is_a_iris(unsigned char *mem);
-struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_saveiris(struct ImBuf * ibuf, const char *name, int flags);
/* jp2 */
int imb_is_a_jp2(unsigned char *buf);
-struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags);
/* jpeg */
int imb_is_a_jpeg(unsigned char *mem);
int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags);
-struct ImBuf * imb_load_jpeg (unsigned char * buffer, size_t size, int flags);
+struct ImBuf * imb_load_jpeg (unsigned char * buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
/* bmp */
int imb_is_a_bmp(unsigned char *buf);
-struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags);
/* cocoa */
-struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_cocoaLoadImage(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
short imb_cocoaSaveImage(struct ImBuf *ibuf, const char *name, int flags);
/* cineon */
int imb_savecineon(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_is_cineon(unsigned char *buf);
/* dpx */
int imb_save_dpx(struct ImBuf *buf, const char *name, int flags);
-struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_is_dpx(unsigned char *buf);
/* hdr */
int imb_is_a_hdr(unsigned char *buf);
-struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
int imb_savehdr(struct ImBuf * ibuf, const char *name, int flags);
/* tiff */
void imb_inittiff(void);
int imb_is_a_tiff(unsigned char *buf);
-struct ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
void imb_loadtiletiff(struct ImBuf *ibuf, unsigned char *mem, size_t size,
int tx, int ty, unsigned int *rect);
int imb_savetiff(struct ImBuf *ibuf, const char *name, int flags);
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 7724f444b2c..69048274104 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -41,6 +41,7 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
#include "IMB_metadata.h"
+#include "IMB_colormanagement_intern.h"
#include "imbuf.h"
@@ -162,8 +163,11 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_metadata_free(ibuf);
- if (ibuf->dds_data.data != NULL)
+ colormanage_cache_free(ibuf);
+
+ if (ibuf->dds_data.data != NULL) {
free(ibuf->dds_data.data); /* dds_data.data is allocated by DirectDrawSurface::readData(), so don't use MEM_freeN! */
+ }
MEM_freeN(ibuf);
}
}
@@ -354,7 +358,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int
ibuf->ftype = TGA;
ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */
ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254; /* IMB_DPI_DEFAULT -> pixels-per-meter */
-
+
if (flags & IB_rect) {
if (imb_addrectImBuf(ibuf) == FALSE) {
IMB_freeImBuf(ibuf);
@@ -382,6 +386,9 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar planes, unsigned int
return NULL;
}
}
+
+ /* assign default spaces */
+ colormanage_imbuf_set_default_spaces(ibuf);
}
return (ibuf);
}
@@ -442,8 +449,11 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
/* for now don't duplicate metadata */
tbuf.metadata = NULL;
+ tbuf.display_buffer_flags = NULL;
+ tbuf.colormanage_cache = NULL;
+
*ibuf2 = tbuf;
-
+
return(ibuf2);
}
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 16dbd0823da..394f5169046 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -113,6 +113,9 @@
#endif
#endif
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
int ismovie(const char *UNUSED(filepath))
{
return 0;
@@ -263,12 +266,20 @@ void IMB_close_anim_proxies(struct anim *anim)
IMB_free_indices(anim);
}
-struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex)
+struct anim *IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
{
struct anim *anim;
anim = (struct anim *)MEM_callocN(sizeof(struct anim), "anim struct");
if (anim != NULL) {
+ if (colorspace) {
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+ BLI_strncpy(anim->colorspace, colorspace, sizeof(anim->colorspace));
+ }
+ else {
+ colorspace_set_default_role(anim->colorspace, sizeof(anim->colorspace), COLOR_ROLE_DEFAULT_BYTE);
+ }
+
BLI_strncpy(anim->name, name, sizeof(anim->name));
anim->ib_flags = ib_flags;
anim->streamindex = streamindex;
@@ -404,7 +415,7 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
if (anim->pgf) {
lpbi = AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo]));
if (lpbi) {
- ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect, "<avi_fetchibuf>");
+ ibuf = IMB_ibImageFromMemory((unsigned char *) lpbi, 100, IB_rect, anim->colorspace, "<avi_fetchibuf>");
//Oh brother...
}
}
@@ -432,8 +443,8 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
MEM_freeN(tmp);
}
- ibuf->profile = IB_PROFILE_SRGB;
-
+ ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace);
+
return ibuf;
}
@@ -634,8 +645,6 @@ static void ffmpeg_postprocess(struct anim *anim)
ImBuf *ibuf = anim->last_frame;
int filter_y = 0;
- ibuf->profile = IB_PROFILE_SRGB;
-
if (!anim->pFrameComplete) {
return;
}
@@ -1090,6 +1099,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position,
IMB_freeImBuf(anim->last_frame);
anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect);
+ anim->last_frame->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace);
ffmpeg_postprocess(anim);
@@ -1213,7 +1223,7 @@ static ImBuf *anim_getnew(struct anim *anim)
switch (anim->curtype) {
case ANIM_SEQUENCE:
- ibuf = IMB_loadiffname(anim->name, anim->ib_flags);
+ ibuf = IMB_loadiffname(anim->name, anim->ib_flags, anim->colorspace);
if (ibuf) {
BLI_strncpy(anim->first, anim->name, sizeof(anim->first));
anim->duration = 1;
@@ -1309,7 +1319,7 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position,
pic = an_stringdec(anim->first, head, tail, &digits);
pic += position;
an_stringenc(anim->name, head, tail, digits, pic);
- ibuf = IMB_loadiffname(anim->name, IB_rect);
+ ibuf = IMB_loadiffname(anim->name, IB_rect, anim->colorspace);
if (ibuf) {
anim->curposition = position;
}
@@ -1319,7 +1329,6 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position,
if (ibuf) {
anim->curposition = position;
IMB_convert_rgba_to_abgr(ibuf);
- ibuf->profile = IB_PROFILE_SRGB;
}
break;
case ANIM_AVI:
@@ -1330,8 +1339,16 @@ struct ImBuf *IMB_anim_absolute(struct anim *anim, int position,
#ifdef WITH_QUICKTIME
case ANIM_QTIME:
ibuf = qtime_fetchibuf(anim, position);
- if (ibuf)
+ if (ibuf) {
+ if (ibuf->rect) {
+ /* OCIO_TODO: should happen in quicktime module, but it currently doesn't have access
+ * to color management's internals
+ */
+ ibuf->rect_colorspace = colormanage_colorspace_get_named(anim->colorspace);
+ }
+
anim->curposition = position;
+ }
break;
#endif
#ifdef WITH_FFMPEG
diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c
index 8fa468949e7..df12f0b703e 100644
--- a/source/blender/imbuf/intern/bmp.c
+++ b/source/blender/imbuf/intern/bmp.c
@@ -38,6 +38,9 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
/* some code copied from article on microsoft.com, copied
* here for enhanced BMP support in the future
* http://www.microsoft.com/msj/defaultframe.asp?page=/msj/0197/mfcp1/mfcp1.htm&nav=/msj/0197/newnav.htm
@@ -115,7 +118,7 @@ int imb_is_a_bmp(unsigned char *buf)
return checkbmp(buf);
}
-struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
BMPINFOHEADER bmi;
@@ -127,6 +130,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
if (checkbmp(mem) == 0) return(NULL);
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
if ((mem[0] == 'B') && (mem[1] == 'M')) {
/* skip fileheader */
mem += BMP_FILEHEADER_SIZE;
@@ -195,7 +200,6 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags)
if (ibuf) {
ibuf->ftype = BMP;
- ibuf->profile = IB_PROFILE_SRGB;
}
return(ibuf);
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index 182e0a7e29d..7705af13b1e 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -44,6 +44,9 @@
#include "IMB_imbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "BKE_global.h"
#include "MEM_guardedalloc.h"
@@ -63,7 +66,7 @@ static void cineon_conversion_parameters(LogImageByteConversionParameters *param
}
#endif
-static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
+static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags, char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
LogImageFile *image;
@@ -72,6 +75,8 @@ static ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size,
int width, height, depth;
float *frow;
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
+
logImageSetVerbose((G.debug & G_DEBUG) ? 1:0);
image = logImageOpenFromMem(mem, size, use_cineon);
@@ -202,10 +207,10 @@ int imb_is_cineon(unsigned char *buf)
return cineonIsMemFileCineon(buf);
}
-ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags)
+ImBuf *imb_loadcineon(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_cineon(mem))
- return imb_load_dpx_cineon(mem, 1, size, flags);
+ return imb_load_dpx_cineon(mem, 1, size, flags, colorspace);
return NULL;
}
@@ -219,9 +224,9 @@ int imb_is_dpx(unsigned char *buf)
return dpxIsMemFileCineon(buf);
}
-ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags)
+ImBuf *imb_loaddpx(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
if (imb_is_dpx(mem))
- return imb_load_dpx_cineon(mem, 0, size, flags);
+ return imb_load_dpx_cineon(mem, 0, size, flags, colorspace);
return NULL;
}
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
new file mode 100644
index 00000000000..6db45f0308a
--- /dev/null
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -0,0 +1,2337 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 by Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Xavier Thomas,
+ * Lukas Toenne,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
+#include <string.h>
+#include <math.h>
+
+#include "DNA_color_types.h"
+#include "DNA_image_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "IMB_filter.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_filetype.h"
+#include "IMB_moviecache.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_math_color.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_threads.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_utildefines.h"
+#include "BKE_main.h"
+
+#include "RNA_define.h"
+
+#include <ocio_capi.h>
+
+/*********************** Global declarations *************************/
+
+#define MAX_COLORSPACE_NAME 64
+
+/* ** list of all supported color spaces, displays and views */
+static char global_role_scene_linear[MAX_COLORSPACE_NAME];
+static char global_role_color_picking[MAX_COLORSPACE_NAME];
+static char global_role_texture_painting[MAX_COLORSPACE_NAME];
+static char global_role_default_byte[MAX_COLORSPACE_NAME];
+static char global_role_default_float[MAX_COLORSPACE_NAME];
+static char global_role_default_sequencer[MAX_COLORSPACE_NAME];
+
+static ListBase global_colorspaces = {NULL};
+static ListBase global_displays = {NULL};
+static ListBase global_views = {NULL};
+
+static int global_tot_colorspace = 0;
+static int global_tot_display = 0;
+static int global_tot_view = 0;
+
+typedef struct ColormanageProcessor {
+ ConstProcessorRcPtr *processor;
+ CurveMapping *curve_mapping;
+} ColormanageProcessor;
+
+/*********************** Color managed cache *************************/
+
+/* Cache Implementation Notes
+ * ==========================
+ *
+ * All color management cache stuff is stored in two properties of
+ * image buffers:
+ *
+ * 1. display_buffer_flags
+ *
+ * This is a bit field which used to mark calculated transformations
+ * for particular image buffer. Index inside of this array means index
+ * of a color managed display. Element with given index matches view
+ * transformations applied for a given display. So if bit B of array
+ * element B is set to 1, this means display buffer with display index
+ * of A and view transform of B was ever calculated for this imbuf.
+ *
+ * In contrast with indices in global lists of displays and views this
+ * indices are 0-based, not 1-based. This is needed to save some bytes
+ * of memory.
+ *
+ * 2. colormanage_cache
+ *
+ * This is a pointer to a structure which holds all data which is
+ * needed for color management cache to work.
+ *
+ * It contains two parts:
+ * - data
+ * - moviecache
+ *
+ * Data field is used to store additional information about cached
+ * buffers which affects on whether cached buffer could be used.
+ * This data can't go to cache key because changes in this data
+ * shouldn't lead extra buffers adding to cache, it shall
+ * invalidate cached images.
+ *
+ * Currently such a data contains only exposure and gamma, but
+ * would likely extended further.
+ *
+ * data field is not null only for elements of cache, not used for
+ * original image buffers.
+ *
+ * Color management cache is using generic MovieCache implementation
+ * to make it easier to deal with memory limitation.
+ *
+ * Currently color management is using the same memory limitation
+ * pool as sequencer and clip editor are using which means color
+ * managed buffers would be removed from the cache as soon as new
+ * frames are loading for the movie clip and there's no space in
+ * cache.
+ *
+ * Every image buffer has got own movie cache instance, which
+ * means keys for color managed buffers could be really simple
+ * and look up in this cache would be fast and independent from
+ * overall amount of color managed images.
+ */
+
+/* NOTE: ColormanageCacheViewSettings and ColormanageCacheDisplaySettings are
+ * quite the same as ColorManagedViewSettings and ColorManageDisplaySettings
+ * but they holds indexes of all transformations and color spaces, not
+ * their names.
+ *
+ * This helps avoid extra colorsmace / display / view lookup without
+ * requiring to pass all variables which affects on display buffer
+ * to color management cache system and keeps calls small and nice.
+ */
+typedef struct ColormanageCacheViewSettings {
+ int flag;
+ int view;
+ float exposure;
+ float gamma;
+ CurveMapping *curve_mapping;
+} ColormanageCacheViewSettings;
+
+typedef struct ColormanageCacheDisplaySettings {
+ int display;
+} ColormanageCacheDisplaySettings;
+
+typedef struct ColormanageCacheKey {
+ int view; /* view transformation used for display buffer */
+ int display; /* display device name */
+} ColormanageCacheKey;
+
+typedef struct ColormnaageCacheData {
+ int flag; /* view flags of cached buffer */
+ float exposure; /* exposure value cached buffer is calculated with */
+ float gamma; /* gamma value cached buffer is calculated with */
+ int predivide; /* predivide flag of cached buffer */
+ CurveMapping *curve_mapping; /* curve mapping used for cached buffer */
+ int curve_mapping_timestamp; /* time stamp of curve mapping used for cached buffer */
+} ColormnaageCacheData;
+
+typedef struct ColormanageCache {
+ struct MovieCache *moviecache;
+
+ ColormnaageCacheData *data;
+} ColormanageCache;
+
+static struct MovieCache *colormanage_moviecache_get(const ImBuf *ibuf)
+{
+ if (!ibuf->colormanage_cache)
+ return NULL;
+
+ return ibuf->colormanage_cache->moviecache;
+}
+
+static ColormnaageCacheData *colormanage_cachedata_get(const ImBuf *ibuf)
+{
+ if (!ibuf->colormanage_cache)
+ return NULL;
+
+ return ibuf->colormanage_cache->data;
+}
+
+static unsigned int colormanage_hashhash(const void *key_v)
+{
+ ColormanageCacheKey *key = (ColormanageCacheKey *)key_v;
+
+ unsigned int rval = (key->display << 16) | (key->view % 0xffff);
+
+ return rval;
+}
+
+static int colormanage_hashcmp(const void *av, const void *bv)
+{
+ const ColormanageCacheKey *a = (ColormanageCacheKey *) av;
+ const ColormanageCacheKey *b = (ColormanageCacheKey *) bv;
+
+ if (a->view < b->view)
+ return -1;
+ else if (a->view > b->view)
+ return 1;
+
+ if (a->display < b->display)
+ return -1;
+ else if (a->display > b->display)
+ return 1;
+
+ return 0;
+}
+
+static struct MovieCache *colormanage_moviecache_ensure(ImBuf *ibuf)
+{
+ if (!ibuf->colormanage_cache)
+ ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache");
+
+ if (!ibuf->colormanage_cache->moviecache) {
+ struct MovieCache *moviecache;
+
+ moviecache = IMB_moviecache_create("colormanage cache", sizeof(ColormanageCacheKey),
+ colormanage_hashhash, colormanage_hashcmp);
+
+ ibuf->colormanage_cache->moviecache = moviecache;
+ }
+
+ return ibuf->colormanage_cache->moviecache;
+}
+
+static void colormanage_cachedata_set(ImBuf *ibuf, ColormnaageCacheData *data)
+{
+ if (!ibuf->colormanage_cache)
+ ibuf->colormanage_cache = MEM_callocN(sizeof(ColormanageCache), "imbuf colormanage cache");
+
+ ibuf->colormanage_cache->data = data;
+}
+
+static void colormanage_view_settings_to_cache(ColormanageCacheViewSettings *cache_view_settings,
+ const ColorManagedViewSettings *view_settings)
+{
+ int view = IMB_colormanagement_view_get_named_index(view_settings->view_transform);
+
+ cache_view_settings->view = view;
+ cache_view_settings->exposure = view_settings->exposure;
+ cache_view_settings->gamma = view_settings->gamma;
+ cache_view_settings->flag = view_settings->flag;
+ cache_view_settings->curve_mapping = view_settings->curve_mapping;
+}
+
+static void colormanage_display_settings_to_cache(ColormanageCacheDisplaySettings *cache_display_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ int display = IMB_colormanagement_display_get_named_index(display_settings->display_device);
+
+ cache_display_settings->display = display;
+}
+
+static void colormanage_settings_to_key(ColormanageCacheKey *key,
+ const ColormanageCacheViewSettings *view_settings,
+ const ColormanageCacheDisplaySettings *display_settings)
+{
+ key->view = view_settings->view;
+ key->display = display_settings->display;
+}
+
+static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, ColormanageCacheKey *key, void **cache_handle)
+{
+ ImBuf *cache_ibuf;
+ struct MovieCache *moviecache = colormanage_moviecache_get(ibuf);
+
+ if (!moviecache) {
+ /* if there's no moviecache it means no color management was applied on given image buffer before */
+
+ return NULL;
+ }
+
+ *cache_handle = NULL;
+
+ cache_ibuf = IMB_moviecache_get(moviecache, key);
+
+ *cache_handle = cache_ibuf;
+
+ return cache_ibuf;
+}
+
+static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings,
+ const ColormanageCacheDisplaySettings *display_settings,
+ void **cache_handle)
+{
+ ColormanageCacheKey key;
+ ImBuf *cache_ibuf;
+ int view_flag = 1 << (view_settings->view - 1);
+ int predivide = ibuf->flags & IB_cm_predivide;
+ CurveMapping *curve_mapping = view_settings->curve_mapping;
+ int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
+
+ colormanage_settings_to_key(&key, view_settings, display_settings);
+
+ /* check whether image was marked as dirty for requested transform */
+ if ((ibuf->display_buffer_flags[display_settings->display - 1] & view_flag) == 0) {
+ return NULL;
+ }
+
+ cache_ibuf = colormanage_cache_get_ibuf(ibuf, &key, cache_handle);
+
+ if (cache_ibuf) {
+ ColormnaageCacheData *cache_data;
+
+ BLI_assert(cache_ibuf->x == ibuf->x &&
+ cache_ibuf->y == ibuf->y &&
+ cache_ibuf->channels == ibuf->channels);
+
+ /* only buffers with different color space conversions are being stored
+ * in cache separately. buffer which were used only different exposure/gamma
+ * are re-suing the same cached buffer
+ *
+ * check here which exposure/gamma/curve was used for cached buffer and if they're
+ * different from requested buffer should be re-generated
+ */
+ cache_data = colormanage_cachedata_get(cache_ibuf);
+
+ if (cache_data->exposure != view_settings->exposure ||
+ cache_data->gamma != view_settings->gamma ||
+ cache_data->predivide != predivide ||
+ cache_data->flag != view_settings->flag ||
+ cache_data->curve_mapping != curve_mapping ||
+ cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
+ {
+ *cache_handle = NULL;
+
+ IMB_freeImBuf(cache_ibuf);
+
+ return NULL;
+ }
+
+ return (unsigned char *) cache_ibuf->rect;
+ }
+
+ return NULL;
+}
+
+static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSettings *view_settings,
+ const ColormanageCacheDisplaySettings *display_settings,
+ unsigned char *display_buffer, void **cache_handle)
+{
+ ColormanageCacheKey key;
+ ImBuf *cache_ibuf;
+ ColormnaageCacheData *cache_data;
+ int view_flag = 1 << (view_settings->view - 1);
+ int predivide = ibuf->flags & IB_cm_predivide;
+ struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
+ CurveMapping *curve_mapping = view_settings->curve_mapping;
+ int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
+
+ colormanage_settings_to_key(&key, view_settings, display_settings);
+
+ /* mark display buffer as valid */
+ ibuf->display_buffer_flags[display_settings->display - 1] |= view_flag;
+
+ /* buffer itself */
+ cache_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
+ cache_ibuf->rect = (unsigned int *) display_buffer;
+
+ cache_ibuf->mall |= IB_rect;
+ cache_ibuf->flags |= IB_rect;
+
+ /* store data which is needed to check whether cached buffer could be used for color managed display settings */
+ cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
+ cache_data->exposure = view_settings->exposure;
+ cache_data->gamma = view_settings->gamma;
+ cache_data->predivide = predivide;
+ cache_data->flag = view_settings->flag;
+ cache_data->curve_mapping = curve_mapping;
+ cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
+
+ colormanage_cachedata_set(cache_ibuf, cache_data);
+
+ *cache_handle = cache_ibuf;
+
+ IMB_moviecache_put(moviecache, &key, cache_ibuf);
+}
+
+static void colormanage_cache_handle_release(void *cache_handle)
+{
+ ImBuf *cache_ibuf = cache_handle;
+
+ IMB_freeImBuf(cache_ibuf);
+}
+
+/*********************** Initialization / De-initialization *************************/
+
+static void colormanage_role_color_space_name_get(ConstConfigRcPtr *config, char *colorspace_name, const char *role)
+{
+ ConstColorSpaceRcPtr *ociocs;
+
+ ociocs = OCIO_configGetColorSpace(config, role);
+
+ if (ociocs) {
+ const char *name = OCIO_colorSpaceGetName(ociocs);
+
+ /* assume function was called with buffer properly allocated to MAX_COLORSPACE_NAME chars */
+ BLI_strncpy(colorspace_name, name, MAX_COLORSPACE_NAME);
+ OCIO_colorSpaceRelease(ociocs);
+ }
+ else {
+ printf("Color management: Error could not find role %s role.\n", role);
+ }
+}
+
+static void colormanage_load_config(ConstConfigRcPtr *config)
+{
+ int tot_colorspace, tot_display, tot_display_view, index, viewindex, viewindex2;
+ const char *name;
+
+ /* get roles */
+ colormanage_role_color_space_name_get(config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR);
+ colormanage_role_color_space_name_get(config, global_role_color_picking, OCIO_ROLE_COLOR_PICKING);
+ colormanage_role_color_space_name_get(config, global_role_texture_painting, OCIO_ROLE_TEXTURE_PAINT);
+ colormanage_role_color_space_name_get(config, global_role_default_sequencer, OCIO_ROLE_DEFAULT_SEQUENCER);
+ colormanage_role_color_space_name_get(config, global_role_default_byte, OCIO_ROLE_DEFAULT_BYTE);
+ colormanage_role_color_space_name_get(config, global_role_default_float, OCIO_ROLE_DEFAULT_FLOAT);
+
+ /* load colorspaces */
+ tot_colorspace = OCIO_configGetNumColorSpaces(config);
+ for (index = 0 ; index < tot_colorspace; index++) {
+ ConstColorSpaceRcPtr *ocio_colorspace;
+ const char *description;
+ int is_invertible;
+
+ name = OCIO_configGetColorSpaceNameByIndex(config, index);
+
+ ocio_colorspace = OCIO_configGetColorSpace(config, name);
+ description = OCIO_colorSpaceGetDescription(ocio_colorspace);
+ is_invertible = OCIO_colorSpaceIsInvertible(ocio_colorspace);
+
+ colormanage_colorspace_add(name, description, is_invertible);
+
+ OCIO_colorSpaceRelease(ocio_colorspace);
+ }
+
+ /* load displays */
+ viewindex2 = 0;
+ tot_display = OCIO_configGetNumDisplays(config);
+
+ for (index = 0 ; index < tot_display; index++) {
+ const char *displayname;
+ ColorManagedDisplay *display;
+
+ displayname = OCIO_configGetDisplay(config, index);
+
+ display = colormanage_display_add(displayname);
+
+ /* load views */
+ tot_display_view = OCIO_configGetNumViews(config, displayname);
+ for (viewindex = 0 ; viewindex < tot_display_view; viewindex++, viewindex2++) {
+ const char *viewname;
+ ColorManagedView *view;
+ LinkData *display_view;
+
+ viewname = OCIO_configGetView(config, displayname, viewindex);
+
+ /* first check if view transform with given name was already loaded */
+ view = colormanage_view_get_named(viewname);
+
+ if (!view) {
+ view = colormanage_view_add(viewname);
+ }
+
+ display_view = BLI_genericNodeN(view);
+
+ BLI_addtail(&display->views, display_view);
+ }
+ }
+
+ global_tot_display = tot_display;
+}
+
+static void colormanage_free_config(void)
+{
+ ColorSpace *colorspace;
+ ColorManagedDisplay *display;
+
+ /* free color spaces */
+ colorspace = global_colorspaces.first;
+ while (colorspace) {
+ ColorSpace *colorspace_next = colorspace->next;
+
+ /* free precomputer processors */
+ if (colorspace->to_scene_linear)
+ OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->to_scene_linear);
+
+ if (colorspace->from_scene_linear)
+ OCIO_processorRelease((ConstProcessorRcPtr *) colorspace->from_scene_linear);
+
+ /* free color space itself */
+ MEM_freeN(colorspace);
+
+ colorspace = colorspace_next;
+ }
+
+ /* free displays */
+ display = global_displays.first;
+ while (display) {
+ ColorManagedDisplay *display_next = display->next;
+
+ /* free precomputer processors */
+ if (display->to_scene_linear)
+ OCIO_processorRelease((ConstProcessorRcPtr *) display->to_scene_linear);
+
+ if (display->from_scene_linear)
+ OCIO_processorRelease((ConstProcessorRcPtr *) display->from_scene_linear);
+
+ /* free list of views */
+ BLI_freelistN(&display->views);
+
+ MEM_freeN(display);
+ display = display_next;
+ }
+
+ /* free views */
+ BLI_freelistN(&global_views);
+}
+
+void IMB_colormanagement_init(void)
+{
+ const char *ocio_env;
+ const char *configdir;
+ char configfile[FILE_MAX];
+ ConstConfigRcPtr *config = NULL;
+
+ ocio_env = getenv("OCIO");
+
+ if (ocio_env && ocio_env[0] != '\0')
+ config = OCIO_configCreateFromEnv();
+
+ if (config == NULL) {
+ configdir = BLI_get_folder(BLENDER_DATAFILES, "colormanagement");
+
+ if (configdir) {
+ BLI_join_dirfile(configfile, sizeof(configfile), configdir, BCM_CONFIG_FILE);
+
+ config = OCIO_configCreateFromFile(configfile);
+ }
+ }
+
+ if (config) {
+ OCIO_setCurrentConfig(config);
+
+ colormanage_load_config(config);
+
+ OCIO_configRelease(config);
+ }
+
+ BLI_init_srgb_conversion();
+}
+
+void IMB_colormanagement_exit(void)
+{
+ colormanage_free_config();
+}
+
+/*********************** Internal functions *************************/
+
+void colormanage_cache_free(ImBuf *ibuf)
+{
+ if (ibuf->display_buffer_flags) {
+ MEM_freeN(ibuf->display_buffer_flags);
+
+ ibuf->display_buffer_flags = NULL;
+ }
+
+ if (ibuf->colormanage_cache) {
+ ColormnaageCacheData *cache_data = colormanage_cachedata_get(ibuf);
+ struct MovieCache *moviecache = colormanage_moviecache_get(ibuf);
+
+ if (cache_data) {
+ MEM_freeN(cache_data);
+ }
+
+ if (moviecache) {
+ IMB_moviecache_free(moviecache);
+ }
+
+ MEM_freeN(ibuf->colormanage_cache);
+
+ ibuf->colormanage_cache = NULL;
+ }
+}
+
+static void display_transform_get_from_ctx(const bContext *C, ColorManagedViewSettings **view_settings_r,
+ ColorManagedDisplaySettings **display_settings_r)
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceImage *sima = CTX_wm_space_image(C);
+
+ *view_settings_r = &scene->view_settings;
+ *display_settings_r = &scene->display_settings;
+
+ if (sima) {
+ if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0)
+ *view_settings_r = NULL;
+ }
+}
+
+static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display,
+ float exposure, float gamma)
+{
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ DisplayTransformRcPtr *dt;
+ ConstProcessorRcPtr *processor;
+
+ if (!config) {
+ /* there's no valid OCIO configuration, can't create processor */
+
+ return NULL;
+ }
+
+ dt = OCIO_createDisplayTransform();
+
+ /* assuming handling buffer was already converted to scene linear space */
+ OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear);
+ OCIO_displayTransformSetView(dt, view_transform);
+ OCIO_displayTransformSetDisplay(dt, display);
+
+ /* fstop exposure control */
+ if (exposure != 0.0f) {
+ MatrixTransformRcPtr *mt;
+ float gain = powf(2.0f, exposure);
+ const float scale4f[] = {gain, gain, gain, gain};
+ float m44[16], offset4[4];
+
+ OCIO_matrixTransformScale(m44, offset4, scale4f);
+ mt = OCIO_createMatrixTransform();
+ OCIO_matrixTransformSetValue(mt, m44, offset4);
+ OCIO_displayTransformSetLinearCC(dt, (ConstTransformRcPtr *) mt);
+
+ OCIO_matrixTransformRelease(mt);
+ }
+
+ /* post-display gamma transform */
+ if (gamma != 1.0f) {
+ ExponentTransformRcPtr *et;
+ float exponent = 1.0f / MAX2(FLT_EPSILON, gamma);
+ const float exponent4f[] = {exponent, exponent, exponent, exponent};
+
+ et = OCIO_createExponentTransform();
+ OCIO_exponentTransformSetValue(et, exponent4f);
+ OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et);
+
+ OCIO_exponentTransformRelease(et);
+ }
+
+ processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt);
+
+ OCIO_displayTransformRelease(dt);
+ OCIO_configRelease(config);
+
+ return processor;
+}
+
+static ConstProcessorRcPtr *create_colorspace_transform_processor(const char *from_colorspace,
+ const char *to_colorspace)
+{
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ ConstProcessorRcPtr *processor;
+
+ if (!config) {
+ /* there's no valid OCIO configuration, can't create processor */
+
+ return NULL;
+ }
+
+ processor = OCIO_configGetProcessorWithNames(config, from_colorspace, to_colorspace);
+
+ OCIO_configRelease(config);
+
+ return processor;
+}
+
+static ConstProcessorRcPtr *colorspace_to_scene_linear_processor(ColorSpace *colorspace)
+{
+ if (colorspace->to_scene_linear == NULL) {
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ if (colorspace->to_scene_linear == NULL) {
+ ConstProcessorRcPtr *to_scene_linear;
+ to_scene_linear = create_colorspace_transform_processor(colorspace->name, global_role_scene_linear);
+ colorspace->to_scene_linear = (struct ConstProcessorRcPtr *) to_scene_linear;
+ }
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ }
+
+ return (ConstProcessorRcPtr *) colorspace->to_scene_linear;
+}
+
+static ConstProcessorRcPtr *colorspace_from_scene_linear_processor(ColorSpace *colorspace)
+{
+ if (colorspace->from_scene_linear == NULL) {
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ if (colorspace->from_scene_linear == NULL) {
+ ConstProcessorRcPtr *from_scene_linear;
+ from_scene_linear = create_colorspace_transform_processor(global_role_scene_linear, colorspace->name);
+ colorspace->from_scene_linear = (struct ConstProcessorRcPtr *) from_scene_linear;
+ }
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ }
+
+ return (ConstProcessorRcPtr *) colorspace->from_scene_linear;
+}
+
+static ConstProcessorRcPtr *display_from_scene_linear_processor(ColorManagedDisplay *display)
+{
+ if (display->from_scene_linear == NULL) {
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ if (display->from_scene_linear == NULL) {
+ const char *view_name = colormanage_view_get_default_name(display);
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ ConstProcessorRcPtr *processor = NULL;
+
+ if (view_name && config) {
+ const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name);
+ processor = OCIO_configGetProcessorWithNames(config, global_role_scene_linear, view_colorspace);
+
+ OCIO_configRelease(config);
+ }
+
+ display->from_scene_linear = (struct ConstProcessorRcPtr *) processor;
+ }
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ }
+
+ return (ConstProcessorRcPtr *) display->from_scene_linear;
+}
+
+static ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedDisplay *display)
+{
+ if (display->to_scene_linear == NULL) {
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ if (display->to_scene_linear == NULL) {
+ const char *view_name = colormanage_view_get_default_name(display);
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ ConstProcessorRcPtr *processor = NULL;
+
+ if (view_name && config) {
+ const char *view_colorspace = OCIO_configGetDisplayColorSpaceName(config, display->name, view_name);
+ processor = OCIO_configGetProcessorWithNames(config, view_colorspace, global_role_scene_linear);
+
+ OCIO_configRelease(config);
+ }
+
+ display->to_scene_linear = (struct ConstProcessorRcPtr *) processor;
+ }
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ }
+
+ return (ConstProcessorRcPtr *) display->to_scene_linear;
+}
+
+static void init_default_view_settings(const ColorManagedDisplaySettings *display_settings,
+ ColorManagedViewSettings *view_settings)
+{
+ ColorManagedDisplay *display;
+ ColorManagedView *default_view;
+
+ display = colormanage_display_get_named(display_settings->display_device);
+ default_view = colormanage_view_get_default(display);
+
+ if (default_view)
+ BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
+ else
+ view_settings->view_transform[0] = '\0';
+
+ view_settings->flag = 0;
+ view_settings->gamma = 1.0f;
+ view_settings->exposure = 0.0f;
+ view_settings->curve_mapping = NULL;
+}
+
+static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels)
+{
+ if (channels == 1) {
+ pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]);
+ }
+ else if (channels == 2) {
+ pixel[0] = curvemap_evaluateF(curve_mapping->cm, pixel[0]);
+ pixel[1] = curvemap_evaluateF(curve_mapping->cm, pixel[1]);
+ }
+ else {
+ curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel);
+ }
+}
+
+void colorspace_set_default_role(char *colorspace, int size, int role)
+{
+ if (colorspace && colorspace[0] == '\0') {
+ const char *role_colorspace;
+
+ role_colorspace = IMB_colormanagement_role_colorspace_name_get(role);
+
+ BLI_strncpy(colorspace, role_colorspace, size);
+ }
+}
+
+void colormanage_imbuf_set_default_spaces(ImBuf *ibuf)
+{
+ ibuf->rect_colorspace = colormanage_colorspace_get_named(global_role_default_byte);
+}
+
+void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
+{
+ if (ibuf->rect_float) {
+ const char *to_colorspace = global_role_scene_linear;
+ int predivide = ibuf->flags & IB_cm_predivide;
+
+ if (ibuf->rect)
+ imb_freerectImBuf(ibuf);
+
+ IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace, predivide);
+ }
+}
+
+/*********************** Generic functions *************************/
+
+static void colormanage_check_display_settings(ColorManagedDisplaySettings *display_settings, const char *what,
+ const ColorManagedDisplay *default_display)
+{
+ if (display_settings->display_device[0] == '\0') {
+ BLI_strncpy(display_settings->display_device, default_display->name, sizeof(display_settings->display_device));
+ }
+ else {
+ ColorManagedDisplay *display = colormanage_display_get_named(display_settings->display_device);
+
+ if (!display) {
+ printf("Color management: display \"%s\" used by %s not found, setting to default (\"%s\").\n",
+ display_settings->display_device, what, default_display->name);
+
+ BLI_strncpy(display_settings->display_device, default_display->name,
+ sizeof(display_settings->display_device));
+ }
+ }
+}
+
+static void colormanage_check_view_settings(ColorManagedDisplaySettings *display_settings,
+ ColorManagedViewSettings *view_settings, const char *what)
+{
+ ColorManagedDisplay *display;
+ ColorManagedView *default_view;
+
+ if (view_settings->view_transform[0] == '\0') {
+ display = colormanage_display_get_named(display_settings->display_device);
+ default_view = colormanage_view_get_default(display);
+
+ if (default_view)
+ BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
+ }
+ else {
+ ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform);
+
+ if (!view) {
+ display = colormanage_display_get_named(display_settings->display_device);
+ default_view = colormanage_view_get_default(display);
+
+ if (default_view) {
+ printf("Color management: %s view \"%s\" not found, setting default \"%s\".\n",
+ what, view_settings->view_transform, default_view->name);
+
+ BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
+ }
+ }
+ }
+
+ /* OCIO_TODO: move to do_versions() */
+ if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) {
+ view_settings->exposure = 0.0f;
+ view_settings->gamma = 1.0f;
+ }
+}
+
+static void colormanage_check_colorspace_settings(ColorManagedColorspaceSettings *colorspace_settings, const char *what)
+{
+ if (colorspace_settings->name[0] == '\0') {
+ /* pass */
+ }
+ else {
+ ColorSpace *colorspace = colormanage_colorspace_get_named(colorspace_settings->name);
+
+ if (!colorspace) {
+ printf("Color management: %s colorspace \"%s\" not found, will use default instead.\n",
+ what, colorspace_settings->name);
+
+ BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name));
+ }
+ }
+
+ (void) what;
+}
+
+void IMB_colormanagement_check_file_config(Main *bmain)
+{
+ Scene *scene;
+ Image *image;
+ MovieClip *clip;
+
+ ColorManagedDisplay *default_display;
+
+ default_display = colormanage_display_get_default();
+
+ if (!default_display) {
+ /* happens when OCIO configuration is incorrect */
+ return;
+ }
+
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ ColorManagedColorspaceSettings *sequencer_colorspace_settings;
+
+ colormanage_check_display_settings(&scene->display_settings, "scene", default_display);
+ colormanage_check_view_settings(&scene->display_settings, &scene->view_settings, "scene");
+
+ sequencer_colorspace_settings = &scene->sequencer_colorspace_settings;
+
+ colormanage_check_colorspace_settings(sequencer_colorspace_settings, "sequencer");
+
+ if (sequencer_colorspace_settings->name[0] == '\0') {
+ BLI_strncpy(sequencer_colorspace_settings->name, global_role_default_sequencer, MAX_COLORSPACE_NAME);
+ }
+ }
+
+ /* ** check input color space settings ** */
+
+ for (image = bmain->image.first; image; image = image->id.next) {
+ colormanage_check_colorspace_settings(&image->colorspace_settings, "image");
+ }
+
+ for (clip = bmain->movieclip.first; clip; clip = clip->id.next) {
+ colormanage_check_colorspace_settings(&clip->colorspace_settings, "clip");
+ }
+}
+
+void IMB_colormanagement_validate_settings(ColorManagedDisplaySettings *display_settings,
+ ColorManagedViewSettings *view_settings)
+{
+ ColorManagedDisplay *display;
+ ColorManagedView *default_view;
+ LinkData *view_link;
+
+ display = colormanage_display_get_named(display_settings->display_device);
+ default_view = colormanage_view_get_default(display);
+
+ for (view_link = display->views.first; view_link; view_link = view_link->next) {
+ ColorManagedView *view = view_link->data;
+
+ if (!strcmp(view->name, view_settings->view_transform))
+ break;
+ }
+
+ if (view_link == NULL)
+ BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
+}
+
+const char *IMB_colormanagement_role_colorspace_name_get(int role)
+{
+ switch (role) {
+ case COLOR_ROLE_SCENE_LINEAR:
+ return global_role_scene_linear;
+ break;
+ case COLOR_ROLE_COLOR_PICKING:
+ return global_role_color_picking;
+ break;
+ case COLOR_ROLE_TEXTURE_PAINTING:
+ return global_role_texture_painting;
+ break;
+ case COLOR_ROLE_DEFAULT_SEQUENCER:
+ return global_role_default_sequencer;
+ break;
+ case COLOR_ROLE_DEFAULT_FLOAT:
+ return global_role_default_float;
+ break;
+ case COLOR_ROLE_DEFAULT_BYTE:
+ return global_role_default_byte;
+ break;
+ default:
+ printf("Unknown role was passed to %s\n", __func__);
+ BLI_assert(0);
+ }
+
+ return NULL;
+}
+
+/*********************** Threaded display buffer transform routines *************************/
+
+typedef struct DisplayBufferThread {
+ ColormanageProcessor *cm_processor;
+
+ float *buffer;
+ unsigned char *byte_buffer;
+
+ float *display_buffer;
+ unsigned char *display_buffer_byte;
+
+ int width;
+ int start_line;
+ int tot_line;
+
+ int channels;
+ float dither;
+ int predivide;
+
+ const char *byte_colorspace;
+ const char *float_colorspace;
+} DisplayBufferThread;
+
+typedef struct DisplayBufferInitData {
+ ImBuf *ibuf;
+ ColormanageProcessor *cm_processor;
+ float *buffer;
+ unsigned char *byte_buffer;
+
+ float *display_buffer;
+ unsigned char *display_buffer_byte;
+
+ int width;
+
+ const char *byte_colorspace;
+ const char *float_colorspace;
+} DisplayBufferInitData;
+
+static void display_buffer_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
+{
+ DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
+ DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v;
+ ImBuf *ibuf = init_data->ibuf;
+
+ int predivide = ibuf->flags & IB_cm_predivide;
+ int channels = ibuf->channels;
+ float dither = ibuf->dither;
+
+ int offset = channels * start_line * ibuf->x;
+
+ memset(handle, 0, sizeof(DisplayBufferThread));
+
+ handle->cm_processor = init_data->cm_processor;
+
+ if (init_data->buffer)
+ handle->buffer = init_data->buffer + offset;
+
+ if (init_data->byte_buffer)
+ handle->byte_buffer = init_data->byte_buffer + offset;
+
+ if (init_data->display_buffer)
+ handle->display_buffer = init_data->display_buffer + offset;
+
+ if (init_data->display_buffer_byte)
+ handle->display_buffer_byte = init_data->display_buffer_byte + offset;
+
+ handle->width = ibuf->x;
+
+ handle->start_line = start_line;
+ handle->tot_line = tot_line;
+
+ handle->channels = channels;
+ handle->dither = dither;
+ handle->predivide = predivide;
+
+ handle->byte_colorspace = init_data->byte_colorspace;
+ handle->float_colorspace = init_data->float_colorspace;
+}
+
+static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
+{
+ float *linear_buffer = NULL;
+
+ int channels = handle->channels;
+ int width = handle->width;
+ int height = handle->tot_line;
+
+ int buffer_size = channels * width * height;
+
+ int predivide = handle->predivide;
+
+ linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer");
+
+ if (!handle->buffer) {
+ unsigned char *byte_buffer = handle->byte_buffer;
+
+ const char *from_colorspace = handle->byte_colorspace;
+ const char *to_colorspace = global_role_scene_linear;
+
+ float *fp;
+ unsigned char *cp;
+ int i;
+
+ /* first convert byte buffer to float, keep in image space */
+ for (i = 0, fp = linear_buffer, cp = byte_buffer;
+ i < channels * width * height;
+ i++, fp++, cp++)
+ {
+ *fp = (float)(*cp) / 255.0f;
+ }
+
+ /* convert float buffer to scene linear space */
+ IMB_colormanagement_transform(linear_buffer, width, height, channels,
+ from_colorspace, to_colorspace, predivide);
+ }
+ else if (handle->float_colorspace) {
+ /* currently float is non-linear only in sequencer, which is working
+ * in it's own color space even to handle float buffers.
+ * This color space is the same for byte and float images.
+ * Need to convert float buffer to linear space before applying display transform
+ */
+
+ const char *from_colorspace = handle->float_colorspace;
+ const char *to_colorspace = global_role_scene_linear;
+
+ memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
+
+ IMB_colormanagement_transform(linear_buffer, width, height, channels,
+ from_colorspace, to_colorspace, predivide);
+ }
+ else {
+ /* some processors would want to modify float original buffer
+ * before converting it into display byte buffer, so we need to
+ * make sure original's ImBuf buffers wouldn't be modified by
+ * using duplicated buffer here
+ *
+ * NOTE: MEM_dupallocN can't be used because buffer could be
+ * specified as an offset inside allocated buffer
+ */
+
+ memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
+ }
+
+ return linear_buffer;
+}
+
+static void *do_display_buffer_apply_thread(void *handle_v)
+{
+ DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
+ ColormanageProcessor *cm_processor = handle->cm_processor;
+ float *buffer = handle->buffer;
+ float *display_buffer = handle->display_buffer;
+ unsigned char *display_buffer_byte = handle->display_buffer_byte;
+ int channels = handle->channels;
+ int width = handle->width;
+ int height = handle->tot_line;
+ float dither = handle->dither;
+ int predivide = handle->predivide;
+
+ float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
+
+ /* apply processor */
+ IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+
+ /* copy result to output buffers */
+ if (display_buffer_byte) {
+ /* do conversion */
+ IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
+ channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ predivide, width, height, width, width);
+ }
+
+ if (display_buffer)
+ memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float));
+
+ if (linear_buffer != buffer)
+ MEM_freeN(linear_buffer);
+
+ return NULL;
+}
+
+static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer, float *display_buffer,
+ unsigned char *display_buffer_byte, ColormanageProcessor *cm_processor)
+{
+ DisplayBufferInitData init_data;
+
+ init_data.ibuf = ibuf;
+ init_data.cm_processor = cm_processor;
+ init_data.buffer = buffer;
+ init_data.byte_buffer = byte_buffer;
+ init_data.display_buffer = display_buffer;
+ init_data.display_buffer_byte = display_buffer_byte;
+
+ if (ibuf->rect_colorspace != NULL) {
+ init_data.byte_colorspace = ibuf->rect_colorspace->name;
+ }
+ else {
+ /* happens for viewer images, which are not so simple to determine where to
+ * set image buffer's color spaces
+ */
+ init_data.byte_colorspace = global_role_default_byte;
+ }
+
+ if (ibuf->float_colorspace != NULL) {
+ /* sequencer stores float buffers in non-linear space */
+ init_data.float_colorspace = ibuf->float_colorspace->name;
+ }
+ else {
+ init_data.float_colorspace = NULL;
+ }
+
+ IMB_processor_apply_threaded(ibuf->y, sizeof(DisplayBufferThread), &init_data,
+ display_buffer_init_handle, do_display_buffer_apply_thread);
+}
+
+static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte,
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ ColormanageProcessor *cm_processor;
+
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+
+ display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect,
+ display_buffer, display_buffer_byte, cm_processor);
+
+ IMB_colormanagement_processor_free(cm_processor);
+}
+
+static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer,
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ colormanage_display_buffer_process_ex(ibuf, NULL, display_buffer, view_settings, display_settings);
+}
+
+/*********************** Threaded processor transform routines *************************/
+
+typedef struct ProcessorTransformThread {
+ ColormanageProcessor *cm_processor;
+ float *buffer;
+ int width;
+ int start_line;
+ int tot_line;
+ int channels;
+ int predivide;
+} ProcessorTransformThread;
+
+typedef struct ProcessorTransformInit {
+ ColormanageProcessor *cm_processor;
+ float *buffer;
+ int width;
+ int height;
+ int channels;
+ int predivide;
+} ProcessorTransformInitData;
+
+static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
+{
+ ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
+ ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v;
+
+ int channels = init_data->channels;
+ int width = init_data->width;
+ int predivide = init_data->predivide;
+
+ int offset = channels * start_line * width;
+
+ memset(handle, 0, sizeof(ProcessorTransformThread));
+
+ handle->cm_processor = init_data->cm_processor;
+
+ handle->buffer = init_data->buffer + offset;
+
+ handle->width = width;
+
+ handle->start_line = start_line;
+ handle->tot_line = tot_line;
+
+ handle->channels = channels;
+ handle->predivide = predivide;
+}
+
+static void *do_processor_transform_thread(void *handle_v)
+{
+ ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
+ float *buffer = handle->buffer;
+ int channels = handle->channels;
+ int width = handle->width;
+ int height = handle->tot_line;
+ int predivide = handle->predivide;
+
+ IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide);
+
+ return NULL;
+}
+
+static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels,
+ ColormanageProcessor *cm_processor, int predivide)
+{
+ ProcessorTransformInitData init_data;
+
+ init_data.cm_processor = cm_processor;
+ init_data.buffer = buffer;
+ init_data.width = width;
+ init_data.height = height;
+ init_data.channels = channels;
+ init_data.predivide = predivide;
+
+ IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data,
+ processor_transform_init_handle, do_processor_transform_thread);
+}
+
+/*********************** Color space transformation functions *************************/
+
+/* convert the whole buffer from specified by name color space to another - internal implementation */
+static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace,
+ const char *to_colorspace, int predivide, int do_threaded)
+{
+ ColormanageProcessor *cm_processor;
+
+ if (from_colorspace[0] == '\0') {
+ return;
+ }
+
+ if (!strcmp(from_colorspace, to_colorspace)) {
+ /* if source and destination color spaces are identical, skip
+ * threading overhead and simply do nothing
+ */
+ return;
+ }
+
+ cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
+
+ if (do_threaded)
+ processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide);
+ else
+ IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
+
+ IMB_colormanagement_processor_free(cm_processor);
+}
+
+/* convert the whole buffer from specified by name color space to another */
+void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace, int predivide)
+{
+ colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, FALSE);
+}
+
+/* convert the whole buffer from specified by name color space to another
+ * will do threaded conversion
+ */
+void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace, int predivide)
+{
+ colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, TRUE);
+}
+
+void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace)
+{
+ ColormanageProcessor *cm_processor;
+
+ if (from_colorspace[0] == '\0') {
+ return;
+ }
+
+ if (!strcmp(from_colorspace, to_colorspace)) {
+ /* if source and destination color spaces are identical, skip
+ * threading overhead and simply do nothing
+ */
+ return;
+ }
+
+ cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
+
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+
+ IMB_colormanagement_processor_free(cm_processor);
+}
+
+/* convert pixel from specified by descriptor color space to scene linear
+ * used by performance-critical areas such as renderer and baker
+ */
+void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], ColorSpace *colorspace)
+{
+ ConstProcessorRcPtr *processor;
+
+ if (!colorspace) {
+ /* OCIO_TODO: make sure it never happens */
+
+ printf("%s: perform conversion from unknown color space\n", __func__);
+
+ return;
+ }
+
+ processor = colorspace_to_scene_linear_processor(colorspace);
+
+ if (processor)
+ OCIO_processorApplyRGB(processor, pixel);
+}
+
+/* same as above, but converts colors in opposite direction */
+void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpace *colorspace)
+{
+ ConstProcessorRcPtr *processor;
+
+ if (!colorspace) {
+ /* OCIO_TODO: make sure it never happens */
+
+ printf("%s: perform conversion from unknown color space\n", __func__);
+
+ return;
+ }
+
+ processor = colorspace_from_scene_linear_processor(colorspace);
+
+ if (processor)
+ OCIO_processorApplyRGB(processor, pixel);
+}
+
+void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide)
+{
+ ConstProcessorRcPtr *processor;
+
+ if (!colorspace) {
+ /* OCIO_TODO: make sure it never happens */
+
+ printf("%s: perform conversion from unknown color space\n", __func__);
+
+ return;
+ }
+
+ processor = colorspace_to_scene_linear_processor(colorspace);
+
+ if (processor) {
+ PackedImageDesc *img;
+
+ img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float),
+ channels * sizeof(float), channels * sizeof(float) * width);
+
+ if (predivide)
+ OCIO_processorApply_predivide(processor, img);
+ else
+ OCIO_processorApply(processor, img);
+
+ OCIO_packedImageDescRelease(img);
+ }
+}
+
+/* convert pixel from scene linear to display space using default view
+ * used by performance-critical areas such as color-related widgets where we want to reduce
+ * amount of per-widget allocations
+ */
+void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], ColorManagedDisplay *display)
+{
+ ConstProcessorRcPtr *processor;
+
+ processor = display_from_scene_linear_processor(display);
+
+ if (processor)
+ OCIO_processorApplyRGB(processor, pixel);
+}
+
+/* same as above, but converts color in opposite direction */
+void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display)
+{
+ ConstProcessorRcPtr *processor;
+
+ processor = display_to_scene_linear_processor(display);
+
+ if (processor)
+ OCIO_processorApplyRGB(processor, pixel);
+}
+
+void IMB_colormanagement_pixel_to_display_space_v4(float result[4], const float pixel[4],
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ ColormanageProcessor *cm_processor;
+
+ copy_v4_v4(result, pixel);
+
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ IMB_colormanagement_processor_apply_v4(cm_processor, result);
+ IMB_colormanagement_processor_free(cm_processor);
+}
+
+void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float pixel[3],
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ ColormanageProcessor *cm_processor;
+
+ copy_v3_v3(result, pixel);
+
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+ IMB_colormanagement_processor_apply_v3(cm_processor, result);
+ IMB_colormanagement_processor_free(cm_processor);
+}
+
+void IMB_colormanagement_imbuf_assign_float_space(ImBuf *ibuf, ColorManagedColorspaceSettings *colorspace_settings)
+{
+ ibuf->float_colorspace = colormanage_colorspace_get_named(colorspace_settings->name);
+}
+
+void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ /* OCIO_TODO: byte buffer management is not supported here yet */
+ if (!ibuf->rect_float)
+ return;
+
+ if (global_tot_display == 0 || global_tot_view == 0) {
+ IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
+ ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ }
+ else {
+ colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, NULL, view_settings, display_settings);
+ }
+}
+
+static void imbuf_verify_float(ImBuf *ibuf)
+{
+ /* multiple threads could request for display buffer at once and in case
+ * view transform is not used it'll lead to display buffer calculated
+ * several times
+ * it is harmless, but would take much more time (assuming thread lock
+ * happens faster than running float->byte conversion for average image)
+ */
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) {
+ IMB_rect_from_float(ibuf);
+
+ ibuf->userflags &= ~IB_RECT_INVALID;
+ }
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+}
+
+/*********************** Public display buffers interfaces *************************/
+
+/* acquire display buffer for given image buffer using specified view and display settings */
+unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings, void **cache_handle)
+{
+ *cache_handle = NULL;
+
+ if (!ibuf->x || !ibuf->y)
+ return NULL;
+
+ if (global_tot_display == 0 || global_tot_view == 0) {
+ /* if there's no view transform or display transforms, fallback to standard sRGB/linear conversion
+ * the same logic would be used if OCIO is disabled
+ */
+
+ imbuf_verify_float(ibuf);
+
+ return (unsigned char *) ibuf->rect;
+ }
+ else {
+ unsigned char *display_buffer;
+ int buffer_size;
+ ColormanageCacheViewSettings cache_view_settings;
+ ColormanageCacheDisplaySettings cache_display_settings;
+ ColorManagedViewSettings default_view_settings;
+ const ColorManagedViewSettings *applied_view_settings;
+
+ if (view_settings) {
+ applied_view_settings = view_settings;
+ }
+ else {
+ /* if no view settings were specified, use default display transformation
+ * this happens for images which don't want to be displayed with render settings
+ */
+
+ init_default_view_settings(display_settings, &default_view_settings);
+ applied_view_settings = &default_view_settings;
+ }
+
+ colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings);
+ colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
+
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ /* ensure color management bit fields exists */
+ if (!ibuf->display_buffer_flags) {
+ if (global_tot_display)
+ ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags");
+ }
+ else if (ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) {
+ /* all display buffers were marked as invalid from other areas,
+ * now propagate this flag to internal color management routines
+ */
+ memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int));
+
+ ibuf->userflags &= ~IB_DISPLAY_BUFFER_INVALID;
+ }
+
+ display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, cache_handle);
+
+ if (display_buffer) {
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ return display_buffer;
+ }
+
+ buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
+ display_buffer = MEM_callocN(buffer_size, "imbuf display buffer");
+
+ colormanage_display_buffer_process(ibuf, display_buffer, applied_view_settings, display_settings);
+
+ colormanage_cache_put(ibuf, &cache_view_settings, &cache_display_settings, display_buffer, cache_handle);
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+
+ return display_buffer;
+ }
+}
+
+/* same as IMB_display_buffer_acquire but gets view and display settings from context */
+unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, void **cache_handle)
+{
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ display_transform_get_from_ctx(C, &view_settings, &display_settings);
+
+ return IMB_display_buffer_acquire(ibuf, view_settings, display_settings, cache_handle);
+}
+
+/* covert float buffer to display space and store it in image buffer's byte array */
+void IMB_display_buffer_to_imbuf_rect(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ if (global_tot_display == 0 || global_tot_view == 0) {
+ imbuf_verify_float(ibuf);
+ }
+ else {
+ if (!ibuf->rect) {
+ imb_addrectImBuf(ibuf);
+ }
+
+ colormanage_display_buffer_process(ibuf, (unsigned char *) ibuf->rect, view_settings, display_settings);
+ }
+}
+
+void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height,
+ int channels, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings, int predivide)
+{
+ if (global_tot_display == 0 || global_tot_view == 0) {
+ IMB_buffer_byte_from_float(display_buffer, linear_buffer, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE,
+ width, height, width, width);
+ }
+ else {
+ float *buffer;
+ ColormanageProcessor *cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+
+ buffer = MEM_callocN(channels * width * height * sizeof(float), "display transform temp buffer");
+ memcpy(buffer, linear_buffer, channels * width * height * sizeof(float));
+
+ IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
+
+ IMB_colormanagement_processor_free(cm_processor);
+
+ IMB_buffer_byte_from_float(display_buffer, buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ FALSE, width, height, width, width);
+
+ MEM_freeN(buffer);
+ }
+}
+
+void IMB_display_buffer_release(void *cache_handle)
+{
+ if (cache_handle) {
+ BLI_lock_thread(LOCK_COLORMANAGE);
+
+ colormanage_cache_handle_release(cache_handle);
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+ }
+}
+
+/*********************** Display functions *************************/
+
+ColorManagedDisplay *colormanage_display_get_default(void)
+{
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ const char *display;
+
+ if (!config) {
+ /* no valid OCIO configuration, can't get default display */
+
+ return NULL;
+ }
+
+ display = OCIO_configGetDefaultDisplay(config);
+
+ OCIO_configRelease(config);
+
+ if (display[0] == '\0')
+ return NULL;
+
+ return colormanage_display_get_named(display);
+}
+
+ColorManagedDisplay *colormanage_display_add(const char *name)
+{
+ ColorManagedDisplay *display;
+ int index = 0;
+
+ if (global_displays.last) {
+ ColorManagedDisplay *last_display = global_displays.last;
+
+ index = last_display->index;
+ }
+
+ display = MEM_callocN(sizeof(ColorManagedDisplay), "ColorManagedDisplay");
+
+ display->index = index + 1;
+
+ BLI_strncpy(display->name, name, sizeof(display->name));
+
+ BLI_addtail(&global_displays, display);
+
+ return display;
+}
+
+ColorManagedDisplay *colormanage_display_get_named(const char *name)
+{
+ ColorManagedDisplay *display;
+
+ for (display = global_displays.first; display; display = display->next) {
+ if (!strcmp(display->name, name))
+ return display;
+ }
+
+ return NULL;
+}
+
+ColorManagedDisplay *colormanage_display_get_indexed(int index)
+{
+ /* display indices are 1-based */
+ return BLI_findlink(&global_displays, index - 1);
+}
+
+int IMB_colormanagement_display_get_named_index(const char *name)
+{
+ ColorManagedDisplay *display;
+
+ display = colormanage_display_get_named(name);
+
+ if (display) {
+ return display->index;
+ }
+
+ return 0;
+}
+
+const char *IMB_colormanagement_display_get_indexed_name(int index)
+{
+ ColorManagedDisplay *display;
+
+ display = colormanage_display_get_indexed(index);
+
+ if (display) {
+ return display->name;
+ }
+
+ return NULL;
+}
+
+const char *IMB_colormanagement_display_get_default_name(void)
+{
+ ColorManagedDisplay *display = colormanage_display_get_default();
+
+ return display->name;
+}
+
+/* used by performance-critical pixel processing areas, such as color widgets */
+ColorManagedDisplay *IMB_colormanagement_display_get_named(const char *name)
+{
+ return colormanage_display_get_named(name);
+}
+
+/*********************** View functions *************************/
+
+const char *colormanage_view_get_default_name(const ColorManagedDisplay *display)
+{
+ ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ const char *name;
+
+ if (!config) {
+ /* no valid OCIO configuration, can't get default view */
+
+ return NULL;
+ }
+
+ name = OCIO_configGetDefaultView(config, display->name);
+
+ OCIO_configRelease(config);
+
+ return name;
+}
+
+ColorManagedView *colormanage_view_get_default(const ColorManagedDisplay *display)
+{
+ const char *name = colormanage_view_get_default_name(display);
+
+ if (!name || name[0] == '\0')
+ return NULL;
+
+ return colormanage_view_get_named(name);
+}
+
+ColorManagedView *colormanage_view_add(const char *name)
+{
+ ColorManagedView *view;
+ int index = global_tot_view;
+
+ view = MEM_callocN(sizeof(ColorManagedView), "ColorManagedView");
+ view->index = index + 1;
+ BLI_strncpy(view->name, name, sizeof(view->name));
+
+ BLI_addtail(&global_views, view);
+
+ global_tot_view++;
+
+ return view;
+}
+
+ColorManagedView *colormanage_view_get_named(const char *name)
+{
+ ColorManagedView *view;
+
+ for (view = global_views.first; view; view = view->next) {
+ if (!strcmp(view->name, name))
+ return view;
+ }
+
+ return NULL;
+}
+
+ColorManagedView *colormanage_view_get_indexed(int index)
+{
+ /* view transform indices are 1-based */
+ return BLI_findlink(&global_views, index - 1);
+}
+
+int IMB_colormanagement_view_get_named_index(const char *name)
+{
+ ColorManagedView *view = colormanage_view_get_named(name);
+
+ if (view) {
+ return view->index;
+ }
+
+ return 0;
+}
+
+const char *IMB_colormanagement_view_get_indexed_name(int index)
+{
+ ColorManagedView *view = colormanage_view_get_indexed(index);
+
+ if (view) {
+ return view->name;
+ }
+
+ return NULL;
+}
+
+const char *IMB_colormanagement_view_get_default_name(const char *display_name)
+{
+ ColorManagedDisplay *display = colormanage_display_get_named(display_name);
+ ColorManagedView *view = colormanage_view_get_default(display);
+
+ if (view) {
+ return view->name;
+ }
+
+ return NULL;
+}
+
+/*********************** Color space functions *************************/
+
+static void colormanage_description_strip(char *description)
+{
+ int i, n;
+
+ for (i = strlen(description) - 1; i >= 0; i--) {
+ if (ELEM(description[i], '\r', '\n')) {
+ description[i] = '\0';
+ }
+ else {
+ break;
+ }
+ }
+
+ for (i = 0, n = strlen(description); i < n; i++) {
+ if (ELEM(description[i], '\r', '\n')) {
+ description[i] = ' ';
+ }
+ }
+}
+
+ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible)
+{
+ ColorSpace *colorspace, *prev_space;
+ int counter = 1;
+
+ colorspace = MEM_callocN(sizeof(ColorSpace), "ColorSpace");
+
+ BLI_strncpy(colorspace->name, name, sizeof(colorspace->name));
+
+ if (description) {
+ BLI_strncpy(colorspace->description, description, sizeof(colorspace->description));
+
+ colormanage_description_strip(colorspace->description);
+ }
+
+ colorspace->is_invertible = is_invertible;
+
+ for (prev_space = global_colorspaces.first; prev_space; prev_space = prev_space->next) {
+ if (BLI_strcasecmp(prev_space->name, colorspace->name) > 0)
+ break;
+
+ prev_space->index = counter++;
+ }
+
+ if (!prev_space)
+ BLI_addtail(&global_colorspaces, colorspace);
+ else
+ BLI_insertlinkbefore(&global_colorspaces, prev_space, colorspace);
+
+ colorspace->index = counter++;
+ for (; prev_space; prev_space = prev_space->next) {
+ prev_space->index = counter++;
+ }
+
+ global_tot_colorspace++;
+
+ return colorspace;
+}
+
+ColorSpace *colormanage_colorspace_get_named(const char *name)
+{
+ ColorSpace *colorspace;
+
+ for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) {
+ if (!strcmp(colorspace->name, name))
+ return colorspace;
+ }
+
+ return NULL;
+}
+
+ColorSpace *colormanage_colorspace_get_roled(int role)
+{
+ const char *role_colorspace = IMB_colormanagement_role_colorspace_name_get(role);
+
+ return colormanage_colorspace_get_named(role_colorspace);
+}
+
+ColorSpace *colormanage_colorspace_get_indexed(int index)
+{
+ /* display indices are 1-based */
+ return BLI_findlink(&global_colorspaces, index - 1);
+}
+
+int IMB_colormanagement_colorspace_get_named_index(const char *name)
+{
+ ColorSpace *colorspace;
+
+ colorspace = colormanage_colorspace_get_named(name);
+
+ if (colorspace) {
+ return colorspace->index;
+ }
+
+ return 0;
+}
+
+const char *IMB_colormanagement_colorspace_get_indexed_name(int index)
+{
+ ColorSpace *colorspace;
+
+ colorspace = colormanage_colorspace_get_indexed(index);
+
+ if (colorspace) {
+ return colorspace->name;
+ }
+
+ return "";
+}
+
+void IMB_colormanagment_colorspace_from_ibuf_ftype(ColorManagedColorspaceSettings *colorspace_settings, ImBuf *ibuf)
+{
+ ImFileType *type;
+
+ for (type = IMB_FILE_TYPES; type->is_a; type++) {
+ if (type->save && type->ftype(type, ibuf)) {
+ const char *role_colorspace;
+
+ role_colorspace = IMB_colormanagement_role_colorspace_name_get(type->default_save_role);
+
+ BLI_strncpy(colorspace_settings->name, role_colorspace, sizeof(colorspace_settings->name));
+ }
+ }
+}
+
+/*********************** RNA helper functions *************************/
+
+void IMB_colormanagement_display_items_add(EnumPropertyItem **items, int *totitem)
+{
+ ColorManagedDisplay *display;
+
+ for (display = global_displays.first; display; display = display->next) {
+ EnumPropertyItem item;
+
+ item.value = display->index;
+ item.name = display->name;
+ item.identifier = display->name;
+ item.icon = 0;
+ item.description = "";
+
+ RNA_enum_item_add(items, totitem, &item);
+ }
+}
+
+static void colormanagement_view_item_add(EnumPropertyItem **items, int *totitem, ColorManagedView *view)
+{
+ EnumPropertyItem item;
+
+ item.value = view->index;
+ item.name = view->name;
+ item.identifier = view->name;
+ item.icon = 0;
+ item.description = "";
+
+ RNA_enum_item_add(items, totitem, &item);
+}
+
+void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem, const char *display_name)
+{
+ ColorManagedDisplay *display = colormanage_display_get_named(display_name);
+ ColorManagedView *view;
+
+ if (display) {
+ LinkData *display_view;
+
+ for (display_view = display->views.first; display_view; display_view = display_view->next) {
+ view = display_view->data;
+
+ colormanagement_view_item_add(items, totitem, view);
+ }
+ }
+}
+
+void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *totitem)
+{
+ ColorSpace *colorspace;
+
+ for (colorspace = global_colorspaces.first; colorspace; colorspace = colorspace->next) {
+ EnumPropertyItem item;
+
+ if (!colorspace->is_invertible)
+ continue;
+
+ item.value = colorspace->index;
+ item.name = colorspace->name;
+ item.identifier = colorspace->name;
+ item.icon = 0;
+
+ if (colorspace->description)
+ item.description = colorspace->description;
+ else
+ item.description = "";
+
+ RNA_enum_item_add(items, totitem, &item);
+ }
+}
+
+/*********************** Partial display buffer update *************************/
+
+/*
+ * Partial display update is supposed to be used by such areas as
+ * compositor and renderer, This areas are calculating tiles of the
+ * images and because of performance reasons only this tiles should
+ * be color managed.
+ * This gives nice visual feedback without slowing things down.
+ *
+ * Updating happens for active display transformation only, all
+ * the rest buffers would be marked as dirty
+ */
+
+static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffer, const float *linear_buffer,
+ const unsigned char *byte_buffer, int display_stride, int linear_stride,
+ int linear_offset_x, int linear_offset_y, ColormanageProcessor *cm_processor,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ int x, y;
+ int channels = ibuf->channels;
+ int predivide = ibuf->flags & IB_cm_predivide;
+ float dither = ibuf->dither;
+ ColorSpace *rect_colorspace = ibuf->rect_colorspace;
+ float *display_buffer_float = NULL;
+ int width = xmax - xmin;
+ int height = ymax - ymin;
+
+ if (dither != 0.0f) {
+ display_buffer_float = MEM_callocN(channels * width * height * sizeof(float), "display buffer for dither");
+ }
+
+ for (y = ymin; y < ymax; y++) {
+ for (x = xmin; x < xmax; x++) {
+ int display_index = (y * display_stride + x) * channels;
+ int linear_index = ((y - linear_offset_y) * linear_stride + (x - linear_offset_x)) * channels;
+ float pixel[4];
+
+ if (linear_buffer) {
+ copy_v4_v4(pixel, (float *) linear_buffer + linear_index);
+ }
+ else if (byte_buffer) {
+ rgba_uchar_to_float(pixel, byte_buffer + linear_index);
+
+ IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
+ }
+
+ if (predivide)
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ else
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+
+ if (display_buffer_float) {
+ int index = ((y - ymin) * width + (x - xmin)) * channels;
+
+ copy_v4_v4(display_buffer_float + index, pixel);
+ }
+ else {
+ rgba_float_to_uchar(display_buffer + display_index, pixel);
+ }
+ }
+ }
+
+ if (display_buffer_float) {
+ int display_index = (ymin * display_stride + xmin) * channels;
+
+ IMB_buffer_byte_from_float(display_buffer + display_index, display_buffer_float, channels, dither,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, width, height, display_stride, width);
+
+ MEM_freeN(display_buffer_float);
+ }
+}
+
+void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer,
+ int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings,
+ int xmin, int ymin, int xmax, int ymax)
+{
+ if (ibuf->rect && ibuf->rect_float) {
+ /* update byte buffer created by legacy color management */
+
+ unsigned char *rect = (unsigned char *) ibuf->rect;
+ int predivide = ibuf->flags & IB_cm_predivide;
+ int channels = ibuf->channels;
+ int width = xmax - xmin;
+ int height = ymax - ymin;
+ int rect_index = (ymin * ibuf->x + xmin) * channels;
+ int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels;
+
+ IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither,
+ IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, ibuf->x, stride);
+ }
+
+ if (ibuf->display_buffer_flags) {
+ ColormanageCacheViewSettings cache_view_settings;
+ ColormanageCacheDisplaySettings cache_display_settings;
+ void *cache_handle = NULL;
+ unsigned char *display_buffer = NULL;
+ int view_flag, display_index, buffer_width;
+
+ colormanage_view_settings_to_cache(&cache_view_settings, view_settings);
+ colormanage_display_settings_to_cache(&cache_display_settings, display_settings);
+
+ view_flag = 1 << (cache_view_settings.view - 1);
+ display_index = cache_display_settings.display - 1;
+
+ BLI_lock_thread(LOCK_COLORMANAGE);
+ if ((ibuf->userflags & IB_DISPLAY_BUFFER_INVALID) == 0)
+ display_buffer = colormanage_cache_get(ibuf, &cache_view_settings, &cache_display_settings, &cache_handle);
+
+ /* in some rare cases buffer's dimension could be changing directly from
+ * different thread
+ * this i.e. happens when image editor acquires render result
+ */
+ buffer_width = ibuf->x;
+
+ /* mark all other buffers as invalid */
+ memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int));
+ ibuf->display_buffer_flags[display_index] |= view_flag;
+
+ BLI_unlock_thread(LOCK_COLORMANAGE);
+
+ if (display_buffer) {
+ ColormanageProcessor *cm_processor;
+
+ cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
+
+ partial_buffer_update_rect(ibuf, display_buffer, linear_buffer, byte_buffer, buffer_width, stride,
+ offset_x, offset_y, cm_processor, xmin, ymin, xmax, ymax);
+
+ IMB_colormanagement_processor_free(cm_processor);
+
+ IMB_display_buffer_release(cache_handle);
+ }
+ }
+}
+
+/*********************** Pixel processor functions *************************/
+
+ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
+{
+ ColormanageProcessor *cm_processor;
+
+ cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor");
+
+ {
+ ColorManagedViewSettings default_view_settings;
+ const ColorManagedViewSettings *applied_view_settings;
+
+ if (view_settings) {
+ applied_view_settings = view_settings;
+ }
+ else {
+ init_default_view_settings(display_settings, &default_view_settings);
+ applied_view_settings = &default_view_settings;
+ }
+
+ cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device,
+ applied_view_settings->exposure, applied_view_settings->gamma);
+
+ if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) {
+ cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping);
+ curvemapping_premultiply(cm_processor->curve_mapping, FALSE);
+ }
+ }
+
+ return cm_processor;
+}
+
+ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace)
+{
+ ColormanageProcessor *cm_processor;
+
+ cm_processor = MEM_callocN(sizeof(ColormanageProcessor), "colormanagement processor");
+
+ cm_processor->processor = create_colorspace_transform_processor(from_colorspace, to_colorspace);
+
+ return cm_processor;
+}
+
+void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, float pixel[4])
+{
+ if (cm_processor->curve_mapping)
+ curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
+
+ OCIO_processorApplyRGBA(cm_processor->processor, pixel);
+}
+
+void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3])
+{
+ if (cm_processor->curve_mapping)
+ curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
+
+ OCIO_processorApplyRGB(cm_processor->processor, pixel);
+}
+
+void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height,
+ int channels, int predivide)
+{
+ /* apply curve mapping */
+ if (cm_processor->curve_mapping) {
+ int x, y;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ float *pixel = buffer + channels * (y * width + x);
+
+ curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels);
+ }
+ }
+ }
+
+ {
+ PackedImageDesc *img;
+
+ /* apply OCIO processor */
+ img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float),
+ channels * sizeof(float), channels * sizeof(float) * width);
+
+ if (predivide)
+ OCIO_processorApply_predivide(cm_processor->processor, img);
+ else
+ OCIO_processorApply(cm_processor->processor, img);
+
+ OCIO_packedImageDescRelease(img);
+ }
+}
+
+void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
+{
+ if (cm_processor->curve_mapping)
+ curvemapping_free(cm_processor->curve_mapping);
+
+ OCIO_processorRelease(cm_processor->processor);
+
+ MEM_freeN(cm_processor);
+}
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
index 71313d4438f..7aacbf20bae 100644
--- a/source/blender/imbuf/intern/dds/dds_api.cpp
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -43,6 +43,9 @@ extern "C" {
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
int imb_save_dds(struct ImBuf * ibuf, const char *name, int flags)
{
return(0); /* todo: finish this function */
@@ -79,7 +82,7 @@ int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
return(1);
}
-struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf * ibuf = 0;
DirectDrawSurface dds(mem, size); /* reads header */
@@ -92,6 +95,12 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
Color32 pixel;
Color32 *pixels = 0;
+ /* OCIO_TODO: never was able to save DDS, so can'ttest loading
+ * but profile used to be set to sRGB and can't see rect_float here, so
+ * default byte space should work fine
+ */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
if (!imb_is_a_dds(mem))
return (0);
@@ -133,7 +142,6 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags)
if (ibuf == 0) return(0); /* memory allocation failed */
ibuf->ftype = DDS;
- ibuf->profile = IB_PROFILE_SRGB;
ibuf->dds_data.fourcc = dds.fourCC();
ibuf->dds_data.nummipmaps = dds.mipmapCount();
diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h
index 589257816e0..2316fefce69 100644
--- a/source/blender/imbuf/intern/dds/dds_api.h
+++ b/source/blender/imbuf/intern/dds/dds_api.h
@@ -32,9 +32,11 @@
extern "C" {
#endif
+#include "../../IMB_imbuf.h"
+
int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags);
int imb_is_a_dds(unsigned char *mem); /* use only first 32 bytes of mem */
-struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 8acceb77b36..9ce5d0e30da 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -40,6 +40,9 @@
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "MEM_guardedalloc.h"
/**************************** Interlace/Deinterlace **************************/
@@ -522,32 +525,34 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
void IMB_rect_from_float(ImBuf *ibuf)
{
int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from;
+ float *buffer;
+ const char *from_colorspace;
/* verify we have a float buffer */
if (ibuf->rect_float == NULL)
return;
/* create byte rect if it didn't exist yet */
- if (ibuf->rect == NULL)
- imb_addrectImBuf(ibuf);
-
- /* determine profiles */
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- profile_from = IB_PROFILE_LINEAR_RGB;
- }
- else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) {
- profile_from = IB_PROFILE_SRGB;
- }
- else {
- profile_from = IB_PROFILE_SRGB; /* should never happen */
- BLI_assert(0);
+ if (ibuf->rect == NULL) {
+ if (imb_addrectImBuf(ibuf) == 0)
+ return;
}
- /* do conversion */
- IMB_buffer_byte_from_float((uchar *)ibuf->rect, ibuf->rect_float,
- ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ if (ibuf->float_colorspace == NULL)
+ from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ else
+ from_colorspace = ibuf->float_colorspace->name;
+
+ buffer = MEM_dupallocN(ibuf->rect_float);
+
+ /* first make float buffer in byte space */
+ IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide);
+
+ /* convert float to byte */
+ IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+
+ MEM_freeN(buffer);
/* ensure user flag is reset */
ibuf->userflags &= ~IB_RECT_INVALID;
@@ -559,7 +564,7 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
float *rect_float;
uchar *rect_byte;
int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from;
+ int profile_from = IB_PROFILE_LINEAR_RGB;
/* verify we have a float buffer */
if (ibuf->rect_float == NULL || buffer == NULL)
@@ -569,18 +574,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
if (ibuf->rect == NULL)
imb_addrectImBuf(ibuf);
- /* determine profiles */
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- profile_from = IB_PROFILE_LINEAR_RGB;
- }
- else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE)) {
- profile_from = IB_PROFILE_SRGB;
- }
- else {
- profile_from = IB_PROFILE_SRGB; /* should never happen */
- BLI_assert(0);
- }
-
/* do conversion */
rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels;
rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4;
@@ -589,6 +582,7 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
w, h, w, ibuf->x);
+ /* XXX: need to convert to image buffer's rect space */
IMB_buffer_byte_from_float(rect_byte, buffer,
4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0,
w, h, ibuf->x, w);
@@ -600,26 +594,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
void IMB_float_from_rect(ImBuf *ibuf)
{
int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from;
/* verify if we byte and float buffers */
if (ibuf->rect == NULL)
return;
- if (ibuf->rect_float == NULL)
+ if (ibuf->rect_float == NULL) {
if (imb_addrectfloatImBuf(ibuf) == 0)
return;
-
- /* determine profiles */
- if (ibuf->profile == IB_PROFILE_NONE)
- profile_from = IB_PROFILE_LINEAR_RGB;
- else
- profile_from = IB_PROFILE_SRGB;
-
- /* do conversion */
- IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
- IB_PROFILE_LINEAR_RGB, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ }
+
+ /* first, create float buffer in non-linear space */
+ IMB_buffer_float_from_byte(ibuf->rect_float, (unsigned char *) ibuf->rect, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ FALSE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+
+ /* then make float be in linear space */
+ IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
+ ibuf->rect_colorspace, predivide);
}
/* no profile conversion */
@@ -635,63 +626,19 @@ void IMB_float_from_rect_simple(ImBuf *ibuf)
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
}
-void IMB_convert_profile(ImBuf *ibuf, int profile)
-{
- int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from, profile_to;
-
- if (ibuf->profile == profile)
- return;
-
- /* determine profiles */
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
- profile_from = IB_PROFILE_LINEAR_RGB;
- else if (ELEM(ibuf->profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
- profile_from = IB_PROFILE_SRGB;
- else {
- BLI_assert(0);
- profile_from = IB_PROFILE_SRGB; /* dummy, should never happen */
- }
-
- if (profile == IB_PROFILE_LINEAR_RGB)
- profile_to = IB_PROFILE_LINEAR_RGB;
- else if (ELEM(profile, IB_PROFILE_SRGB, IB_PROFILE_NONE))
- profile_to = IB_PROFILE_SRGB;
- else {
- BLI_assert(0);
- profile_to = IB_PROFILE_SRGB; /* dummy, should never happen */
- }
-
- /* do conversion */
- if (ibuf->rect_float) {
- IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float,
- 4, profile_to, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
-
- if (ibuf->rect) {
- IMB_buffer_byte_from_byte((uchar *)ibuf->rect, (uchar *)ibuf->rect,
- profile_to, profile_from, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
- }
-
- /* set new profile */
- ibuf->profile = profile;
-}
-
/* use when you need to get a buffer with a certain profile
* if the return */
+
+/* OCIO_TODO: used only by Cineon/DPX exporter which is still broken, so can not guarantee
+ * this function is working properly
+ */
float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
{
int predivide = (ibuf->flags & IB_cm_predivide);
- int profile_from, profile_to;
-
- /* determine profiles */
- if (ibuf->profile == IB_PROFILE_NONE)
- profile_from = IB_PROFILE_LINEAR_RGB;
- else
- profile_from = IB_PROFILE_SRGB;
+ int profile_from = IB_PROFILE_LINEAR_RGB;
+ int profile_to;
+ /* determine profile */
if (profile == IB_PROFILE_NONE)
profile_to = IB_PROFILE_LINEAR_RGB;
else
diff --git a/source/blender/imbuf/intern/filetype.c b/source/blender/imbuf/intern/filetype.c
index d67de3be68b..ed4db50035d 100644
--- a/source/blender/imbuf/intern/filetype.c
+++ b/source/blender/imbuf/intern/filetype.c
@@ -30,6 +30,8 @@
#include "IMB_imbuf_types.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+
#ifdef WITH_OPENEXR
#include "openexr/openexr_api.h"
#endif
@@ -66,34 +68,34 @@ void quicktime_exit(void);
#endif
ImFileType IMB_FILE_TYPES[] = {
- {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG},
- {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG},
- {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP},
- {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA},
- {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC},
+ {NULL, NULL, imb_is_a_jpeg, imb_ftype_default, imb_load_jpeg, imb_savejpeg, NULL, 0, JPG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_png, imb_ftype_default, imb_loadpng, imb_savepng, NULL, 0, PNG, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_bmp, imb_ftype_default, imb_bmp_decode, imb_savebmp, NULL, 0, BMP, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_targa, imb_ftype_default, imb_loadtarga, imb_savetarga, NULL, 0, TGA, COLOR_ROLE_DEFAULT_BYTE},
+ {NULL, NULL, imb_is_a_iris, imb_ftype_iris, imb_loadiris, imb_saveiris, NULL, 0, IMAGIC, COLOR_ROLE_DEFAULT_BYTE},
#ifdef WITH_CINEON
- {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX},
- {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON},
+ {NULL, NULL, imb_is_dpx, imb_ftype_default, imb_loaddpx, imb_save_dpx, NULL, IM_FTYPE_FLOAT, DPX, COLOR_ROLE_DEFAULT_FLOAT},
+ {NULL, NULL, imb_is_cineon, imb_ftype_default, imb_loadcineon, imb_savecineon, NULL, IM_FTYPE_FLOAT, CINEON, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_TIFF
- {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF},
+ {imb_inittiff, NULL, imb_is_a_tiff, imb_ftype_default, imb_loadtiff, imb_savetiff, imb_loadtiletiff, 0, TIF, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_HDR
- {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR},
+ {NULL, NULL, imb_is_a_hdr, imb_ftype_default, imb_loadhdr, imb_savehdr, NULL, IM_FTYPE_FLOAT, RADHDR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENEXR
- {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR},
+ {imb_initopenexr, NULL, imb_is_a_openexr, imb_ftype_default, imb_load_openexr, imb_save_openexr, NULL, IM_FTYPE_FLOAT, OPENEXR, COLOR_ROLE_DEFAULT_FLOAT},
#endif
#ifdef WITH_OPENJPEG
- {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2},
+ {NULL, NULL, imb_is_a_jp2, imb_ftype_default, imb_jp2_decode, imb_savejp2, NULL, IM_FTYPE_FLOAT, JP2, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_DDS
- {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS},
+ {NULL, NULL, imb_is_a_dds, imb_ftype_default, imb_load_dds, NULL, NULL, 0, DDS, COLOR_ROLE_DEFAULT_BYTE},
#endif
#ifdef WITH_QUICKTIME
- {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME},
+ {quicktime_init, quicktime_exit, imb_is_a_quicktime, imb_ftype_quicktime, imb_quicktime_decode, NULL, NULL, 0, QUICKTIME, COLOR_ROLE_DEFAULT_BYTE},
#endif
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0}
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0}
};
void imb_filetypes_init(void)
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index ea493e277f3..97316c48621 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -1254,7 +1254,8 @@ struct anim *IMB_anim_open_proxy(
get_proxy_filename(anim, preview_size, fname, FALSE);
- anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0);
+ /* proxies are generated in default color space */
+ anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, NULL);
anim->proxies_tried |= preview_size;
diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c
index 13b0fc1b55a..3fd25fff92f 100644
--- a/source/blender/imbuf/intern/iris.c
+++ b/source/blender/imbuf/intern/iris.c
@@ -42,6 +42,9 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
typedef struct {
unsigned short imagic; /* stuff saved on disk . . */
unsigned short type;
@@ -247,7 +250,7 @@ int imb_is_a_iris(unsigned char *mem)
*
*/
-struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
unsigned int *base, *lptr = NULL;
float *fbase, *fptr = NULL;
@@ -265,6 +268,9 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags)
if (!imb_is_a_iris(mem)) return NULL;
+ /* OCIO_TODO: only tested with 1 byte per pixel, not sure how to test with other settings */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
/*printf("new iris\n");*/
file_data = mem;
@@ -523,7 +529,6 @@ struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags)
}
ibuf->ftype = IMAGIC;
- ibuf->profile = IB_PROFILE_SRGB;
test_endian_zbuf(ibuf);
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index 1fe9a5ab522..dd559c55402 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -36,6 +36,9 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "openjpeg.h"
#define JP2_FILEHEADER_SIZE 14
@@ -109,7 +112,7 @@ static void info_callback(const char *msg, void *client_data)
} \
} (void)0 \
-struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
int use_float = FALSE; /* for precision higher then 8 use float */
@@ -137,6 +140,9 @@ struct ImBuf *imb_jp2_decode(unsigned char *mem, size_t size, int flags)
if (!is_jp2 && !is_j2k)
return(NULL);
+ /* both 8, 12 and 16 bit JP2Ks are default to standard byte colorspace */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
/* configure the event callbacks (not required) */
memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
event_mgr.error_handler = error_callback;
@@ -641,136 +647,67 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters)
switch (prec) {
case 8: /* Convert blenders float color channels to 8, 12 or 16bit ints */
if (numcomps == 4) {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]);
- a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]);
}
+ PIXEL_LOOPER_END;
}
else {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2]));
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[2]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(linearrgb_to_srgb(rect_float[2]));
}
+ PIXEL_LOOPER_END;
}
break;
case 12:
if (numcomps == 4) {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]);
- a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]);
}
+ PIXEL_LOOPER_END;
}
else {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2]));
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[2]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(linearrgb_to_srgb(rect_float[2]));
}
+ PIXEL_LOOPER_END;
}
break;
case 16:
if (numcomps == 4) {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2]));
- a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]);
- a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2]));
+ a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]);
}
+ PIXEL_LOOPER_END;
}
else {
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0]));
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1]));
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2]));
- }
- PIXEL_LOOPER_END;
- }
- else {
- PIXEL_LOOPER_BEGIN(rect_float)
- {
- r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[0]);
- g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[1]);
- b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[2]);
- }
- PIXEL_LOOPER_END;
+ PIXEL_LOOPER_BEGIN(rect_float)
+ {
+ r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[0]));
+ g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[1]));
+ b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(linearrgb_to_srgb(rect_float[2]));
}
+ PIXEL_LOOPER_END;
}
break;
}
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index 364950b99cb..691db96989d 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -48,6 +48,9 @@
#include "jpeglib.h"
#include "jerror.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#define IS_jpg(x) (x->ftype & JPG)
#define IS_stdjpg(x) ((x->ftype & JPG_MSK) == JPG_STD)
#define IS_vidjpg(x) ((x->ftype & JPG_MSK) == JPG_VID)
@@ -435,21 +438,22 @@ next_stamp_marker:
jpeg_destroy((j_common_ptr) cinfo);
if (ibuf) {
ibuf->ftype = ibuf_ftype;
- ibuf->profile = IB_PROFILE_SRGB;
}
}
return(ibuf);
}
-ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags)
+ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
struct my_error_mgr jerr;
ImBuf *ibuf;
if (!imb_is_a_jpeg(buffer)) return NULL;
-
+
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
cinfo->err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg_error;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 26aab29b8dd..13078921d1c 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -64,6 +64,9 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void)
#include "IMB_allocimbuf.h"
#include "IMB_metadata.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "openexr_multi.h"
}
@@ -379,30 +382,15 @@ static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags
else {
unsigned char *from;
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB) {
- for (int i = ibuf->y - 1; i >= 0; i--) {
- from = (unsigned char *)ibuf->rect + channels * i * width;
+ for (int i = ibuf->y - 1; i >= 0; i--) {
+ from = (unsigned char *)ibuf->rect + channels * i * width;
- for (int j = ibuf->x; j > 0; j--) {
- to->r = (float)(from[0]) / 255.0f;
- to->g = (float)(from[1]) / 255.0f;
- to->b = (float)(from[2]) / 255.0f;
- to->a = (float)(channels >= 4) ? from[3] / 255.0f : 1.0f;
- to++; from += 4;
- }
- }
- }
- else {
- for (int i = ibuf->y - 1; i >= 0; i--) {
- from = (unsigned char *)ibuf->rect + channels * i * width;
-
- for (int j = ibuf->x; j > 0; j--) {
- to->r = srgb_to_linearrgb((float)from[0] / 255.0f);
- to->g = srgb_to_linearrgb((float)from[1] / 255.0f);
- to->b = srgb_to_linearrgb((float)from[2] / 255.0f);
- to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f;
- to++; from += 4;
- }
+ for (int j = ibuf->x; j > 0; j--) {
+ to->r = srgb_to_linearrgb((float)from[0] / 255.0f);
+ to->g = srgb_to_linearrgb((float)from[1] / 255.0f);
+ to->b = srgb_to_linearrgb((float)from[2] / 255.0f);
+ to->a = channels >= 4 ? (float)from[3] / 255.0f : 1.0f;
+ to++; from += 4;
}
}
}
@@ -1129,13 +1117,15 @@ static int exr_is_multilayer(InputFile *file)
return 0;
}
-struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
InputFile *file = NULL;
if (imb_is_a_openexr(mem) == 0) return(NULL);
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
+
try
{
Mem_IStream *membuf = new Mem_IStream(mem, size);
@@ -1164,9 +1154,6 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags)
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0);
ibuf->ftype = OPENEXR;
- /* openEXR is linear as per EXR spec */
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
-
if (!(flags & IB_test)) {
if (is_multi) { /* only enters with IB_multilayer flag set */
/* constructs channels for reading, allocates memory in channels */
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h
index d12fe2fc49f..3135795fb3f 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.h
+++ b/source/blender/imbuf/intern/openexr/openexr_api.h
@@ -50,7 +50,7 @@ int imb_is_a_openexr (unsigned char *mem);
int imb_save_openexr (struct ImBuf *ibuf, const char *name, int flags);
-struct ImBuf *imb_load_openexr (unsigned char *mem, size_t size, int flags);
+struct ImBuf *imb_load_openexr (unsigned char *mem, size_t size, int flags, char *colorspace);
#ifdef __cplusplus
}
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index 92cd9622849..6310d8e105f 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -47,6 +47,9 @@
#include "IMB_metadata.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
typedef struct PNGReadStruct {
unsigned char *data;
unsigned int size;
@@ -302,7 +305,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
return(1);
}
-ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
+ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
png_structp png_ptr;
@@ -317,11 +320,13 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
unsigned char *from, *to;
unsigned short *from16;
float *to_float;
- float tmp[4];
int i, bytesperpixel;
if (imb_is_a_png(mem) == 0) return(NULL);
+ /* both 8 and 16 bit PNGs are default to standard byte colorspace */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL);
if (png_ptr == NULL) {
@@ -389,10 +394,6 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
if (ibuf) {
ibuf->ftype = PNG;
- if (bit_depth == 16)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
- else
- ibuf->profile = IB_PROFILE_SRGB;
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
int unit_type;
@@ -443,37 +444,33 @@ ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
switch (bytesperpixel) {
case 4:
for (i = ibuf->x * ibuf->y; i > 0; i--) {
- tmp[0] = from16[0] / 65535.0;
- tmp[1] = from16[1] / 65535.0;
- tmp[2] = from16[2] / 65535.0;
- tmp[3] = from16[3] / 65535.0;
- srgb_to_linearrgb_v4(to_float, tmp);
+ to_float[0] = from16[0] / 65535.0;
+ to_float[1] = from16[1] / 65535.0;
+ to_float[2] = from16[2] / 65535.0;
+ to_float[3] = from16[3] / 65535.0;
to_float += 4; from16 += 4;
}
break;
case 3:
for (i = ibuf->x * ibuf->y; i > 0; i--) {
- tmp[0] = from16[0] / 65535.0;
- tmp[1] = from16[1] / 65535.0;
- tmp[2] = from16[2] / 65535.0;
- tmp[3] = 1.0;
- srgb_to_linearrgb_v4(to_float, tmp);
+ to_float[0] = from16[0] / 65535.0;
+ to_float[1] = from16[1] / 65535.0;
+ to_float[2] = from16[2] / 65535.0;
+ to_float[3] = 1.0;
to_float += 4; from16 += 3;
}
break;
case 2:
for (i = ibuf->x * ibuf->y; i > 0; i--) {
- tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0;
- tmp[3] = from16[1] / 65535.0;
- srgb_to_linearrgb_v4(to_float, tmp);
+ to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
+ to_float[3] = from16[1] / 65535.0;
to_float += 4; from16 += 2;
}
break;
case 1:
for (i = ibuf->x * ibuf->y; i > 0; i--) {
- tmp[0] = tmp[1] = tmp[2] = from16[0] / 65535.0;
- tmp[3] = 1.0;
- srgb_to_linearrgb_v4(to_float, tmp);
+ to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
+ to_float[3] = 1.0;
to_float += 4; from16++;
}
break;
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 4cd50484a64..5add372cd4e 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -53,6 +53,9 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
/* needed constants */
#define MINELEN 8
#define MAXELEN 0x7fff
@@ -171,7 +174,7 @@ int imb_is_a_hdr(unsigned char *buf)
return 0;
}
-struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags)
+struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf;
RGBE *sline;
@@ -184,6 +187,8 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags)
char oriY[80], oriX[80];
if (imb_is_a_hdr((void *)mem)) {
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_FLOAT);
+
/* find empty line, next line is resolution info */
for (x = 1; x < size; x++) {
if ((mem[x - 1] == '\n') && (mem[x] == '\n')) {
@@ -207,7 +212,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags)
if (ibuf == NULL) return NULL;
ibuf->ftype = RADHDR;
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
if (flags & IB_test) return ibuf;
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 4bde71588b7..a1fa05d1098 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -54,20 +54,42 @@
#include "IMB_imbuf.h"
#include "IMB_filetype.h"
-ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, const char *descr)
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
+ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
ImFileType *type;
+ char effective_colorspace[IM_MAX_SPACE] = "";
if (mem == NULL) {
fprintf(stderr, "%s: NULL pointer\n", __func__);
return NULL;
}
+ if (colorspace)
+ BLI_strncpy(effective_colorspace, colorspace, sizeof(effective_colorspace));
+
for (type = IMB_FILE_TYPES; type->is_a; type++) {
if (type->load) {
- ibuf = type->load(mem, size, flags);
+ ibuf = type->load(mem, size, flags, effective_colorspace);
if (ibuf) {
+ if (colorspace) {
+ if (ibuf->rect) {
+ /* byte buffer is never internally converted to some standard space,
+ * store pointer to it's color space descriptor instead
+ */
+ ibuf->rect_colorspace = colormanage_colorspace_get_named(effective_colorspace);
+ }
+
+ BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
+ }
+
+ /* OCIO_TODO: in some cases it's faster to do threaded conversion,
+ * but how to distinguish such cases */
+ colormanage_imbuf_make_linear(ibuf, effective_colorspace);
+
if (flags & IB_premul) {
IMB_premultiply_alpha(ibuf);
ibuf->flags |= IB_premul;
@@ -83,7 +105,7 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, const c
return NULL;
}
-ImBuf *IMB_loadifffile(int file, int flags, const char *descr)
+ImBuf *IMB_loadifffile(int file, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
{
ImBuf *ibuf;
unsigned char *mem;
@@ -99,7 +121,7 @@ ImBuf *IMB_loadifffile(int file, int flags, const char *descr)
return NULL;
}
- ibuf = IMB_ibImageFromMemory(mem, size, flags, descr);
+ ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr);
if (munmap(mem, size))
fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr);
@@ -122,7 +144,7 @@ static void imb_cache_filename(char *filename, const char *name, int flags)
BLI_strncpy(filename, name, IB_FILENAME_SIZE);
}
-ImBuf *IMB_loadiffname(const char *filepath, int flags)
+ImBuf *IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
int file, a;
@@ -133,7 +155,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags)
file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
if (file < 0) return NULL;
- ibuf = IMB_loadifffile(file, flags, filepath_tx);
+ ibuf = IMB_loadifffile(file, flags, colorspace, filepath_tx);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
@@ -148,7 +170,7 @@ ImBuf *IMB_loadiffname(const char *filepath, int flags)
return ibuf;
}
-ImBuf *IMB_testiffname(const char *filepath, int flags)
+ImBuf *IMB_testiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
{
ImBuf *ibuf;
int file;
@@ -159,7 +181,7 @@ ImBuf *IMB_testiffname(const char *filepath, int flags)
file = BLI_open(filepath_tx, O_BINARY | O_RDONLY, 0);
if (file < 0) return NULL;
- ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, filepath_tx);
+ ibuf = IMB_loadifffile(file, flags | IB_test | IB_multilayer, colorspace, filepath_tx);
if (ibuf) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index c3e23246638..a11f16d5669 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -42,6 +42,7 @@
#include "IMB_imbuf.h"
#include "IMB_allocimbuf.h"
+#include "IMB_colormanagement.h"
/* blend modes */
@@ -486,7 +487,7 @@ void IMB_rectfill(struct ImBuf *drect, const float col[4])
void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
- const float col[4], const int do_color_management,
+ const float col[4], struct ColorManagedDisplay *display,
int x1, int y1, int x2, int y2)
{
int i, j;
@@ -553,11 +554,12 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
float col_conv[4];
float *pixel;
- if (do_color_management) {
- srgb_to_linearrgb_v4(col_conv, col);
+ if (display) {
+ copy_v4_v4(col_conv, col);
+ IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
}
else {
- copy_v4_v4(col_conv, col);
+ srgb_to_linearrgb_v4(col_conv, col);
}
for (j = 0; j < y2 - y1; j++) {
@@ -581,12 +583,10 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
}
}
-void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2)
+void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display)
{
- int do_color_management;
if (!ibuf) return;
- do_color_management = (ibuf->profile == IB_PROFILE_LINEAR_RGB);
- buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, do_color_management,
+ buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display,
x1, y1, x2, y2);
}
diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c
index 2f7452772ef..253680e4bea 100644
--- a/source/blender/imbuf/intern/targa.c
+++ b/source/blender/imbuf/intern/targa.c
@@ -46,6 +46,8 @@
#include "IMB_allocimbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
/* this one is only def-ed once, strangely... related to GS? */
#define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
@@ -546,22 +548,23 @@ partial_load:
}
-ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags)
+ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colorspace[IM_MAX_SPACE])
{
TARGA tga;
struct ImBuf *ibuf;
int col, count, size;
unsigned int *rect, *cmap = NULL /*, mincol = 0*/, maxcol = 0;
uchar *cp = (uchar *) &col;
-
+
if (checktarga(&tga, mem) == 0) return(NULL);
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0);
else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect);
if (ibuf == NULL) return(NULL);
ibuf->ftype = TGA;
- ibuf->profile = IB_PROFILE_SRGB;
mem = mem + 18 + tga.numid;
cp[0] = 0xff;
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
index 2a2aedb49ff..ff7218d649c 100644
--- a/source/blender/imbuf/intern/thumbs.c
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -313,7 +313,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
img = IMB_loadblend_thumb(path);
}
else {
- img = IMB_loadiffname(path, IB_rect | IB_metadata);
+ img = IMB_loadiffname(path, IB_rect | IB_metadata, NULL);
}
}
@@ -326,7 +326,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
}
else if (THB_SOURCE_MOVIE == source) {
struct anim *anim = NULL;
- anim = IMB_open_anim(path, IB_rect | IB_metadata, 0);
+ anim = IMB_open_anim(path, IB_rect | IB_metadata, 0, NULL);
if (anim != NULL) {
img = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
if (img == NULL) {
@@ -376,6 +376,7 @@ ImBuf *IMB_thumb_create(const char *path, ThumbSize size, ThumbSource source, Im
}
img->ftype = PNG;
img->planes = 32;
+
if (IMB_saveiff(img, temp, IB_rect | IB_metadata)) {
#ifndef WIN32
chmod(temp, S_IRUSR | S_IWUSR);
@@ -401,7 +402,7 @@ ImBuf *IMB_thumb_read(const char *path, ThumbSize size)
return NULL;
}
if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
- img = IMB_loadiffname(thumb, IB_rect | IB_metadata);
+ img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL);
}
return img;
@@ -456,10 +457,10 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source)
if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
if (BLI_path_ncmp(path, thumb, sizeof(thumb)) == 0) {
- img = IMB_loadiffname(path, IB_rect);
+ img = IMB_loadiffname(path, IB_rect, NULL);
}
else {
- img = IMB_loadiffname(thumb, IB_rect | IB_metadata);
+ img = IMB_loadiffname(thumb, IB_rect | IB_metadata, NULL);
if (img) {
char mtime[40];
if (!IMB_metadata_get_field(img, "Thumb::MTime", mtime, 40)) {
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index ac5f5da8a67..932a4941a0a 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -57,6 +57,9 @@
#include "IMB_filetype.h"
#include "IMB_filter.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "tiffio.h"
#ifdef WIN32
@@ -464,8 +467,6 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
_TIFFfree(sbuf);
if (success) {
- ibuf->profile = (bitspersample == 32) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
-
/* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */
if (bitspersample < 16)
if (ENDIAN_ORDER == B_ENDIAN)
@@ -508,7 +509,7 @@ void imb_inittiff(void)
*
* \return: A newly allocated ImBuf structure if successful, otherwise NULL.
*/
-ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags)
+ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
TIFF *image = NULL;
ImBuf *ibuf = NULL, *hbuf;
@@ -527,6 +528,9 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags)
if (imb_is_a_tiff(mem) == 0)
return NULL;
+ /* both 8 and 16 bit PNGs are default to standard byte colorspace */
+ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
+
image = imb_tiff_client_open(&memFile, mem, size);
if (image == NULL) {
@@ -786,10 +790,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
/* convert from float source */
float rgb[4];
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
- linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
- else
- copy_v3_v3(rgb, &fromf[from_i]);
+ linearrgb_to_srgb_v3_v3(rgb, &fromf[from_i]);
rgb[3] = fromf[from_i + 3];
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 1c182e9784e..5d785e08212 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -38,8 +38,28 @@
#include "IMB_imbuf.h"
#include "IMB_filetype.h"
+#include "IMB_colormanagement.h"
+#include "IMB_colormanagement_intern.h"
+
#include "imbuf.h"
+static ImBuf *prepare_write_imbuf(ImFileType *type, ImBuf *ibuf)
+{
+ ImBuf *write_ibuf = ibuf;
+
+ if (type->flag & IM_FTYPE_FLOAT) {
+ /* pass */
+ }
+ else {
+ if (ibuf->rect == NULL && ibuf->rect_float) {
+ ibuf->rect_colorspace = colormanage_colorspace_get_roled(COLOR_ROLE_DEFAULT_BYTE);
+ IMB_rect_from_float(ibuf);
+ }
+ }
+
+ return write_ibuf;
+}
+
short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
{
ImFileType *type;
@@ -49,11 +69,17 @@ short IMB_saveiff(struct ImBuf *ibuf, const char *name, int flags)
for (type = IMB_FILE_TYPES; type->is_a; type++) {
if (type->save && type->ftype(type, ibuf)) {
- if (!(type->flag & IM_FTYPE_FLOAT)) {
- if (ibuf->rect == NULL && ibuf->rect_float)
- IMB_rect_from_float(ibuf);
- }
- return type->save(ibuf, name, flags);
+ ImBuf *write_ibuf;
+ short result = FALSE;
+
+ write_ibuf = prepare_write_imbuf(type, ibuf);
+
+ result = type->save(write_ibuf, name, flags);
+
+ if (write_ibuf != ibuf)
+ IMB_freeImBuf(write_ibuf);
+
+ return result;
}
}
diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h
index 4ead26c04f3..32a0629c338 100644
--- a/source/blender/makesdna/DNA_color_types.h
+++ b/source/blender/makesdna/DNA_color_types.h
@@ -160,6 +160,26 @@ typedef struct Scopes {
#define SCOPES_WAVEFRM_YCC_709 3
#define SCOPES_WAVEFRM_YCC_JPEG 4
+typedef struct ColorManagedViewSettings {
+ int flag, pad;
+ char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */
+ float exposure; /* fstop exposure */
+ float gamma; /* post-display gamma transform */
+ struct CurveMapping *curve_mapping; /* pre-display RGB curves transform */
+ void *pad2;
+} ColorManagedViewSettings;
+
+typedef struct ColorManagedDisplaySettings {
+ char display_device[64];
+} ColorManagedDisplaySettings;
+
+typedef struct ColorManagedColorspaceSettings {
+ char name[64]; /* MAX_COLORSPACE_NAME */
+} ColorManagedColorspaceSettings;
+
+/* ColorManagedViewSettings->flag */
+enum {
+ COLORMANAGE_VIEW_USE_CURVES = (1 << 0)
+};
#endif
-
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 4a4b21017db..38058dbb699 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -33,6 +33,7 @@
#define __DNA_IMAGE_TYPES_H__
#include "DNA_ID.h"
+#include "DNA_color_types.h" /* for color management */
struct PackedFile;
struct Scene;
@@ -107,6 +108,9 @@ typedef struct Image {
/* display aspect - for UV editing images resized for faster openGL display */
float aspx, aspy;
+
+ /* color management */
+ ColorManagedColorspaceSettings colorspace_settings;
} Image;
@@ -123,6 +127,7 @@ typedef struct Image {
#define IMA_CM_PREDIVIDE 256
#define IMA_USED_FOR_RENDER 512
#define IMA_USER_FRAME_IN_RANGE 1024 /* for image user, but these flags are mixed */
+#define IMA_VIEW_AS_RENDER 2048
/* Image.tpageflag */
#define IMA_TILES 1
diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h
index d8bba4a3bf5..cda51779528 100644
--- a/source/blender/makesdna/DNA_movieclip_types.h
+++ b/source/blender/makesdna/DNA_movieclip_types.h
@@ -37,6 +37,7 @@
#include "DNA_ID.h"
#include "DNA_tracking_types.h"
+#include "DNA_color_types.h" /* for color management */
struct anim;
struct AnimData;
@@ -94,6 +95,9 @@ typedef struct MovieClip {
/* from a file. affects only a way how scene frame is mapping */
/* to a file name and not touches other data associated with */
/* a clip */
+
+ /* color management */
+ ColorManagedColorspaceSettings colorspace_settings;
} MovieClip;
typedef struct MovieClipScopes {
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 23a8cb098f4..e3a8863714a 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -41,6 +41,7 @@
extern "C" {
#endif
+#include "DNA_color_types.h" /* color management */
#include "DNA_vec_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
@@ -273,6 +274,9 @@ typedef struct ImageFormatData {
char pad[7];
+ /* color management */
+ ColorManagedViewSettings view_settings;
+ ColorManagedDisplaySettings display_settings;
} ImageFormatData;
@@ -1133,6 +1137,11 @@ typedef struct Scene {
uint64_t customdata_mask; /* XXX. runtime flag for drawing, actually belongs in the window, only used by BKE_object_handle_update() */
uint64_t customdata_mask_modal; /* XXX. same as above but for temp operator use (gl renders) */
+
+ /* Color Management */
+ ColorManagedViewSettings view_settings;
+ ColorManagedDisplaySettings display_settings;
+ ColorManagedColorspaceSettings sequencer_colorspace_settings;
} Scene;
@@ -1254,7 +1263,7 @@ typedef struct Scene {
#define R_ALPHAKEY 2
/* color_mgt_flag */
-#define R_COLOR_MANAGEMENT (1 << 0)
+#define R_COLOR_MANAGEMENT (1 << 0) /* deprecated, should only be used in versioning code only */
#define R_COLOR_MANAGEMENT_PREDIVIDE (1 << 1)
/* subimtype, flag options for imtype */
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index d094c1d6255..4d259fad246 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -275,6 +275,18 @@ typedef struct BrightContrastModifierData {
float contrast;
} BrightContrastModifierData;
+/* ***************** Scopes ****************** */
+
+typedef struct SequencerScopes {
+ struct ImBuf *reference_ibuf;
+
+ struct ImBuf *zebra_ibuf;
+ struct ImBuf *waveform_ibuf;
+ struct ImBuf *sep_waveform_ibuf;
+ struct ImBuf *vector_ibuf;
+ struct ImBuf *histogram_ibuf;
+} SequencerScopes;
+
#define MAXSEQ 32
#define SELECT 1
@@ -317,6 +329,7 @@ typedef struct BrightContrastModifierData {
#define SEQ_USE_PROXY_CUSTOM_FILE (1 << 21)
#define SEQ_USE_EFFECT_DEFAULT_FADE (1 << 22)
+#define SEQ_USE_LINEAR_MODIFIERS (1 << 23)
// flags for whether those properties are animated or not
#define SEQ_AUDIO_VOLUME_ANIMATED (1 << 24)
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index b828247c816..6cc4541f19e 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -40,6 +40,7 @@
#include "DNA_outliner_types.h" /* for TreeStoreElem */
#include "DNA_image_types.h" /* ImageUser */
#include "DNA_movieclip_types.h" /* MovieClipUser */
+#include "DNA_sequence_types.h" /* SequencerScopes */
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@@ -473,6 +474,8 @@ typedef struct SpaceSeq {
int overlay_type;
struct bGPdata *gpd; /* grease-pencil data */
+
+ struct SequencerScopes scopes; /* different scoped displayed in space */
} SpaceSeq;
@@ -685,8 +688,9 @@ typedef struct SpaceImage {
struct Image *image;
struct ImageUser iuser;
- struct CurveMapping *cumap;
-
+
+ struct CurveMapping *cumap DNA_DEPRECATED; /* was switched to scene's color management settings */
+
struct Scopes scopes; /* histogram waveform and vectorscope */
struct Histogram sample_line_hist; /* sample line histogram */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index a32272e2a7f..8e387dd4eba 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -104,6 +104,9 @@ extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSensor;
extern StructRNA RNA_CollisionSettings;
+extern StructRNA RNA_ColorManagedColorspaceSettings;
+extern StructRNA RNA_ColorManagedDisplaySettings;
+extern StructRNA RNA_ColorManagedViewSettings;
extern StructRNA RNA_ColorRamp;
extern StructRNA RNA_ColorRampElement;
extern StructRNA RNA_ColorSequence;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 0bd42c2f5a0..0edcad59577 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -34,25 +34,31 @@
#include "DNA_color_types.h"
#include "DNA_texture_types.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#ifdef RNA_RUNTIME
#include "RNA_access.h"
+#include "DNA_image_types.h"
#include "DNA_material_types.h"
+#include "DNA_movieclip_types.h"
#include "DNA_node_types.h"
#include "MEM_guardedalloc.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
+#include "BKE_image.h"
+#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "BKE_texture.h"
-#include "WM_api.h"
-#include "WM_types.h"
-
#include "ED_node.h"
+#include "IMB_colormanagement.h"
+
static int rna_CurveMapping_curves_length(PointerRNA *ptr)
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -337,6 +343,154 @@ static void rna_Scopes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer
s->ok = 0;
}
+static int rna_ColorManagedDisplaySettings_display_device_get(struct PointerRNA *ptr)
+{
+ ColorManagedDisplaySettings *display = (ColorManagedDisplaySettings *) ptr->data;
+
+ return IMB_colormanagement_display_get_named_index(display->display_device);
+}
+
+static void rna_ColorManagedDisplaySettings_display_device_set(struct PointerRNA *ptr, int value)
+{
+ ColorManagedDisplaySettings *display = (ColorManagedDisplaySettings *) ptr->data;
+ const char *name = IMB_colormanagement_display_get_indexed_name(value);
+
+ if (name) {
+ BLI_strncpy(display->display_device, name, sizeof(display->display_device));
+ }
+}
+
+static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
+
+ IMB_colormanagement_display_items_add(&items, &totitem);
+ RNA_enum_item_end(&items, &totitem);
+
+ *free = TRUE;
+
+ return items;
+}
+
+static void rna_ColorManagedDisplaySettings_display_device_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+
+ if (GS(id->name) == ID_SCE) {
+ Scene *scene = (Scene *) id;
+
+ IMB_colormanagement_validate_settings(&scene->display_settings, &scene->view_settings);
+
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
+ }
+}
+
+static int rna_ColorManagedViewSettings_view_transform_get(PointerRNA *ptr)
+{
+ ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
+
+ return IMB_colormanagement_view_get_named_index(view->view_transform);
+}
+
+static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int value)
+{
+ ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
+
+ const char *name = IMB_colormanagement_view_get_indexed_name(value);
+
+ if (name) {
+ BLI_strncpy(view->view_transform, name, sizeof(view->view_transform));
+ }
+}
+
+static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ Scene *scene = CTX_data_scene(C);
+ EnumPropertyItem *items = NULL;
+ ColorManagedDisplaySettings *display_settings = &scene->display_settings;
+ int totitem = 0;
+
+ IMB_colormanagement_view_items_add(&items, &totitem, display_settings->display_device);
+ RNA_enum_item_end(&items, &totitem);
+
+ *free = TRUE;
+ return items;
+}
+
+static void rna_ColorManagedViewSettings_use_curves_set(PointerRNA *ptr, int value)
+{
+ ColorManagedViewSettings *view_settings = (ColorManagedViewSettings *) ptr->data;
+
+ if (value) {
+ view_settings->flag |= COLORMANAGE_VIEW_USE_CURVES;
+
+ if (view_settings->curve_mapping == NULL) {
+ view_settings->curve_mapping = curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
+ }
+ }
+ else {
+ view_settings->flag &= ~COLORMANAGE_VIEW_USE_CURVES;
+ }
+}
+
+static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr)
+{
+ ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data;
+
+ return IMB_colormanagement_colorspace_get_named_index(colorspace->name);
+}
+
+static void rna_ColorManagedColorspaceSettings_colorspace_set(struct PointerRNA *ptr, int value)
+{
+ ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *) ptr->data;
+ const char *name = IMB_colormanagement_colorspace_get_indexed_name(value);
+
+ if (name) {
+ BLI_strncpy(colorspace->name, name, sizeof(colorspace->name));
+ }
+}
+
+static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
+{
+ EnumPropertyItem *items = NULL;
+ int totitem = 0;
+
+ IMB_colormanagement_colorspace_items_add(&items, &totitem);
+ RNA_enum_item_end(&items, &totitem);
+
+ *free = TRUE;
+
+ return items;
+}
+
+static void rna_ColorManagedColorspaceSettings_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+
+ if (GS(id->name) == ID_IM) {
+ Image *ima = (Image *) id;
+
+ BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+ WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
+ }
+ else if (GS(id->name) == ID_MC) {
+ MovieClip *clip = (MovieClip *) id;
+
+ BKE_movieclip_reload(clip);
+ WM_main_add_notifier(NC_MOVIECLIP | ND_DISPLAY, &clip->id);
+ }
+}
+
+static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ ID *id = ptr->id.data;
+
+ if (GS(id->name) == ID_SCE) {
+ WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
+ }
+}
+
/* this function only exists because #curvemap_evaluateF uses a 'const' qualifier */
float rna_CurveMap_evaluateF(struct CurveMap *cuma, float value)
{
@@ -682,6 +836,87 @@ static void rna_def_scopes(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vectorscope Opacity", "Opacity of the points");
}
+static void rna_def_colormanage(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem display_device_items[] = {
+ {0, "DEFAULT", 0, "Default", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem view_transform_items[] = {
+ {0, "NONE", 0, "None", "Do not perform any color transform on display, use old non-color managed technique for display"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem color_space_items[] = {
+ {0, "NONE", 0, "None", "Do not perform any color transform on load, treat colors as in scene linear space already"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* ** Display Settings ** */
+ srna = RNA_def_struct(brna, "ColorManagedDisplaySettings", NULL);
+ RNA_def_struct_ui_text(srna, "ColorManagedDisplaySettings", "Color management specific to display device");
+
+ prop= RNA_def_property(srna, "display_device", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, display_device_items);
+ RNA_def_property_enum_funcs(prop, "rna_ColorManagedDisplaySettings_display_device_get",
+ "rna_ColorManagedDisplaySettings_display_device_set",
+ "rna_ColorManagedDisplaySettings_display_device_itemf");
+ RNA_def_property_ui_text(prop, "Display Device", "Display device name");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedDisplaySettings_display_device_update");
+
+ /* ** View Settings ** */
+ srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL);
+ RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display");
+
+ prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, view_transform_items);
+ RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_view_transform_get",
+ "rna_ColorManagedViewSettings_view_transform_set",
+ "rna_ColorManagedViewSettings_view_transform_itemf");
+ RNA_def_property_ui_text(prop, "View Transform", "View used ");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
+ prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "exposure");
+ RNA_def_property_range(prop, -10.0f, 10.0f);
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied before display transform");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
+ prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "gamma");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_range(prop, 0.0f, 5.0f);
+ RNA_def_property_ui_text(prop, "Gamma", "Amount of gamma modification applied after display transform");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
+ prop = RNA_def_property(srna, "curve_mapping", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_mapping");
+ RNA_def_property_ui_text(prop, "Curve", "Color curve mapping applied before display transform");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
+ prop = RNA_def_property(srna, "use_curve_mapping", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_CURVES);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ColorManagedViewSettings_use_curves_set");
+ RNA_def_property_ui_text(prop, "Use Curves", "Use RGB curved for pre-display transformation");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
+ /* ** Colorspace ** */
+ srna = RNA_def_struct(brna, "ColorManagedColorspaceSettings", NULL);
+ RNA_def_struct_ui_text(srna, "ColorManagedColorspaceSettings", "Input color space settings");
+
+ prop= RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, color_space_items);
+ RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get",
+ "rna_ColorManagedColorspaceSettings_colorspace_set",
+ "rna_ColorManagedColorspaceSettings_colorspace_itemf");
+ RNA_def_property_ui_text(prop, "Color Space", "Input color space name");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
+}
void RNA_def_color(BlenderRNA *brna)
{
@@ -692,6 +927,7 @@ void RNA_def_color(BlenderRNA *brna)
rna_def_color_ramp(brna);
rna_def_histogram(brna);
rna_def_scopes(brna);
+ rna_def_colormanage(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 62a06888613..495d60df49c 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -513,6 +513,11 @@ static void rna_def_image(BlenderRNA *brna)
"to avoid fringing for images with light backgrounds");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
+ prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
+ RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
+ RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
+
prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -652,6 +657,11 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_dynamic_array_funcs(prop, "rna_Image_pixels_get_length");
RNA_def_property_float_funcs(prop, "rna_Image_pixels_get", "rna_Image_pixels_set", NULL);
+ prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings");
+
RNA_api_image(srna);
}
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index fa3f8d69c47..c66c0085763 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -50,6 +50,7 @@
#include "BKE_global.h" /* grr: G.main->name */
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "BIF_gl.h"
#include "GPU_draw.h"
@@ -80,16 +81,17 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports
BKE_reportf(reports, RPT_ERROR, "Couldn't acquire buffer from image");
}
else {
- /* temp swap out the color */
- const unsigned char imb_planes_back = ibuf->planes;
- const float dither_back = ibuf->dither;
- ibuf->planes = scene->r.im_format.planes;
- ibuf->dither = scene->r.dither_intensity;
- if (!BKE_imbuf_write(ibuf, path, &scene->r.im_format)) {
+ ImBuf *write_ibuf = IMB_dupImBuf(ibuf);
+
+ IMB_display_buffer_to_imbuf_rect(write_ibuf, &scene->view_settings, &scene->display_settings);
+
+ write_ibuf->planes = scene->r.im_format.planes;
+ write_ibuf->dither = scene->r.dither_intensity;
+
+ if (!BKE_imbuf_write(write_ibuf, path, &scene->r.im_format)) {
BKE_reportf(reports, RPT_ERROR, "Couldn't write image: %s", path);
}
- ibuf->planes = imb_planes_back;
- ibuf->dither = dither_back;
+ IMB_freeImBuf(write_ibuf);
}
BKE_image_release_ibuf(image, lock);
@@ -118,6 +120,8 @@ static void rna_Image_save(Image *image, ReportList *reports)
if (image->source == IMA_SRC_GENERATED)
image->source = IMA_SRC_FILE;
+ IMB_colormanagment_colorspace_from_ibuf_ftype(&image->colorspace_settings, ibuf);
+
ibuf->userflags &= ~IB_BITMAPDIRTY;
}
else {
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 8b2b741b83e..8d1105fd620 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -299,6 +299,12 @@ static void rna_def_movieclip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Frame Offset", "Offset of footage first frame relative to it's file name "
"(affects only how footage is loading, does not change data associated with a clip)");
RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClip_reload_update");
+
+ /* color management */
+ prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_ui_text(prop, "Colorspace Settings", "Input color space settings");
}
void RNA_def_movieclip(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index f34c23a463e..0227d9c1554 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1093,34 +1093,6 @@ static void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
DAG_id_tag_update(&scene->id, 0);
}
-static void rna_RenderSettings_color_management_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
-{
- /* reset image nodes */
- Scene *scene = (Scene *)ptr->id.data;
- bNodeTree *ntree = scene->nodetree;
- bNode *node;
-
- if (ntree && scene->use_nodes) {
- /* images are freed here, stop render and preview threads, until
- * Image is threadsafe. when we are changing this property from a
- * python script in the render thread, don't stop own thread */
- if (BLI_thread_is_main())
- WM_jobs_stop_all(bmain->wm.first);
-
- for (node = ntree->nodes.first; node; node = node->next) {
- if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_IMAGE)) {
- ED_node_changed_update(&scene->id, node);
- WM_main_add_notifier(NC_NODE | NA_EDITED, node);
-
- if (node->type == CMP_NODE_IMAGE)
- BKE_image_signal((Image *)node->id, NULL, IMA_SIGNAL_FREE);
- }
- }
- }
-
- rna_Scene_glsl_update(bmain, scene, ptr);
-}
-
static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -2958,6 +2930,17 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "G", "Log conversion gamma");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+
+ /* color management */
+ prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
+ RNA_def_property_ui_text(prop, "View Settings", "Color management settings applied on image before saving");
+
+ prop = RNA_def_property(srna, "display_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "display_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings");
+ RNA_def_property_ui_text(prop, "Display Settings", "Settings of device saved image would be displayed on");
}
static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
@@ -3698,11 +3681,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
"editor pipeline, if sequencer strips exist");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "use_color_management", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT);
- RNA_def_property_ui_text(prop, "Color Management", "Use linear workflow - gamma corrected imaging pipeline");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_RenderSettings_color_management_update");
-
prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT_PREDIVIDE);
RNA_def_property_ui_text(prop, "Color Unpremultiply",
@@ -4574,6 +4552,22 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Active Movie Clip", "Active movie clip used for constraints and viewport drawing");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ /* color management */
+ prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
+ RNA_def_property_ui_text(prop, "View Settings", "Color management settings applied on image before saving");
+
+ prop = RNA_def_property(srna, "display_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "display_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedDisplaySettings");
+ RNA_def_property_ui_text(prop, "Display Settings", "Settings of device saved image would be displayed on");
+
+ prop = RNA_def_property(srna, "sequencer_colorspace_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "sequencer_colorspace_settings");
+ RNA_def_property_struct_type(prop, "ColorManagedColorspaceSettings");
+ RNA_def_property_ui_text(prop, "Sequencer Colorspace Settings", "Settings of color space sequencer is working in");
+
/* Nestled Data */
rna_def_tool_settings(brna);
rna_def_unified_paint_settings(brna);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index e3e467a9abb..b27148e964d 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1433,6 +1433,11 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_channel_set", NULL); /* overlap test */
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ prop = RNA_def_property(srna, "use_linear_modifiers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_LINEAR_MODIFIERS);
+ RNA_def_property_ui_text(prop, "Use Linear Modifiers", "Calculate modifiers in linear space instead of sequencer's space");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+
/* blending */
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 549868e5ed0..ab1dfbf22b0 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -188,7 +188,8 @@ static Sequence *rna_Sequences_new_movie(ID *id, Editing *ed, ReportList *report
Scene *scene = (Scene *)id;
Sequence *seq;
- struct anim *an = openanim(file, IB_rect, 0);
+ /* OCIO_TODO: support configurable color spaces for strips */
+ struct anim *an = openanim(file, IB_rect, 0, NULL);
if (an == NULL) {
BKE_report(reports, RPT_ERROR, "Sequences.new_movie: unable to open movie file");
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index a00e8bfea2d..246f9fef98a 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -658,20 +658,6 @@ static void rna_SpaceImageEditor_cursor_location_set(PointerRNA *ptr, const floa
}
}
-static void rna_SpaceImageEditor_curves_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- SpaceImage *sima = (SpaceImage *)ptr->data;
- ImBuf *ibuf;
- void *lock;
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
- if (ibuf->rect_float)
- curvemapping_do_ibuf(sima->cumap, ibuf);
- ED_space_image_release_buffer(sima, lock);
-
- WM_main_add_notifier(NC_IMAGE, sima->image);
-}
-
static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)ptr->data;
@@ -680,7 +666,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
ibuf = ED_space_image_acquire_buffer(sima, &lock);
if (ibuf) {
- scopes_update(&sima->scopes, ibuf, scene->r.color_mgt_flag & R_COLOR_MANAGEMENT);
+ scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings);
WM_main_add_notifier(NC_IMAGE, sima->image);
}
ED_space_image_release_buffer(sima, lock);
@@ -1980,11 +1966,6 @@ static void rna_def_space_image(BlenderRNA *brna)
"Parameters defining which layer, pass and frame of the image is displayed");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
- prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "cumap");
- RNA_def_property_ui_text(prop, "Curve", "Color curve mapping to use for displaying the image");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_SpaceImageEditor_curves_update");
-
prop = RNA_def_property(srna, "scopes", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "scopes");
RNA_def_property_struct_type(prop, "Scopes");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index cf43bd74d72..ea38b60b25f 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -415,6 +415,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "User interface for setting image format options");
parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", "");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ RNA_def_boolean(func, "color_management", 0, "", "Show color management settings");
func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip");
RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths");
@@ -497,6 +498,17 @@ void RNA_api_ui_layout(StructRNA *srna)
func = RNA_def_function(srna, "introspect", "uiLayoutIntrospect");
parm = RNA_def_string(func, "string", "", 1024 * 1024, "Descr", "DESCR");
RNA_def_function_return(func, parm);
+
+ /* color management templates */
+ func = RNA_def_function(srna, "template_colorspace_settings", "uiTemplateColorspaceSettings");
+ RNA_def_function_ui_description(func, "Item. A widget to control input color space settings.");
+ api_ui_item_rna_common(func);
+
+ func = RNA_def_function(srna, "template_colormanaged_view_settings", "uiTemplateColormanagedViewSettings");
+ RNA_def_function_ui_description(func, "Item. A widget to control color managed view settings settings.");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ /* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */
}
#endif
diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c
index e1510f9f813..c9960df1345 100644
--- a/source/blender/nodes/composite/node_composite_tree.c
+++ b/source/blender/nodes/composite/node_composite_tree.c
@@ -33,6 +33,7 @@
#include <stdio.h>
#include "DNA_anim_types.h"
+#include "DNA_color_types.h"
#include "DNA_scene_types.h"
#include "DNA_node_types.h"
@@ -693,7 +694,9 @@ static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_pr
void *COM_linker_hack = NULL;
-void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int do_preview)
+void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int do_preview,
+ const ColorManagedViewSettings *view_settings,
+ const ColorManagedDisplaySettings *display_settings)
{
#ifdef WITH_COMPOSITOR
#ifdef WITH_COMPOSITOR_LEGACY
@@ -704,10 +707,11 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int
else
#endif
{
- COM_execute(rd, ntree, rendering);
+ COM_execute(rd, ntree, rendering, view_settings, display_settings);
}
#else
(void)ntree, (void)rd, (void)rendering, (void)do_preview;
+ (void)view_settings, (void)display_settings;
#endif
(void)do_preview;
diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c
index 2277c5a2836..fe4eebc9492 100644
--- a/source/blender/nodes/composite/node_composite_util.c
+++ b/source/blender/nodes/composite/node_composite_util.c
@@ -606,6 +606,9 @@ static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy)
return outbuf;
}
+/* OCIO_TODO: this function is only used by legacy compositor system only, which would likely be removed soon,
+ * keep check for old color management flag for now
+ */
void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
{
RenderData *rd= data;
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index dcc88c7c010..9f3874560ac 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -292,33 +292,20 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
*alloc= FALSE;
+ /* OCIO_TODO: this is a part of legacy compositor system, don't bother with porting this code
+ * to new color management system since this code would likely be simply removed soon
+ */
if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
- if (ibuf->profile != IB_PROFILE_NONE) {
- rect= ibuf->rect_float;
- }
- else {
- rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
-
- IMB_buffer_float_from_float(rect, ibuf->rect_float,
- 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
-
- *alloc= TRUE;
- }
+ rect= ibuf->rect_float;
}
else {
- if (ibuf->profile == IB_PROFILE_NONE) {
- rect= ibuf->rect_float;
- }
- else {
- rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
+ rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
- IMB_buffer_float_from_float(rect, ibuf->rect_float,
- 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
- ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+ IMB_buffer_float_from_float(rect, ibuf->rect_float,
+ 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
+ ibuf->x, ibuf->y, ibuf->x, ibuf->x);
*alloc= TRUE;
- }
}
return rect;
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 2d9b9348668..656e2a72c03 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -267,9 +267,6 @@ static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack
ibuf->rect_float = cbuf->rect;
ibuf->dither = rd->dither_intensity;
- if (rd->color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
-
/* get full path */
BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path);
BKE_makepicstring(filename, path, bmain->name, rd->cfra, format->imtype, (rd->scemode & R_EXTENSION), TRUE);
diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m
index e30b8331fc0..75b9056de1b 100644
--- a/source/blender/quicktime/apple/qtkit_import.m
+++ b/source/blender/quicktime/apple/qtkit_import.m
@@ -291,7 +291,6 @@ ImBuf * qtime_fetchibuf (struct anim *anim, int position)
ibuf = nsImageToiBuf(frameImage,anim->x, anim->y);
[pool drain];
- ibuf->profile = IB_PROFILE_SRGB;
return ibuf;
}
diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c
index 5b13d77a030..e44eba2bfe0 100644
--- a/source/blender/quicktime/apple/quicktime_import.c
+++ b/source/blender/quicktime/apple/quicktime_import.c
@@ -392,8 +392,6 @@ ImBuf *qtime_fetchibuf(struct anim *anim, int position)
}
#endif
- ibuf->profile = IB_PROFILE_SRGB;
-
IMB_flipy(ibuf);
return ibuf;
}
diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h
index 303d4094f8e..999fb24ba32 100644
--- a/source/blender/render/intern/include/render_result.h
+++ b/source/blender/render/intern/include/render_result.h
@@ -47,6 +47,8 @@ struct RenderLayer;
struct RenderResult;
struct Scene;
struct rcti;
+struct ColorManagedDisplaySettings;
+struct ColorManagedViewSettings;
/* New */
@@ -90,7 +92,9 @@ void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd
void render_result_rect_fill_zero(struct RenderResult *rr);
void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd,
- unsigned int *rect, int rectx, int recty);
+ unsigned int *rect, int rectx, int recty,
+ const struct ColorManagedViewSettings *view_settings,
+ const struct ColorManagedDisplaySettings *display_settings);
#endif /* __RENDER_RESULT_H__ */
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 26bd482af69..03eb21dfa23 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -472,9 +472,6 @@ static void render_envmap(Render *re, EnvMap *env)
ibuf = IMB_allocImBuf(envre->rectx, envre->recty, 24, IB_rect | IB_rectfloat);
memcpy(ibuf->rect_float, rl->rectf, ibuf->channels * ibuf->x * ibuf->y * sizeof(float));
- if (re->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
-
/* envmap renders without alpha */
alpha = ibuf->rect_float + 3;
for (y = ibuf->x * ibuf->y - 1; y >= 0; y--, alpha += 4)
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 5f110410978..599d91333e6 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -67,6 +67,7 @@
#include "BLI_callbacks.h"
#include "PIL_time.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -333,7 +334,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
RenderResult rres;
RE_AcquireResultImage(re, &rres);
- render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty);
+ render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
RE_ReleaseResultImage(re);
}
@@ -1434,7 +1435,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
ntreeCompositTagRender(re->scene);
ntreeCompositTagAnimated(ntree);
- ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0);
+ ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
}
/* ensure we get either composited result or the active layer */
@@ -1598,7 +1599,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
else {
- ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0);
+ ntreeCompositExecTree(ntree, &re->r, 1, G.background == 0, &re->scene->view_settings, &re->scene->display_settings);
}
ntree->stats_draw = NULL;
@@ -1647,7 +1648,7 @@ int RE_seq_render_active(Scene *scene, RenderData *rd)
static void do_render_seq(Render *re)
{
static int recurs_depth = 0;
- struct ImBuf *ibuf;
+ struct ImBuf *ibuf, *out;
RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
int cfra = re->r.cfra;
SeqRenderData context;
@@ -1674,7 +1675,11 @@ static void do_render_seq(Render *re)
100);
}
- ibuf = BKE_sequencer_give_ibuf(context, cfra, 0);
+ out = BKE_sequencer_give_ibuf(context, cfra, 0);
+
+ ibuf = IMB_dupImBuf(out);
+ IMB_freeImBuf(out);
+ BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf);
recurs_depth--;
@@ -2069,6 +2074,14 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
G.is_rendering = FALSE;
}
+static void colormanage_image_for_write(Scene *scene, ImBuf *ibuf)
+{
+ IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings);
+
+ if (ibuf)
+ imb_freerectfloatImBuf(ibuf);
+}
+
static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovieHandle *mh, const char *name_override)
{
char name[FILE_MAX];
@@ -2081,19 +2094,27 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
/* write movie or image */
if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
int do_free = FALSE;
- unsigned int *rect32 = (unsigned int *)rres.rect32;
+ ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+
/* note; the way it gets 32 bits rects is weak... */
- if (rres.rect32 == NULL) {
- rect32 = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
- RE_ResultGet32(re, rect32);
+ if (ibuf->rect == NULL) {
+ ibuf->rect = MEM_mapallocN(sizeof(int) * rres.rectx * rres.recty, "temp 32 bits rect");
+ RE_ResultGet32(re, ibuf->rect);
do_free = TRUE;
}
- ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *)rect32,
- rres.rectx, rres.recty, re->reports);
+ colormanage_image_for_write(scene, ibuf);
+
+ ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect,
+ ibuf->x, ibuf->y, re->reports);
if (do_free) {
- MEM_freeN(rect32);
+ MEM_freeN(ibuf->rect);
+ ibuf->rect = NULL;
}
+
+ /* imbuf knows which rects are not part of ibuf */
+ IMB_freeImBuf(ibuf);
+
printf("Append frame %d", scene->r.cfra);
}
else {
@@ -2110,6 +2131,12 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
}
else {
ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r);
+ int do_colormanagement;
+
+ do_colormanagement = !BKE_imtype_supports_float(scene->r.im_format.imtype);
+
+ if (do_colormanagement)
+ colormanage_image_for_write(scene, ibuf);
ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format);
@@ -2127,6 +2154,9 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie
name[strlen(name) - 4] = 0;
BKE_add_image_extension(name, R_IMF_IMTYPE_JPEG90);
ibuf->planes = 24;
+
+ colormanage_image_for_write(scene, ibuf);
+
BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf);
printf("\nSaved: %s", name);
}
@@ -2381,7 +2411,8 @@ void RE_init_threadcount(Render *re)
* x/y offsets are only used on a partial copy when dimensions don't match */
void RE_layer_load_from_file(RenderLayer *layer, ReportList *reports, const char *filename, int x, int y)
{
- ImBuf *ibuf = IMB_loadiffname(filename, IB_rect);
+ /* OCIO_TODO: assume layer was saved in defaule color space */
+ ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL);
if (ibuf && (ibuf->rect || ibuf->rect_float)) {
if (ibuf->x == layer->rectx && ibuf->y == layer->recty) {
@@ -2470,8 +2501,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env,
return 0;
}
- if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
+ IMB_display_buffer_to_imbuf_rect(ibuf, &scene->view_settings, &scene->display_settings);
/* to save, we first get absolute path */
BLI_strncpy(filepath, relpath, sizeof(filepath));
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 2f932b2149e..f11f84c9d3b 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -50,6 +50,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "IMB_colormanagement.h"
#include "intern/openexr/openexr_multi.h"
@@ -1081,16 +1082,12 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
/* float factor for random dither, imbuf takes care of it */
ibuf->dither = rd->dither_intensity;
- /* prepare to gamma correct to sRGB color space */
- if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
- /* sequence editor can generate 8bpc render buffers */
- if (ibuf->rect) {
- ibuf->profile = IB_PROFILE_SRGB;
- if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32))
- IMB_float_from_rect(ibuf);
- }
- else {
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
+ /* prepare to gamma correct to sRGB color space
+ * note that sequence editor can generate 8bpc render buffers
+ */
+ if (ibuf->rect) {
+ if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32)) {
+ IMB_float_from_rect(ibuf);
}
}
@@ -1106,22 +1103,14 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
return ibuf;
}
-void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf)
+void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf)
{
if (ibuf->rect_float) {
- /* color management: when off ensure rectf is non-lin, since thats what the internal
- * render engine delivers */
- int profile_to = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
- int profile_from = (ibuf->profile == IB_PROFILE_LINEAR_RGB) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
- int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-
if (!rr->rectf)
rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
- IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
- 4, profile_to, profile_from, predivide,
- rr->rectx, rr->recty, rr->rectx, rr->rectx);
-
+ memcpy(rr->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
+
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
* can hang around when sequence render has rendered a 32 bits one before */
if (rr->rect32) {
@@ -1153,19 +1142,17 @@ void render_result_rect_fill_zero(RenderResult *rr)
rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
}
-void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty)
+void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty,
+ const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
{
if (rr->rect32) {
memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
}
else if (rr->rectf) {
- int profile_from = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
- int dither = 0;
- IMB_buffer_byte_from_float((unsigned char *)rect, rr->rectf,
- 4, dither, IB_PROFILE_SRGB, profile_from, predivide,
- rr->rectx, rr->recty, rr->rectx, rr->rectx);
+ IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
+ view_settings, display_settings, predivide);
}
else
/* else fill with black */
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 4d3b9c2493e..6d22d8991b4 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -50,6 +50,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "BKE_colortools.h"
#include "BKE_image.h"
@@ -1226,8 +1227,8 @@ int multitex_nodes(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser);
/* don't linearize float buffers, assumed to be linear */
- if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
- srgb_to_linearrgb_v3_v3(&texres->tr, &texres->tr);
+ if (ibuf && !(ibuf->rect_float))
+ IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace);
}
}
else {
@@ -2379,8 +2380,8 @@ void do_material_tex(ShadeInput *shi, Render *re)
ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
/* don't linearize float buffers, assumed to be linear */
- if (ibuf && !(ibuf->rect_float) && re->r.color_mgt_flag & R_COLOR_MANAGEMENT)
- srgb_to_linearrgb_v3_v3(tcol, tcol);
+ if (ibuf && !(ibuf->rect_float))
+ IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
}
if (mtex->mapto & MAP_COL) {
@@ -2891,8 +2892,8 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
ImBuf *ibuf = BKE_image_get_ibuf(ima, &mtex->tex->iuser);
/* don't linearize float buffers, assumed to be linear */
- if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
- srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr);
+ if (ibuf && !(ibuf->rect_float))
+ IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
}
fact= texres.tin*mtex->colfac;
@@ -3106,8 +3107,8 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h
ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
/* don't linearize float buffers, assumed to be linear */
- if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
- srgb_to_linearrgb_v3_v3(tcol, tcol);
+ if (ibuf && !(ibuf->rect_float))
+ IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace);
}
if (mtex->mapto & WOMAP_HORIZ) {
@@ -3320,8 +3321,8 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
ImBuf *ibuf = BKE_image_get_ibuf(ima, &tex->iuser);
/* don't linearize float buffers, assumed to be linear */
- if (ibuf && !(ibuf->rect_float) && R.r.color_mgt_flag & R_COLOR_MANAGEMENT)
- srgb_to_linearrgb_v3_v3(&texres.tr, &texres.tr);
+ if (ibuf && !(ibuf->rect_float))
+ IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace);
}
/* lamp colors were premultiplied with this */
diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c
index c009c7b7394..97a05e6a4c9 100644
--- a/source/blender/render/intern/source/rendercore.c
+++ b/source/blender/render/intern/source/rendercore.c
@@ -62,6 +62,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
/* local include */
#include "rayintersection.h"
@@ -1993,6 +1994,8 @@ typedef struct BakeShade {
float dxco[3], dyco[3];
short *do_update;
+
+ struct ColorSpace *rect_colorspace;
} BakeShade;
static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v)
@@ -2168,8 +2171,12 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(qua
else {
unsigned char *col= (unsigned char *)(bs->rect + bs->rectx*y + x);
- if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE) && (R.r.color_mgt_flag & R_COLOR_MANAGEMENT)) {
- linearrgb_to_srgb_uchar3(col, shr.combined);
+ if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) {
+ float rgb[3];
+
+ copy_v3_v3(rgb, shr.combined);
+ IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace);
+ rgb_float_to_uchar(col, rgb);
}
else {
rgb_float_to_uchar(col, shr.combined);
@@ -2503,6 +2510,7 @@ static void shade_tface(BakeShade *bs)
bs->rectx= bs->ibuf->x;
bs->recty= bs->ibuf->y;
bs->rect= bs->ibuf->rect;
+ bs->rect_colorspace= bs->ibuf->rect_colorspace;
bs->rect_float= bs->ibuf->rect_float;
bs->quad= 0;
@@ -2613,8 +2621,6 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up
ima->flag&= ~IMA_USED_FOR_RENDER;
if (ibuf) {
ibuf->userdata = NULL; /* use for masking if needed */
- if (ibuf->rect_float)
- ibuf->profile = IB_PROFILE_LINEAR_RGB;
}
}
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index bbdcfbb5a73..d1d2c66985e 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1325,7 +1325,14 @@ void shade_input_initialize(ShadeInput *shi, RenderPart *pa, RenderLayer *rl, in
shi->sample = sample;
shi->thread = pa->thread;
shi->do_preview = (R.r.scemode & R_MATNODE_PREVIEW) != 0;
- shi->do_manage = (R.r.color_mgt_flag & R_COLOR_MANAGEMENT);
+
+ /* OCIO_TODO: for now assume color management is always enabled and vertes colors are in sRGB space
+ * probably would be nice to have this things configurable, but for now it should work
+ * also probably this flag could be removed (in separated commit) before the release
+ * since it's not actually meaningful anymore
+ */
+ shi->do_manage = TRUE;
+
shi->lay = rl->lay;
shi->layflag = rl->layflag;
shi->passflag = rl->passflag;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 46a669eb495..eb6fabd03c6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -705,11 +705,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, FALSE, err_out);
+ IB_rect, OB_SOLID, FALSE, FALSE, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, FALSE, err_out);
+ IB_rect, FALSE, FALSE, err_out);
}
if (ibuf) {
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 71d6cf557e1..908f7e27f0b 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -67,7 +67,6 @@
#include "BKE_tracking.h" /* free tracking clipboard */
#include "BLI_listbase.h"
-#include "BLI_math_color.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -115,6 +114,8 @@
#include "BKE_sound.h"
#include "COM_compositor.h"
+#include "IMB_colormanagement.h"
+
static void wm_init_reports(bContext *C)
{
BKE_reports_init(CTX_wm_reports(C), RPT_STORE);
@@ -149,8 +150,8 @@ void WM_init(bContext *C, int argc, const char **argv)
BLF_init(11, U.dpi); /* Please update source/gamengine/GamePlayer/GPG_ghost.cpp if you change this */
BLF_lang_init();
- /* initialize color stuff */
- BLI_init_srgb_conversion();
+ /* initialize color management stuff */
+ IMB_colormanagement_init();
/* get the default database, plus a wm */
WM_homefile_read(C, NULL, G.factory_startup);
@@ -370,6 +371,8 @@ void WM_exit_ext(bContext *C, const short do_python)
sound_exit();
+ IMB_colormanagement_exit();
+
/* first wrap up running stuff, we assume only the active WM is running */
/* modal handlers are on window level freed, others too? */
/* note; same code copied in wm_files.c */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index d3d90970b0c..313fc0a819e 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1296,7 +1296,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
extern int datatoc_splash_png_size;
ImBuf *ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png,
- datatoc_splash_png_size, IB_rect, "<splash screen>");
+ datatoc_splash_png_size, IB_rect, NULL, "<splash screen>");
#else
ImBuf *ibuf = NULL;
#endif
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 6d245730795..bff40faf1d1 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -281,7 +281,8 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
struct anim *anim;
if (IMB_isanim(first)) {
- anim = IMB_open_anim(first, IB_rect, 0);
+ /* OCIO_TODO: support different input color space */
+ anim = IMB_open_anim(first, IB_rect, 0, NULL);
if (anim) {
int pic;
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
@@ -380,12 +381,13 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid)
pupdate_time();
if (ptottime > 1.0) {
+ /* OCIO_TODO: support different input color space */
if (picture->mem) {
ibuf = IMB_ibImageFromMemory((unsigned char *)picture->mem, picture->size,
- picture->IB_flags, picture->name);
+ picture->IB_flags, NULL, picture->name);
}
else {
- ibuf = IMB_loadiffname(picture->name, picture->IB_flags);
+ ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL);
}
if (ibuf) {
playanim_toscreen(picture, ibuf, fontid);
@@ -826,7 +828,8 @@ void WM_main_playanim(int argc, const char **argv)
}
if (IMB_isanim(filepath)) {
- anim = IMB_open_anim(filepath, IB_rect, 0);
+ /* OCIO_TODO: support different input color spaces */
+ anim = IMB_open_anim(filepath, IB_rect, 0, NULL);
if (anim) {
ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE);
IMB_close_anim(anim);
@@ -838,7 +841,8 @@ void WM_main_playanim(int argc, const char **argv)
}
if (ibuf == NULL) {
- ibuf = IMB_loadiffname(filepath, IB_rect);
+ /* OCIO_TODO: support different input color space */
+ ibuf = IMB_loadiffname(filepath, IB_rect, NULL);
}
if (ibuf == NULL) {
@@ -950,11 +954,13 @@ void WM_main_playanim(int argc, const char **argv)
ibuf = IMB_anim_absolute(ps.picture->anim, ps.picture->frame, IMB_TC_NONE, IMB_PROXY_NONE);
}
else if (ps.picture->mem) {
+ /* use correct colorspace here */
ibuf = IMB_ibImageFromMemory((unsigned char *) ps.picture->mem, ps.picture->size,
- ps.picture->IB_flags, ps.picture->name);
+ ps.picture->IB_flags, NULL, ps.picture->name);
}
else {
- ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags);
+ /* use correct colorspace here */
+ ibuf = IMB_loadiffname(ps.picture->name, ps.picture->IB_flags, NULL);
}
if (ibuf) {
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 44991adcc9d..04d4be05034 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -147,6 +147,7 @@ endif()
bf_intern_mikktspace
extern_recastnavigation
bf_intern_raskter
+ bf_intern_opencolorio
)
if(WITH_MOD_CLOTH_ELTOPO)
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index b600c08f4dc..c6383b471f7 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -428,6 +428,8 @@ void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct Poi
void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {}
void uiTemplateMarker(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *userptr, PointerRNA *trackptr, int compact) {}
void uiTemplateImageSettings(struct uiLayout *layout, struct PointerRNA *imfptr) {}
+void uiTemplateColorspaceSettings(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {}
+void uiTemplateColormanagedViewSettings(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int show_global_settings) {}
/* rna render */
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h) {return (struct RenderResult *) NULL;}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 0229079c13c..3356091b97f 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -301,6 +301,15 @@ if(WITH_INTERNATIONAL)
)
endif()
+# color management
+if(WITH_OPENCOLORIO)
+ install(
+ DIRECTORY ${CMAKE_SOURCE_DIR}/release/datafiles/colormanagement
+ DESTINATION ${TARGETDIR_VER}/datafiles
+ PATTERN ".svn" EXCLUDE
+ )
+endif()
+
# helpful tip when using make
if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*")
# message after building.
@@ -636,6 +645,17 @@ elseif(WIN32)
endif()
endif()
+ if(WITH_OPENCOLORIO)
+ if(NOT MINGW)
+ set_lib_path(OCIOBIN "opencolorio/bin")
+ install(
+ FILES
+ ${OCIOBIN}/OpenColorIO.dll
+ DESTINATION ${TARGETDIR}
+ )
+ endif()
+ endif()
+
elseif(APPLE)
# handy install macro to exclude files, we use \$ escape for the "to"
@@ -907,6 +927,7 @@ endif()
cycles_util
cycles_subd
bf_intern_raskter
+ bf_intern_opencolorio
)
if(WITH_COMPOSITOR)