Alpha premul pipeline cleanup
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 31 Dec 2012 13:52:13 +0000 (13:52 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 31 Dec 2012 13:52:13 +0000 (13:52 +0000)
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.

48 files changed:
intern/cycles/blender/addon/properties.py
release/scripts/startup/bl_ui/properties_scene.py
release/scripts/startup/bl_ui/properties_texture.py
release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/seqmodifier.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_math_color.h
source/blender/blenlib/intern/math_color_inline.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_legacy.c
source/blender/collada/DocumentImporter.cpp
source/blender/editors/render/render_preview.c
source/blender/editors/space_image/image_buttons.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_material.c
source/blender/imbuf/IMB_colormanagement.h
source/blender/imbuf/IMB_imbuf.h
source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/IMB_filter.h
source/blender/imbuf/intern/cineon/cineon_dpx.c
source/blender/imbuf/intern/colormanagement.c
source/blender/imbuf/intern/divers.c
source/blender/imbuf/intern/filter.c
source/blender/imbuf/intern/openexr/openexr_api.cpp
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/radiance_hdr.c
source/blender/imbuf/intern/readimage.c
source/blender/imbuf/intern/scaling.c
source/blender/imbuf/intern/tiff.c
source/blender/makesdna/DNA_image_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_texture.c
source/blender/nodes/composite/node_composite_util.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/render/intern/include/render_result.h
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/render_result.c
source/blender/render/intern/source/rendercore.c

index abc251d..2bc4afe 100644 (file)
@@ -269,7 +269,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 )
         cls.film_transparent = BoolProperty(
                 name="Transparent",
-                description="World background is transparent",
+                description="World background is transparent with premultiplied alpha",
                 default=False,
                 )
 
index 3230fb7..66a16da 100644 (file)
@@ -263,7 +263,6 @@ class SCENE_PT_color_management(Panel):
         col.separator()
         col.label(text="Render:")
         col.template_colormanaged_view_settings(scene, "view_settings")
-        col.prop(rd, "use_color_unpremultiply")
 
         col = layout.column()
         col.separator()
index cb7cc1d..eddb542 100644 (file)
@@ -442,7 +442,6 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
 
         col = split.column()
         col.label(text="Alpha:")
-        col.prop(tex, "use_alpha", text="Use")
         col.prop(tex, "use_calculate_alpha", text="Calculate")
         col.prop(tex, "invert_alpha", text="Invert")
         col.separator()
index 5b7a3a8..d6f8de9 100644 (file)
@@ -602,6 +602,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
                 split.prop(elem, "filename", text="")  # strip.elements[0] could be a fallback
 
             layout.prop(strip.colorspace_settings, "name")
+            layout.prop(strip, "alpha_mode")
 
             layout.operator("sequencer.change_path")
 
@@ -797,7 +798,6 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
         col.label(text="Colors:")
         col.prop(strip, "color_saturation", text="Saturation")
         col.prop(strip, "color_multiply", text="Multiply")
-        col.prop(strip, "use_premultiply")
         col.prop(strip, "use_float")
 
 
index ecd3840..10528f1 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         265
-#define BLENDER_SUBVERSION      4
+#define BLENDER_SUBVERSION      5
 
 /* 262 was the last editmesh release but it has compatibility code for bmesh data */
 #define BLENDER_MINVERSION      262
index 8630ace..b93f917 100644 (file)
@@ -312,10 +312,6 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame)
                                break;
 
                ibuf->index = index;
-               if (ima->flag & IMA_CM_PREDIVIDE)
-                       ibuf->flags |= IB_cm_predivide;
-               else
-                       ibuf->flags &= ~IB_cm_predivide;
 
                /* this function accepts (link == NULL) */
                BLI_insertlinkbefore(&ima->ibufs, link, ibuf);
@@ -552,6 +548,26 @@ int BKE_image_scale(Image *image, int width, int height)
        return (ibuf != NULL);
 }
 
+static void image_init_color_management(Image *ima)
+{
+       ImBuf *ibuf;
+       char name[FILE_MAX];
+
+       BKE_image_user_file_path(NULL, ima, name);
+
+       /* will set input color space to image format default's */
+       ibuf = IMB_loadiffname(name, IB_test | IB_alphamode_detect, ima->colorspace_settings.name);
+
+       if (ibuf) {
+               if (ibuf->flags & IB_alphamode_premul)
+                       ima->alpha_mode = IMA_ALPHA_PREMUL;
+               else
+                       ima->alpha_mode = IMA_ALPHA_STRAIGHT;
+
+               IMB_freeImBuf(ibuf);
+       }
+}
+
 Image *BKE_image_load(const char *filepath)
 {
        Image *ima;
@@ -579,6 +595,8 @@ Image *BKE_image_load(const char *filepath)
        if (BLI_testextensie_array(filepath, imb_ext_movie))
                ima->source = IMA_SRC_MOVIE;
 
+       image_init_color_management(ima);
+
        return ima;
 }
 
@@ -666,7 +684,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
                /* both byte and float buffers are filling in sRGB space, need to linearize float buffer after BKE_image_buf_fill* functions */
 
                IMB_buffer_float_from_float(rect_float, rect_float, ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB,
-                                           ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+                                           TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
        }
 
        return ibuf;
@@ -2343,7 +2361,7 @@ void BKE_image_backup_render(Scene *scene, Image *ima)
 static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
 {
        const char *colorspace = ima->colorspace_settings.name;
-       int predivide = ima->flag & IMA_CM_PREDIVIDE;
+       int predivide = ima->alpha_mode == IMA_ALPHA_PREMUL;
 
        ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
 
@@ -2375,6 +2393,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *ibuf)
 
 }
 
+static int imbuf_alpha_flags_for_image(Image *ima)
+{
+       int flag = 0;
+
+       if (ima->flag & IMA_IGNORE_ALPHA)
+               flag |= IB_ignore_alpha;
+       else if (ima->alpha_mode == IMA_ALPHA_PREMUL)
+               flag |= IB_alphamode_premul;
+
+       return flag;
+}
+
 static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
 {
        struct ImBuf *ibuf;
@@ -2389,8 +2419,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame)
        BKE_image_user_file_path(iuser, ima, name);
 
        flag = IB_rect | IB_multilayer;
-       if (ima->flag & IMA_DO_PREMUL)
-               flag |= IB_premul;
+       flag |= imbuf_alpha_flags_for_image(ima);
 
        /* read ibuf */
        ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
@@ -2549,15 +2578,14 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
        /* is there a PackedFile with this image ? */
        if (ima->packedfile) {
                flag = IB_rect | IB_multilayer;
-               if (ima->flag & IMA_DO_PREMUL) flag |= IB_premul;
+               flag |= imbuf_alpha_flags_for_image(ima);
 
                ibuf = IMB_ibImageFromMemory((unsigned char *)ima->packedfile->data, ima->packedfile->size, flag,
                                             ima->colorspace_settings.name, "<packed data>");
        }
        else {
                flag = IB_rect | IB_multilayer | IB_metadata;
-               if (ima->flag & IMA_DO_PREMUL)
-                       flag |= IB_premul;
+               flag |= imbuf_alpha_flags_for_image(ima);
 
                /* get the right string */
                BKE_image_user_frame_calc(iuser, cfra, 0);
@@ -2777,15 +2805,6 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_
 
        ibuf->dither = dither;
 
-       if (iuser->scene->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) {
-               ibuf->flags |= IB_cm_predivide;
-               ima->flag |= IMA_CM_PREDIVIDE;
-       }
-       else {
-               ibuf->flags &= ~IB_cm_predivide;
-               ima->flag &= ~IMA_CM_PREDIVIDE;
-       }
-
        ima->ok = IMA_OK_LOADED;
 
        return ibuf;
index 3bff209..7dbbca6 100644 (file)
@@ -156,42 +156,43 @@ static void init_alpha_over_or_under(Sequence *seq)
        seq->seq1 = seq2;
 }
 
-static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  char *rect1, char *rect2, char *out)
+static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
-       int fac2, mfac, fac, fac4;
-       int xo, tempc;
-       char *rt1, *rt2, *rt;
+       float fac2, mfac, fac, fac4;
+       int xo;
+       unsigned char *cp1, *cp2, *rt;
+       float tempc[4], rt1[4], rt2[4];
 
        xo = x;
-       rt1 = (char *) rect1;
-       rt2 = (char *) rect2;
-       rt = (char *) out;
+       cp1 = rect1;
+       cp2 = rect2;
+       rt = out;
 
-       fac2 = (int) (256.0f * facf0);
-       fac4 = (int) (256.0f * facf1);
+       fac2 = facf0;
+       fac4 = facf1;
 
        while (y--) {
                x = xo;
                while (x--) {
-
                        /* rt = rt1 over rt2  (alpha from rt1) */
 
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
+
                        fac = fac2;
-                       mfac = 256 - ( (fac2 * rt1[3]) >> 8);
+                       mfac = 1.0f - fac2 * rt1[3];
 
-                       if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
-                       else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+                       if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2);
+                       else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1);
                        else {
-                               tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
-                               if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
-                               tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
-                               if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
-                               tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
-                               if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
-                               tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
-                               if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+                               tempc[0] = fac * rt1[0] + mfac * rt2[0];
+                               tempc[1] = fac * rt1[1] + mfac * rt2[1];
+                               tempc[2] = fac * rt1[2] + mfac * rt2[2];
+                               tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+                               premul_float_to_straight_uchar(rt, tempc);
                        }
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
 
                if (y == 0) break;
@@ -199,22 +200,23 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,  ch
 
                x = xo;
                while (x--) {
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
+
                        fac = fac4;
-                       mfac = 256 - ( (fac4 * rt1[3]) >> 8);
+                       mfac = 1.0f - (fac4 * rt1[3]);
 
-                       if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2);
-                       else if (mfac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt1);
+                       if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2);
+                       else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1);
                        else {
-                               tempc = (fac * rt1[0] + mfac * rt2[0]) >> 8;
-                               if (tempc > 255) rt[0] = 255; else rt[0] = tempc;
-                               tempc = (fac * rt1[1] + mfac * rt2[1]) >> 8;
-                               if (tempc > 255) rt[1] = 255; else rt[1] = tempc;
-                               tempc = (fac * rt1[2] + mfac * rt2[2]) >> 8;
-                               if (tempc > 255) rt[2] = 255; else rt[2] = tempc;
-                               tempc = (fac * rt1[3] + mfac * rt2[3]) >> 8;
-                               if (tempc > 255) rt[3] = 255; else rt[3] = tempc;
+                               tempc[0] = fac * rt1[0] + mfac * rt2[0];
+                               tempc[1] = fac * rt1[1] + mfac * rt2[1];
+                               tempc[2] = fac * rt1[2] + mfac * rt2[2];
+                               tempc[3] = fac * rt1[3] + mfac * rt2[3];
+
+                               premul_float_to_straight_uchar(rt, tempc);
                        }
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
        }
 }
@@ -298,17 +300,17 @@ static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), fl
 
                slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-               do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
 }
 
 /*********************** Alpha Under *************************/
 
-static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
        int fac2, mfac, fac, fac4;
        int xo;
