Color management refactoiring and some extra options

- Move space-being settings (such as view transform) into own
  DNA and RNA structure to avoid code duplication in some areas
  and save some arguments on display buffer acquiring function.

  Also added some utility functions to BKE to manipulate this
  settings.

- Replace static sized color managed buffer flags array with
  dynamically sized array which matches actual number of displays.

  Probably this flags better be transfposed so it'll support
  any number of view transforms and 32 displays (currently it's
  other way around). it's runtime flags only, so would be simple
  to change any time.

- Added support of configurable exposure and gamma.

  Changing this settings wouldn't generate new item in cache,
  it'll affect on buffer with the same color spaces conversion.

  It'll also run full color transform from scratch on every run,
  this could be changes in a way that it'll re-use color managed
  buffer, but from quick glance it doesn't give really noticeable
  boost.

  Currently this settings are stored as pointer in ImBuf structure
  itself. Probably it make sense removing them from ImBuf and make
  moviecache be able to store some kind of tags associated with
  cached ImBuf.
This commit is contained in:
Sergey Sharybin
2012-06-30 12:37:16 +00:00
parent dc40cb4fb0
commit b57a5521c4
18 changed files with 418 additions and 156 deletions

View File

@@ -361,6 +361,16 @@ extern void OCIO_displayTransformSetView(DisplayTransformRcPtr* dt, const char *
(*dt)->setView(name);
}
extern void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
{
(*dt)->setDisplayCC(*t);
}
extern void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *t)
{
(*dt)->setLinearCC(*t);
}
extern void OCIO_displayTransformRelease(DisplayTransformRcPtr* dt)
{
if(dt){
@@ -392,3 +402,45 @@ void OCIO_packedImageDescRelease(PackedImageDesc* id)
}
}
ExponentTransformRcPtr *OCIO_createExponentTransform(void)
{
ExponentTransformRcPtr *et = new ExponentTransformRcPtr();
*et = ExponentTransform::Create();
return et;
}
void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent)
{
(*et)->setValue(exponent);
}
void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et)
{
delete et;
}
MatrixTransformRcPtr *OCIO_createMatrixTransform(void)
{
MatrixTransformRcPtr *mt = new MatrixTransformRcPtr();
*mt = MatrixTransform::Create();
return mt;
}
void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *mt, const float *m44, const float *offset4)
{
(*mt)->setValue(m44, offset4);
}
void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt)
{
delete mt;
}
void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4f)
{
MatrixTransform::Scale(m44, offset4, scale4f);
}

View File

@@ -49,6 +49,8 @@ extern "C" {
OCIO_DECLARE_HANDLE(PackedImageDesc);
OCIO_DECLARE_HANDLE(DisplayTransformRcPtr);
OCIO_DECLARE_HANDLE(ConstTransformRcPtr);
OCIO_DECLARE_HANDLE(ExponentTransformRcPtr);
OCIO_DECLARE_HANDLE(MatrixTransformRcPtr);
#endif
@@ -92,6 +94,8 @@ extern DisplayTransformRcPtr* OCIO_createDisplayTransform(void);
extern void OCIO_displayTransformSetInputColorSpaceName(DisplayTransformRcPtr* dt, const char * name);
extern void OCIO_displayTransformSetDisplay(DisplayTransformRcPtr* dt, const char * name);
extern void OCIO_displayTransformSetView(DisplayTransformRcPtr* dt, const char * name);
extern void OCIO_displayTransformSetDisplayCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et);
extern void OCIO_displayTransformSetLinearCC(DisplayTransformRcPtr *dt, ConstTransformRcPtr *et);
extern void OCIO_displayTransformRelease(DisplayTransformRcPtr* dt);
PackedImageDesc* OCIO_createPackedImageDesc(float * data, long width, long height, long numChannels,
@@ -99,6 +103,16 @@ PackedImageDesc* OCIO_createPackedImageDesc(float * data, long width, long heigh
extern void OCIO_packedImageDescRelease(PackedImageDesc* p);
ExponentTransformRcPtr *OCIO_createExponentTransform(void);
void OCIO_exponentTransformSetValue(ExponentTransformRcPtr *et, const float *exponent);
void OCIO_exponentTransformRelease(ExponentTransformRcPtr *et);
MatrixTransformRcPtr *OCIO_createMatrixTransform(void);
void OCIO_matrixTransformSetValue(MatrixTransformRcPtr *et, const float *m44, const float *offset4);
void OCIO_matrixTransformRelease(MatrixTransformRcPtr *mt);
void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4);
#ifdef __cplusplus
}
#endif

