Color Management, Stage 2: Switch color pipeline to use OpenColorIO
authorSergey Sharybin <sergey.vfx@gmail.com>
Sat, 15 Sep 2012 10:05:07 +0000 (10:05 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Sat, 15 Sep 2012 10:05:07 +0000 (10:05 +0000)
Replace old color pipeline which was supporting linear/sRGB color spaces
only with OpenColorIO-based pipeline.

This introduces two configurable color spaces:

- Input color space for images and movie clips. This space is used to convert
  images/movies from color space in which file is saved to Blender's linear
  space (for float images, byte images are not internally converted, only input
  space is stored for such images and used later).

  This setting could be found in image/clip data block settings.

- Display color space which defines space in which particular display is working.

  This settings could be found in scene's Color Management panel.

When render result is being displayed on the screen, apart from converting image
to display space, some additional conversions could happen.

This conversions are:

- View, which defines tone curve applying before display transformation.
  These are different ways to view the image on the same display device.
  For example it could be used to emulate film view on sRGB display.

- Exposure affects on image exposure before tone map is applied.

- Gamma is post-display gamma correction, could be used to match particular
  display gamma.

- RGB curves are user-defined curves which are applying before display
  transformation, could be used for different purposes.

All this settings by default are only applying on render result and does not
affect on other images. If some particular image needs to be affected by this
transformation, "View as Render" setting of image data block should be set to
truth. Movie clips are always affected by all display transformations.

This commit also introduces configurable color space in which sequencer is
working. This setting could be found in scene's Color Management panel and
it should be used if such stuff as grading needs to be done in color space
different from sRGB (i.e. when Film view on sRGB display is use, using VD16
space as sequencer's internal space would make grading working in space
which is close to the space using for display).

Some technical notes:

- Image buffer's float buffer is now always in linear space, even if it was
  created from 16bit byte images.

- Space of byte buffer is stored in image buffer's rect_colorspace property.

- Profile of image buffer was removed since it's not longer meaningful.

- OpenGL and GLSL is supposed to always work in sRGB space. It is possible
  to support other spaces, but it's quite large project which isn't so
  much important.

- Legacy Color Management option disabled is emulated by using None display.
  It could have some regressions, but there's no clear way to avoid them.

- If OpenColorIO is disabled on build time, it should make blender behaving
  in the same way as previous release with color management enabled.

More details could be found at this page (more details would be added soon):
http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.64/Color_Management

--
Thanks to Xavier Thomas, Lukas Toene for initial work on OpenColorIO
integration and to Brecht van Lommel for some further development and code/
usecase review!

178 files changed:
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/properties_scene.py
release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenfont/BLF_api.h
source/blender/blenfont/CMakeLists.txt
source/blender/blenfont/SConscript
source/blender/blenfont/intern/blf.c
source/blender/blenfont/intern/blf_font.c
source/blender/blenfont/intern/blf_internal_types.h
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_colortools.h
source/blender/blenkernel/BKE_image.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/image_gen.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/ocean.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/seqmodifier.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/intern/threads.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/collada/ImageExporter.cpp
source/blender/compositor/COM_compositor.h
source/blender/compositor/intern/COM_CompositorContext.cpp
source/blender/compositor/intern/COM_CompositorContext.h
source/blender/compositor/intern/COM_ExecutionSystem.cpp
source/blender/compositor/intern/COM_ExecutionSystem.h
source/blender/compositor/intern/COM_Node.cpp
source/blender/compositor/intern/COM_Node.h
source/blender/compositor/intern/COM_compositor.cpp
source/blender/compositor/nodes/COM_BlurNode.cpp
source/blender/compositor/nodes/COM_BokehImageNode.cpp
source/blender/compositor/nodes/COM_ChannelMatteNode.cpp
source/blender/compositor/nodes/COM_ChromaMatteNode.cpp
source/blender/compositor/nodes/COM_ColorMatteNode.cpp
source/blender/compositor/nodes/COM_CompositorNode.cpp
source/blender/compositor/nodes/COM_DespeckleNode.cpp
source/blender/compositor/nodes/COM_DifferenceMatteNode.cpp
source/blender/compositor/nodes/COM_DilateErodeNode.cpp
source/blender/compositor/nodes/COM_DistanceMatteNode.cpp
source/blender/compositor/nodes/COM_FilterNode.cpp
source/blender/compositor/nodes/COM_ImageNode.cpp
source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp
source/blender/compositor/nodes/COM_MixNode.cpp
source/blender/compositor/nodes/COM_MovieClipNode.cpp
source/blender/compositor/nodes/COM_OutputFileNode.cpp
source/blender/compositor/nodes/COM_RenderLayersNode.cpp
source/blender/compositor/nodes/COM_RenderLayersNode.h
source/blender/compositor/nodes/COM_SplitViewerNode.cpp
source/blender/compositor/nodes/COM_TextureNode.cpp
source/blender/compositor/nodes/COM_ViewerNode.cpp
source/blender/compositor/operations/COM_ImageOperation.cpp
source/blender/compositor/operations/COM_OutputFileOperation.cpp
source/blender/compositor/operations/COM_OutputFileOperation.h
source/blender/compositor/operations/COM_PreviewOperation.cpp
source/blender/compositor/operations/COM_PreviewOperation.h
source/blender/compositor/operations/COM_SplitViewerOperation.cpp
source/blender/compositor/operations/COM_ViewerBaseOperation.cpp
source/blender/compositor/operations/COM_ViewerBaseOperation.h
source/blender/compositor/operations/COM_ViewerOperation.cpp
source/blender/editors/include/ED_clip.h
source/blender/editors/include/ED_image.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_draw.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_icons.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_ops.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/object/object_bake.c
source/blender/editors/render/render_internal.c
source/blender/editors/render/render_opengl.c
source/blender/editors/render/render_preview.c
source/blender/editors/screen/screendump.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/space_clip/clip_buttons.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_file/filelist.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_intern.h
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_view.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_scopes.c
source/blender/editors/space_sequencer/sequencer_view.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_material.c
source/blender/imbuf/CMakeLists.txt
source/blender/imbuf/IMB_colormanagement.h [new file with mode: 0644]
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/SConscript
source/blender/imbuf/intern/IMB_anim.h
source/blender/imbuf/intern/IMB_colormanagement_intern.h [new file with mode: 0644]
source/blender/imbuf/intern/IMB_filetype.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/bmp.c
source/blender/imbuf/intern/cineon/cineon_dpx.c
source/blender/imbuf/intern/colormanagement.c [new file with mode: 0644]
source/blender/imbuf/intern/dds/dds_api.cpp
source/blender/imbuf/intern/dds/dds_api.h
source/blender/imbuf/intern/divers.c
source/blender/imbuf/intern/filetype.c
source/blender/imbuf/intern/indexer.c
source/blender/imbuf/intern/iris.c
source/blender/imbuf/intern/jp2.c
source/blender/imbuf/intern/jpeg.c
source/blender/imbuf/intern/openexr/openexr_api.cpp
source/blender/imbuf/intern/openexr/openexr_api.h
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/radiance_hdr.c
source/blender/imbuf/intern/readimage.c
source/blender/imbuf/intern/rectop.c
source/blender/imbuf/intern/targa.c
source/blender/imbuf/intern/thumbs.c
source/blender/imbuf/intern/tiff.c
source/blender/imbuf/intern/writeimage.c
source/blender/makesdna/DNA_color_types.h
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_movieclip_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_color.c
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_image_api.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_sequencer_api.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_ui_api.c
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/composite/node_composite_util.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/composite/nodes/node_composite_outputFile.c
source/blender/quicktime/apple/qtkit_import.m
source/blender/quicktime/apple/quicktime_import.c
source/blender/render/intern/include/render_result.h
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_result.c
source/blender/render/intern/source/render_texture.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/shadeinput.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_playanim.c
source/blenderplayer/CMakeLists.txt
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt

index 74bb720..b777fcd 100644 (file)
@@ -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")
index 8449d26..2ccdb9c 100644 (file)
@@ -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"
index dd13b8a..39c8929 100644 (file)
@@ -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:
index 0732e02..ce10951 100644 (file)
@@ -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);
index ebf9ff4..da60710 100644 (file)
@@ -27,6 +27,7 @@ set(INC
        ../blenlib
        ../editors/include
        ../makesdna
+       ../imbuf
        ../../../intern/guardedalloc
 )
 