-       char *rt1, *rt2, *rt;
+       unsigned char *rt1, *rt2, *rt;
 
        xo = x;
        rt1 = rect1;
@@ -460,17 +462,17 @@ static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), f
 
                slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-               do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
 }
 
 /*********************** Cross *************************/
 
-static void do_cross_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_cross_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
        int fac1, fac2, fac3, fac4;
        int xo;
-       char *rt1, *rt2, *rt;
+       unsigned char *rt1, *rt2, *rt;
 
        xo = x;
        rt1 = rect1;
@@ -570,7 +572,7 @@ static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float
 
                slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-               do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
 }
 
@@ -713,31 +715,32 @@ static void free_gammacross(Sequence *UNUSED(seq))
 static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1),  int x, int y, unsigned char *rect1,
                                       unsigned char *rect2, unsigned char *out)
 {
-       int fac1, fac2, col;
+       float fac1, fac2;
        int xo;
-       unsigned char *rt1, *rt2, *rt;
-       
+       unsigned char *cp1, *cp2, *rt;
+       float rt1[4], rt2[4], tempc[4];
+
        xo = x;
-       rt1 = (unsigned char *) rect1;
-       rt2 = (unsigned char *) rect2;
-       rt = (unsigned char *) out;
+       cp1 = rect1;
+       cp2 = rect2;
+       rt = out;
 
-       fac2 = (int)(256.0f * facf0);
-       fac1 = 256 - fac2;
+       fac2 = facf0;
+       fac1 = 1.0f - fac2;
 
        while (y--) {
                x = xo;
                while (x--) {
-                       col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
-                       if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
-                       if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
-                       if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
-                       if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+                       tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+                       tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+                       tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+                       premul_float_to_straight_uchar(rt, tempc);
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
 
                if (y == 0)
@@ -746,16 +749,16 @@ static void do_gammacross_effect_byte(float facf0, float UNUSED(facf1),  int x,
 
                x = xo;
                while (x--) {
-                       col = (fac1 * igamtab1[rt1[0]] + fac2 * igamtab1[rt2[0]]) >> 8;
-                       if (col > 65535) rt[0] = 255; else rt[0] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[1]] + fac2 * igamtab1[rt2[1]]) >> 8;
-                       if (col > 65535) rt[1] = 255; else rt[1] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[2]] + fac2 * igamtab1[rt2[2]]) >> 8;
-                       if (col > 65535) rt[2] = 255; else rt[2] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
-                       col = (fac1 * igamtab1[rt1[3]] + fac2 * igamtab1[rt2[3]]) >> 8;
-                       if (col > 65535) rt[3] = 255; else rt[3] = ( (char *)(gamtab + col))[MOST_SIG_BYTE];
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
+                       tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
+                       tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
+                       tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
+
+                       premul_float_to_straight_uchar(rt, tempc);
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
        }
 }
