Color management: make it behave closer to trunk
Avoid using tricks with ibuf->profile to check whether image buffer is in sequencer or linear space. Assume the whole sequencer works in non linear float space and do transformation to linear where it;s needed only. This removes confusion from the code, fixes wrong behavior of some effects.
This commit is contained in:
@@ -140,8 +140,6 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf *
|
||||
IMB_rect_from_float(ibuf3);
|
||||
}
|
||||
|
||||
out->profile = IB_PROFILE_SRGB;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -2461,7 +2461,8 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo
|
||||
imb_freerectImBuf(ibuf);
|
||||
|
||||
/* all sequencer color is done in SRGB space, linear gives odd crossfades */
|
||||
IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE);
|
||||
if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
|
||||
IMB_colormanagement_imbuf_to_sequencer_space(ibuf, FALSE);
|
||||
|
||||
copy_to_ibuf_still(context, seq, nr, ibuf);
|
||||
|
||||
@@ -2653,18 +2654,13 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep,
|
||||
|
||||
if (count == 1) {
|
||||
out = seq_render_strip(context, seq_arr[0], cfra);
|
||||
|
||||
if (out) {
|
||||
/* put buffer back to linear space */
|
||||
IMB_colormanagement_imbuf_from_sequencer_space(out);
|
||||
}
|
||||
out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT;
|
||||
|
||||
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];
|
||||
@@ -2738,10 +2734,7 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep,
|
||||
BKE_sequencer_cache_put(context, seq_arr[i], cfra, SEQ_STRIPELEM_IBUF_COMP, out);
|
||||
}
|
||||
|
||||
if (out) {
|
||||
/* put buffer back to linear space */
|
||||
IMB_colormanagement_imbuf_from_sequencer_space(out);
|
||||
}
|
||||
out->colormanage_flags |= IMB_COLORMANAGE_NOLINEAR_FLOAT;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ typedef struct ImBuf {
|
||||
unsigned int encodedbuffersize; /* Size of encodedbuffer */
|
||||
|
||||
/* color management */
|
||||
int colormanage_flags;
|
||||
unsigned int *display_buffer_flags; /* array of per-display display buffers dirty flags */
|
||||
struct ColormanageCache *colormanage_cache; /* cache used by color management */
|
||||
|
||||
@@ -258,4 +259,9 @@ extern const char *imb_ext_image_qt[];
|
||||
extern const char *imb_ext_movie[];
|
||||
extern const char *imb_ext_audio[];
|
||||
|
||||
/* ImBuf->colormanage_flags */
|
||||
enum {
|
||||
IMB_COLORMANAGE_NOLINEAR_FLOAT = (1 << 0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -616,6 +616,8 @@ typedef struct DisplayBufferThread {
|
||||
int channels;
|
||||
int dither;
|
||||
int predivide;
|
||||
|
||||
int nolinear_float;
|
||||
} DisplayBufferThread;
|
||||
|
||||
typedef struct DisplayBufferInitData {
|
||||
@@ -659,6 +661,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
|
||||
handle->channels = channels;
|
||||
handle->dither = dither;
|
||||
handle->predivide = predivide;
|
||||
|
||||
handle->nolinear_float = ibuf->colormanage_flags & IMB_COLORMANAGE_NOLINEAR_FLOAT;
|
||||
}
|
||||
|
||||
static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned char *byte_buffer,
|
||||
@@ -703,6 +707,20 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
|
||||
IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB,
|
||||
predivide, width, height, width, width);
|
||||
}
|
||||
else if (handle->nolinear_float) {
|
||||
/* currently float is non-linear only in sequencer, which is working
|
||||
* in it's own color space even to handle float buffers, so we need to ensure
|
||||
* float buffer is in linear space before applying all the view transformations
|
||||
*/
|
||||
|
||||
const char *from_colorspace = global_role_sequencer;
|
||||
const char *to_colorspace = global_role_scene_linear;
|
||||
|
||||
memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
|
||||
|
||||
IMB_colormanagement_colorspace_transform(linear_buffer, width, height, channels,
|
||||
from_colorspace, to_colorspace);
|
||||
}
|
||||
else {
|
||||
/* some processors would want to modify float original buffer
|
||||
* before converting it into display byte buffer, so we need to
|
||||
@@ -1060,9 +1078,6 @@ void IMB_colormanagement_imbuf_from_role(ImBuf *ibuf, int role)
|
||||
|
||||
IMB_colormanagement_colorspace_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
|
||||
from_colorspace, to_colorspace);
|
||||
|
||||
/* buffer in now in scene linear space */
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
}
|
||||
#else
|
||||
(void) ibuf;
|
||||
@@ -1118,13 +1133,13 @@ void IMB_colormanagement_imbuf_to_sequencer_space(ImBuf *ibuf, int make_float)
|
||||
if (global_role_sequencer[0]) {
|
||||
IMB_colormanagement_imbuf_to_role(ibuf, COLOR_ROLE_SEQUENCER);
|
||||
|
||||
ibuf->profile = IB_PROFILE_SRGB;
|
||||
ibuf->profile = IB_PROFILE_NONE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* if no sequencer's working space defined fallback to legacy sRGB space */
|
||||
IMB_convert_profile(ibuf, IB_PROFILE_SRGB);
|
||||
IMB_convert_profile(ibuf, IB_PROFILE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,10 +1150,8 @@ void IMB_colormanagement_imbuf_from_sequencer_space(ImBuf *ibuf)
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
if (global_role_sequencer[0]) {
|
||||
if (ibuf->profile == IB_PROFILE_SRGB) {
|
||||
IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER);
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
}
|
||||
IMB_colormanagement_imbuf_from_role(ibuf, COLOR_ROLE_SEQUENCER);
|
||||
ibuf->profile = IB_PROFILE_LINEAR_RGB;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
@@ -1648,7 +1648,7 @@ int RE_seq_render_active(Scene *scene, RenderData *rd)
|
||||
static void do_render_seq(Render *re)
|
||||
{
|
||||
static int recurs_depth = 0;
|
||||
struct ImBuf *ibuf;
|
||||
struct ImBuf *ibuf, *out;
|
||||
RenderResult *rr; /* don't assign re->result here as it might change during give_ibuf_seq */
|
||||
int cfra = re->r.cfra;
|
||||
SeqRenderData context;
|
||||
@@ -1675,7 +1675,11 @@ static void do_render_seq(Render *re)
|
||||
100);
|
||||
}
|
||||
|
||||
ibuf = BKE_sequencer_give_ibuf(context, cfra, 0);
|
||||
out = BKE_sequencer_give_ibuf(context, cfra, 0);
|
||||
|
||||
ibuf = IMB_dupImBuf(out);
|
||||
IMB_freeImBuf(out);
|
||||
IMB_colormanagement_imbuf_from_sequencer_space(ibuf);
|
||||
|
||||
recurs_depth--;
|
||||
|
||||
|
||||
@@ -1089,22 +1089,14 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
|
||||
return ibuf;
|
||||
}
|
||||
|
||||
void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf)
|
||||
void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf)
|
||||
{
|
||||
if (ibuf->rect_float) {
|
||||
/* color management: when off ensure rectf is non-lin, since thats what the internal
|
||||
* render engine delivers */
|
||||
int profile_to = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
|
||||
int profile_from = (ibuf->profile == IB_PROFILE_LINEAR_RGB) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
|
||||
int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
|
||||
|
||||
if (!rr->rectf)
|
||||
rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
|
||||
|
||||
IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
|
||||
4, profile_to, profile_from, predivide,
|
||||
rr->rectx, rr->recty, rr->rectx, rr->rectx);
|
||||
|
||||
memcpy(rr->rectf, ibuf->rect_float, 4 * sizeof(float) * rr->rectx * rr->recty);
|
||||
|
||||
/* TSK! Since sequence render doesn't free the *rr render result, the old rect32
|
||||
* can hang around when sequence render has rendered a 32 bits one before */
|
||||
if (rr->rect32) {
|
||||
|
||||
Reference in New Issue
Block a user