Color management cleanup and improvements

- De-duplicate code used by color management panel drawing,
  moved this panel to utility file in bl_ui

- Added support of per-window color management control
  which means view transform. exposure and gamma could be
  set per window and all spaces would use this settings.

  This is default behavior for older files now.

- Added support of color management display of movie clips
  in clip editor.

  Supported both texture buffer and fallback draw methods.

- Fixed default values for exposure and gamma
This commit is contained in:
Sergey Sharybin
2012-06-30 12:37:41 +00:00
parent b57a5521c4
commit 6bfe9266be
17 changed files with 144 additions and 63 deletions

View File

@@ -0,0 +1,44 @@
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
class ColorManagedViewSettingsPanel:
def draw(self, context):
layout = self.layout
space = context.space_data
window = context.window
space_view_settings = space.view_settings
if space_view_settings.use_global_settings:
view_settings = window.view_settings
else:
view_settings = space.view_settings
col = layout.column()
col.prop(space_view_settings, "use_global_settings")
col.prop(window, "display_device", text="Display")
col.prop(view_settings, "view_transform", text="View")
col = layout.column()
col.active = view_settings.view_transform not in {'ACES ODT Tonecurve', 'NONE'}
col.prop(view_settings, "exposure")
col.prop(view_settings, "gamma")

View File