@@ -828,31 +831,34 @@ static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), f
 static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2,
                                unsigned char *out)
 {
-       int col, xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
+       int xo;
+       unsigned char *cp1, *cp2, *rt;
+       float fac1, fac3;
+       float tempc[4], rt1[4], rt2[4];
 
        xo = x;
-       rt1 = (char *)rect1;
-       rt2 = (char *)rect2;
-       rt = (char *)out;
+       cp1 = rect1;
+       cp2 = rect2;
+       rt = out;
 
-       fac1 = (int)(256.0f * facf0);
-       fac3 = (int)(256.0f * facf1);
+       fac1 = facf0;
+       fac3 = facf1;
 
        while (y--) {
                x = xo;
 
                while (x--) {
-                       col = rt1[0] + ((fac1 * rt2[0]) >> 8);
-                       if (col > 255) rt[0] = 255; else rt[0] = col;
-                       col = rt1[1] + ((fac1 * rt2[1]) >> 8);
-                       if (col > 255) rt[1] = 255; else rt[1] = col;
-                       col = rt1[2] + ((fac1 * rt2[2]) >> 8);
-                       if (col > 255) rt[2] = 255; else rt[2] = col;
-                       col = rt1[3] + ((fac1 * rt2[3]) >> 8);
-                       if (col > 255) rt[3] = 255; else rt[3] = col;
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = rt1[0] + fac1 * rt2[0];
+                       tempc[1] = rt1[1] + fac1 * rt2[1];
+                       tempc[2] = rt1[2] + fac1 * rt2[2];
+                       tempc[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
+
+                       premul_float_to_straight_uchar(rt, tempc);
+
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
 
                if (y == 0)
@@ -861,16 +867,17 @@ static void do_add_effect_byte(float facf0, float facf1, int x, int y, unsigned
 
                x = xo;
                while (x--) {
-                       col = rt1[0] + ((fac3 * rt2[0]) >> 8);
-                       if (col > 255) rt[0] = 255; else rt[0] = col;
-                       col = rt1[1] + ((fac3 * rt2[1]) >> 8);
-                       if (col > 255) rt[1] = 255; else rt[1] = col;
-                       col = rt1[2] + ((fac3 * rt2[2]) >> 8);
-                       if (col > 255) rt[2] = 255; else rt[2] = col;
-                       col = rt1[3] + ((fac3 * rt2[3]) >> 8);
-                       if (col > 255) rt[3] = 255; else rt[3] = col;
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = rt1[0] + fac3 * rt2[0];
+                       tempc[1] = rt1[1] + fac3 * rt2[1];
+                       tempc[2] = rt1[2] + fac3 * rt2[2];
+                       tempc[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
+
+                       premul_float_to_straight_uchar(rt, tempc);
+
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
        }
 }
@@ -890,22 +897,28 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, float *r
        fac3 = facf1;
 
        while (y--) {
-               x = xo * 4;
+               x = xo;
                while (x--) {
-                       *rt = *rt1 + fac1 * (*rt2);
+                       rt[0] = rt1[0] + fac1 * rt2[0];
+                       rt[1] = rt1[1] + fac1 * rt2[1];
+                       rt[2] = rt1[2] + fac1 * rt2[2];
+                       rt[3] = min_ff(1.0f, rt1[3] + fac1 * rt2[3]);
 
-                       rt1++; rt2++; rt++;
+                       rt1 += 4; rt2 += 4; rt += 4;
                }
 
                if (y == 0)
                        break;
                y--;
 
-               x = xo * 4;
+               x = xo;
                while (x--) {
-                       *rt = *rt1 + fac3 * (*rt2);
+                       rt[0] = rt1[0] + fac1 * rt2[0];
+                       rt[1] = rt1[1] + fac1 * rt2[1];
+                       rt[2] = rt1[2] + fac1 * rt2[2];
+                       rt[3] = min_ff(1.0f, rt1[3] + fac3 * rt2[3]);
 
-                       rt1++; rt2++; rt++;
+                       rt1 += 4; rt2 += 4; rt += 4;
                }
        }
 }
@@ -931,32 +944,35 @@ static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 
 /*********************** Sub *************************/
 
-static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rect1, char *rect2, char *out)
+static void do_sub_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect1, unsigned char *rect2, unsigned char *out)
 {
-       int col, xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
+       int xo;
+       unsigned char *cp1, *cp2, *rt;
+       float fac1, fac3;
+       float tempc[4], rt1[4], rt2[4];
 
        xo = x;
-       rt1 = (char *) rect1;
-       rt2 = (char *) rect2;
-       rt = (char *) out;
+       cp1 = rect1;
+       cp2 = rect2;
+       rt = out;
 
-       fac1 = (int) (256.0f * facf0);
-       fac3 = (int) (256.0f * facf1);
+       fac1 = facf0;
+       fac3 = facf1;
 
        while (y--) {
                x = xo;
                while (x--) {
-                       col = rt1[0] - ((fac1 * rt2[0]) >> 8);
-                       if (col < 0) rt[0] = 0; else rt[0] = col;
-                       col = rt1[1] - ((fac1 * rt2[1]) >> 8);
-                       if (col < 0) rt[1] = 0; else rt[1] = col;
-                       col = rt1[2] - ((fac1 * rt2[2]) >> 8);
-                       if (col < 0) rt[2] = 0; else rt[2] = col;
-                       col = rt1[3] - ((fac1 * rt2[3]) >> 8);
-                       if (col < 0) rt[3] = 0; else rt[3] = col;
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = rt1[0] - fac1 * rt2[0];
+                       tempc[1] = rt1[1] - fac1 * rt2[1];
+                       tempc[2] = rt1[2] - fac1 * rt2[2];
+                       tempc[3] = rt1[3] - fac1 * rt2[3];
+
+                       premul_float_to_straight_uchar(rt, tempc);
+
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
 
                if (y == 0)
@@ -965,16 +981,17 @@ static void do_sub_effect_byte(float facf0, float facf1, int x, int y, char *rec
 
                x = xo;
                while (x--) {
-                       col = rt1[0] - ((fac3 * rt2[0]) >> 8);
-                       if (col < 0) rt[0] = 0; else rt[0] = col;
-                       col = rt1[1] - ((fac3 * rt2[1]) >> 8);
-                       if (col < 0) rt[1] = 0; else rt[1] = col;
-                       col = rt1[2] - ((fac3 * rt2[2]) >> 8);
-                       if (col < 0) rt[2] = 0; else rt[2] = col;
-                       col = rt1[3] - ((fac3 * rt2[3]) >> 8);
-                       if (col < 0) rt[3] = 0; else rt[3] = col;
+                       straight_uchar_to_premul_float(rt1, cp1);
+                       straight_uchar_to_premul_float(rt2, cp2);
 
-                       rt1 += 4; rt2 += 4; rt += 4;
+                       tempc[0] = rt1[0] - fac3 * rt2[0];
+                       tempc[1] = rt1[1] - fac3 * rt2[1];
+                       tempc[2] = rt1[2] - fac3 * rt2[2];
+                       tempc[3] = rt1[3] - fac3 * rt2[3];
+
+                       premul_float_to_straight_uchar(rt, tempc);
+
+                       cp1 += 4; cp2 += 4; rt += 4;
                }
        }
 }
@@ -1029,7 +1046,7 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 
                slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-               do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
 }
 
@@ -1039,10 +1056,10 @@ static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UN
 #define XOFF    8
 #define YOFF    8
 
-static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *rect2i, char *rect1i, char *outi)
+static void do_drop_effect_byte(float facf0, float facf1, int x, int y, unsigned char *rect2i, unsigned char *rect1i, unsigned char *outi)
 {
        int height, width, temp, fac, fac1, fac2;
-       char *rt1, *rt2, *out;
+       unsigned char *rt1, *rt2, *out;
        int field = 1;
 
        width = x;
@@ -1051,9 +1068,9 @@ static void do_drop_effect_byte(float facf0, float facf1, int x, int y, char *re
        fac1 = (int) (70.0f * facf0);
        fac2 = (int) (70.0f * facf1);
 
-       rt2 = (char *) (rect2i + YOFF * width);
-       rt1 = (char *) rect1i;
-       out = (char *) outi;
+       rt2 = (unsigned char *) (rect2i + YOFF * width);
+       rt1 = (unsigned char *) rect1i;
+       out = (unsigned char *) outi;
        for (y = 0; y < height - YOFF; y++) {
                if (field) fac = fac1;
                else fac = fac2;
@@ -1122,12 +1139,12 @@ static void do_mul_effect_byte(float facf0, float facf1, int x, int y, unsigned
                                unsigned char *out)
 {
        int xo, fac1, fac3;
-       char *rt1, *rt2, *rt;
+       unsigned char *rt1, *rt2, *rt;
 
        xo = x;
-       rt1 = (char *)rect1;
-       rt2 = (char *)rect2;
-       rt = (char *)out;
+       rt1 = rect1;
+       rt2 = rect2;
+       rt = out;
 
        fac1 = (int)(256.0f * facf0);
        fac3 = (int)(256.0f * facf1);
@@ -1539,13 +1556,13 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
        WipeZone wipezone;
        WipeVars *wipe = (WipeVars *)seq->effectdata;
        int xo, yo;
-       char *rt1, *rt2, *rt;
+       unsigned char *cp1, *cp2, *rt;
 
        precalc_wipe_zone(&wipezone, wipe, x, y);
 
-       rt1 = (char *)rect1;
-       rt2 = (char *)rect2;
-       rt = (char *)out;
+       cp1 = rect1;
+       cp2 = rect2;
+       rt = out;
 
        xo = x;
        yo = y;
@@ -1553,11 +1570,18 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
                for (x = 0; x < xo; x++) {
                        float check = check_zone(&wipezone, x, y, seq, facf0);
                        if (check) {
-                               if (rt1) {
-                                       rt[0] = (int)(rt1[0] * check) + (int)(rt2[0] * (1 - check));
-                                       rt[1] = (int)(rt1[1] * check) + (int)(rt2[1] * (1 - check));
-                                       rt[2] = (int)(rt1[2] * check) + (int)(rt2[2] * (1 - check));
-                                       rt[3] = (int)(rt1[3] * check) + (int)(rt2[3] * (1 - check));
+                               if (cp1) {
+                                       float rt1[4], rt2[4], tempc[4];
+
+                                       straight_uchar_to_premul_float(rt1, cp1);
+                                       straight_uchar_to_premul_float(rt2, cp2);
+
+                                       tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
+                                       tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
+                                       tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
+                                       tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
+
+                                       premul_float_to_straight_uchar(rt, tempc);
                                }
                                else {
                                        rt[0] = 0;
@@ -1567,11 +1591,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
                                }
                        }
                        else {
-                               if (rt2) {
-                                       rt[0] = rt2[0];
-                                       rt[1] = rt2[1];
-                                       rt[2] = rt2[2];
-                                       rt[3] = rt2[3];
+                               if (cp2) {
+                                       rt[0] = cp2[0];
+                                       rt[1] = cp2[1];
+                                       rt[2] = cp2[2];
+                                       rt[3] = cp2[3];
                                }
                                else {
                                        rt[0] = 0;
@@ -1582,11 +1606,11 @@ static void do_wipe_effect_byte(Sequence *seq, float facf0, float UNUSED(facf1),
                        }
 
                        rt += 4;
-                       if (rt1 != NULL) {
-                               rt1 += 4;
+                       if (cp1 != NULL) {
+                               cp1 += 4;
                        }
-                       if (rt2 != NULL) {
-                               rt2 += 4;
+                       if (cp2 != NULL) {
+                               cp2 += 4;
                        }
                }
        }
@@ -2254,16 +2278,42 @@ static void copy_glow_effect(Sequence *dst, Sequence *src)
 }
 
 static void do_glow_effect_byte(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
-                                char *rect1, char *UNUSED(rect2), char *out)
+                                unsigned char *rect1, unsigned char *UNUSED(rect2), unsigned char *out)
 {
-       unsigned char *outbuf = (unsigned char *)out;
-       unsigned char *inbuf = (unsigned char *)rect1;
+#if 0
+       /* XXX: not sure what's better here, on the one hand conversion to floats
+        *      here is not so much trouble, but on the other hand who're using
+        *      glow on buffers with alpha?
+        */
+       unsigned char *outbuf = out;
+       unsigned char *inbuf = rect1;
        GlowVars *glow = (GlowVars *)seq->effectdata;
-       
+
        RVIsolateHighlights_byte(inbuf, outbuf, x, y, glow->fMini * 765, glow->fBoost * facf0, glow->fClamp);
        RVBlurBitmap2_byte(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
        if (!glow->bNoComp)
                RVAddBitmaps_byte(inbuf, outbuf, outbuf, x, y);
+#else
+       float *outbuf, *inbuf;
+       GlowVars *glow = (GlowVars *)seq->effectdata;
+
+       inbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect input");
+       outbuf = MEM_mallocN(4 * sizeof(float) * x * y, "glow effect output");
+
+       IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+       IMB_buffer_float_premultiply(inbuf, x, y);
+
+       RVIsolateHighlights_float(inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
+       RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
+       if (!glow->bNoComp)
+               RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
+
+       IMB_buffer_float_unpremultiply(outbuf, x, y);
+       IMB_buffer_byte_from_float(out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, FALSE, x, y, x, x);
+
+       MEM_freeN(inbuf);
+       MEM_freeN(outbuf);
+#endif
 }
 
 static void do_glow_effect_float(Sequence *seq, int render_size, float facf0, float UNUSED(facf1),  int x, int y,
@@ -2292,7 +2342,7 @@ static ImBuf *do_glow_effect(SeqRenderData context, Sequence *seq, float UNUSED(
        }
        else {
                do_glow_effect_byte(seq, render_size, facf0, facf1, context.rectx, context.recty,
-                                   (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+                                   (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
        }
 
        return out;
@@ -2735,7 +2785,7 @@ static ImBuf *do_speed_effect(SeqRenderData context, Sequence *UNUSED(seq), floa
        }
        else {
                do_cross_effect_byte(facf0, facf1, context.rectx, context.recty,
-                                    (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+                                    (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
        }
        return out;
 }
@@ -2761,8 +2811,8 @@ static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), flo
 
                slice_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
 
-               do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
-               do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
+               do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
        }
 }
 
index 5b2e9f2..3d8a2f7 100644 (file)
@@ -226,24 +226,28 @@ static void curves_apply_threaded(int width, int height, unsigned char *rect, fl
                        }
                        if (rect) {
                                unsigned char *pixel = rect + pixel_index;
-                               unsigned char result[3];
+                               float result[3], tempc[4];
 
-                               curvemapping_evaluate_premulRGB(curve_mapping, result, pixel);
+                               straight_uchar_to_premul_float(tempc, pixel);
+
+                               curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc);
 
                                if (mask_rect) {
                                        float t[3];
 
                                        rgb_uchar_to_float(t, mask_rect + pixel_index);
 
-                                       pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
-                                       pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
-                                       pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
+                                       tempc[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
+                                       tempc[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
+                                       tempc[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
                                }
                                else {
-                                       pixel[0] = result[0];
-                                       pixel[1] = result[1];
-                                       pixel[2] = result[2];
+                                       tempc[0] = result[0];
+                                       tempc[1] = result[1];
+                                       tempc[2] = result[2];
                                }
+
+                               premul_float_to_straight_uchar(pixel, tempc);
                        }
                }
        }
index a82704d..69c125b 100644 (file)
@@ -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);
                }
index 149842b..fbaf6f7 100644 (file)
@@ -440,7 +440,7 @@ void default_tex(Tex *tex)
        tex->type = TEX_CLOUDS;
        tex->stype = 0;
        tex->flag = TEX_CHECKER_ODD;
-       tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA;
+       tex->imaflag = TEX_INTERPOL | TEX_MIPMAP;
        tex->extend = TEX_REPEAT;
        tex->cropxmin = tex->cropymin = 0.0;
        tex->cropxmax = tex->cropymax = 1.0;
index c71463d..3831ec3 100644 (file)
@@ -100,6 +100,13 @@ MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[
 
 void BLI_init_srgb_conversion(void);
 
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]);
+MINLINE void straight_to_premul_v4(float straight[4], const float premul[4]);
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]);
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]);
+
 /************************** Other *************************/
 
 int constrain_rgb(float *r, float *g, float *b);
index 4c8bd43..b8eeca5 100644 (file)
@@ -149,31 +149,6 @@ MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linea
        srgb[3] = FTOUSHORT(linear[3]);
 }
 
-MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
-{
-       float alpha, inv_alpha, t;
-       int i;
-
-       if (linear[3] == 1.0f || linear[3] == 0.0f) {
-               linearrgb_to_srgb_ushort4(srgb, linear);
-               return;
-       }
-
-       alpha = linear[3];
-       inv_alpha = 1.0f / alpha;
-
-       for (i = 0; i < 3; ++i) {
-               t = linear[i] * inv_alpha;
-               srgb[i] = (t <= 1.0f) ?
-                         /* warning - converts: float -> short -> float -> short */
-                         (unsigned short) (to_srgb_table_lookup(t) * alpha) :
-                         /* if FTOUSHORT was an inline function this could be done less confusingly */
-                         ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t));
-       }
-
-       srgb[3] = FTOUSHORT(linear[3]);
-}
-
 MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
 {
        linear[0] = BLI_color_from_srgb_table[srgb[0]];
@@ -293,4 +268,62 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char
        return 0;
 }
 
+/**************** Alpha Transformations *****************/
+
+MINLINE void premul_to_straight_v4(float straight[4], const float premul[4])
+{
+       if (premul[3] == 0.0f || premul[3] == 1.0f) {
+               straight[0] = premul[0];
+               straight[1] = premul[1];
+               straight[2] = premul[2];
+               straight[3] = premul[3];
+       }
+       else {
+               float alpha_inv = 1.0f / premul[3];
+               straight[0] = premul[0] * alpha_inv;
+               straight[1] = premul[1] * alpha_inv;
+               straight[2] = premul[2] * alpha_inv;
+               straight[3] = premul[3];
+       }
+}
+
+MINLINE void straight_to_premul_v4(float premul[4], const float straight[4])
+{
+       float alpha = straight[3];
+       premul[0] = straight[0] * alpha;
+       premul[1] = straight[1] * alpha;
+       premul[2] = straight[2] * alpha;
+       premul[3] = straight[3];
+}
+
+MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
+{
+       float alpha = color[3] / 255.0f;
+       float fac = alpha / 255.0f;
+
+       result[0] = color[0] * fac;
+       result[1] = color[1] * fac;
+       result[2] = color[2] * fac;
+       result[3] = alpha;
+}
+
+MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
+{
+       if (color[3] == 0.0f || color[3] == 1.0f) {
+               result[0] = FTOCHAR(color[0]);
+               result[1] = FTOCHAR(color[1]);
+               result[2] = FTOCHAR(color[2]);
+               result[3] = FTOCHAR(color[3]);
+       }
+       else {
+               float alpha_inv = 1.0f / color[3];
+
+               /* hopefully this would be optimized */
+               result[0] = FTOCHAR(color[0] * alpha_inv);
+               result[1] = FTOCHAR(color[1] * alpha_inv);
+               result[2] = FTOCHAR(color[2] * alpha_inv);
+               result[3] = FTOCHAR(color[3]);
+       }
+}
+
 #endif /* __MATH_COLOR_INLINE_C__ */
index 8ddd69f..7827a3a 100644 (file)
@@ -8568,14 +8568,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       {
+       if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
                Scene *scene;
+               Image *image;
+               Tex *tex;
 
                for (scene = main->scene.first; scene; scene = scene->id.next) {
+                       Sequence *seq;
+
+                       SEQ_BEGIN (scene->ed, seq)
+                       {
+                               if (seq->flag & SEQ_MAKE_PREMUL)
+                                       seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+                       }
+                       SEQ_END
+
                        if (scene->r.bake_samples == 0)
-                               scene->r.bake_samples = 256;
+                       scene->r.bake_samples = 256;
+               }
+
+               for (image = main->image.first; image; image = image->id.next) {
+                       if (image->flag & IMA_DO_PREMUL)
+                               image->alpha_mode = IMA_ALPHA_STRAIGHT;
+               }
+
+               for (tex = main->tex.first; tex; tex = tex->id.next) {
+                       if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
+                               if (tex->ima) {
+                                       image = blo_do_versions_newlibadr(fd, lib, tex->ima);
+                                       image->flag |= IMA_IGNORE_ALPHA;
+                               }
+                       }
                }
        }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
 
index 2e783ac..65a60e1 100644 (file)
@@ -289,11 +289,10 @@ static void ntree_version_245(FileData *fd, Library *lib, bNodeTree *ntree)
                                iuser = node->storage;
                                if (iuser->flag & IMA_OLD_PREMUL) {
                                        iuser->flag &= ~IMA_OLD_PREMUL;
-                                       iuser->flag |= IMA_DO_PREMUL;
                                }
                                if (iuser->flag & IMA_DO_PREMUL) {
                                        image->flag &= ~IMA_OLD_PREMUL;
-                                       image->flag |= IMA_DO_PREMUL;
+                                       image->alpha_mode = IMA_ALPHA_STRAIGHT;
                                }
                        }
                }
@@ -1840,7 +1839,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
                                SEQ_BEGIN (sce->ed, seq)
                                {
                                        if (seq->type == SEQ_TYPE_IMAGE || seq->type == SEQ_TYPE_MOVIE)
-                                               seq->flag |= SEQ_MAKE_PREMUL;
+                                               seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
                                }
                                SEQ_END
                        }
@@ -2901,20 +2900,19 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main)
                for (ima = main->image.first; ima; ima = ima->id.next) {
                        if (ima->flag & IMA_OLD_PREMUL) {
                                ima->flag &= ~IMA_OLD_PREMUL;
-                               ima->flag |= IMA_DO_PREMUL;
+                               ima->alpha_mode = IMA_ALPHA_STRAIGHT;
                        }
                }
 
                for (tex = main->tex.first; tex; tex = tex->id.next) {
                        if (tex->iuser.flag & IMA_OLD_PREMUL) {
                                tex->iuser.flag &= ~IMA_OLD_PREMUL;
-                               tex->iuser.flag |= IMA_DO_PREMUL;
                        }
 
                        ima = blo_do_versions_newlibadr(fd, lib, tex->ima);
                        if (ima && (tex->iuser.flag & IMA_DO_PREMUL)) {
                                ima->flag &= ~IMA_OLD_PREMUL;
-                               ima->flag |= IMA_DO_PREMUL;
+                               ima->alpha_mode = IMA_ALPHA_STRAIGHT;
                        }
                }
        }
