Color management support for sequencer

This adds color management controls to the sequencer space,
which are applying on the displaying image.

Currently used the same UI approach as was used for other
areas, but this would probably be cleaned up in the nearest
future.

This required a bit of hackish stuff to be done, Namely color
management for the sequencer requires one extra step in the
conversion chain to convert sRGB float buffer to linear space.
This was made by setting special flag in ImBuf. Later this
could be done using input color space for the ImBuf probably.
This commit is contained in:
Sergey Sharybin
2012-07-11 19:39:43 +00:00
parent ecfa1965da
commit ba4a5ff74f
6 changed files with 101 additions and 16 deletions

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
def act_strip(context):
@@ -860,5 +861,8 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
col.prop(st, "show_separate_color")
col.prop(st, "proxy_render_size")
class SEQUENCER_PT_display_properties(SequencerButtonsPanel_Output, Panel, ColorManagedViewSettingsPanel):
bl_label = "Display Properties"
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -52,6 +52,7 @@
#include "BKE_sound.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "BIF_gl.h"
@@ -68,6 +69,9 @@
#include "UI_resources.h"
#include "UI_view2d.h"
#include "WM_api.h"
#include "WM_types.h"
/* own include */
#include "sequencer_intern.h"
@@ -812,6 +816,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
GLuint texid;
GLuint last_texid;
SeqRenderData context;
unsigned char *display_buffer;
void *cache_handle = NULL;
render_size = sseq->render_size;
if (render_size == 0) {
@@ -892,12 +898,23 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
if (ibuf->rect_float && ibuf->rect == NULL) {
IMB_rect_from_float(ibuf);
}
display_buffer = (unsigned char *)ibuf->rect;
}
else {
const ColorManagedViewSettings *view_settings;
wmWindow *win = CTX_wm_window(C);
ibuf->colormanagement_flags |= IMB_COLORMANAGEMENT_SRGB_SOURCE;
view_settings = IMB_view_settings_get_effective(win, &sseq->view_settings);
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, &win->display_settings, &cache_handle);
}
if (ibuf->rect_float && ibuf->rect == NULL) {
IMB_rect_from_float(ibuf);
}
/* setting up the view - actual drawing starts here */
UI_view2d_view_ortho(v2d);
@@ -910,7 +927,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer);
glBegin(GL_QUADS);
if (frame_ofs) {
@@ -1042,6 +1059,8 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
if (cache_handle)
IMB_display_buffer_release(cache_handle);
}
#if 0

View File

