Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / colortools.c
index 2932939b208df00d4d9caaafe1762ccc17fdbc91..6c97380b9ca94ab45679ef82146b89290ca16086 100644 (file)
@@ -4,7 +4,7 @@
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. 
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -130,7 +130,7 @@ void curvemapping_free(CurveMapping *cumap)
        }
 }
 
-void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
+void curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
 {
        int a;
 
@@ -146,7 +146,7 @@ void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
        }
 }
 
-CurveMapping *curvemapping_copy(CurveMapping *cumap)
+CurveMapping *curvemapping_copy(const CurveMapping *cumap)
 {
        if (cumap) {
                CurveMapping *cumapn = MEM_dupallocN(cumap);
@@ -293,8 +293,8 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
                        cuma->curve[1].x = clipr->xmax;
                        cuma->curve[1].y = clipr->ymin;
                        if (slope == CURVEMAP_SLOPE_POS_NEG) {
-                               cuma->curve[0].flag |= CUMA_VECTOR;
-                               cuma->curve[1].flag |= CUMA_VECTOR;
+                               cuma->curve[0].flag |= CUMA_HANDLE_VECTOR;
+                               cuma->curve[1].flag |= CUMA_HANDLE_VECTOR;
                        }
                        break;
                case CURVE_PRESET_SHARP:
@@ -391,15 +391,25 @@ void curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
        }
 }
 
-/* if type==1: vector, else auto */
-void curvemap_sethandle(CurveMap *cuma, int type)
+/**
+ * \param type: eBezTriple_Handle
+ */
+void curvemap_handle_set(CurveMap *cuma, int type)
 {
        int a;
        
        for (a = 0; a < cuma->totpoint; a++) {
                if (cuma->curve[a].flag & CUMA_SELECT) {
-                       if (type) cuma->curve[a].flag |= CUMA_VECTOR;
-                       else cuma->curve[a].flag &= ~CUMA_VECTOR;
+                       cuma->curve[a].flag &= ~(CUMA_HANDLE_VECTOR | CUMA_HANDLE_AUTO_ANIM);
+                       if (type == HD_VECT) {
+                               cuma->curve[a].flag |= CUMA_HANDLE_VECTOR;
+                       }
+                       else if (type == HD_AUTO_ANIM) {
+                               cuma->curve[a].flag |= CUMA_HANDLE_AUTO_ANIM;
+                       }
+                       else {
+                               /* pass */
+                       }
                }
        }
 }
@@ -457,7 +467,7 @@ static void calchandle_curvemap(
        if (len_a == 0.0f) len_a = 1.0f;
        if (len_b == 0.0f) len_b = 1.0f;
 
-       if (bezt->h1 == HD_AUTO || bezt->h2 == HD_AUTO) { /* auto */
+       if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) || ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {    /* auto */
                float tvec[2];
                tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
                tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
@@ -465,13 +475,57 @@ static void calchandle_curvemap(
                len = len_v2(tvec) * 2.5614f;
                if (len != 0.0f) {
                        
-                       if (bezt->h1 == HD_AUTO) {
+                       if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
                                len_a /= len;
                                madd_v2_v2v2fl(p2_h1, p2, tvec, -len_a);
+
+                               if ((bezt->h1 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
+                                       const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
+                                       const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
+                                       if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) ||
+                                           (ydiff1 >= 0.0f && ydiff2 >= 0.0f))
+                                       {
+                                               bezt->vec[0][1] = bezt->vec[1][1];
+                                       }
+                                       else { /* handles should not be beyond y coord of two others */
+                                               if (ydiff1 <= 0.0f) {
+                                                       if (prev->vec[1][1] > bezt->vec[0][1]) {
+                                                               bezt->vec[0][1] = prev->vec[1][1];
+                                                       }
+                                               }
+                                               else {
+                                                       if (prev->vec[1][1] < bezt->vec[0][1]) {
+                                                               bezt->vec[0][1] = prev->vec[1][1];
+                                                       }
+                                               }
+                                       }
+                               }
                        }
-                       if (bezt->h2 == HD_AUTO) {
+                       if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
                                len_b /= len;
                                madd_v2_v2v2fl(p2_h2, p2, tvec,  len_b);
+
+                               if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
+                                       const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
+                                       const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
+                                       if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) ||
+                                           (ydiff1 >= 0.0f && ydiff2 >= 0.0f))
+                                       {
+                                               bezt->vec[2][1] = bezt->vec[1][1];
+                                       }
+                                       else { /* handles should not be beyond y coord of two others */
+                                               if (ydiff1 <= 0.0f) {
+                                                       if (next->vec[1][1] < bezt->vec[2][1]) {
+                                                               bezt->vec[2][1] = next->vec[1][1];
+                                                       }
+                                               }
+                                               else {
+                                                       if (next->vec[1][1] > bezt->vec[2][1]) {
+                                                               bezt->vec[2][1] = next->vec[1][1];
+                                                       }
+                                               }
+                                       }
+                               }
                        }
                }
        }
@@ -540,10 +594,15 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
                cuma->maxtable = max_ff(cuma->maxtable, cmp[a].x);
                bezt[a].vec[1][0] = cmp[a].x;
                bezt[a].vec[1][1] = cmp[a].y;
-               if (cmp[a].flag & CUMA_VECTOR)
+               if (cmp[a].flag & CUMA_HANDLE_VECTOR) {
                        bezt[a].h1 = bezt[a].h2 = HD_VECT;
-               else
+               }
+               else if (cmp[a].flag & CUMA_HANDLE_AUTO_ANIM) {
+                       bezt[a].h1 = bezt[a].h2 = HD_AUTO_ANIM;
+               }
+               else {
                        bezt[a].h1 = bezt[a].h2 = HD_AUTO;
+               }
        }
        
        const BezTriple *bezt_prev = NULL;