index 084f71e..b7797b5 100644 (file)
@@ -614,7 +614,6 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T
        ma->mtex[i]->texco = TEXCO_UV;
        ma->mtex[i]->tex = add_texture("Texture");
        ma->mtex[i]->tex->type = TEX_IMAGE;
-       ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
        ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
        
        texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
@@ -745,7 +744,6 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
                mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
                if (mtex != NULL) {
                        mtex->mapto = MAP_ALPHA;
-                       mtex->tex->imaflag |= TEX_USEALPHA;
                        i++;
                        ma->spectra = ma->alpha = 0;
                        ma->mode |= MA_ZTRANSP | MA_TRANSP;
index a864fe3..6ca8478 100644 (file)
@@ -502,7 +502,7 @@ static int ed_preview_draw_rect(ScrArea *sa, Scene *sce, ID *id, int split, int
                /* exception: don't color manage texture previews - show the raw values */
                if (sce) {
                        do_gamma_correct = TRUE;
-                       do_predivide = sce->r.color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE;
+                       do_predivide = TRUE;
                }
        }
 
index 09d2037..060a181 100644 (file)
@@ -674,6 +674,24 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
 
                        if (ima->source != IMA_SRC_GENERATED) {
                                if (compact == 0) { /* background image view doesnt need these */
+                                       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+                                       int has_alpha = TRUE;
+
+                                       if (ibuf) {
+                                               int imtype = BKE_ftype_to_imtype(ibuf->ftype);
+                                               char valid_channels = BKE_imtype_valid_channels(imtype);
+
+                                               has_alpha = valid_channels & IMA_CHAN_FLAG_ALPHA;
+
+                                               BKE_image_release_ibuf(ima, ibuf, NULL);
+                                       }
+
+                                       if (has_alpha) {
+                                               col = uiLayoutColumn(layout, FALSE);
+                                               uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
+                                               uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
+                                       }
+
                                        uiItemS(layout);
 
                                        split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -694,10 +712,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char
                                        row = uiLayoutRow(col, FALSE);
                                        uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
                                        uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
-                                       
-                                       row = uiLayoutRow(layout, FALSE);
-                                       uiItemR(row, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
-                                       uiItemR(row, &imaptr, "use_color_unpremultiply", 0, NULL, ICON_NONE);
                                }
                        }
 
index a633b39..254899e 100644 (file)
@@ -556,8 +556,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
                                if (do_color_management) {
                                        srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
                                        IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
-                                               ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
+                                               ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
                                                ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+                                       IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
                                        /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
                                        IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
                                        frect= srgb_frect + texwinsy*ibuf->x + texwinsx;
@@ -581,8 +582,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int
                                if (do_color_management) {
                                        frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
                                        IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
-                                                       ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, 0,
+                                                       ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
                                                        ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+                                       IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
                                        /* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
                                        IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
                                }
index 2039f01..a2fc1eb 100644 (file)
@@ -1035,8 +1035,7 @@ static void do_material_tex(GPUShadeInput *shi)
                                GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, FALSE), &tin, &trgb);
                                rgbnor= TEX_RGB;
 
-                               if (tex->imaflag & TEX_USEALPHA)
-                                       talpha= 1;
+                               talpha= 1;
                        }
                        else {
                                continue;
index 0653956..1e33f8d 100644 (file)
@@ -138,6 +138,7 @@ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(const str
                                                                        const struct ColorManagedDisplaySettings *display_settings);
 struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *from_colorspace, const char *to_colorspace);
 void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4]);
+void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]);
 void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]);
 void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
                                          int channels, int predivide);
index db14048..850060e 100644 (file)
@@ -373,7 +373,6 @@ void IMB_rect_from_float(struct ImBuf *ibuf);
  * Changed part will be stored in buffer. This is expected to be used for texture painting updates */
 void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, int is_data);
 void IMB_float_from_rect(struct ImBuf *ibuf);
-void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */
 /* note, check that the conversion exists, only some are supported */
 float *IMB_float_profile_ensure(struct ImBuf *ibuf, int profile, int *alloc);
 void IMB_color_to_bw(struct ImBuf *ibuf);
@@ -393,6 +392,8 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect
        int profile_to, int profile_from, int predivide,
        int width, int height, int stride_to, int stride_from);
 void IMB_buffer_float_clamp(float *buf, int width, int height);
+void IMB_buffer_float_unpremultiply(float *buf, int width, int height);
+void IMB_buffer_float_premultiply(float *buf, int width, int height);
 
 /**
  * Change the ordering of the color bytes pointed to by rect from
@@ -467,6 +468,7 @@ void IMB_flipy(struct ImBuf *ibuf);
 /* Premultiply alpha */
 
 void IMB_premultiply_alpha(struct ImBuf *ibuf);
+void IMB_unpremultiply_alpha(struct ImBuf *ibuf);
 
 /**
  *
index 9fe66b5..49e2e7f 100644 (file)
@@ -167,8 +167,9 @@ typedef struct ImBuf {
 #define IB_animdeinterlace     (1 << 9)
 #define IB_tiles                       (1 << 10)
 #define IB_tilecache           (1 << 11)
-#define IB_premul                      (1 << 12)
-#define IB_cm_predivide                (1 << 13)
+#define IB_alphamode_premul    (1 << 12)  /* indicates whether image on disk have premul alpha */
+#define IB_alphamode_detect    (1 << 13)  /* if this flag is set, alpha mode would be guessed from file */
+#define IB_ignore_alpha                (1 << 14)  /* ignore alpha on load and substitude it with 1.0f */
 
 /*
  * The bit flag is stored in the ImBuf.ftype variable.
index eaedb16..6bd5f44 100644 (file)
@@ -41,6 +41,9 @@ void imb_filterx(struct ImBuf *ibuf);
 void IMB_premultiply_rect(unsigned int *rect, char planes, int w, int h);
 void IMB_premultiply_rect_float(float *rect_float, char planes, int w, int h);
 
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h);
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h);
+
 void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1);
 
 #endif
index c8bc3f8..ba84063 100644 (file)
@@ -95,6 +95,9 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int us
        if (flags & IB_rect)
                IMB_rect_from_float(ibuf);
 
+       if (flags & IB_alphamode_detect)
+               ibuf->flags |= IB_alphamode_premul;
+
        return ibuf;
 }
 
index 1c68a46..bcfddfe 100644 (file)
@@ -189,7 +189,6 @@ typedef struct ColormnaageCacheData {
        int flag;        /* view flags of cached buffer */
        float exposure;  /* exposure value cached buffer is calculated with */
        float gamma;     /* gamma value cached buffer is calculated with */
-       int predivide;   /* predivide flag of cached buffer */
        CurveMapping *curve_mapping;  /* curve mapping used for cached buffer */
        int curve_mapping_timestamp;  /* time stamp of curve mapping used for cached buffer */
 } ColormnaageCacheData;
@@ -323,7 +322,6 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
        ColormanageCacheKey key;
        ImBuf *cache_ibuf;
        int view_flag = 1 << (view_settings->view - 1);
-       int predivide = ibuf->flags & IB_cm_predivide;
        CurveMapping *curve_mapping = view_settings->curve_mapping;
        int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
 
@@ -353,7 +351,6 @@ static unsigned char *colormanage_cache_get(ImBuf *ibuf, const ColormanageCacheV
 
                if (cache_data->exposure != view_settings->exposure ||
                    cache_data->gamma != view_settings->gamma ||
-                       cache_data->predivide != predivide ||
                        cache_data->flag != view_settings->flag ||
                        cache_data->curve_mapping != curve_mapping ||
                        cache_data->curve_mapping_timestamp != curve_mapping_timestamp)
@@ -379,7 +376,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
        ImBuf *cache_ibuf;
        ColormnaageCacheData *cache_data;
        int view_flag = 1 << (view_settings->view - 1);
-       int predivide = ibuf->flags & IB_cm_predivide;
        struct MovieCache *moviecache = colormanage_moviecache_ensure(ibuf);
        CurveMapping *curve_mapping = view_settings->curve_mapping;
        int curve_mapping_timestamp = curve_mapping ? curve_mapping->changed_timestamp : 0;
@@ -400,7 +396,6 @@ static void colormanage_cache_put(ImBuf *ibuf, const ColormanageCacheViewSetting
        cache_data = MEM_callocN(sizeof(ColormnaageCacheData), "color manage cache imbuf data");
        cache_data->exposure = view_settings->exposure;
        cache_data->gamma = view_settings->gamma;
-       cache_data->predivide = predivide;
        cache_data->flag = view_settings->flag;
        cache_data->curve_mapping = curve_mapping;
        cache_data->curve_mapping_timestamp = curve_mapping_timestamp;
@@ -897,13 +892,12 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
 
        if (ibuf->rect_float) {
                const char *to_colorspace = global_role_scene_linear;
-               int predivide = ibuf->flags & IB_cm_predivide;
 
                if (ibuf->rect)
                        imb_freerectImBuf(ibuf);
 
                IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-                                             from_colorspace, to_colorspace, predivide);
+                                             from_colorspace, to_colorspace, TRUE);
        }
 }
 
