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 74bb720b6189605ded8268130a4900e9ed5b2073..b777fcddcf2b8e71f209dc9ae71113934c4bff00 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 8449d26f6e6d92eb8452b54ca3297195cc35ad0a..2ccdb9cee268883a753116874eeb4aac7f77ba78 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 dd13b8a9b51ddf1d9b28419d932076a26f3b3578..39c892930f4419d07cbc182df7eb907fc0b42742 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 0732e02b5fc9d8aaf3f88c952495c80f8763ee2c..ce10951d6ff7fad1f278b8ad85ec87bcc7a04cdb 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 ebf9ff4db39b831f4157c915aef1b9d475bab658..da60710a137f92b5746aa2b12276309884b53e71 100644 (file)
@@ -27,6 +27,7 @@ set(INC
        ../blenlib
        ../editors/include
        ../makesdna
+       ../imbuf
        ../../../intern/guardedalloc
 )
 
index c46960d2311c5ca83fcf8a01427fb2f8ccc647c7..d3c7b1c2fcc7e49166cde07964950246092e7c13 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 d4739b37f93dfb612d8aab9fd2778107b06b82d9..92fcb576e7dde5ab38c5bd313d33ba2b6bbb4ba3 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 cb05c89921ebfe05f95b2dced88c7e88198ded9a..02b66993c0ae8078e88ffe7cf7f998321c9f6f02 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 4c617da75836db3ca1bf8e28d434d6a6f1f733a8..1acc3dad4cf8c54db7f8a82633758f2309b33680 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 1e67027ae8c211a972cb44c04ae1ee8fc8b3f0f6..fed82d7e93d05de853eec384901bfaa9bf25e56c 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 9b7fc1fddad780efd82ef63eb61a1f910252b144..cd67059ea8cf98615e7803747c3e90549ae6e9b7 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 67461281674ff277652273623f3cfd76186fbddc..ac324b2af00bd897e9ac17ac8b9bc207a3038da9 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 438d51106663473f79ddbe56cedecfec447c013a..6ad2ad924e23c2e6c03577ff689fbfc856405985 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 bce4243190ad6606f8957bc58267313e313663da..023b7e85c40f149c79da1f873889566ff3cd60dc 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 51a64c97ca609c896da96e0664cf2cef1ba007d1..0c571f62f0e897a2149c8f0bd4c637aa8f80854a 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 68ca3170bd89e64f27c8a89067efe76c0a4932cb..d1a35b122e8daf552f6e543c1d835504969d9053 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 45e2167af2f2b2ae10b2672f89185af00170727f..99b788e80ce5dda6514be2fbca5775f48c7bbba1 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 d65c81b4f9befabe21a60cc883722b888a8a5ae2..19c8c2cd63214c80796ed5e4b3821581f5d76415 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 3f756e74b2655d968794520148029f82a42c97dc..d514a0a7dd03525a71285eba28234ad41f7b05e3 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 4d7013b9f73b17df856272c9fe73292eefa3ab7b..37572eebed69214d3949d90ff028c9fa79cea81a 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 1a6a950388732d7954f44f6bfb1e08aaeb229f2b..97d4c150b845565a2955851cda23250cf6a2d697 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 b862a824d50ffeb04cae0d46a4d450063dc71ed8..4f3921936e8805cfd18bdf1b1f1d8b294d3e44a3 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 145bd6a88e5af3ddbd4dd2988e435d42ada87b15..2dec72560a228f0d69bbbb539ce00b34cf8a9450 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 4dbe0b6290ceb09c7bf7b3136028dab43b1b76c4..eaf3ec384c8f4b01cca26cd9083601c4d29dfd6a 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 65fcd0d85d6f236334eda4ff7f0c16e6445f5ccd..b0dcad64722f86fa97eda033437f11de541084ff 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 2596bf57f052969e53bd1f995cd5b24132a2854e..8d7ca94ed4823d7763d2473eaa6a58f95609dd98 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 ff48f5db9aaccb76535150f6ccbf7e47e90859a9..97ebc3a90ba6f4f381fd7dfc4ad81a2e5c9733f2 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 902373bcd6bd06f85de82e9dbe872a6a71187b01..9cd801f819dd54085137a2a159b699322c6312b9 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 9994f89acd5a154844ac7e31badfe8048b00b4ed..66527b9b92ae3686cc125c9863cef52d96c30786 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 a7f8026ad5d7e09715161469bd9256df8baadf27..c6483442b0063376c83a130b04b7087d52bbbcb8 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 109a844352f56262bd3d68f8c483f2bb5e5b41f6..b8d63b3c5d5a93a973a3e50aeb733add1cbcf6f5 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 a15dadda8cf1e372b9ef4920e79080b592ad296b..f1f1efdbd33e22390242ea24a7bc2e420c7e49cd 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 f35bf71392c249e6045845d7f3545e50f76bc52b..a64583b68ffa5c8b51d8f617192c1035efbc3d00 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 fbdb4cd6b2810870b6db5d57aea4d4d2a9b2fb03..e1cc25d028aa0ebbf345d011b88e1167c2fb79d2 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 2f6abf399850590de5230073097dd8bb710b5f92..2f5e8c0648d58337fbad18785364cc4a03e109cb 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 801505e9d39dc81f0325732c0d7735fca584f16c..a13717c9d86a1885286bda2a3101737e53936998 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 39e7bc8027976dff17b2ac4cbe4439bb0a7c9e69..56a60bf7a039ffb113aaa70cabbdb9438e0385b1 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 50393d14f3528fb03d4a9655a73c9180d57728e0..5922b0e6b0884d3dc09392904741278740c61f01 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 7ce40e3cb349a538568be099f58ab36c75036626..bfccd069ad107e90913c28edd8bf1ba564607422 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 cb9166c929d149b98f60e00eadb43de72a06d57e..5cfcd83f8f15926a6c4f3f3e4bc2243332cd567c 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 e39ef2b3f23c4d405bd499117e9c87fc125e5eef..4f120ea5a6ef8286526e679a6d46627db6e10744 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 f6abbbb9a9ae7365ee6558cda4f25f6cb01d3afb..a89ed9e0c64f0da822835637ae5a27ccdfacd88a 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 eab921863e917df82978e236061d028cef8645bd..c1511ee611b588df22ce30753cd42b69c4f87955 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 0fb09157351eab43522dccc706dba15cb46e8137..4c4b77ba6cc5a12b028b677c1b5ebfe73c37d1da 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 38ab6ba8da2af61a67c12e60e2ac9914569e6734..54e6762961b5685769da6534c8920d6e41c7b622 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 d0d66a81c77723ec8eea89819d021771b45e8782..e3313750e6652e07690d3734f3f8f48f81ffe20c 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 603ddcd1389515baf9d10550901b4cc85da91416..a97714c870e4e2d9cf55a63609febcb8a48460de 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 6dca049a6ae8b50b92efda02b0872b6cab3b7179..b5ad07be3194666be99cea67ac91d704ba6dd265 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 cecc3bf6e8636bce00e27215517f42349192258d..5bd2f78d8a615a6a292f5f93b45a431a9ef9b7c3 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 87e7b9d078868732a3af7244fcd20c9d79617d7b..782c897f6fbdaefa652816c642330e4735ea1833 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 021ec6c250873b502f2f6a79edec8a7ddf87eca7..990cdb480caf7ae8823811b8444d73268882bd2a 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 2d13ffb82b6ec48e24b6ffeda4d4badf233c9af7..4ebd28d710a54f4bad5c0b4aba55174bf9849f3b 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 be949e2cacb7c8b915194ba3496d5b79f6700d1c..4656e00b0065095a07d4fa694998a4957307021d 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 7aeaaf56c9894a4c54720a320ae7d1ef8cf838f4..ab4e464327d32bb08877ac4cd7bc0309d5cff172 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 6d5b9bba8aa4093765e6049d88d0daa37942daea..5d5e68fba37575d27d660a960375fb0f910c5b7f 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 b8cee29fee6c988d5782ab1401370829e6d100d9..921b9e63a73bcba4911de55c3abab2fa158e50e3 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 dfb46af841c798f2844bf59b49c0426c9750bfd9..b57e99754d62101fd0fc205580e11e5446440d8e 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 32672c8ba2d4ee434aa652633ec7dd5f485b3108..9bd74624b0c32b739b47150909aa1d2ee8038a12 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 388466cee3c6b670a653db57d98b84c1cedbf1f5..37b888becca057eb6127bc2e01f95fba2baf4c65 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 b035e0a392c4e3ea8a5ea9de5ebe43e3b3452726..5b386a504e473d62845116011ff74a680296f5a5 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 88ce0ff2016dd396711ad1bbcb7f70f3d1e5852e..d67e9e274b058c57f03debade07915b66fe97a9f 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 4ec5643c0bbbc46e40d2b07a4bd062a7bd62abc6..fb3efbb67ed40c172f479529b7b3f8f105ca7782 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 b72875ab2f979e8d0a58f9953ba2021a990dc179..21ecfdb527244f1aefab6f9ed98424d3a5cf8fd6 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 532242c97ce9abd91b0cff7fb88007df86f338dd..69d1ad48cedbbac1364a42d349b94afd791dc09d 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 aff374cdded54c19a998ef7fe3b7fbd7f6a31d9d..6e58b277f66c7cbfb87d31eb0779e010df6ded17 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 ffd80ff27af0d8ae651739acbc4b6da00c70dc8b..9e774d0e41be8a7660d747620bca98b511474b1d 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 d59d1f9f10d531ad429c92e90085c03b32254ad3..7325e32a863b328086ef3a5b313e24a517a7c2b1 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 f443c33cd541577552fe9bdc05b89d85e5739311..d9ca131721fe03bcfd936e37abf4b1e27a29c2c9 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 d90eb343f6caa93719aa6c3bcba0c891a98c3a1f..f7d479eb3b895b7175228aeec7edf3540e0be89d 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 b85b86bddc3adc9ba0302ba20ddd91d34d6645db..576d5da4d740b4c3a1b4ebc01794d0be5dab2798 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 13c3b180230df9ea7a5eb36742f8343a7d2687cf..28727c913cbf6986165bffed038906e46c798a75 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 87f12b8ac9cfa27418e1dae8157e556395ffd69e..a50b33966c6deb62dfcbdde9b2c4455446677f7d 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 7f40024a056046a7dfc0dd8775201ae947329986..b1bccfa32c53d41aaffea2f72f9c57b6e8c8ac2b 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 c6f58fdd70b84a7d43a2148be5682361a78b85a3..917153c91992bca2878ecae4d5ed31ddc5fd67ab 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 823f8d7be39ffcf197d9051646c8950c50ac4a8a..742aed4fbb1ef6f277b11f721080a2454a30b8ab 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 77dbbc878a7729a7a191fd38e79946486e1d02d9..f535c3c3e2aebae28a4fc7e2611a1cff4ad164b5 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 b8a84e1638aa66306ab24ba4725340f1e038a2c0..f7b2209883560b47701a2cd675fa9c12b83b2a05 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 f6f12f98181b9d5114bfa7083d94f7d7812b47a9..0921107b8e660eb77ded4d1186aee0cca419acd8 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 73e6427d1cb52ddacbed65d14078ae0d7543ded2..928e1671cee77e4aa0519c79a73fd2bd9c8295bb 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 bf77e605d6e223717262488e16a5d6c08b62afe0..ded5887f7f2ad19d832c512a21a33a1c0b3ba3e5 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 59fa66b12af5251e3ff6af54695fbc9ae892f341..dc9347b3852057d2e0798e655ea3fd572d821c03 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 6a63e2b571f5435939a14df1c8e9fffb502c46dd..79b9d3137755c6ba3c004d2d2c8c3e0c3a6d2044 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 026f02d10893be7ebfdead6988547362d6b634ed..8a7f2d9ca47e884aff082fcf64d6a4be71d17c77 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 f9b73a564031d4a5e251eee560cd87d9b47f0f48..f03cb312e3ecbd8aec4bd1b6ffe92a4dbe1727e5 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 b236b5558503a55226636a874cee4638f1434d40..ebacac917e86ab7a9e3ba6f8112276e7d324cf0d 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 55df1caf3eb2e24e37fcd660ef22f719c6e9e127..d9618e89b689812843656f42e4bdf796fdd68c64 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 068a7aaa50ab73b01b85e42dfb2c06bbb4bdb176..a829ef57b85f2b9f28e3c06f655f062a8090ac78 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 4e71c49465f979a6444f5e1dab1104b2a099772e..5e54119118a3866e9d032ad9820361074771395c 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 101235e9c9992a87edf2aa3e9e02b851242fbf5a..64430a263f08d24e04944a55ee50e19db105116b 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 e66faa88b9320a9277a1ad2a59743c4eb3e0d931..0a1e1d750985ae504744c0e805edaa591ef495a1 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 2353f8f8c12cdcf925c39b2bea20db3bcc9dfecd..d486caeacc20bf38e0b4be1cad404f65a00a14cc 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 08ad6aac970e2925abbef72ac024e4a7e7fc15b0..f2a48f299cfd1d50c8324d150ffa352fe13313b1 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 337e13f778576a011df36fe3d0552065ca461d10..d3b4df05aa93979717783aa07d24a2571049889d 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 40f0683a8524e87b1fc8c8886b232d17f4355d7e..c372973b7b0d0f65edac421ec943f51ac0f6a4fd 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 e293264c02170dada4141a3549f763c1e683f524..638a2ac668122bb83aec30a1973f8b0378d6630a 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 0d3a7614f1065a310c58efd499cea8a186d288ac..f86e59c41a81cfbe67aaa6312011bab09ac1a086 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 52a2bf22d4b7b973b59e752c8878af6623d92c81..16804c5a1c66b1c5ed2bfc85136f1afe8f1377ba 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);
 