@@ -128,6 +128,7 @@ typedef struct ImBuf {
unsigned int encodedbuffersize; /* Size of encodedbuffer */
/* color management */
unsigned int colormanagement_flags; /* flags filed used by color management rutines */
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
struct ColormanageCache *colormanage_cache; /* cache used by color management */
@@ -256,4 +257,12 @@ extern const char *imb_ext_image_qt[];
extern const char *imb_ext_movie[];
extern const char *imb_ext_audio[];
/* imbuf->colormanagement_flags */
/* special flag used for color management of compositor results,
* which are in sRGB space and requires extra step in color conversions
* could be replaced with something more general in the future
*/
#define IMB_COLORMANAGEMENT_SRGB_SOURCE (1 << 0)
#endif

View File

@@ -625,6 +625,8 @@ typedef struct DisplayBufferThread {
int channels;
int dither;
int predivide;
int buffer_in_srgb;
} DisplayBufferThread;
static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *display_buffer,
@@ -637,8 +639,16 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
int i, tot_thread = BLI_system_thread_count();
int start_line, tot_line;
if (tot_thread > 1)
if (tot_thread > 1) {
/* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of
* possible non-initialized sRGB conversion stuff. Make sure it's properly
* initialized before starting threads, but likely this stuff should be
* initialized somewhere before to avoid possible issues in other issues.
*/
BLI_init_srgb_conversion();
BLI_init_threads(&threads, do_thread, tot_thread);
}
start_line = 0;
tot_line = ((float)(ibuf->y / tot_thread)) + 0.5f;
@@ -664,6 +674,7 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
handles[i].channels = ibuf->channels;
handles[i].dither = ibuf->dither;
handles[i].predivide = predivide;
handles[i].buffer_in_srgb = ibuf->colormanagement_flags & IMB_COLORMANAGEMENT_SRGB_SOURCE;
if (tot_thread > 1)
BLI_insert_thread(&threads, &handles[i]);
@@ -677,6 +688,30 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c
do_thread(&handles[0]);
}
static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
{
float *linear_buffer = handle->buffer;
if (handle->buffer_in_srgb) {
float *buffer = handle->buffer;
int channels = handle->channels;
int width = handle->width;
int height = handle->tot_line;
int predivide = handle->predivide;
int buffer_size = 4 * channels * width * height;
linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer");
IMB_buffer_float_from_float(linear_buffer, buffer, channels,
IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB,
predivide, width, height, width, width);
}
return linear_buffer;
}
static void *do_display_buffer_apply_tonemap_thread(void *handle_v)
{
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
@@ -691,24 +726,22 @@ static void *do_display_buffer_apply_tonemap_thread(void *handle_v)
int dither = handle->dither;
int predivide = handle->predivide;
IMB_buffer_byte_from_float_tonecurve(display_buffer, buffer, channels, dither,
float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
IMB_buffer_byte_from_float_tonecurve(display_buffer, linear_buffer, channels, dither,
IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
predivide, width, height, width, width,
tonecurve_func);
if (linear_buffer != buffer)
MEM_freeN(linear_buffer);
return NULL;
}
static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer,
imb_tonecurveCb tonecurve_func)
{
/* XXX: IMB_buffer_byte_from_float_tonecurve isn't thread-safe because of
* possible non-initialized sRGB conversion stuff. Make sure it's properly
* initialized before starting threads, but likely this stuff should be
* initialized somewhere before to avoid possible issues in other issues.
*/
BLI_init_srgb_conversion();
display_buffer_apply_threaded(ibuf, ibuf->rect_float, display_buffer, tonecurve_func,
do_display_buffer_apply_tonemap_thread);
}
@@ -726,7 +759,9 @@ static void *do_display_buffer_apply_ocio_thread(void *handle_v)
int dither = handle->dither;
int predivide = handle->predivide;
img = OCIO_createPackedImageDesc(buffer, width, height, channels, sizeof(float),
float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
img = OCIO_createPackedImageDesc(linear_buffer, width, height, channels, sizeof(float),
channels * sizeof(float), channels * sizeof(float) * width);
OCIO_processorApply(processor, img);
@@ -734,10 +769,13 @@ static void *do_display_buffer_apply_ocio_thread(void *handle_v)
OCIO_packedImageDescRelease(img);
/* do conversion */
IMB_buffer_byte_from_float(display_buffer, buffer,
IMB_buffer_byte_from_float(display_buffer, linear_buffer,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
predivide, width, height, width, width);
if (linear_buffer != buffer)
MEM_freeN(linear_buffer);
return NULL;
}
@@ -1103,6 +1141,11 @@ void IMB_colormanagement_check_file_config(Main *bmain)
colormanage_check_view_settings(&sclip->view_settings, "clip editor", default_view);
}
else if (sl->spacetype == SPACE_SEQ) {
SpaceSeq *sseq = (SpaceSeq *) sl;
colormanage_check_view_settings(&sseq->view_settings, "sequencer editor", default_view);
}
}
}
}

View File

@@ -473,6 +473,9 @@ typedef struct SpaceSeq {
int pad;
struct bGPdata *gpd; /* grease-pencil data */
/* **** color management **** */
ColorManagedViewSettings view_settings;
} SpaceSeq;
@@ -690,6 +693,7 @@ typedef struct SpaceImage {
char dt_uvstretch;
char around;
/* **** color management **** */
ColorManagedViewSettings view_settings;
} SpaceImage;
@@ -874,6 +878,7 @@ typedef struct SpaceNode {
struct bGPdata *gpd; /* grease-pencil data */
/* **** color management **** */
ColorManagedViewSettings view_settings;
} SpaceNode;

View File

@@ -2143,6 +2143,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "GreasePencil");
RNA_def_property_ui_text(prop, "Grease Pencil", "Grease pencil data for this space");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, 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_text(BlenderRNA *brna)