@@ -1130,7 +1124,6 @@ typedef struct DisplayBufferThread {
 
        int channels;
        float dither;
-       int predivide;
        int is_data;
 
        const char *byte_colorspace;
@@ -1158,7 +1151,6 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l
        DisplayBufferInitData *init_data = (DisplayBufferInitData *) init_data_v;
        ImBuf *ibuf = init_data->ibuf;
 
-       int predivide = ibuf->flags & IB_cm_predivide;
        int channels = ibuf->channels;
        float dither = ibuf->dither;
        int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA;
@@ -1189,7 +1181,6 @@ 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->is_data = is_data;
 
        handle->byte_colorspace = init_data->byte_colorspace;
@@ -1206,7 +1197,6 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
 
        int buffer_size = channels * width * height;
 
-       int predivide = handle->predivide;
        int is_data = handle->is_data;
        int is_data_display = handle->cm_processor->is_data_result;
 
@@ -1224,16 +1214,25 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
 
                /* first convert byte buffer to float, keep in image space */
                for (i = 0, fp = linear_buffer, cp = byte_buffer;
-                    i < channels * width * height;
-                    i++, fp++, cp++)
+                    i < width * height;
+                    i++, fp += channels, cp += channels)
                {
-                       *fp = (float)(*cp) / 255.0f;
+                       if (channels == 3) {
+                               rgb_uchar_to_float(fp, cp);
+                       }
+                       else if (channels == 4) {
+                               rgba_uchar_to_float(fp, cp);
+                               straight_to_premul_v4(fp, fp);
+                       }
+                       else {
+                               BLI_assert(!"Buffers of 3 or 4 channels are only supported here");
+                       }
                }
 
                if (!is_data && !is_data_display) {
                        /* convert float buffer to scene linear space */
                        IMB_colormanagement_transform(linear_buffer, width, height, channels,
-                                                     from_colorspace, to_colorspace, predivide);
+                                                     from_colorspace, to_colorspace, TRUE);
                }
        }
        else if (handle->float_colorspace) {
@@ -1249,7 +1248,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
                memcpy(linear_buffer, handle->buffer, buffer_size * sizeof(float));
 
                IMB_colormanagement_transform(linear_buffer, width, height, channels,
-                                             from_colorspace, to_colorspace, predivide);
+                                             from_colorspace, to_colorspace, TRUE);
        }
        else {
                /* some processors would want to modify float original buffer
@@ -1277,13 +1276,12 @@ static void *do_display_buffer_apply_thread(void *handle_v)
        int width = handle->width;
        int height = handle->tot_line;
        float dither = handle->dither;
-       int predivide = handle->predivide;
        int is_data = handle->is_data;
 
        if (cm_processor == NULL) {
                if (display_buffer_byte) {
                        IMB_buffer_byte_from_byte(display_buffer_byte, handle->byte_buffer, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
-                                                FALSE, width, height, width, width);
+                                                 FALSE, width, height, width, width);
                }
 
                if (display_buffer) {
@@ -1301,7 +1299,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
                }
                else {
                        /* apply processor */
-                       IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, predivide);
+                       IMB_colormanagement_processor_apply(cm_processor, linear_buffer, width, height, channels, TRUE);
                }
 
                /* copy result to output buffers */
@@ -1309,7 +1307,7 @@ static void *do_display_buffer_apply_thread(void *handle_v)
                        /* do conversion */
                        IMB_buffer_byte_from_float(display_buffer_byte, linear_buffer,
                                                   channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
-                                                  predivide, width, height, width, width);
+                                                  TRUE, width, height, width, width);
                }
 
                if (display_buffer)
@@ -1663,7 +1661,7 @@ static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorMan
 
        if (global_tot_display == 0 || global_tot_view == 0) {
                IMB_buffer_float_from_float(ibuf->rect_float, ibuf->rect_float, ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
-                                           ibuf->flags & IB_cm_predivide, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+                                           TRUE, ibuf->x, ibuf->y, ibuf->x, ibuf->x);
        }
        else {
                colormanage_display_buffer_process_ex(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect,
@@ -2326,7 +2324,6 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
 {
        int x, y;
        int channels = ibuf->channels;
-       int predivide = ibuf->flags & IB_cm_predivide;
        float dither = ibuf->dither;
        ColorSpace *rect_colorspace = ibuf->rect_colorspace;
        float *display_buffer_float = NULL;
@@ -2350,13 +2347,11 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
                        else if (byte_buffer) {
                                rgba_uchar_to_float(pixel, byte_buffer + linear_index);
                                IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace);
+                               straight_to_premul_v4(pixel, pixel);
                        }
 
                        if (!is_data) {
-                               if (predivide)
-                                       IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
-                               else
-                                       IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+                               IMB_colormanagement_processor_apply_v4_predivide(cm_processor, pixel);
                        }
 
                        if (display_buffer_float) {
@@ -2365,7 +2360,9 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe
                                copy_v4_v4(display_buffer_float + index, pixel);
                        }
                        else {
-                               rgba_float_to_uchar(display_buffer + display_index, pixel);
+                               float pixel_straight[4];
+                               premul_to_straight_v4(pixel_straight, pixel);
+                               rgba_float_to_uchar(display_buffer + display_index, pixel_straight);
                        }
                }
        }
@@ -2389,7 +2386,6 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
                /* update byte buffer created by legacy color management */
 
                unsigned char *rect = (unsigned char *) ibuf->rect;
-               int predivide = ibuf->flags & IB_cm_predivide;
                int channels = ibuf->channels;
                int width = xmax - xmin;
                int height = ymax - ymin;
@@ -2397,7 +2393,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
                int linear_index = ((ymin - offset_y) * stride + (xmin - offset_x)) * channels;
 
                IMB_buffer_byte_from_float(rect + rect_index, linear_buffer + linear_index, channels, ibuf->dither,
-                                          IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide, width, height, ibuf->x, stride);
+                                          IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE, width, height, ibuf->x, stride);
        }
 
        if (ibuf->display_buffer_flags) {
@@ -2503,6 +2499,15 @@ void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor,
                OCIO_processorApplyRGBA(cm_processor->processor, pixel);
 }
 