@@ -2044,6 +2115,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
                        info->colf[2] = (float)cp[2] / 255.0f;
                        info->colf[3] = (float)cp[3] / 255.0f;
                        info->colfp = info->colf;
+
+                       info->color_manage = FALSE;
                }
                if (ibuf->rect_float) {
                        fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
@@ -2053,6 +2126,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
                        info->colf[2] = fp[2];
                        info->colf[3] = fp[3];
                        info->colfp = info->colf;
+
+                       info->color_manage = TRUE;
                }
 
                if (ibuf->zbuf) {
@@ -2063,25 +2138,21 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event)
                        info->zf = ibuf->zbuf_float[y * ibuf->x + x];
                        info->zfp = &info->zf;
                }
-               
-               if (sima->cumap && ibuf->channels == 4) {
+
+               if (curve_mapping && ibuf->channels == 4) {
                        /* we reuse this callback for set curves point operators */
                        if (RNA_struct_find_property(op->ptr, "point")) {
                                int point = RNA_enum_get(op->ptr, "point");
 
                                if (point == 1) {
-                                       curvemapping_set_black_white(sima->cumap, NULL, info->colfp);
-                                       if (ibuf->rect_float)
-                                               curvemapping_do_ibuf(sima->cumap, ibuf);
+                                       curvemapping_set_black_white(curve_mapping, NULL, info->colfp);
                                }
                                else if (point == 0) {
-                                       curvemapping_set_black_white(sima->cumap, info->colfp, NULL);
-                                       if (ibuf->rect_float)
-                                               curvemapping_do_ibuf(sima->cumap, ibuf);
+                                       curvemapping_set_black_white(curve_mapping, info->colfp, NULL);
                                }
                        }
                }
-                               
+
                // XXX node curve integration ..
 #if 0
                {
@@ -2211,7 +2282,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
        hist->co[1][0] = x2f;
        hist->co[1][1] = y2f;
 
-       BKE_histogram_update_sample_line(hist, ibuf, (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) != 0);
+       BKE_histogram_update_sample_line(hist, ibuf, &scene->view_settings, &scene->display_settings);
        
        /* reset y zoom */
        hist->ymax = 1.0f;
@@ -2306,7 +2377,8 @@ static int image_record_composite_apply(bContext *C, wmOperator *op)
        
        BKE_image_all_free_anim_ibufs(scene->r.cfra);
        ntreeCompositTagAnimated(scene->nodetree);
-       ntreeCompositExecTree(scene->nodetree, &scene->r, 0, scene->r.cfra != rcd->old_cfra);  /* 1 is no previews */
+