diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2012-12-31 17:52:13 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2012-12-31 17:52:13 +0400 |
commit | 08cea96ab08026ae9a3351b3e5830eda93f3106f (patch) | |
tree | 5fdcc1f2dc6ccf6388ba8bbe5792c18ddeddb424 /source/blender/blenkernel/intern/sequencer.c | |
parent | 97c6a55c39e1a1949e04cf491946f8b275e2efb5 (diff) |
Alpha premul pipeline cleanup
This assumptions are now made:
- Internally float buffers are always linear alpha-premul colors
- Readers should worry about delivering float buffers with that
assumptions.
- There's an input image setting to say whether it's stored with
straight/premul alpha on the disk.
- Byte buffers are now assumed have straight alpha, readers should
deliver straight alpha.
Some implementation details:
- Removed scene's color unpremultiply setting, which was very
much confusing and was wrong for default settings.
Now all renderers assumes to deliver premultiplied alpha.
- IMB_buffer_byte_from_float will now linearize alpha when
converting from buffer.
- Sequencer's effects were changed to assume bytes have got
straight alpha. Most of effects will work with bytes still,
however for glow it was more tricky to avoid data loss, so
there's a commented out glow implementation which converts
byte buffer to floats first, operates on floats and returns
bytes back. It's slower and not sure if it should actually
be used -- who're using glow on alpha anyway?
- Sequencer modifiers should also be working nice with straight
bytes now.
- GLSL preview will predivide float textures to make nice shading,
shading with byte textures worked nice (GLSL was assuming straight
alpha).
- Blender Internal will set alpha=1 to the whole sky. The same
happens in Cycles and there's no way to avoid this -- sky is
neither straight nor premul and doesn't fit color pipeline well.
- Straight alpha mode for render result was also eliminated.
- Conversion to correct alpha need to be done before linearizing
float buffer.
- TIFF will now load and save files with proper alpha mode setting
in file meta data header.
- Remove Use Alpha from texture mapping and replaced with image
datablock setting.
Behaves much more predictable and clear from code point of view
and solves possible regressions when non-premultiplied images were
used as textures with ignoring alpha channel.
Diffstat (limited to 'source/blender/blenkernel/intern/sequencer.c')
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a82704d9e38..69c125b0ece 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -324,7 +324,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ { 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) { @@ -354,7 +353,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ imb_freerectImBuf(ibuf); IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); + from_colorspace, to_colorspace, TRUE); } } @@ -367,10 +366,8 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) 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); + from_colorspace, to_colorspace, TRUE); } } @@ -1517,18 +1514,6 @@ MINLINE float color_balance_fl(float in, const float lift, const float gain, con return powf(x, gamma) * mul; } -static void make_cb_table_byte(float lift, float gain, float gamma, - unsigned char *table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul); - - table[y] = FTOCHAR(v); - } -} - static void make_cb_table_float(float lift, float gain, float gamma, float *table, float mul) { @@ -1543,35 +1528,33 @@ static void make_cb_table_float(float lift, float gain, float gamma, static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul) { - unsigned char cb_tab[3][256]; - int c; - unsigned char *p = rect; - unsigned char *e = p + width * 4 * height; + //unsigned char cb_tab[3][256]; + unsigned char *cp = rect; + unsigned char *e = cp + width * 4 * height; unsigned char *m = mask_rect; StripColorBalance cb = calc_cb(cb_); - for (c = 0; c < 3; c++) { - make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); - } + while (cp < e) { + float p[4]; + int c; - while (p < e) { - if (m) { - float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f}; + straight_uchar_to_premul_float(p, cp); - p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]]; - p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]]; - p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]]; + for (c = 0; c < 3; c++) { + float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul); - m += 4; - } - else { - p[0] = cb_tab[0][p[0]]; - p[1] = cb_tab[1][p[1]]; - p[2] = cb_tab[2][p[2]]; + if (m) + p[c] = p[c] * (1.0f - (float)m[c] / 255.0f) + t * m[c]; + else + p[c] = t; } - p += 4; + premul_float_to_straight_uchar(cp, p); + + cp += 4; + if (m) + m += 4; } } @@ -1795,7 +1778,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 | SEQ_MAKE_FLOAT)) { + if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) { return TRUE; } @@ -1892,7 +1875,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); - + sequencer_imbuf_assign_spaces(context.scene, i); + IMB_freeImBuf(ibuf); ibuf = i; @@ -1931,12 +1915,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, multibuf(ibuf, mul); } - if (seq->flag & SEQ_MAKE_PREMUL) { - if (ibuf->planes == 32 && ibuf->zbuf == NULL) { - IMB_premultiply_alpha(ibuf); - } - } - if (ibuf->x != context.rectx || ibuf->y != context.recty) { if (context.scene->r.mode & R_OSA) { IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty); @@ -2546,13 +2524,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_IMAGE: { StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + int flag; if (s_elem) { BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); BLI_path_abs(name, G.main->name); } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name))) { + flag = IB_rect; + if (seq->alpha_mode == SEQ_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); @@ -2641,7 +2624,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) { ImBuf *ibuf = NULL; - int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + int use_preprocess = FALSE; int is_proxy_image = FALSE; float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ @@ -2650,30 +2633,36 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, - * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ - if (ibuf) - use_preprocess = FALSE; - - if (ibuf == NULL) - ibuf = copy_from_ibuf_still(context, seq, nr); - if (ibuf == NULL) { - ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + if (ibuf == NULL) + ibuf = copy_from_ibuf_still(context, seq, nr); if (ibuf == NULL) { - /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { - ibuf = seq_proxy_fetch(context, seq, cfra); - is_proxy_image = (ibuf != NULL); - } + ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - if (ibuf == NULL) - ibuf = do_render_strip_uncached(context, seq, cfra); + if (ibuf == NULL) { + /* MOVIECLIPs have their own proxy management */ + if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { + ibuf = seq_proxy_fetch(context, seq, cfra); + is_proxy_image = (ibuf != NULL); + } - if (ibuf) - BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + if (ibuf == NULL) + ibuf = do_render_strip_uncached(context, seq, cfra); + + if (ibuf) + BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + } } + + if (ibuf) + use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + } + else { + /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, + * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL + * so, no need in check for preprocess here + */ } if (ibuf == NULL) { @@ -3975,6 +3964,14 @@ void BKE_sequence_init_colorspace(Sequence *seq) if (seq->type == SEQ_TYPE_IMAGE) { ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name); + /* byte images are default to straight alpha, however sequencer + * works in premul space, so mark strip to be premultiplied first + */ + if (!ibuf->rect_float) + seq->alpha_mode = SEQ_ALPHA_STRAIGHT; + else + seq->alpha_mode = SEQ_ALPHA_PREMUL; + if (ibuf) IMB_freeImBuf(ibuf); } |