@@ -773,12 +832,12 @@ void curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
                        dy = cmp[a].y - cmp[a + 1].y;
                        if (sqrtf(dx * dx + dy * dy) < thresh) {
                                if (a == 0) {
-                                       cmp[a + 1].flag |= CUMA_VECTOR;
+                                       cmp[a + 1].flag |= CUMA_HANDLE_VECTOR;
                                        if (cmp[a + 1].flag & CUMA_SELECT)
                                                cmp[a].flag |= CUMA_SELECT;
                                }
                                else {
-                                       cmp[a].flag |= CUMA_VECTOR;
+                                       cmp[a].flag |= CUMA_HANDLE_VECTOR;
                                        if (cmp[a].flag & CUMA_SELECT)
                                                cmp[a + 1].flag |= CUMA_SELECT;
                                }
@@ -896,9 +955,9 @@ void curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char ve
 
        curvemapping_evaluate_premulRGBF(cumap, vecout, vecin);
 
-       vecout_byte[0] = FTOCHAR(vecout[0]);
-       vecout_byte[1] = FTOCHAR(vecout[1]);
-       vecout_byte[2] = FTOCHAR(vecout[2]);
+       vecout_byte[0] = unit_float_to_uchar_clamp(vecout[0]);
+       vecout_byte[1] = unit_float_to_uchar_clamp(vecout[1]);
+       vecout_byte[2] = unit_float_to_uchar_clamp(vecout[2]);
 }
 
 int curvemapping_RGBA_does_something(const CurveMapping *cumap)
@@ -975,13 +1034,14 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons
        float yuv[3];
 
        /* vectorscope*/
-       rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2]);
+       rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709);
        scopes->vecscope[idx + 0] = yuv[1];
        scopes->vecscope[idx + 1] = yuv[2];
 
        /* waveform */
        switch (scopes->wavefrm_mode) {
                case SCOPES_WAVEFRM_RGB:
+               case SCOPES_WAVEFRM_RGB_PARADE:
                        scopes->waveform_1[idx + 0] = fx;
                        scopes->waveform_1[idx + 1] = rgb[0];
                        scopes->waveform_2[idx + 0] = fx;
@@ -1105,7 +1165,9 @@ typedef struct ScopesUpdateDataChunk {
        float min[3], max[3];
 } ScopesUpdateDataChunk;
 
-static void scopes_update_cb(void *userdata, void *userdata_chunk, const int y, const int UNUSED(threadid))
+static void scopes_update_cb(void *__restrict userdata, 
+                             const int y,
+                             const ParallelRangeTLS *__restrict tls)
 {
        const ScopesUpdateData *data = userdata;
 
@@ -1115,7 +1177,7 @@ static void scopes_update_cb(void *userdata, void *userdata_chunk, const int y,
        const unsigned char *display_buffer = data->display_buffer;
        const int ycc_mode = data->ycc_mode;
 
-       ScopesUpdateDataChunk *data_chunk = userdata_chunk;
+       ScopesUpdateDataChunk *data_chunk = tls->userdata_chunk;
        unsigned int *bin_lum = data_chunk->bin_lum;
        unsigned int *bin_r = data_chunk->bin_r;
        unsigned int *bin_g = data_chunk->bin_g;
@@ -1199,7 +1261,8 @@ static void scopes_update_cb(void *userdata, void *userdata_chunk, const int y,
        }
 }
 
-static void scopes_update_finalize(void *userdata, void *userdata_chunk)
+static void scopes_update_finalize(void *__restrict userdata,
+                                   void *__restrict userdata_chunk)
 {
        const ScopesUpdateData *data = userdata;
        const ScopesUpdateDataChunk *data_chunk = userdata_chunk;
@@ -1265,6 +1328,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
 
        switch (scopes->wavefrm_mode) {
                case SCOPES_WAVEFRM_RGB:
+                       /* fall-through */
+               case SCOPES_WAVEFRM_RGB_PARADE:
                        ycc_mode = -1;
                        break;
                case SCOPES_WAVEFRM_LUMA:
@@ -1318,15 +1383,23 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
 
        /* Keep number of threads in sync with the merge parts below. */
        ScopesUpdateData data = {
-               .scopes = scopes, . ibuf = ibuf,
+               .scopes = scopes, .ibuf = ibuf,
                .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode,
                .bin_lum = bin_lum, .bin_r = bin_r, .bin_g = bin_g, .bin_b = bin_b, .bin_a = bin_a,
        };
        ScopesUpdateDataChunk data_chunk = {{0}};
        INIT_MINMAX(data_chunk.min, data_chunk.max);
 
-       BLI_task_parallel_range_finalize(0, ibuf->y, &data, &data_chunk, sizeof(data_chunk),
-                                        scopes_update_cb, scopes_update_finalize, ibuf->y > 256, false);
+       ParallelRangeSettings settings;
+       BLI_parallel_range_settings_defaults(&settings);
+       settings.use_threading = (ibuf->y > 256);
+       settings.userdata_chunk = &data_chunk;
+       settings.userdata_chunk_size = sizeof(data_chunk);
+       settings.func_finalize = scopes_update_finalize;
+       BLI_task_parallel_range(0, ibuf->y,
+                               &data,
+                               scopes_update_cb,
+                               &settings);
 
        /* test for nicer distribution even - non standard, leave it out for a while */
 #if 0