+void IMB_colormanagement_processor_apply_v4_predivide(ColormanageProcessor *cm_processor, float pixel[4])
+{
+       if (cm_processor->curve_mapping)
+               curvemapping_evaluate_premulRGBF(cm_processor->curve_mapping, pixel, pixel);
+
+       if (cm_processor->processor)
+               OCIO_processorApplyRGBA_predivide(cm_processor->processor, pixel);
+}
+
 void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, float pixel[3])
 {
        if (cm_processor->curve_mapping)
index f049c40..f0d8b7c 100644 (file)
@@ -39,6 +39,7 @@
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 #include "IMB_allocimbuf.h"
+#include "IMB_filter.h"
 
 #include "IMB_colormanagement.h"
 #include "IMB_colormanagement_intern.h"
@@ -249,11 +250,25 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                        uchar *to = rect_to + stride_to * y * 4;
 
                        if (profile_to == profile_from) {
+                               float straight[4];
+
                                /* no color space conversion */
-                               if (dither) {
+                               if (dither && predivide) {
+                                       for (x = 0; x < width; x++, from += 4, to += 4) {
+                                               premul_to_straight_v4(straight, from);
+                                               float_to_byte_dither_v4(to, straight, di);
+                                       }
+                               }
+                               else if (dither) {
                                        for (x = 0; x < width; x++, from += 4, to += 4)
                                                float_to_byte_dither_v4(to, from, di);
                                }
+                               else if (predivide) {
+                                       for (x = 0; x < width; x++, from += 4, to += 4) {
+                                               premul_to_straight_v4(straight, from);
+                                               rgba_float_to_uchar(to, straight);
+                                       }
+                               }
                                else {
                                        for (x = 0; x < width; x++, from += 4, to += 4)
                                                rgba_float_to_uchar(to, from);
@@ -262,10 +277,12 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                        else if (profile_to == IB_PROFILE_SRGB) {
                                /* convert from linear to sRGB */
                                unsigned short us[4];
+                               float straight[4];
 
                                if (dither && predivide) {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4_predivide(us, from);
+                                               premul_to_straight_v4(straight, from);
+                                               linearrgb_to_srgb_ushort4(us, from);
                                                ushort_to_byte_dither_v4(to, us, di);
                                        }
                                }
@@ -277,7 +294,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
                                }
                                else if (predivide) {
                                        for (x = 0; x < width; x++, from += 4, to += 4) {
-                                               linearrgb_to_srgb_ushort4_predivide(us, from);
+                                               premul_to_straight_v4(straight, from);
+                                               linearrgb_to_srgb_ushort4(us, from);
                                                ushort_to_byte_v4(to, us);
                                        }
                                }
@@ -526,7 +544,6 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from,
 
 void IMB_rect_from_float(ImBuf *ibuf)
 {
-       int predivide = (ibuf->flags & IB_cm_predivide);
        float *buffer;
        const char *from_colorspace;
 
@@ -548,7 +565,10 @@ void IMB_rect_from_float(ImBuf *ibuf)
        buffer = MEM_dupallocN(ibuf->rect_float);
 
        /* first make float buffer in byte space */
-       IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, predivide);
+       IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, TRUE);
+
+       /* convert from float's premul alpha to byte's straight alpha */
+       IMB_unpremultiply_rect_float(buffer, ibuf->planes, ibuf->x, ibuf->y);
 
        /* convert float to byte */
        IMB_buffer_byte_from_float((unsigned char *) ibuf->rect, buffer, ibuf->channels, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -565,7 +585,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 {
        float *rect_float;
        uchar *rect_byte;
-       int predivide = (ibuf->flags & IB_cm_predivide);
        int profile_from = IB_PROFILE_LINEAR_RGB;
 
        /* verify we have a float buffer */
@@ -588,12 +607,12 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 
                /* and do color space conversion to byte */
                IMB_buffer_byte_from_float(rect_byte, rect_float,
-                                          4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide,
+                                          4, ibuf->dither, IB_PROFILE_SRGB, profile_from, TRUE,
                                           w, h, ibuf->x, w);
        }
        else {
                IMB_buffer_float_from_float(buffer, rect_float,
-                                           ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide,
+                                           ibuf->channels, IB_PROFILE_SRGB, profile_from, TRUE,
                                            w, h, w, ibuf->x);
 
                /* XXX: need to convert to image buffer's rect space */
@@ -608,8 +627,6 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w
 
 void IMB_float_from_rect(ImBuf *ibuf)
 {
-       int predivide = (ibuf->flags & IB_cm_predivide);
-
        /* verify if we byte and float buffers */
        if (ibuf->rect == NULL)
                return;
@@ -634,22 +651,12 @@ void IMB_float_from_rect(ImBuf *ibuf)
 
        /* then make float be in linear space */
        IMB_colormanagement_colorspace_to_scene_linear(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
-                                                      ibuf->rect_colorspace, predivide);
-
-       BLI_unlock_thread(LOCK_COLORMANAGE);
-}
-
-/* no profile conversion */
-void IMB_float_from_rect_simple(ImBuf *ibuf)
-{
-       int predivide = (ibuf->flags & IB_cm_predivide);
+                                                      ibuf->rect_colorspace, FALSE);
 
-       if (ibuf->rect_float == NULL)
-               imb_addrectfloatImBuf(ibuf);
+       /* byte buffer is straight alpha, float should always be premul */
+       IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
 
-       IMB_buffer_float_from_byte(ibuf->rect_float, (uchar *)ibuf->rect,
-                                  IB_PROFILE_SRGB, IB_PROFILE_SRGB, predivide,
-                                  ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+       BLI_unlock_thread(LOCK_COLORMANAGE);
 }
 
 /* use when you need to get a buffer with a certain profile
@@ -660,7 +667,6 @@ void IMB_float_from_rect_simple(ImBuf *ibuf)
  */
 float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
 {
-       int predivide = (ibuf->flags & IB_cm_predivide);
        int profile_from = IB_PROFILE_LINEAR_RGB;
        int profile_to;
 
@@ -686,12 +692,13 @@ float *IMB_float_profile_ensure(ImBuf *ibuf, int profile, int *alloc)
 
                if (ibuf->rect_float == NULL) {
                        IMB_buffer_float_from_byte(fbuf, (uchar *)ibuf->rect,
-                                                  profile_to, profile_from, predivide,
+                                                  profile_to, profile_from, FALSE,
                                                   ibuf->x, ibuf->y, ibuf->x, ibuf->x);
+                       IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
                }
                else {
                        IMB_buffer_float_from_float(fbuf, ibuf->rect_float,
-                                                   4, profile_to, profile_from, predivide,
+                                                   4, profile_to, profile_from, TRUE,
                                                    ibuf->x, ibuf->y, ibuf->x, ibuf->x);
                }
 
@@ -727,6 +734,26 @@ void IMB_buffer_float_clamp(float *buf, int width, int height)
        }
 }
 
+void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
+{
+       int total = width * height;
+       float *cp = buf;
+       while (total--) {
+               premul_to_straight_v4(cp, cp);
+               cp += 4;
+       }
+}
+
+void IMB_buffer_float_premultiply(float *buf, int width, int height)
+{
+       int total = width * height;
+       float *cp = buf;
+       while (total--) {
+               straight_to_premul_v4(cp, cp);
+               cp += 4;
+       }
+}
+
 /**************************** alter saturation *****************************/
 
 void IMB_saturation(ImBuf *ibuf, float sat)
index 678b290..51fee23 100644 (file)
@@ -599,3 +599,67 @@ void IMB_premultiply_alpha(ImBuf *ibuf)
                IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
 }
 
+void IMB_unpremultiply_rect(unsigned int *rect, char planes, int w, int h)
+{
+       char *cp;
+       int x, y;
+       float val;
+
+       if (planes == 24) { /* put alpha at 255 */
+               cp = (char *)(rect);
+
+               for (y = 0; y < h; y++)
+                       for (x = 0; x < w; x++, cp += 4)
+                               cp[3] = 255;
+       }
+       else {
+               cp = (char *)(rect);
+
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++, cp += 4) {
+                               val = cp[3] != 0 ? 1.0f / (float)cp[3] : 1.0f;
+                               cp[0] = FTOCHAR(cp[0] * val);
+                               cp[1] = FTOCHAR(cp[1] * val);
+                               cp[2] = FTOCHAR(cp[2] * val);
+                       }
+               }
+       }
+}
+
+void IMB_unpremultiply_rect_float(float *rect_float, char planes, int w, int h)
+{
+       float val, *fp;
+       int x, y;
+
+       if (planes == 24) {   /* put alpha at 1.0 */
+               fp = rect_float;
+
+               for (y = 0; y < h; y++)
+                       for (x = 0; x < w; x++, fp += 4)
+                               fp[3] = 1.0;
+       }
+       else {
+               fp = rect_float;
+               for (y = 0; y < h; y++) {
+                       for (x = 0; x < w; x++, fp += 4) {
+                               val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f;
+                               fp[0] = fp[0] * val;
+                               fp[1] = fp[1] * val;
+                               fp[2] = fp[2] * val;
+                       }
+               }
+       }
+
+}
+
+void IMB_unpremultiply_alpha(ImBuf *ibuf)
+{
+       if (ibuf == NULL)
+               return;
+
+       if (ibuf->rect)
+               IMB_unpremultiply_rect(ibuf->rect, ibuf->planes, ibuf->x, ibuf->y);
+
+       if (ibuf->rect_float)
+               IMB_unpremultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
+}
index da7b31c..18b08c9 100644 (file)
@@ -1197,6 +1197,9 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char
                                        delete file;
                                }
                        }
+
+                       if (flags & IB_alphamode_detect)
+                               ibuf->flags |= IB_alphamode_premul;
                }
                return(ibuf);
        }
index c0737fa..bbe4313 100644 (file)
@@ -110,7 +110,7 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
        unsigned char *pixels = NULL;
        unsigned char *from, *to;
        unsigned short *pixels16 = NULL, *to16;
-       float *from_float;
+       float *from_float, from_straight[4];
        png_bytepp row_pointers = NULL;
        int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
        FILE *fp = NULL;
@@ -175,10 +175,11 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
                        color_type = PNG_COLOR_TYPE_RGBA;
                        if (is_16bit) {
                                for (i = ibuf->x * ibuf->y; i > 0; i--) {
-                                       to16[0] = FTOUSHORT(from_float[0]);
-                                       to16[1] = FTOUSHORT(from_float[1]);
-                                       to16[2] = FTOUSHORT(from_float[2]);
-                                       to16[3] = FTOUSHORT(from_float[3]);
+                                       premul_to_straight_v4(from_straight, from_float);
+                                       to16[0] = FTOUSHORT(from_straight[0]);
+                                       to16[1] = FTOUSHORT(from_straight[1]);
+                                       to16[2] = FTOUSHORT(from_straight[2]);
+                                       to16[3] = FTOUSHORT(from_straight[3]);
                                        to16 += 4; from_float += 4;
                                }
                        }
@@ -196,9 +197,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
                        color_type = PNG_COLOR_TYPE_RGB;
                        if (is_16bit) {
                                for (i = ibuf->x * ibuf->y; i > 0; i--) {
-                                       to16[0] = FTOUSHORT(from_float[0]);
-                                       to16[1] = FTOUSHORT(from_float[1]);
-                                       to16[2] = FTOUSHORT(from_float[2]);
+                                       premul_to_straight_v4(from_straight, from_float);
+                                       to16[0] = FTOUSHORT(from_straight[0]);
+                                       to16[1] = FTOUSHORT(from_straight[1]);
+                                       to16[2] = FTOUSHORT(from_straight[2]);
                                        to16 += 3; from_float += 4;
                                }
                        }
@@ -215,7 +217,8 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
                        color_type = PNG_COLOR_TYPE_GRAY;
                        if (is_16bit) {
                                for (i = ibuf->x * ibuf->y; i > 0; i--) {
-                                       to16[0] = FTOUSHORT(from_float[0]);
+                                       premul_to_straight_v4(from_straight, from_float);
+                                       to16[0] = FTOUSHORT(from_straight[0]);
                                        to16++; from_float += 4;
                                }
                        }
index 03ed1bb..d09adeb 100644 (file)
@@ -212,6 +212,9 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, size_t size, int flags, char color
                        if (ibuf == NULL) return NULL;
                        ibuf->ftype = RADHDR;
 
+                       if (flags & IB_alphamode_detect)
+                               ibuf->flags |= IB_alphamode_premul;
+
                        if (flags & IB_test) return ibuf;
 
                        /* read in and decode the actual data */
index be20c80..8e0709e 100644 (file)
@@ -86,15 +86,28 @@ ImBuf *IMB_ibImageFromMemory(unsigned char *mem, size_t size, int flags, char co
                                        BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
                                }
 
+                               if (flags & IB_ignore_alpha) {
+                                       IMB_rectfill_alpha(ibuf, 1.0f);
+                               }
+                               else {
+                                       if (flags & IB_alphamode_premul) {
+                                               if (ibuf->rect)
+                                                       IMB_unpremultiply_alpha(ibuf);
+                                               else
+                                                       /* pass, floats are expected to be premul */ ;
+                                       }
+                                       else {
+                                               if (ibuf->rect_float)
+                                                       IMB_premultiply_alpha(ibuf);
+                                               else
+                                                       /* pass, bytes are expected to be straight */ ;
+                                       }
+                               }
+
                                /* OCIO_TODO: in some cases it's faster to do threaded conversion,
                                 *            but how to distinguish such cases */
                                colormanage_imbuf_make_linear(ibuf, effective_colorspace);
 
-                               if (flags & IB_premul) {
-                                       IMB_premultiply_alpha(ibuf);
-                                       ibuf->flags |= IB_premul;
-                               }
-
                                return ibuf;
                        }
                }
@@ -230,4 +243,3 @@ void imb_loadtile(ImBuf *ibuf, int tx, int ty, unsigned int *rect)
 
        close(file);
 }
-
index 1e701b8..75d1f4c 100644 (file)
@@ -33,6 +33,7 @@
 
 
 #include "BLI_utildefines.h"
+#include "BLI_math_color.h"
 #include "MEM_guardedalloc.h"
 
 #include "imbuf.h"
@@ -303,23 +304,33 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1)
        }
 
        if (do_rect) {
-               char *p1, *p2, *dest;
+               unsigned char *cp1, *cp2, *dest;
                
-               p1 = (char *) ibuf1->rect;
-               dest = (char *) ibuf2->rect;
+               cp1 = (unsigned char *) ibuf1->rect;
+               dest = (unsigned char *) ibuf2->rect;
                for (y = ibuf2->y; y > 0; y--) {
-                       p2 = p1 + (ibuf1->x << 2);
+                       cp2 = cp1 + (ibuf1->x << 2);
                        for (x = ibuf2->x; x > 0; x--) {
-                               dest[0] = (p1[0] + p2[0] + p1[4] + p2[4]) >> 2;
-                               dest[1] = (p1[1] + p2[1] + p1[5] + p2[5]) >> 2;
-                               dest[2] = (p1[2] + p2[2] + p1[6] + p2[6]) >> 2;
-                               dest[3] = (p1[3] + p2[3] + p1[7] + p2[7]) >> 2;
-                               p1 += 8; 
-                               p2 += 8; 
+                               float p1f[8], p2f[8], destf[4];
+
+                               straight_uchar_to_premul_float(p1f, cp1);
+                               straight_uchar_to_premul_float(p2f, cp2);
+                               straight_uchar_to_premul_float(p1f + 4, cp1 + 4);
+                               straight_uchar_to_premul_float(p2f + 4, cp2 + 4);
+
+                               destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
+                               destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
+                               destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
+                               destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
+
+                               premul_float_to_straight_uchar(dest, destf);
+
+                               cp1 += 8;
+                               cp2 += 8;
                                dest += 4;
                        }
-                       p1 = p2;
-                       if (ibuf1->x & 1) p1 += 4;
+                       cp1 = cp2;
+                       if (ibuf1->x & 1) cp1 += 4;
                }
        }
        