View File

@@ -437,9 +437,17 @@ class IMAGE_PT_display_properties(Panel):
sima = context.space_data
window = context.window
view_settings = sima.view_settings
layout.prop(window, "display_device", text="Display")
layout.prop(sima, "view_transform", text="View")
# 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):

View File

@@ -194,9 +194,17 @@ class NODE_PT_display_properties(Panel):
snode = context.space_data
window = context.window
view_settings = snode.view_settings
layout.prop(window, "display_device", text="Display")
layout.prop(snode, "view_transform", text="View")
# 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

View File

@@ -31,6 +31,7 @@
* \ingroup bke
*/
struct ColorManagedViewSettings;
struct CurveMapping;
struct CurveMap;
struct CurveMapPoint;
@@ -80,5 +81,8 @@ void scopes_update(struct Scopes *scopes, struct ImBuf *ibuf, int
void scopes_free(struct Scopes *scopes);
void scopes_new(struct Scopes *scopes);
#endif
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);
#endif

View File

@@ -1207,3 +1207,21 @@ void scopes_new(Scopes *scopes)
scopes->waveform_3 = NULL;
scopes->vecscope = NULL;
}
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, "NONE", sizeof(settings->view_transform));
settings->gamma = 1.0f;
settings->exposure = 0.5f;
}
void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings,
const ColorManagedViewSettings *settings)
{
*new_settings = *settings;
}

View File

@@ -461,7 +461,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_transform, win->display_device, &cache_handle);
display_buffer = IMB_display_buffer_acquire(ibuf, &sima->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

@@ -387,11 +387,7 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
simage->zoom = 1;
simage->lock = 1;
/* 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(simage->view_transform, "NONE", sizeof(simage->view_transform));
BKE_color_managed_view_settings_init(&simage->view_settings);
simage->iuser.ok = 1;
simage->iuser.fie_ima = 2;
@@ -464,7 +460,7 @@ static SpaceLink *image_duplicate(SpaceLink *sl)
scopes_new(&simagen->scopes);
BLI_strncpy(simagen->view_transform, simage->view_transform, sizeof(simage->view_transform));
BKE_color_managed_view_settings_copy(&simagen->view_settings, &simage->view_settings);
return (SpaceLink *)simagen;
}

View File

@@ -2984,7 +2984,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_transform, win->display_device, &cache_handle);
display_buffer = IMB_display_buffer_acquire(ibuf, &snode->view_settings,
win->display_device, &cache_handle);
if (display_buffer) {
if (snode->flag & SNODE_SHOW_ALPHA) {

View File

@@ -46,6 +46,7 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_node.h"
@@ -104,12 +105,7 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
/* backdrop */
snode->zoom = 1.0f;
/* 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(snode->view_transform, "NONE", sizeof(snode->view_transform));
BKE_color_managed_view_settings_init(&snode->view_settings);
/* header */
ar= MEM_callocN(sizeof(ARegion), "header for node");
@@ -322,13 +318,14 @@ static void node_area_refresh(const struct bContext *C, struct ScrArea *sa)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
SpaceImage *snode = (SpaceImage *) sl;
SpaceNode *snoden= MEM_dupallocN(sl);
/* clear or remove stuff from old */
snoden->nodetree= NULL;
snoden->linkdrag.first= snoden->linkdrag.last= NULL;
BLI_strncpy(snoden->view_transform, snoden->view_transform, sizeof(snoden->view_transform));
BKE_color_managed_view_settings_copy(&snoden->view_settings, &snode->view_settings);
return (SpaceLink *)snoden;
}

View File

@@ -33,6 +33,7 @@
#define BCM_CONFIG_FILE "config.ocio"
struct ColorManagedViewSettings;
struct EnumPropertyItem;
struct ImBuf;
struct Main;
@@ -46,8 +47,13 @@ void IMB_colormanagement_exit(void);
/* ** Public display buffers interfaces ** */
unsigned char *IMB_display_buffer_acquire(struct ImBuf *ibuf, const char *view_transform, const char *display,
void **cache_handle);
void IMB_colormanage_flags_allocate(struct ImBuf *ibuf);
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,
const char *display, void **cache_handle);
void IMB_display_buffer_release(void *cache_handle);
void IMB_display_buffer_invalidate(struct ImBuf *ibuf);