@@ -20,6 +20,7 @@
import bpy
from bpy.types import Panel, Header, Menu
from bl_ui.properties_color_management import ColorManagedViewSettingsPanel
class CLIP_HT_header(Header):
@@ -1002,6 +1003,13 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel):
col.prop(sc.clip_user, "use_render_undistorted")
class CLIP_PT_display_properties(Panel, ColorManagedViewSettingsPanel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'
bl_label = "Display Properties"
bl_options = {'DEFAULT_CLOSED'}
class CLIP_PT_footage(CLIP_PT_clip_view_panel, Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'UI'

View File

@@ -20,6 +20,7 @@
import bpy
from bpy.types import Header, Menu, Panel
from bl_ui.properties_paint_common import UnifiedPaintPanel
from bl_ui.properties_color_management import ColorManagedViewSettingsPanel
class ImagePaintPanel(UnifiedPaintPanel):
@@ -427,28 +428,11 @@ class IMAGE_HT_header(Header):
layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
class IMAGE_PT_display_properties(Panel):
class IMAGE_PT_display_properties(Panel, ColorManagedViewSettingsPanel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "Display Properties"
def draw(self, context):
layout = self.layout
sima = context.space_data
window = context.window
view_settings = sima.view_settings
# OCIO_TODO: de-duplicate this between different spaces
col = layout.column()
col.prop(window, "display_device", text="Display")
col.prop(view_settings, "view_transform", text="View")
col = layout.column()
col.active = view_settings.view_transform not in {'ACES ODT Tonecurve', 'NONE'}
col.prop(view_settings, "exposure")
col.prop(view_settings, "gamma")
class IMAGE_PT_image_properties(Panel):
bl_space_type = 'IMAGE_EDITOR'

View File

@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
from bl_ui.properties_color_management import ColorManagedViewSettingsPanel
class NODE_HT_header(Header):
@@ -184,28 +185,11 @@ class NODE_MT_node(Menu):
layout.operator("node.read_fullsamplelayers")
class NODE_PT_display_properties(Panel):
class NODE_PT_display_properties(Panel, ColorManagedViewSettingsPanel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_label = "Display Properties"
def draw(self, context):
layout = self.layout
snode = context.space_data
window = context.window
view_settings = snode.view_settings
# OCIO_TODO: de-duplicate this between different spaces
col = layout.column()
col.prop(window, "display_device", text="Display")
col.prop(view_settings, "view_transform", text="View")
col = layout.column()
col.active = view_settings.view_transform not in {'ACES ODT Tonecurve', 'NONE'}
col.prop(view_settings, "exposure")
col.prop(view_settings, "gamma")
# Node Backdrop options
class NODE_PT_properties(Panel):

View File

@@ -81,7 +81,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);

View 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"
@@ -251,7 +252,7 @@ static void verify_buffer_float(ImBuf *ibuf)
}
}
static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
static void draw_movieclip_buffer(wmWindow *win, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
int width, int height, float zoomx, float zoomy)
{
int x, y;
@@ -265,13 +266,20 @@ static void draw_movieclip_buffer(SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
glRectf(x, y, x + zoomx * width, y + zoomy * height);
}
else {
const ColorManagedViewSettings *view_settings;
unsigned char *display_buffer;
void *cache_handle;
verify_buffer_float(ibuf);
if (ibuf->rect) {
view_settings = IMB_view_settings_get_effective(win, &sc->view_settings);
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, win->display_device, &cache_handle);
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);
@@ -297,12 +305,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 */
@@ -1410,6 +1420,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
void clip_draw_main(const bContext *C, ARegion *ar)
{
wmWindow *win = CTX_wm_window(C);
SpaceClip *sc = CTX_wm_space_clip(C);
MovieClip *clip = ED_space_clip_get_clip(sc);
Scene *scene = CTX_data_scene(C);
@@ -1460,7 +1471,7 @@ void clip_draw_main(const bContext *C, ARegion *ar)
}
if (ibuf) {
draw_movieclip_buffer(sc, ar, ibuf, width, height, zoomx, zoomy);
draw_movieclip_buffer(win, sc, ar, ibuf, width, height, zoomx, zoomy);
IMB_freeImBuf(ibuf);
}
else {

View File

@@ -533,6 +533,7 @@ 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 */
@@ -563,7 +564,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);
@@ -575,6 +576,7 @@ 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;
@@ -620,16 +622,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;

View File

@@ -43,6 +43,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
#include "BKE_colortools.h"
#include "BKE_main.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -252,6 +253,8 @@ static SpaceLink *clip_new(const bContext *C)
sc->scopes.track_preview_height = 120;
sc->around = V3D_LOCAL;
BKE_color_managed_view_settings_init(&sc->view_settings);
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for clip");
@@ -332,6 +335,7 @@ static void clip_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
static SpaceLink *clip_duplicate(SpaceLink *sl)
{
SpaceClip *sc = (SpaceClip *) sl;
SpaceClip *scn = MEM_dupallocN(sl);
/* clear or remove stuff from old */
@@ -340,6 +344,8 @@ static SpaceLink *clip_duplicate(SpaceLink *sl)
scn->scopes.ok = FALSE;
scn->draw_context = NULL;
BKE_color_managed_view_settings_copy(&scn->view_settings, &sc->view_settings);
return (SpaceLink *)scn;
}

View File

@@ -447,6 +447,7 @@ static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scen
sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
}
else {
const ColorManagedViewSettings *view_settings;
unsigned char *display_buffer;
void *cache_handle;
@@ -461,8 +462,8 @@ static void draw_image_buffer(wmWindow *win, SpaceImage *sima, ARegion *ar, Scen
* convert them, and optionally apply curves */
image_verify_buffer_float(ima, ibuf, color_manage);
display_buffer = IMB_display_buffer_acquire(ibuf, &sima->view_settings,
win->display_device, &cache_handle);
view_settings = IMB_view_settings_get_effective(win, &sima->view_settings);
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, win->display_device, &cache_handle);
if (display_buffer)
glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);

View File

@@ -2962,6 +2962,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
if (ibuf) {
SpaceNode *snode = CTX_wm_space_node(C);
wmWindow *win = CTX_wm_window(C);
const ColorManagedViewSettings *view_settings;
float x, y;
unsigned char *display_buffer;
void *cache_handle;
@@ -2984,8 +2985,8 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
display_buffer = IMB_display_buffer_acquire(ibuf, &snode->view_settings,
win->display_device, &cache_handle);
view_settings = IMB_view_settings_get_effective(win, &snode->view_settings);
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, win->display_device, &cache_handle);
if (display_buffer) {
if (snode->flag & SNODE_SHOW_ALPHA) {

View File

@@ -39,6 +39,7 @@ struct ImBuf;
struct Main;
struct rcti;
struct PartialBufferUpdateContext;
struct wmWindow;
/* ** Initialization / De-initialization ** */
@@ -52,7 +53,7 @@ void IMB_colormanage_flags_free(struct ImBuf *ibuf);
void IMB_colormanage_cache_data_free(struct ImBuf *ibuf);
unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, struct ColorManagedViewSettings *view_settings,
unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings,
const char *display, void **cache_handle);
void IMB_display_buffer_release(void *cache_handle);
@@ -60,6 +61,9 @@ void IMB_display_buffer_invalidate(struct ImBuf *ibuf);
void IMB_colormanagement_check_file_config(struct Main *bmain);
const struct ColorManagedViewSettings *IMB_view_settings_get_effective(struct wmWindow *win,
const struct ColorManagedViewSettings *view_settings);
/* ** Display funcrions ** */
int IMB_colormanagement_display_get_named_index(const char *name);
const char *IMB_colormanagement_display_get_indexed_name(int index);

View File

@@ -636,13 +636,13 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
/* fstop exposure control */
/* fstop exposure control */
OCIO_matrixTransformScale(m44, offset4, scale4f);
mt = OCIO_createMatrixTransform();
OCIO_matrixTransformSetValue(mt, m44, offset4);
OCIO_displayTransformSetLinearCC(dt, (ConstTransformRcPtr *) mt);
/* post-display gamma transform */
/* post-display gamma transform */
et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, exponent4f);
OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et);
@@ -704,7 +704,7 @@ void IMB_colormanage_cache_data_free(ImBuf *ibuf)
}
}
unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, ColorManagedViewSettings *view_settings,
unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
const char *display, void **cache_handle)
{
const char *view_transform = view_settings->view_transform;
@@ -828,7 +828,7 @@ static void colormanage_check_view_settings(ColorManagedViewSettings *view_setti
ColorManagedView *view = colormanage_view_get_named(view_settings->view_transform);
if (!view) {
printf("Blender color management: %s editor view \"%s\" not found, setting default \"%s\".\n",
printf("Blender color management: %s view \"%s\" not found, setting default \"%s\".\n",
editor, view_settings->view_transform, default_view->name);
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
@@ -837,7 +837,8 @@ static void colormanage_check_view_settings(ColorManagedViewSettings *view_setti
/* OCIO_TODO: move to do_versions() */
if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) {
view_settings->exposure = 0.5f;
view_settings->flag |= COLORMANAGE_VIEW_USE_GLOBAL;
view_settings->exposure = 0.0f;
view_settings->gamma = 1.0f;
}
}
@@ -868,6 +869,8 @@ void IMB_colormanagement_check_file_config(Main *bmain)
BLI_strncpy(win->display_device, default_display->name, sizeof(win->display_device));
}
}
colormanage_check_view_settings(&win->view_settings, "window", default_view);
}
}
@@ -881,12 +884,17 @@ void IMB_colormanagement_check_file_config(Main *bmain)
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *) sl;
colormanage_check_view_settings(&sima->view_settings, "image", default_view);
colormanage_check_view_settings(&sima->view_settings, "image editor", default_view);
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *) sl;
colormanage_check_view_settings(&snode->view_settings, "node", default_view);
colormanage_check_view_settings(&snode->view_settings, "node editor", default_view);
}
else if (sl->spacetype == SPACE_CLIP) {
SpaceClip *sclip = (SpaceClip *) sl;
colormanage_check_view_settings(&sclip->view_settings, "clip editor", default_view);
}
}
}
@@ -896,6 +904,16 @@ void IMB_colormanagement_check_file_config(Main *bmain)
#endif
}
const ColorManagedViewSettings *IMB_view_settings_get_effective(wmWindow *win,
const ColorManagedViewSettings *view_settings)
{
if (view_settings->flag & COLORMANAGE_VIEW_USE_GLOBAL) {
return &win->view_settings;
}
return view_settings;
}
/*********************** Display functions *************************/
#ifdef WITH_OCIO