index 83830f2..2630aeb 100644 (file)
@@ -376,7 +376,7 @@ static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
  * This method is most flexible and can handle multiple different bit depths 
  * and RGB channel orderings.
  */
-static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
+static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image)
 {
        ImBuf *tmpibuf;
        int success = 0;
@@ -390,6 +390,23 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
        TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);     /* number of 'channels' */
        TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
 
+       if (spp == 4) {
+               /* HACK: this is really tricky hack, which is only needed to force libtiff
+                *       do not touch RGB channels when there's alpha channel present
+                *       The thing is: libtiff will premul RGB if alpha mode is set to
+                *       unassociated, which really conflicts with blender's assumptions
+                *
+                *       Alternative would be to unpremul after load, but it'll be really
+                *       lossy and unwanted behavior
+                *
+                *       So let's keep this thing here for until proper solution is found (sergey)
+                */
+
+               unsigned short extraSampleTypes[1];
+               extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+               TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1, extraSampleTypes);
+       }
+
        imb_read_tiff_resolution(ibuf, image);
 
        scanline = TIFFScanlineSize(image);
@@ -471,10 +488,6 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
                if (bitspersample < 16)
                        if (ENDIAN_ORDER == B_ENDIAN)
                                IMB_convert_rgba_to_abgr(tmpibuf);
-               if (premul) {
-                       IMB_premultiply_alpha(tmpibuf);
-                       ibuf->flags |= IB_premul;
-               }
                
                /* assign rect last */
                if (tmpibuf->rect_float)
@@ -557,6 +570,18 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
                return NULL;
        }
 
+       /* get alpha mode from file header */
+       if (flags & IB_alphamode_detect) {
+               if (spp == 4) {
+                       unsigned short extra, *extraSampleTypes;
+
+                       TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);
+
+                       if (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)
+                               ibuf->flags |= IB_alphamode_premul;
+               }
+       }
+
        /* if testing, we're done */
        if (flags & IB_test) {
                TIFFClose(image);
@@ -585,9 +610,6 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
                                        hbuf->miplevel = level;
                                        hbuf->ftype = ibuf->ftype;
                                        ibuf->mipmap[level - 1] = hbuf;
-
-                                       if (flags & IB_premul)
-                                               hbuf->flags |= IB_premul;
                                }
                                else
                                        hbuf = ibuf;
@@ -608,7 +630,7 @@ ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[
        }
 
        /* read pixels */
-       if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image, 0)) {
+       if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
                fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
                TIFFClose(image);
                return NULL;
@@ -644,9 +666,6 @@ void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int
                                if (TIFFReadRGBATile(image, tx * ibuf->tilex, (ibuf->ytiles - 1 - ty) * ibuf->tiley, rect) == 1) {
                                        if (ibuf->tiley > ibuf->y)
                                                memmove(rect, rect + ibuf->tilex * (ibuf->tiley - ibuf->y), sizeof(int) * ibuf->tilex * ibuf->y);
-
-                                       if (ibuf->flags & IB_premul)
-                                               IMB_premultiply_rect(rect, 32, ibuf->tilex, ibuf->tiley);
                                }
                                else
                                        printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel);
@@ -689,8 +708,6 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
        float *fromf = NULL;
        float xres, yres;
        int x, y, from_i, to_i, i;
-       int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
-       
 
        /* check for a valid number of bytes per pixel.  Like the PNG writer,
         * the TIFF writer supports 1, 3 or 4 bytes per pixel, corresponding
@@ -763,6 +780,13 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
        TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
 
        if (samplesperpixel == 4) {
+               unsigned short extraSampleTypes[1];
+
+               if (bitspersample == 16)
+                       extraSampleTypes[0] = EXTRASAMPLE_ASSOCALPHA;
+               else
+                       extraSampleTypes[0] = EXTRASAMPLE_UNASSALPHA;
+
                /* RGBA images */
                TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
                             extraSampleTypes);
index fe35503..0f47ee2 100644 (file)
@@ -111,6 +111,9 @@ typedef struct Image {
 
        /* color management */
        ColorManagedColorspaceSettings colorspace_settings;
+       char alpha_mode;
+
+       char pad[7];
 } Image;
 
 
@@ -119,15 +122,16 @@ typedef struct Image {
 /* Image.flag */
 #define IMA_FIELDS                     1
 #define IMA_STD_FIELD          2
-#define IMA_DO_PREMUL          4
+#define IMA_DO_PREMUL          4    /* deprecated, should not be used */
 #define IMA_REFLECT                    16
 #define IMA_NOCOLLECT          32
 #define IMA_DEPRECATED         64
 #define IMA_OLD_PREMUL         128
-#define IMA_CM_PREDIVIDE       256
+/*#define IMA_CM_PREDIVIDE     256*/  /* deprecated, should not be used */
 #define IMA_USED_FOR_RENDER    512
 #define IMA_USER_FRAME_IN_RANGE        1024 /* for image user, but these flags are mixed */
 #define IMA_VIEW_AS_RENDER     2048
+#define IMA_IGNORE_ALPHA       4096
 
 /* Image.tpageflag */
 #define IMA_TILES                      1
@@ -148,4 +152,10 @@ typedef struct Image {
 /* gen_flag */
 #define IMA_GEN_FLOAT          1
 
+/* alpha_mode */
+enum {
+       IMA_ALPHA_STRAIGHT = 0,
+       IMA_ALPHA_PREMUL = 1,
+};
+
 #endif
index fad539d..1e83b3d 100644 (file)
@@ -1292,11 +1292,11 @@ typedef struct Scene {
 /* alphamode */
 #define R_ADDSKY               0
 #define R_ALPHAPREMUL  1
-#define R_ALPHAKEY             2
+/*#define R_ALPHAKEY           2*/ /* deprecated, shouldn't be used */
 
 /* color_mgt_flag */
 #define R_COLOR_MANAGEMENT              (1 << 0)  /* deprecated, should only be used in versioning code only */
-#define R_COLOR_MANAGEMENT_PREDIVIDE    (1 << 1)
+/*#define R_COLOR_MANAGEMENT_PREDIVIDE    (1 << 1)*/  /* deprecated, shouldn't be used */
 
 /* subimtype, flag options for imtype */
 #define R_OPENEXR_HALF    1                                      /*deprecated*/
index f106c8f..0aa466f 100644 (file)
@@ -172,7 +172,10 @@ typedef struct Sequence {
        float blend_opacity;
 
        /* is sfra needed anymore? - it looks like its only used in one place */
-       int sfra, pad;  /* starting frame according to the timeline of the scene. */
+       int sfra;  /* starting frame according to the timeline of the scene. */
+
+       char alpha_mode;
+       char pad[3];
 
        /* modifiers */
        ListBase modifiers;
@@ -315,7 +318,7 @@ typedef struct SequencerScopes {
 #define SEQ_OVERLAP                 (1 << 3)
 #define SEQ_FILTERY                 (1 << 4)
 #define SEQ_MUTE                    (1 << 5)
-#define SEQ_MAKE_PREMUL             (1 << 6)
+#define SEQ_MAKE_PREMUL             (1 << 6) /* deprecated, used for compatibility code only */
 #define SEQ_REVERSE_FRAMES          (1 << 7)
 #define SEQ_IPO_FRAME_LOCKED        (1 << 8)
 #define SEQ_EFFECT_NOT_LOADED       (1 << 9)
@@ -366,6 +369,12 @@ typedef struct SequencerScopes {
 #define SEQ_PROXY_TC_RECORD_RUN_NO_GAPS         8
 #define SEQ_PROXY_TC_ALL                        15
 
+/* seq->alpha_mode */
+enum {
+       SEQ_ALPHA_STRAIGHT = 0,
+       SEQ_ALPHA_PREMUL   = 1
+};
+
 /* seq->type WATCH IT: SEQ_TYPE_EFFECT BIT is used to determine if this is an effect strip!!! */
 enum {
        SEQ_TYPE_IMAGE       = 0,
index dd63e6a..ea4f281 100644 (file)
@@ -340,7 +340,7 @@ typedef struct ColorMapping {
 
 /* imaflag */
 #define TEX_INTERPOL   1
-#define TEX_USEALPHA   2
+#define TEX_USEALPHA   2 /* deprecated, used for versioning only */
 #define TEX_MIPMAP             4
 #define TEX_IMAROT             16
 #define TEX_CALCALPHA  32
index ad7682b..11e3315 100644 (file)
@@ -134,6 +134,15 @@ static void rna_Image_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
 }
 
 static void rna_Image_generated_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       Image *ima = ptr->id.data;
+       BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE);
+       DAG_id_tag_update(&ima->id, 0);
+       WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id);
+       WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
+}
+
+static void rna_Image_colormanage_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
 {
        Image *ima = ptr->id.data;
        BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE);
@@ -463,6 +472,11 @@ static void rna_def_image(BlenderRNA *brna)
                {IMA_STD_FIELD, "ODD", 0, "Lower First", "Lower field first"},
                {0, NULL, 0, NULL, NULL}
        };
+       static const EnumPropertyItem alpha_mode_items[] = {
+               {IMA_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "Transparent RGB and alpha pixels are unmodified"},
+               {IMA_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
+               {0, NULL, 0, NULL, NULL}
+       };
 
        srna = RNA_def_struct(brna, "Image", "ID");
        RNA_def_struct_ui_text(srna, "Image", "Image datablock referencing an external or packed image");
@@ -512,23 +526,17 @@ static void rna_def_image(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_fields_update");
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        
-       prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DO_PREMUL);
-       RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
-       RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
-       
-       prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_CM_PREDIVIDE);
-       RNA_def_property_ui_text(prop, "Color Unpremultiply",
-                                "For premultiplied alpha images, do color space conversion on colors without alpha, "
-                                "to avoid fringing for images with light backgrounds");
-       RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_free_update");
 
        prop = RNA_def_property(srna, "view_as_render", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_VIEW_AS_RENDER);
        RNA_def_property_ui_text(prop, "View as Render", "Apply render part of display transformation when displaying this image on the screen");
        RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
 
+       prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
+       RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information from the image or make image fully opaque");
+       RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
+
        prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_funcs(prop, "rna_Image_dirty_get", NULL);
        RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -677,6 +685,11 @@ static void rna_def_image(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings");
        RNA_def_property_ui_text(prop, "Color Space Settings", "Input color space settings");
 
+       prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, alpha_mode_items);
+       RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
+       RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update");
+
        RNA_api_image(srna);
 }
 
index 5696511..b08e473 100644 (file)
@@ -3332,8 +3332,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                
        static EnumPropertyItem alpha_mode_items[] = {
                {R_ADDSKY, "SKY", 0, "Sky", "Transparent pixels are filled with sky color"},
-               {R_ALPHAPREMUL, "PREMUL", 0, "Premultiplied", "Transparent RGB pixels are multiplied by the alpha channel"},
-               {R_ALPHAKEY, "STRAIGHT", 0, "Straight Alpha", "Transparent RGB and alpha pixels are unmodified"},
+               {R_ALPHAPREMUL, "TRANSPARENT", 0, "Transparent", "World background is transparent with premultiplied alpha"},
                {0, NULL, 0, NULL, NULL}
        };
 
@@ -3767,13 +3766,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
                                 "editor pipeline, if sequencer strips exist");
        RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
        
-       prop = RNA_def_property(srna, "use_color_unpremultiply", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "color_mgt_flag", R_COLOR_MANAGEMENT_PREDIVIDE);
-       RNA_def_property_ui_text(prop, "Color Unpremultiply",
-                                "For premultiplied alpha render output, do color space conversion on "
-                                "colors without alpha, to avoid fringing on light backgrounds");
-       RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-       
        prop = RNA_def_property(srna, "use_file_extension", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "scemode", R_EXTENSION);
        RNA_def_property_ui_text(prop, "File Extensions",
index 5c51f87..e849e84 100644 (file)
@@ -1541,14 +1541,20 @@ static void rna_def_filter_video(StructRNA *srna)
 {
        PropertyRNA *prop;
 
+       static const EnumPropertyItem alpha_mode_items[] = {
+               {SEQ_ALPHA_STRAIGHT, "STRAIGHT", 0, "Straight", "RGB channels in transparent pixels are unaffected by the alpha channel"},
+               {SEQ_ALPHA_PREMUL, "PREMUL", 0, "Premultiplied", "RGB channels in transparent pixels are multiplied by the alpha channel"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FILTERY);
        RNA_def_property_ui_text(prop, "De-Interlace", "For video movies to remove fields");
        RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files");
 
-       prop = RNA_def_property(srna, "use_premultiply", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MAKE_PREMUL);
-       RNA_def_property_ui_text(prop, "Premultiply", "Convert RGB from key alpha to premultiplied alpha");
+       prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, alpha_mode_items);
+       RNA_def_property_ui_text(prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
        RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
 
        prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
index e116e5d..2ab448c 100644 (file)
@@ -1194,11 +1194,6 @@ static void rna_def_texture_image(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Flip Axis", "Flip the texture's X and Y axis");
        RNA_def_property_update(prop, 0, "rna_Texture_update");
 
-       prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_USEALPHA);
-       RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information in the image");
-       RNA_def_property_update(prop, 0, "rna_Texture_update");
-
        prop = RNA_def_property(srna, "use_calculate_alpha", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_CALCALPHA);
        RNA_def_property_ui_text(prop, "Calculate Alpha", "Calculate an alpha channel based on RGB values in the image");
index 57eb990..c4b48b8 100644 (file)
@@ -615,7 +615,7 @@ void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
        bNodePreview *preview= node->preview;
        int xsize, ysize;
        int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
-       int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
+       int predivide= TRUE;
        int dither= 0;
        unsigned char *rect;
        
index 88d78df..7e44210 100644 (file)
@@ -291,7 +291,6 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
 float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
 {
        float *rect;
-       int predivide= (ibuf->flags & IB_cm_predivide);
 
        *alloc= FALSE;
 
@@ -305,7 +304,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc)
                rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image");
 
                IMB_buffer_float_from_float(rect, ibuf->rect_float,
-                       4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, predivide,
+                       4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE,
                        ibuf->x, ibuf->y, ibuf->x, ibuf->x);
 
                        *alloc= TRUE;
index 5d61417..61b39a5 100644 (file)
@@ -91,7 +91,7 @@ void render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd
        struct ImBuf *ibuf);
 
 void render_result_rect_fill_zero(struct RenderResult *rr);
-void render_result_rect_get_pixels(struct RenderResult *rr, struct RenderData *rd,
+void render_result_rect_get_pixels(struct RenderResult *rr,
        unsigned int *rect, int rectx, int recty,
        const struct ColorManagedViewSettings *view_settings,
        const struct ColorManagedDisplaySettings *display_settings);
index 7c14e0e..4aaa624 100644 (file)
@@ -102,6 +102,11 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y)
                col[1] = ((float)rect[1])*(1.0f/255.0f);
                col[2] = ((float)rect[2])*(1.0f/255.0f);
                col[3] = ((float)rect[3])*(1.0f/255.0f);
+
+               /* bytes are internally straight, however render pipeline seems to expect premul */
+               col[0] *= col[3];
+               col[1] *= col[3];
+               col[2] *= col[3];
        }
 }
 
@@ -219,10 +224,8 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul
        }
 
        /* keep this before interpolation [#29761] */