View File

@@ -123,8 +123,9 @@ typedef struct ImBuf {
/* color management */
int colormanage_refcounter;
unsigned int colormanage_flags;
unsigned int display_buffer_flags[16]; /* array of per-display display buffers dirty flags */
/* currently supports 16 display spaces and 32 view-transform */
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
void *colormanage_cache_data; /* cache data which is being assigned when */
/* put ImBuf to colormanage cache */
} ImBuf;
/* Moved from BKE_bmfont_types.h because it is a userflag bit mask. */

View File

@@ -163,6 +163,8 @@ void IMB_freeImBuf(ImBuf *ibuf)
IMB_freezbuffloatImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_metadata_free(ibuf);
IMB_colormanage_flags_free(ibuf);
IMB_colormanage_cache_data_free(ibuf);
MEM_freeN(ibuf);
}
}
@@ -443,6 +445,8 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1)
*ibuf2 = tbuf;
IMB_display_buffer_invalidate(ibuf2);
IMB_colormanage_cache_data_free(ibuf2);
ibuf2->colormanage_flags &= ~ IMB_COLORMANAGED;
return(ibuf2);

View File

@@ -34,9 +34,10 @@
#include <string.h>
#include <math.h>
#include "DNA_windowmanager_types.h"
#include "DNA_space_types.h"
#include "DNA_color_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "IMB_filter.h"
#include "IMB_imbuf.h"
@@ -71,6 +72,8 @@ static ListBase global_colorspaces = {NULL};
static ListBase global_displays = {NULL};
static ListBase global_views = {NULL};
static int global_tot_display = 0;
/*********************** Color managed cache *************************/
/* Currently it's original ImBuf pointer is used to distinguish which
@@ -121,6 +124,11 @@ typedef struct ColormanageCacheKey {
int display; /* display device name */
} ColormanageCacheKey;
typedef struct ColormnaageCacheImBufData {
float exposure; /* exposure value cached buffer is calculated with */
float gamma; /* gamma value cached buffer is calculated with */
} ColormnaageCacheImBufData;
static struct MovieCache *colormanage_cache = NULL;
static unsigned int colormanage_hashhash(const void *key_v)
@@ -205,35 +213,62 @@ static ImBuf *colormanage_cache_get_ibuf(ImBuf *ibuf, int view_transform, int di
return cache_ibuf;
}
static unsigned char *colormanage_cache_get(ImBuf *ibuf, int view_transform, int display, void **cache_handle)
static unsigned char *colormanage_cache_get(ImBuf *ibuf, int view_transform, int display,
float exposure, float gamma, void **cache_handle)
{
ImBuf *cache_ibuf = colormanage_cache_get_ibuf(ibuf, view_transform, display, cache_handle);
if (cache_ibuf) {
ColormnaageCacheImBufData *cache_data;
/* only buffers with different color space conversions are being stored
* in cache separately. buffer which were used only different exposure/gamma
* are re-suing the same cached buffer
*
* check here which exposure/gamma was used for cached buffer and if they're
* different from requested buffer should be re-generated
*/
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
if (cache_data->exposure != exposure || cache_data->gamma != gamma) {
IMB_freeImBuf(cache_ibuf);
return NULL;
}
return (unsigned char *) cache_ibuf->rect;
}
return NULL;
}
static void colormanage_cache_put(ImBuf *ibuf, int view_transform, int display,
static void colormanage_cache_put(ImBuf *ibuf, int view_transform, int display, float exposure, float gamma,
unsigned char *display_buffer, void **cache_handle)
{
ColormanageCacheKey key;
ImBuf *cache_ibuf;
ColormnaageCacheImBufData *cache_data;
key.ibuf = ibuf;
key.view_transform = view_transform;
key.display = display;
/* buffer itself */
cache_ibuf = IMB_allocImBuf(ibuf->x, ibuf->y, ibuf->planes, 0);
cache_ibuf->rect = (unsigned int *) display_buffer;
cache_ibuf->mall |= IB_rect;
cache_ibuf->flags |= IB_rect;
/* store data which is needed to check whether cached buffer could be used for color managed display settings */
cache_data = MEM_callocN(sizeof(ColormnaageCacheImBufData), "color manage cache imbuf data");
cache_data->exposure = exposure;
cache_data->gamma = gamma;
cache_ibuf->colormanage_cache_data = cache_data;
*cache_handle = cache_ibuf;
/* mark source buffer as having color managed buffer and increment color managed buffers count for it */
if ((ibuf->colormanage_flags & IMB_COLORMANAGED) == 0) {
ibuf->colormanage_flags |= IMB_COLORMANAGED;
@@ -245,19 +280,33 @@ static void colormanage_cache_put(ImBuf *ibuf, int view_transform, int display,
IMB_moviecache_put(colormanage_cache, &key, cache_ibuf);
}
/* validation function checks whether there's buffer with given display transform
* in the cache and if so, check whether it matches resolution of source buffer.
* if resolution is different new buffer would be put into the cache and it'll
* be returned as a result
*
* this function does not check exposure / gamma because currently it's only
* used by partial buffer update functions which uses the same exposure / gamma
* settings as cached buffer had
*/
static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, int view_transform, int display, void **cache_handle)
{
ImBuf *cache_ibuf = colormanage_cache_get_ibuf(ibuf, view_transform, display, cache_handle);
if (cache_ibuf) {
if (cache_ibuf->x != ibuf->x || cache_ibuf->y != ibuf->y) {
ColormnaageCacheImBufData *cache_data;
unsigned char *display_buffer;
int buffer_size;
/* use the same settings as original cached buffer */
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
display_buffer = MEM_callocN(buffer_size, "imbuf validated display buffer");
colormanage_cache_put(ibuf, view_transform, display, display_buffer, cache_handle);
colormanage_cache_put(ibuf, view_transform, display, cache_data->exposure, cache_data->gamma,
display_buffer, cache_handle);
IMB_freeImBuf(cache_ibuf);
@@ -269,6 +318,18 @@ static unsigned char *colormanage_cache_get_validated(ImBuf *ibuf, int view_tran
return NULL;
}
/* return view settings which are stored in cached buffer, not in key itself */
static void colormanage_cache_get_cache_data(void *cache_handle, float *exposure, float *gamma)
{
ImBuf *cache_ibuf = (ImBuf *) cache_handle;
ColormnaageCacheImBufData *cache_data;
cache_data = (ColormnaageCacheImBufData *) cache_ibuf->colormanage_cache_data;
*exposure = cache_data->exposure;
*gamma = cache_data->gamma;
}
#endif
static void colormanage_cache_handle_release(void *cache_handle)
@@ -338,6 +399,8 @@ static void colormanage_load_config(ConstConfigRcPtr* config)
BLI_addtail(&display->views, display_view);
}
}
global_tot_display = tot_display;
}
void colormanage_free_config(void)
@@ -551,16 +614,21 @@ static void *do_display_buffer_apply_ocio_thread(void *handle_v)
return NULL;
}
static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer,
const char *view_transform, const char *display)
static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display,
float exposure, float gamma)
{
ConstConfigRcPtr *config = OCIO_getCurrentConfig();
DisplayTransformRcPtr *dt = OCIO_createDisplayTransform();
ExponentTransformRcPtr *et;
MatrixTransformRcPtr *mt;
ConstProcessorRcPtr *processor;
float *rect_float;
float exponent = 1.0f / MAX2(FLT_EPSILON, gamma);
const float exponent4f[] = {exponent, exponent, exponent, exponent};
rect_float = MEM_dupallocN(ibuf->rect_float);
float gain = powf(2.0f, exposure);
const float scale4f[] = {gain, gain, gain, gain};
float m44[16], offset4[4];
/* OCIO_TODO: get rid of hardcoded input and display spaces */
OCIO_displayTransformSetInputColorSpaceName(dt, "aces");
@@ -568,26 +636,83 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
/* 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 */
et = OCIO_createExponentTransform();
OCIO_exponentTransformSetValue(et, exponent4f);
OCIO_displayTransformSetDisplayCC(dt, (ConstTransformRcPtr *) et);
processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt);
OCIO_exponentTransformRelease(et);
OCIO_displayTransformRelease(dt);
OCIO_configRelease(config);
return processor;
}
static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer,
const ColorManagedViewSettings *view_settings,
const char *display)
{
ConstProcessorRcPtr *processor;
const float gamma = view_settings->gamma;
const float exposure = view_settings->exposure;
const char *view_transform = view_settings->view_transform;
float *rect_float;
rect_float = MEM_dupallocN(ibuf->rect_float);
processor = create_display_buffer_processor(view_transform, display, exposure, gamma);
if (processor) {
display_buffer_apply_threaded(ibuf, rect_float, display_buffer, processor,
do_display_buffer_apply_ocio_thread);
}
OCIO_displayTransformRelease(dt);
OCIO_processorRelease(processor);
OCIO_configRelease(config);
MEM_freeN(rect_float);
}
#endif
unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transform, const char *display, void **cache_handle)
void IMB_colormanage_flags_allocate(ImBuf *ibuf)
{
ibuf->display_buffer_flags = MEM_callocN(sizeof(unsigned int) * global_tot_display, "imbuf display_buffer_flags");
}
void IMB_colormanage_flags_free(ImBuf *ibuf)
{
if (ibuf->display_buffer_flags) {
MEM_freeN(ibuf->display_buffer_flags);
ibuf->display_buffer_flags = NULL;
}
}
void IMB_colormanage_cache_data_free(ImBuf *ibuf)
{
if (ibuf->colormanage_cache_data) {
MEM_freeN(ibuf->colormanage_cache_data);
ibuf->colormanage_cache_data = NULL;
}
}
unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, ColorManagedViewSettings *view_settings,
const char *display, void **cache_handle)
{
const char *view_transform = view_settings->view_transform;
*cache_handle = NULL;
#ifdef WITH_OCIO
if (!ibuf->x || !ibuf->y)
return NULL;
@@ -610,9 +735,17 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transfor
int display_index = IMB_colormanagement_display_get_named_index(display);
int view_transform_flag = 1 << (view_transform_index - 1);
float exposure = view_settings->exposure;
float gamma = view_settings->gamma;
/* ensure color management bit fields exists */
if (!ibuf->display_buffer_flags)
IMB_colormanage_flags_allocate(ibuf);
/* check whether display buffer isn't marked as dirty and if so try to get buffer from cache */
if (ibuf->display_buffer_flags[display_index - 1] & view_transform_flag) {
display_buffer = colormanage_cache_get(ibuf, view_transform_index, display_index, cache_handle);
display_buffer = colormanage_cache_get(ibuf, view_transform_index, display_index,
exposure, gamma, cache_handle);
if (display_buffer) {
return display_buffer;
@@ -621,6 +754,9 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transfor
/* OCIO_TODO: in case when image is being resized it is possible
* to save buffer allocation here
*
* actually not because there might be other users of
* that buffer which better not to change
*/
buffer_size = ibuf->channels * ibuf->x * ibuf->y * sizeof(float);
@@ -634,10 +770,11 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transfor
display_buffer_apply_tonemap(ibuf, display_buffer, IMB_ratio_preserving_odt_tonecurve);
}
else {
display_buffer_apply_ocio(ibuf, display_buffer, view_transform, display);
display_buffer_apply_ocio(ibuf, display_buffer, view_settings, display);
}
colormanage_cache_put(ibuf, view_transform_index, display_index, display_buffer, cache_handle);
colormanage_cache_put(ibuf, view_transform_index, display_index, exposure, gamma,
display_buffer, cache_handle);
ibuf->display_buffer_flags[display_index - 1] |= view_transform_flag;
@@ -648,6 +785,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const char *view_transfor
* generated from float buffer (if any) using standard
* profiles without applying any view / display transformation */
(void) view_settings;
(void) view_transform;
(void) display;
@@ -668,29 +806,40 @@ void IMB_display_buffer_release(void *cache_handle)
void IMB_display_buffer_invalidate(ImBuf *ibuf)
{
memset(ibuf->display_buffer_flags, 0, sizeof(ibuf->display_buffer_flags));
/* if there's no display_buffer_flags this means there's no color managed
* buffers created for this imbuf, no need to invalidate
*/
if (ibuf->display_buffer_flags) {
memset(ibuf->display_buffer_flags, 0, global_tot_display * sizeof(unsigned int));
}
}
#ifdef WITH_OCIO
static void colormanage_check_space_view_transform(char *view_transform, int max_view_transform, const char *editor,
const ColorManagedView *default_view)
static void colormanage_check_view_settings(ColorManagedViewSettings *view_settings, const char *editor,
const ColorManagedView *default_view)
{
if (view_transform[0] == '\0') {
BLI_strncpy(view_transform, "NONE", max_view_transform);
if (view_settings->view_transform[0] == '\0') {
BLI_strncpy(view_settings->view_transform, "NONE", sizeof(view_settings->view_transform));
}
else if (!strcmp(view_transform, "NONE")) {
else if (!strcmp(view_settings->view_transform, "NONE")) {
/* pass */
}
else {
ColorManagedView *view = colormanage_view_get_named(view_transform);
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",
editor, view_transform, default_view->name);
editor, view_settings->view_transform, default_view->name);
BLI_strncpy(view_transform, default_view->name, max_view_transform);
BLI_strncpy(view_settings->view_transform, default_view->name, sizeof(view_settings->view_transform));
}
}
/* OCIO_TODO: move to do_versions() */
if (view_settings->exposure == 0.0f && view_settings->gamma == 0.0f) {
view_settings->exposure = 0.5f;
view_settings->gamma = 1.0f;
}
}
#endif
@@ -732,14 +881,12 @@ void IMB_colormanagement_check_file_config(Main *bmain)
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *) sl;
colormanage_check_space_view_transform(sima->view_transform, sizeof(sima->view_transform),
"image", default_view);
colormanage_check_view_settings(&sima->view_settings, "image", default_view);
}
else if (sl->spacetype == SPACE_NODE) {
SpaceNode *snode = (SpaceNode *) sl;
colormanage_check_space_view_transform(snode->view_transform, sizeof(snode->view_transform),
"node", default_view);
colormanage_check_view_settings(&snode->view_settings, "node", default_view);
}
}
}
@@ -990,7 +1137,6 @@ typedef struct PartialBufferUpdateItem {
int display, view;
#ifdef WITH_OCIO
DisplayTransformRcPtr *dt;
ConstProcessorRcPtr *processor;
#endif
@@ -1009,10 +1155,7 @@ PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf)
PartialBufferUpdateContext *context = NULL;
#ifdef WITH_OCIO
ConstConfigRcPtr *config = OCIO_getCurrentConfig();
int display;
int tot_display = sizeof(ibuf->display_buffer_flags) / sizeof(ibuf->display_buffer_flags[0]);
context = MEM_callocN(sizeof(PartialBufferUpdateContext), "partial buffer update context");
@@ -1021,7 +1164,12 @@ PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf)
context->predivide = ibuf->flags & IB_cm_predivide;
context->dither = ibuf->dither;
for (display = 0; display < tot_display; display++) {
if (!ibuf->display_buffer_flags) {
/* there's no cached display buffers, so no need to iterate though bit fields */
return context;
}
for (display = 0; display < global_tot_display; display++) {
int display_index = display + 1; /* displays in configuration are 1-based */
const char *display_name = IMB_colormanagement_display_get_indexed_name(display_index);
int view_flags = ibuf->display_buffer_flags[display];
@@ -1038,6 +1186,9 @@ PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf)
if (display_buffer) {
PartialBufferUpdateItem *item;
const char *view_name = IMB_colormanagement_view_get_indexed_name(view_index);
float exposure, gamma;
colormanage_cache_get_cache_data(cache_handle, &exposure, &gamma);
item = MEM_callocN(sizeof(PartialBufferUpdateItem), "partial buffer update item");
@@ -1050,18 +1201,10 @@ PartialBufferUpdateContext *IMB_partial_buffer_update_context_new(ImBuf *ibuf)
item->tonecurve_func = IMB_ratio_preserving_odt_tonecurve;
}
else {
DisplayTransformRcPtr *dt = OCIO_createDisplayTransform();
ConstProcessorRcPtr *processor;
/* OCIO_TODO: get rid of hardcoded input and display spaces */
OCIO_displayTransformSetInputColorSpaceName(dt, "aces");
processor = create_display_buffer_processor(view_name, display_name, exposure, gamma);
OCIO_displayTransformSetView(dt, view_name);
OCIO_displayTransformSetDisplay(dt, display_name);
processor = OCIO_configGetProcessor(config, (ConstTransformRcPtr *) dt);
item->dt = dt;
item->processor = processor;
}
@@ -1135,7 +1278,6 @@ void IMB_partial_buffer_update_free(PartialBufferUpdateContext *context, ImBuf *
colormanage_cache_handle_release(item->cache_handle);
OCIO_processorRelease(item->processor);
OCIO_displayTransformRelease(item->dt);
MEM_freeN(item);

View File

@@ -158,6 +158,16 @@ typedef struct Scopes {
#define SCOPES_WAVEFRM_YCC_709 3
#define SCOPES_WAVEFRM_YCC_JPEG 4
typedef struct ColorManagedViewSettings {
int flag; /* assodted flags such as using global settings from window and so */
char view_transform[64]; /* view transform which is being applied when displaying buffer on the screen */
float exposure; /* fstop exposure */
float gamma; /* post-display gamma transform */
} ColorManagedViewSettings;
enum {
COLORMANAGE_VIEW_USE_GLOBAL = (1 << 0) /* use global display settings instead of per-space setting */
};
#endif

View File

@@ -35,7 +35,7 @@
#include "DNA_defs.h"
#include "DNA_listBase.h"
#include "DNA_color_types.h" /* for Histogram */
#include "DNA_color_types.h" /* for Histogram and color management */
#include "DNA_vec_types.h"
#include "DNA_outliner_types.h" /* for TreeStoreElem */
#include "DNA_image_types.h" /* ImageUser */
@@ -690,8 +690,8 @@ typedef struct SpaceImage {
char dt_uvstretch;
char around;
/* color transformation */
char view_transform[64];
ColorManagedViewSettings view_settings;
int pad1;
} SpaceImage;
@@ -875,8 +875,8 @@ typedef struct SpaceNode {
struct bGPdata *gpd; /* grease-pencil data */
/* color transformation */
char view_transform[64];
ColorManagedViewSettings view_settings;
int pad2;
} SpaceNode;
/* snode->flag */

View File

@@ -34,6 +34,14 @@
#include "DNA_color_types.h"
#include "DNA_texture_types.h"
#include "WM_api.h"
#include "WM_types.h"
static EnumPropertyItem view_transform_items[] = {
{0, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}
};
#ifdef RNA_RUNTIME
#include "RNA_access.h"
@@ -48,11 +56,10 @@
#include "BKE_node.h"
#include "BKE_texture.h"
#include "WM_api.h"
#include "WM_types.h"
#include "ED_node.h"
#include "IMB_colormanagement.h"
static int rna_CurveMapping_curves_length(PointerRNA *ptr)
{
CurveMapping *cumap = (CurveMapping *)ptr->data;
@@ -337,6 +344,38 @@ static void rna_Scopes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointer
s->ok = 0;
}
static int rna_ColorManagedViewSettings_view_transform_get(PointerRNA *ptr)
{
ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
return IMB_colormanagement_view_get_named_index(view->view_transform);
}
static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int value)
{
ColorManagedViewSettings *view = (ColorManagedViewSettings *) ptr->data;
const char *name = IMB_colormanagement_view_get_indexed_name(value);
if (name) {
BLI_strncpy(view->view_transform, name, sizeof(view->view_transform));
}
}
static EnumPropertyItem* rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
{
wmWindow *win = CTX_wm_window(C);
EnumPropertyItem *items = NULL;
int totitem = 0;
RNA_enum_item_add(&items, &totitem, &view_transform_items[0]);
IMB_colormanagement_view_items_add(&items, &totitem, win->display_device);
RNA_enum_item_end(&items, &totitem);
*free = 1;
return items;
}
#else
static void rna_def_curvemappoint(BlenderRNA *brna)
@@ -676,6 +715,39 @@ static void rna_def_scopes(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vectorscope Opacity", "Opacity of the points");
}
static void rna_def_colormanage(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "ColorManagedViewSettings", NULL);
RNA_def_struct_ui_text(srna, "ColorManagedViewSettings", "Color management settings used for displaying images on the display");
prop = RNA_def_property(srna, "use_global_settings", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", COLORMANAGE_VIEW_USE_GLOBAL);
RNA_def_property_ui_text(prop, "Use Global Settings", "Use global display settings instead of per-space setting");
RNA_def_property_update(prop, NC_WINDOW, NULL);
prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, view_transform_items);
RNA_def_property_enum_funcs(prop, "rna_ColorManagedViewSettings_view_transform_get",
"rna_ColorManagedViewSettings_view_transform_set",
"rna_ColorManagedViewSettings_view_transform_itemf");
RNA_def_property_ui_text(prop, "View Transform", "View transform used for this image editor");
RNA_def_property_update(prop, NC_WINDOW, NULL);
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_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_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);
}
void RNA_def_color(BlenderRNA *brna)
{
@@ -686,6 +758,7 @@ void RNA_def_color(BlenderRNA *brna)
rna_def_color_ramp(brna);
rna_def_histogram(brna);
rna_def_scopes(brna);
rna_def_colormanage(brna);
}
#endif