index c46960d..d3c7b1c 100644 (file)
@@ -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']
index d4739b3..92fcb57 100644 (file)
@@ -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;
        }
 }
 
index cb05c89..02b6699 100644 (file)
@@ -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]) {
index 4c617da..1acc3da 100644 (file)
@@ -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 */
index 1e67027..fed82d7 100644 (file)
@@ -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 */
index 9b7fc1f..cd67059 100644 (file)
@@ -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
index 6746128..ac324b2 100644 (file)
@@ -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);
 
index 438d511..6ad2ad9 100644 (file)
@@ -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);
index bce4243..023b7e8 100644 (file)
@@ -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
index 51a64c9..0c571f6 100644 (file)
@@ -176,6 +176,16 @@ struct ImBuf *BKE_sequencer_give_ibuf_direct(SeqRenderData context, float cfra,
 struct ImBuf *BKE_sequencer_give_ibuf_seqbase(SeqRenderData context, float cfra, int chan_shown, struct ListBase *seqbasep);
 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
  * ********************************************************************** */
@@ -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 */
index 68ca317..d1a35b1 100644 (file)
@@ -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] )
index 45e2167..99b788e 100644 (file)
@@ -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 */
index d65c81b..19c8c2c 100644 (file)
@@ -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));
+}
index 3f756e7..d514a0a 100644 (file)
@@ -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) {
index 4d7013b..37572ee 100644 (file)
@@ -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';
index 1a6a950..97d4c15 100644 (file)
@@ -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 |
index b862a82..4f39219 100644 (file)
@@ -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 */
index 145bd6a..2dec725 100644 (file)
@@ -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));
+       }
+}
index 4dbe0b6..eaf3ec3 100644 (file)
@@ -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;
 }
 
