diff options
Diffstat (limited to 'source/blender')
44 files changed, 795 insertions, 494 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index ecd38403d72..10528f1b270 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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 diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 8630ace4edf..b93f917c9e2 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -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; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 3bff209f53c..7dbbca6ddaa 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -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); } } diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index 5b2e9f2bf23..3d8a2f7cddf 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -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); } } } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a82704d9e38..69c125b0ece 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -324,7 +324,6 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ { const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); const char *to_colorspace = scene->sequencer_colorspace_settings.name; - int predivide = ibuf->flags & IB_cm_predivide; if (!ibuf->rect_float) { if (make_float && ibuf->rect) { @@ -354,7 +353,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ imb_freerectImBuf(ibuf); IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); + from_colorspace, to_colorspace, TRUE); } } @@ -367,10 +366,8 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) return; if (to_colorspace && to_colorspace[0] != '\0') { - int predivide = ibuf->flags & IB_cm_predivide; - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, predivide); + from_colorspace, to_colorspace, TRUE); } } @@ -1517,18 +1514,6 @@ MINLINE float color_balance_fl(float in, const float lift, const float gain, con return powf(x, gamma) * mul; } -static void make_cb_table_byte(float lift, float gain, float gamma, - unsigned char *table, float mul) -{ - int y; - - for (y = 0; y < 256; y++) { - float v = color_balance_fl((float)y * (1.0f / 255.0f), lift, gain, gamma, mul); - - table[y] = FTOCHAR(v); - } -} - static void make_cb_table_float(float lift, float gain, float gamma, float *table, float mul) { @@ -1543,35 +1528,33 @@ static void make_cb_table_float(float lift, float gain, float gamma, static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul) { - unsigned char cb_tab[3][256]; - int c; - unsigned char *p = rect; - unsigned char *e = p + width * 4 * height; + //unsigned char cb_tab[3][256]; + unsigned char *cp = rect; + unsigned char *e = cp + width * 4 * height; unsigned char *m = mask_rect; StripColorBalance cb = calc_cb(cb_); - for (c = 0; c < 3; c++) { - make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul); - } + while (cp < e) { + float p[4]; + int c; - while (p < e) { - if (m) { - float t[3] = {m[0] / 255.0f, m[1] / 255.0f, m[2] / 255.0f}; + straight_uchar_to_premul_float(p, cp); - p[0] = p[0] * (1.0f - t[0]) + t[0] * cb_tab[0][p[0]]; - p[1] = p[1] * (1.0f - t[1]) + t[1] * cb_tab[1][p[1]]; - p[2] = p[2] * (1.0f - t[2]) + t[2] * cb_tab[2][p[2]]; + for (c = 0; c < 3; c++) { + float t = color_balance_fl(p[c], cb.lift[c], cb.gain[c], cb.gamma[c], mul); - m += 4; - } - else { - p[0] = cb_tab[0][p[0]]; - p[1] = cb_tab[1][p[1]]; - p[2] = cb_tab[2][p[2]]; + if (m) + p[c] = p[c] * (1.0f - (float)m[c] / 255.0f) + t * m[c]; + else + p[c] = t; } - p += 4; + premul_float_to_straight_uchar(cp, p); + + cp += 4; + if (m) + m += 4; } } @@ -1795,7 +1778,7 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen { float mul; - if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_PREMUL | SEQ_MAKE_FLOAT)) { + if (seq->flag & (SEQ_FILTERY | SEQ_USE_CROP | SEQ_USE_TRANSFORM | SEQ_FLIPX | SEQ_FLIPY | SEQ_MAKE_FLOAT)) { return TRUE; } @@ -1892,7 +1875,8 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, ImBuf *i = IMB_allocImBuf(dx, dy, 32, ibuf->rect_float ? IB_rectfloat : IB_rect); IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); - + sequencer_imbuf_assign_spaces(context.scene, i); + IMB_freeImBuf(ibuf); ibuf = i; @@ -1931,12 +1915,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra, multibuf(ibuf, mul); } - if (seq->flag & SEQ_MAKE_PREMUL) { - if (ibuf->planes == 32 && ibuf->zbuf == NULL) { - IMB_premultiply_alpha(ibuf); - } - } - if (ibuf->x != context.rectx || ibuf->y != context.recty) { if (context.scene->r.mode & R_OSA) { IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty); @@ -2546,13 +2524,18 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo case SEQ_TYPE_IMAGE: { StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra); + int flag; if (s_elem) { BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name); BLI_path_abs(name, G.main->name); } - if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name))) { + flag = IB_rect; + if (seq->alpha_mode == SEQ_ALPHA_PREMUL) + flag |= IB_alphamode_premul; + + if (s_elem && (ibuf = IMB_loadiffname(name, flag, seq->strip->colorspace_settings.name))) { /* we don't need both (speed reasons)! */ if (ibuf->rect_float && ibuf->rect) imb_freerectImBuf(ibuf); @@ -2641,7 +2624,7 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) { ImBuf *ibuf = NULL; - int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + int use_preprocess = FALSE; int is_proxy_image = FALSE; float nr = give_stripelem_index(seq, cfra); /* all effects are handled similarly with the exception of speed effect */ @@ -2650,30 +2633,36 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra) ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, - * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */ - if (ibuf) - use_preprocess = FALSE; - - if (ibuf == NULL) - ibuf = copy_from_ibuf_still(context, seq, nr); - if (ibuf == NULL) { - ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); + if (ibuf == NULL) + ibuf = copy_from_ibuf_still(context, seq, nr); if (ibuf == NULL) { - /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { - ibuf = seq_proxy_fetch(context, seq, cfra); - is_proxy_image = (ibuf != NULL); - } + ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF); - if (ibuf == NULL) - ibuf = do_render_strip_uncached(context, seq, cfra); + if (ibuf == NULL) { + /* MOVIECLIPs have their own proxy management */ + if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { + ibuf = seq_proxy_fetch(context, seq, cfra); + is_proxy_image = (ibuf != NULL); + } - if (ibuf) - BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + if (ibuf == NULL) + ibuf = do_render_strip_uncached(context, seq, cfra); + + if (ibuf) + BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf); + } } + + if (ibuf) + use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra); + } + else { + /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF, + * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL + * so, no need in check for preprocess here + */ } if (ibuf == NULL) { @@ -3975,6 +3964,14 @@ void BKE_sequence_init_colorspace(Sequence *seq) if (seq->type == SEQ_TYPE_IMAGE) { ibuf = IMB_loadiffname(name, IB_rect, seq->strip->colorspace_settings.name); + /* byte images are default to straight alpha, however sequencer + * works in premul space, so mark strip to be premultiplied first + */ + if (!ibuf->rect_float) + seq->alpha_mode = SEQ_ALPHA_STRAIGHT; + else + seq->alpha_mode = SEQ_ALPHA_PREMUL; + if (ibuf) IMB_freeImBuf(ibuf); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 149842bc038..fbaf6f70fbc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -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; diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index c71463da61d..3831ec3cbb4 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -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); diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 4c8bd43ef73..b8eeca50db6 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -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__ */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8ddd69f2f03..7827a3a9bf1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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! */ diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 2e783ac956e..65a60e11ab3 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -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; } } } diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 084f71e0afc..b7797b51252 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -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; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index a864fe306b3..6ca8478b489 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -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; } } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 09d203784e4..060a181612b 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -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); } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index a633b39cb32..254899e6e07 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -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); } diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 2039f01a740..a2fc1eb05ec 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -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; diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 0653956e113..1e33f8da363 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -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); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index db1404813b1..850060ef4d5 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -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); /** * diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 9fe66b562d1..49e2e7fc80d 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -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. diff --git a/source/blender/imbuf/intern/IMB_filter.h b/source/blender/imbuf/intern/IMB_filter.h index eaedb160c94..6bd5f44307f 100644 --- a/source/blender/imbuf/intern/IMB_filter.h +++ b/source/blender/imbuf/intern/IMB_filter.h @@ -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 diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index c8bc3f8ebb8..ba84063f317 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -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; } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1c68a466ade..bcfddfe425a 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -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) diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index f049c404e2d..f0d8b7cac72 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -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) diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 678b2908b96..51fee232034 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -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); +} diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index da7b31cc2ba..18b08c9b59b 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -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); } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index c0737fadffa..bbe43132051 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -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; } } diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 03ed1bb8008..d09adeb09b5 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -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 */ diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index be20c80bdec..8e0709e3670 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -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); } - diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 1e701b8d615..75d1f4c412d 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -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; } } diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 83830f260e1..2630aebef3b 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -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); diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index fe3550327f7..0f47ee224ae 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -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 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index fad539de284..1e83b3dadf9 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -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*/ diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index f106c8f918a..0aa466f7245 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -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, diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index dd63e6aad59..ea4f281efd6 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -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 diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index ad7682b3af5..11e33152375 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -136,6 +136,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); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5696511b614..b08e4731789 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -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", diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 5c51f871ac8..e849e84ff38 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -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); diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index e116e5df0de..2ab448c9188 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -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"); diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 57eb99021f6..c4b48b83b16 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -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; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 88d78df190f..7e44210928c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -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; diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index 5d61417cbaf..61b39a59b0b 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -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); diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 7c14e0e5465..4aaa6247478 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -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; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 0545d2940ab..f2db84c47a9 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -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; } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index f8281586038..78750cfd1ca 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -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 */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 9f171ba71db..9b08d6c07e9 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -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; |