View File

@@ -118,11 +118,6 @@ EnumPropertyItem viewport_shade_items[] = {
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem view_transform_items[] = {
{0, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL}
};
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
@@ -671,38 +666,6 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene
ED_space_image_release_buffer(sima, lock);
}
static int rna_SpaceImageEditor_view_transform_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *) ptr->data;
return IMB_colormanagement_view_get_named_index(sima->view_transform);
}
static void rna_SpaceImageEditor_view_transform_set(PointerRNA *ptr, int value)
{
SpaceImage *sima = (SpaceImage*) ptr->data;
const char *name = IMB_colormanagement_view_get_indexed_name(value);
if (name) {
BLI_strncpy(sima->view_transform, name, sizeof(sima->view_transform));
}
}
static EnumPropertyItem* rna_SpaceImageEditor_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
{
wmWindow *win = CTX_wm_window(C);
EnumPropertyItem *items = NULL;
int totitem = 0;
RNA_enum_item_add(&items, &totitem, &view_transform_items[0]);
IMB_colormanagement_view_items_add(&items, &totitem, win->display_device);
RNA_enum_item_end(&items, &totitem);
*free = 1;
return items;
}
/* Space Text Editor */
static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, int value)
@@ -1015,38 +978,6 @@ static void rna_SpaceNodeEditor_node_tree_update(Main *UNUSED(bmain), Scene *sce
ED_node_tree_update(snode, scene);
}
static int rna_SpaceNodeEditor_view_transform_get(PointerRNA *ptr)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
return IMB_colormanagement_view_get_named_index(snode->view_transform);
}
static void rna_SpaceNodeEditor_view_transform_set(PointerRNA *ptr, int value)
{
SpaceNode *snode = (SpaceNode *)ptr->data;
const char *name = IMB_colormanagement_view_get_indexed_name(value);
if (name) {
BLI_strncpy(snode->view_transform, name, sizeof(snode->view_transform));
}
}
static EnumPropertyItem *rna_SpaceNodeEditor_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free)
{
wmWindow *win = CTX_wm_window(C);
EnumPropertyItem *items = NULL;
int totitem = 0;
RNA_enum_item_add(&items, &totitem, &view_transform_items[0]);
IMB_colormanagement_view_items_add(&items, &totitem, win->display_device);
RNA_enum_item_end(&items, &totitem);
*free = 1;
return items;
}
static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop), int *free)
{
@@ -2096,12 +2027,10 @@ static void rna_def_space_image(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Show UV Editor", "Show UV editing related properties");
prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, view_transform_items);
RNA_def_property_enum_funcs(prop, "rna_SpaceImageEditor_view_transform_get", "rna_SpaceImageEditor_view_transform_set",
"rna_SpaceImageEditor_view_transform_itemf");
RNA_def_property_ui_text(prop, "View Transform", "View transform used for this image editor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, 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", "Sampled colors alongColor management settings used for displaying images on the display");
rna_def_space_image_uv(brna);
}
@@ -3004,12 +2933,10 @@ static void rna_def_space_node(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the image to draw");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL);
prop= RNA_def_property(srna, "view_transform", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, view_transform_items);
RNA_def_property_enum_funcs(prop, "rna_SpaceNodeEditor_view_transform_get", "rna_SpaceNodeEditor_view_transform_set",
"rna_SpaceNodeEditor_view_transform_itemf");
RNA_def_property_ui_text(prop, "View Transform", "View transform used for this node editor");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, 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", "Sampled colors alongColor management settings used for displaying images on the display");
}
static void rna_def_space_logic(BlenderRNA *brna)