index 65fcd0d..b0dcad6 100644 (file)
@@ -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;
 }
 
index 2596bf5..8d7ca94 100644 (file)
@@ -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;
index ff48f5d..97ebc3a 100644 (file)
@@ -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;
index 902373b..9cd801f 100644 (file)
@@ -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);
index 9994f89..66527b9 100644 (file)
@@ -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 */
index a7f8026..c648344 100644 (file)
@@ -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! */
 
index 109a844..b8d63b3 100644 (file)
@@ -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 */
index a15dadd..f1f1efd 100644 (file)
@@ -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;
                        }
index f35bf71..a64583b 100644 (file)
@@ -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.
index fbdb4cd..e1cc25d 100644 (file)
@@ -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 */
-       }
-}
index 2f6abf3..2f5e8c0 100644 (file)
@@ -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.
@@ -125,6 +129,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
         */
@@ -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;}
 };
index 801505e..a13717c 100644 (file)
@@ -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;
index 39e7bc8..56a60bf 100644 (file)
@@ -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
index 50393d1..5922b0e 100644 (file)
@@ -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);
        }
 }
 
index 7ce40e3..bfccd06 100644 (file)
@@ -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);
index cb9166c..5cfcd83 100644 (file)
@@ -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;
 
index e39ef2b..4f120ea 100644 (file)
@@ -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);
index f6abbbb..a89ed9e 100644 (file)
@@ -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));
 }
index eab9218..c1511ee 100644 (file)
@@ -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());
index 0fb0915..4c4b77b 100644 (file)
@@ -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());
index 38ab6ba..54e6762 100644 (file)
@@ -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());
index d0d66a8..e331375 100644 (file)
@@ -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));
 }