-       if (tex->imaflag & TEX_USEALPHA) {
-               if ((tex->imaflag & TEX_CALCALPHA) == 0) {
-                       texres->talpha = TRUE;
-               }
+       if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+               texres->talpha = TRUE;
        }
 
        /* interpolate */
@@ -710,9 +713,10 @@ static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extf
        }
        else {
                char *rect = (char *)(ibuf->rect + x + y*ibuf->x);
-               col[0] = rect[0]*(1.f/255.f);
-               col[1] = rect[1]*(1.f/255.f);
-               col[2] = rect[2]*(1.f/255.f);
+               float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
+               col[0] = rect[0] * inv_alpha_fac;
+               col[1] = rect[1] * inv_alpha_fac;
+               col[2] = rect[2] * inv_alpha_fac;
                col[3] = clip ? 0.f : rect[3]*(1.f/255.f);
        }
        return clip;
@@ -1088,7 +1092,8 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex
        /* mipmap test */
        image_mipmap_test(tex, ibuf);
        
-       if ((tex->imaflag & TEX_USEALPHA) && ((tex->imaflag & TEX_CALCALPHA) == 0)) texres->talpha = 1;
+       if ((tex->imaflag & TEX_CALCALPHA) == 0)
+               texres->talpha = 1;
        texr.talpha = texres->talpha;
 
        if (tex->imaflag & TEX_IMAROT) {
@@ -1501,13 +1506,8 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const
        /* mipmap test */
        image_mipmap_test(tex, ibuf);
 
-       if (tex->imaflag & TEX_USEALPHA) {
-               if (tex->imaflag & TEX_CALCALPHA) {
-                       /* pass */
-               }
-               else {
-                       texres->talpha = TRUE;
-               }
+       if ((tex->imaflag & TEX_CALCALPHA) == 0) {
+               texres->talpha = TRUE;
        }
        
        texr.talpha= texres->talpha;
index 0545d29..f2db84c 100644 (file)
@@ -336,7 +336,7 @@ void RE_ResultGet32(Render *re, unsigned int *rect)
        RenderResult rres;
        
        RE_AcquireResultImage(re, &rres);
-       render_result_rect_get_pixels(&rres, &re->r, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
+       render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings);
        RE_ReleaseResultImage(re);
 }
 
@@ -833,7 +833,7 @@ static void threaded_tile_processor(Render *re)
        
        if (re->result == NULL)
                return;
-       
+
        /* warning; no return here without closing exr file */
        
        RE_parts_init(re, TRUE);
@@ -1092,7 +1092,7 @@ static void do_render_blur_3d(Render *re)
                
                blurfac = 1.0f / (float)(re->r.mblur_samples - blur);
                
-               merge_renderresult_blur(rres, re->result, blurfac, re->r.alphamode & R_ALPHAKEY);
+               merge_renderresult_blur(rres, re->result, blurfac, FALSE);
                if (re->test_break(re->tbh)) break;
        }
        
index f828158..78750cf 100644 (file)
@@ -434,7 +434,7 @@ RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuf
        rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
        /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
        rr->crop = crop;
-       
+
        /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
        rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
        rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
@@ -1077,8 +1077,7 @@ int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, c
 
 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
 {
-       int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) ? IB_cm_predivide : 0;
-       ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
+       ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
        
        /* if not exists, BKE_imbuf_write makes one */
        ibuf->rect = (unsigned int *)rr->rect32;
@@ -1148,17 +1147,15 @@ void render_result_rect_fill_zero(RenderResult *rr)
                rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
 }
 
-void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty,
+void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty,
                                    const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
 {
        if (rr->rect32) {
                memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
        }
        else if (rr->rectf) {
-               int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
-
                IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4,
-                                                  view_settings, display_settings, predivide);
+                                                  view_settings, display_settings, TRUE);
        }
        else
                /* else fill with black */
index 9f171ba..9b08d6c 100644 (file)
@@ -710,9 +710,11 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
                                        
                                        if (pass[3]==0.0f) {
                                                copy_v4_v4(pass, col);
+                                               pass[3] = 1.0f;
                                        }
                                        else {
                                                addAlphaUnderFloat(pass, col);
+                                               pass[3] = 1.0f;
                                        }
                                }
                        }
@@ -981,29 +983,6 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect)
        }
 }
 
-static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl)
-{
-       RenderLayer *rlpp[RE_MAX_OSA];
-       int y, sample, totsample;
-       
-       totsample= get_sample_layers(pa, rl, rlpp);
-       
-       for (sample= 0; sample<totsample; sample++) {
-               float *rectf= rlpp[sample]->rectf;
-               
-               for (y= pa->rectx*pa->recty; y>0; y--, rectf+=4) {
-                       if (rectf[3] >= 1.0f) {
-                               /* pass */
-                       }
-                       else if (rectf[3] > 0.0f) {
-                               rectf[0] /= rectf[3];
-                               rectf[1] /= rectf[3];
-                               rectf[2] /= rectf[3];
-                       }
-               }
-       }
-}
-
 /* clamp alpha and RGB to 0..1 and 0..inf, can go outside due to filter */
 static void clamp_alpha_rgb_range(RenderPart *pa, RenderLayer *rl)
 {
@@ -1312,10 +1291,6 @@ void zbufshadeDA_tile(RenderPart *pa)
                /* clamp alpha to 0..1 range, can go outside due to filter */
                clamp_alpha_rgb_range(pa, rl);
                
-               /* de-premul alpha */
-               if (R.r.alphamode & R_ALPHAKEY)
-                       convert_to_key_alpha(pa, rl);
-               
                /* free stuff within loop! */
                MEM_freeN(pa->rectdaps); pa->rectdaps= NULL;
                freeps(&psmlist);
@@ -1476,10 +1451,6 @@ void zbufshade_tile(RenderPart *pa)
                if (rl->passflag & SCE_PASS_VECTOR)
                        reset_sky_speed(pa, rl);
                
-               /* de-premul alpha */
-               if (R.r.alphamode & R_ALPHAKEY)
-                       convert_to_key_alpha(pa, rl);
-               
                if (edgerect) MEM_freeN(edgerect);
                edgerect= NULL;