View File

@@ -1020,6 +1020,10 @@ typedef struct SpaceClip {
char mask_draw_flag;
char mask_draw_type;
char pad3[6];
/* **** color management **** */
ColorManagedViewSettings view_settings;
int pad1;
} SpaceClip;
/* SpaceClip->flag */

View File

@@ -31,6 +31,7 @@
#ifndef __DNA_WINDOWMANAGER_TYPES_H__
#define __DNA_WINDOWMANAGER_TYPES_H__
#include "DNA_color_types.h" /* for color management */
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
@@ -196,7 +197,11 @@ typedef struct wmWindow {
ListBase subwindows; /* opengl stuff for sub windows, see notes in wm_subwindow.c */
ListBase gesture; /* gesture stuff */
/* color management */
char display_device[64]; /* color managed display device name */
ColorManagedViewSettings view_settings; /* global view settings */
int pad1;
} wmWindow;
/* should be something like DNA_EXCLUDE

View File

@@ -739,11 +739,13 @@ static void rna_def_colormanage(BlenderRNA *brna)
prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "exposure");
RNA_def_property_range(prop, -10.0f, 10.0f);
RNA_def_property_float_default(prop, 0.0f);
RNA_def_property_ui_text(prop, "Exposure", "Exposure (stops) applied on displaying image buffers");
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "gamma");
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_range(prop, 0.0f, 5.0f);
RNA_def_property_ui_text(prop, "Gamma", "Amount f gamma modification for displaying image buffers");
RNA_def_property_update(prop, NC_WINDOW, NULL);

View File

@@ -2936,7 +2936,7 @@ static void rna_def_space_node(BlenderRNA *brna)
prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
RNA_def_property_ui_text(prop, "View Settings", "Sampled colors alongColor management settings used for displaying images on the display");
RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display");
}
static void rna_def_space_logic(BlenderRNA *brna)
@@ -3271,6 +3271,12 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_enum_items(prop, pivot_items);
RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
/* color management view settings */
prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
RNA_def_property_ui_text(prop, "View Settings", "Color management settings used for displaying images on the display");
}

View File

@@ -1634,6 +1634,11 @@ static void rna_def_window(BlenderRNA *brna)
"rna_Window_display_device_itemf");
RNA_def_property_ui_text(prop, "Display Device", "Display device name used for this window");
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop = RNA_def_property(srna, "view_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "view_settings");
RNA_def_property_struct_type(prop, "ColorManagedViewSettings");
RNA_def_property_ui_text(prop, "View Settings", "Global color management settings used for displaying images on the display");
}
/* curve.splines */