index 603ddcd..a97714c 100644 (file)
@@ -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);
 }
index 6dca049..b5ad07b 100644 (file)
@@ -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());
 }
index cecc3bf..5bd2f78 100644 (file)
@@ -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 */
index 87e7b9d..782c897 100644 (file)
@@ -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());
index 021ec6c..990cdb4 100644 (file)
@@ -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);
 }
index 2d13ffb..4ebd28d 100644 (file)
@@ -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) {
index be949e2..4656e00 100644 (file)
@@ -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());
index 7aeaaf5..ab4e464 100644 (file)
@@ -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());
        
index 6d5b9bb..5d5e68f 100644 (file)
@@ -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);
index b8cee29..921b9e6 100644 (file)
@@ -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;
                                }
                        }
index dfb46af..b57e997 100644 (file)
@@ -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));
 }
index 32672c8..9bd7462 100644 (file)
@@ -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);
 };
index 388466c..37b888b 100644 (file)
@@ -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);
        }
 }
index b035e0a..5b386a5 100644 (file)
@@ -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();
index 88ce0ff..d67e9e2 100644 (file)
@@ -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));
 }
index 4ec5643..fb3efbb 100644 (file)
@@ -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()
index b72875a..21ecfdb 100644 (file)
 #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);
index 532242c..69d1ad4 100644 (file)
@@ -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; }
index aff374c..6e58b27 100644 (file)
@@ -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)
 {
index ffd80ff..9e774d0 100644 (file)
@@ -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();
index d59d1f9..7325e32 100644 (file)
@@ -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;
index f443c33..d9ca131 100644 (file)
@@ -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);
 }
 
index d90eb34..f7d479e 100644 (file)
@@ -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);
index b85b86b..576d5da 100644 (file)
@@ -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;
index 13c3b18..28727c9 100644 (file)
@@ -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);
 
index 87f12b8..a50b339 100644 (file)
@@ -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__ */
index 7f40024..b1bccfa 100644 (file)
@@ -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]);
index c6f58fd..917153c 100644 (file)
@@ -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);
index 823f8d7..742aed4 100644 (file)
@@ -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
  *
index 77dbbc8..f535c3c 100644 (file)
@@ -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;
                
index b8a84e1..f7b2209 100644 (file)
@@ -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);
 }
index f6f12f9..0921107 100644 (file)
@@ -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 */
index 73e6427..928e167 100644 (file)
@@ -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 {
index bf77e60..ded5887 100644 (file)
@@ -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);
index 59fa66b..dc9347b 100644 (file)
@@ -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;
                }
        }
        
index 6a63e2b..79b9d31 100644 (file)
@@ -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);
+}
index 026f02d..8a7f2d9 100644 (file)
@@ -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);
 
index f9b73a5..f03cb31 100644 (file)
@@ -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);
                                        }
index b236b55..ebacac9 100644 (file)
@@ -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 ***************** */
index 55df1ca..d9618e8 100644 (file)
@@ -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;
                }
 
index 068a7aa..a829ef5 100644 (file)
@@ -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"
 #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);
 
index 4e71c49..5e54119 100644 (file)
@@ -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);
index 101235e..64430a2 100644 (file)
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 
+#include "IMB_colormanagement.h"
+
 #include "paint_intern.h"
 
 /* Defines and Structs */
 #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 */
index e66faa8..0a1e1d7 100644 (file)
@@ -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");
        }
 }
 
index 2353f8f..d486cae 100644 (file)
@@ -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 {
index 08ad6aa..f2a48f2 100644 (file)
@@ -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,
index 337e13f..d3b4df0 100644 (file)
@@ -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++) {
index 40f0683..c372973 100644 (file)
@@ -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");
index e293264..638a2ac 100644 (file)
@@ -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"
 
 
 #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 */
index 0d3a761..f86e59c 100644 (file)
@@ -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);
 
index 52a2bf2..16804c5 100644 (file)
@@ -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);
 
@@