Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / seqmodifier.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/blenkernel/intern/seqmodifier.c
28  *  \ingroup bke
29  */
30
31 #include <stddef.h>
32 #include <string.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_listbase.h"
37 #include "BLI_string.h"
38 #include "BLI_string_utils.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_math.h"
41
42 #include "BLT_translation.h"
43
44 #include "DNA_sequence_types.h"
45 #include "DNA_scene_types.h"
46
47 #include "BKE_colortools.h"
48 #include "BKE_sequencer.h"
49
50 #include "IMB_imbuf.h"
51 #include "IMB_imbuf_types.h"
52 #include "IMB_colormanagement.h"
53
54 static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES];
55 static bool modifierTypesInit = false;
56
57 /*********************** Modifiers *************************/
58
59 typedef void (*modifier_apply_threaded_cb) (int width, int height, unsigned char *rect, float *rect_float,
60                                             unsigned char *mask_rect, float *mask_rect_float, void *data_v);
61
62 typedef struct ModifierInitData {
63         ImBuf *ibuf;
64         ImBuf *mask;
65         void *user_data;
66
67         modifier_apply_threaded_cb apply_callback;
68 } ModifierInitData;
69
70 typedef struct ModifierThread {
71         int width, height;
72
73         unsigned char *rect, *mask_rect;
74         float *rect_float, *mask_rect_float;
75
76         void *user_data;
77
78         modifier_apply_threaded_cb apply_callback;
79 } ModifierThread;
80
81
82 static ImBuf *modifier_mask_get(SequenceModifierData *smd, const SeqRenderData *context, int cfra, int fra_offset, bool make_float)
83 {
84         return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, fra_offset, make_float);
85 }
86
87 static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
88 {
89         ModifierThread *handle = (ModifierThread *) handle_v;
90         ModifierInitData *init_data = (ModifierInitData *) init_data_v;
91         ImBuf *ibuf = init_data->ibuf;
92         ImBuf *mask = init_data->mask;
93
94         int offset = 4 * start_line * ibuf->x;
95
96         memset(handle, 0, sizeof(ModifierThread));
97
98         handle->width = ibuf->x;
99         handle->height = tot_line;
100         handle->apply_callback = init_data->apply_callback;
101         handle->user_data = init_data->user_data;
102
103         if (ibuf->rect)
104                 handle->rect = (unsigned char *) ibuf->rect + offset;
105
106         if (ibuf->rect_float)
107                 handle->rect_float = ibuf->rect_float + offset;
108
109         if (mask) {
110                 if (mask->rect)
111                         handle->mask_rect = (unsigned char *) mask->rect + offset;
112
113                 if (mask->rect_float)
114                         handle->mask_rect_float = mask->rect_float + offset;
115         }
116         else {
117                 handle->mask_rect = NULL;
118                 handle->mask_rect_float = NULL;
119         }
120 }
121
122 static void *modifier_do_thread(void *thread_data_v)
123 {
124         ModifierThread *td = (ModifierThread *) thread_data_v;
125
126         td->apply_callback(td->width, td->height, td->rect, td->rect_float, td->mask_rect, td->mask_rect_float, td->user_data);
127
128         return NULL;
129 }
130
131 static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_threaded_cb apply_callback, void *user_data)
132 {
133         ModifierInitData init_data;
134
135         init_data.ibuf = ibuf;
136         init_data.mask = mask;
137         init_data.user_data = user_data;
138
139         init_data.apply_callback = apply_callback;
140
141         IMB_processor_apply_threaded(ibuf->y, sizeof(ModifierThread), &init_data,
142                                      modifier_init_handle, modifier_do_thread);
143 }
144
145 /* **** Color Balance Modifier **** */
146
147 static void colorBalance_init_data(SequenceModifierData *smd)
148 {
149         ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
150         int c;
151
152         cbmd->color_multiply = 1.0f;
153
154         for (c = 0; c < 3; c++) {
155                 cbmd->color_balance.lift[c] = 1.0f;
156                 cbmd->color_balance.gamma[c] = 1.0f;
157                 cbmd->color_balance.gain[c] = 1.0f;
158         }
159 }
160
161 static void colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
162 {
163         ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
164
165         BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf, cbmd->color_multiply, false, mask);
166 }
167
168 static SequenceModifierTypeInfo seqModifier_ColorBalance = {
169         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Color Balance"),  /* name */
170         "ColorBalanceModifierData",                            /* struct_name */
171         sizeof(ColorBalanceModifierData),                      /* struct_size */
172         colorBalance_init_data,                                /* init_data */
173         NULL,                                                  /* free_data */
174         NULL,                                                  /* copy_data */
175         colorBalance_apply                                     /* apply */
176 };
177
178 /* **** White Balance Modifier **** */
179
180 static void whiteBalance_init_data(SequenceModifierData *smd)
181 {
182         WhiteBalanceModifierData *cbmd = (WhiteBalanceModifierData *) smd;
183         copy_v3_fl(cbmd->white_value, 1.0f);
184 }
185
186 typedef struct WhiteBalanceThreadData {
187         float white[3];
188 } WhiteBalanceThreadData;
189
190 static void whiteBalance_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
191                                         unsigned char *mask_rect, float *mask_rect_float, void *data_v)
192 {
193         int x, y;
194         float multiplier[3];
195
196         WhiteBalanceThreadData *data = (WhiteBalanceThreadData *) data_v;
197
198         multiplier[0] = (data->white[0] != 0.0f) ? 1.0f / data->white[0] : FLT_MAX;
199         multiplier[1] = (data->white[1] != 0.0f) ? 1.0f / data->white[1] : FLT_MAX;
200         multiplier[2] = (data->white[2] != 0.0f) ? 1.0f / data->white[2] : FLT_MAX;
201
202         for (y = 0; y < height; y++) {
203                 for (x = 0; x < width; x++) {
204                         int pixel_index = (y * width + x) * 4;
205                         float rgba[4], result[4], mask[3] = {1.0f, 1.0f, 1.0f};
206
207                         if (rect_float) {
208                                 copy_v3_v3(rgba, rect_float + pixel_index);
209                         }
210                         else {
211                                 straight_uchar_to_premul_float(rgba, rect + pixel_index);
212                         }
213
214                         copy_v4_v4(result, rgba);
215 #if 0
216                         mul_v3_v3(result, multiplier);
217 #else
218                         /* similar to division without the clipping */
219                         for (int i = 0; i < 3; i++) {
220                                 result[i] = 1.0f - powf(1.0f - rgba[i], multiplier[i]);
221                         }
222 #endif
223
224                         if (mask_rect_float) {
225                                 copy_v3_v3(mask, mask_rect_float + pixel_index);
226                         }
227                         else if (mask_rect) {
228                                 rgb_uchar_to_float(mask, mask_rect + pixel_index);
229                         }
230
231                         result[0] = rgba[0] * (1.0f - mask[0]) + result[0] * mask[0];
232                         result[1] = rgba[1] * (1.0f - mask[1]) + result[1] * mask[1];
233                         result[2] = rgba[2] * (1.0f - mask[2]) + result[2] * mask[2];
234
235                         if (rect_float) {
236                                 copy_v3_v3(rect_float + pixel_index, result);
237                         }
238                         else {
239                                 premul_float_to_straight_uchar(rect + pixel_index, result);
240                         }
241                 }
242         }
243 }
244
245 static void whiteBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
246 {
247         WhiteBalanceThreadData data;
248         WhiteBalanceModifierData *wbmd = (WhiteBalanceModifierData *) smd;
249
250         copy_v3_v3(data.white, wbmd->white_value);
251
252         modifier_apply_threaded(ibuf, mask, whiteBalance_apply_threaded, &data);
253 }
254
255 static SequenceModifierTypeInfo seqModifier_WhiteBalance = {
256         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "White Balance"),  /* name */
257         "WhiteBalanceModifierData",                            /* struct_name */
258         sizeof(WhiteBalanceModifierData),                      /* struct_size */
259         whiteBalance_init_data,                                /* init_data */
260         NULL,                                                  /* free_data */
261         NULL,                                                  /* copy_data */
262         whiteBalance_apply                                     /* apply */
263 };
264
265 /* **** Curves Modifier **** */
266
267 static void curves_init_data(SequenceModifierData *smd)
268 {
269         CurvesModifierData *cmd = (CurvesModifierData *) smd;
270
271         curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f);
272 }
273
274 static void curves_free_data(SequenceModifierData *smd)
275 {
276         CurvesModifierData *cmd = (CurvesModifierData *) smd;
277
278         curvemapping_free_data(&cmd->curve_mapping);
279 }
280
281 static void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
282 {
283         CurvesModifierData *cmd = (CurvesModifierData *) smd;
284         CurvesModifierData *cmd_target = (CurvesModifierData *) target;
285
286         curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping);
287 }
288
289 static void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
290                                   unsigned char *mask_rect, float *mask_rect_float, void *data_v)
291 {
292         CurveMapping *curve_mapping = (CurveMapping *) data_v;
293         int x, y;
294
295         for (y = 0; y < height; y++) {
296                 for (x = 0; x < width; x++) {
297                         int pixel_index = (y * width + x) * 4;
298
299                         if (rect_float) {
300                                 float *pixel = rect_float + pixel_index;
301                                 float result[3];
302
303                                 curvemapping_evaluate_premulRGBF(curve_mapping, result, pixel);
304
305                                 if (mask_rect_float) {
306                                         const float *m = mask_rect_float + pixel_index;
307
308                                         pixel[0] = pixel[0] * (1.0f - m[0]) + result[0] * m[0];
309                                         pixel[1] = pixel[1] * (1.0f - m[1]) + result[1] * m[1];
310                                         pixel[2] = pixel[2] * (1.0f - m[2]) + result[2] * m[2];
311                                 }
312                                 else {
313                                         pixel[0] = result[0];
314                                         pixel[1] = result[1];
315                                         pixel[2] = result[2];
316                                 }
317                         }
318                         if (rect) {
319                                 unsigned char *pixel = rect + pixel_index;
320                                 float result[3], tempc[4];
321
322                                 straight_uchar_to_premul_float(tempc, pixel);
323
324                                 curvemapping_evaluate_premulRGBF(curve_mapping, result, tempc);
325
326                                 if (mask_rect) {
327                                         float t[3];
328
329                                         rgb_uchar_to_float(t, mask_rect + pixel_index);
330
331                                         tempc[0] = tempc[0] * (1.0f - t[0]) + result[0] * t[0];
332                                         tempc[1] = tempc[1] * (1.0f - t[1]) + result[1] * t[1];
333                                         tempc[2] = tempc[2] * (1.0f - t[2]) + result[2] * t[2];
334                                 }
335                                 else {
336                                         tempc[0] = result[0];
337                                         tempc[1] = result[1];
338                                         tempc[2] = result[2];
339                                 }
340
341                                 premul_float_to_straight_uchar(pixel, tempc);
342                         }
343                 }
344         }
345 }
346
347 static void curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
348 {
349         CurvesModifierData *cmd = (CurvesModifierData *) smd;
350
351         float black[3] = {0.0f, 0.0f, 0.0f};
352         float white[3] = {1.0f, 1.0f, 1.0f};
353
354         curvemapping_initialize(&cmd->curve_mapping);
355
356         curvemapping_premultiply(&cmd->curve_mapping, 0);
357         curvemapping_set_black_white(&cmd->curve_mapping, black, white);
358
359         modifier_apply_threaded(ibuf, mask, curves_apply_threaded, &cmd->curve_mapping);
360
361         curvemapping_premultiply(&cmd->curve_mapping, 1);
362 }
363
364 static SequenceModifierTypeInfo seqModifier_Curves = {
365         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Curves"),   /* name */
366         "CurvesModifierData",                            /* struct_name */
367         sizeof(CurvesModifierData),                      /* struct_size */
368         curves_init_data,                                /* init_data */
369         curves_free_data,                                /* free_data */
370         curves_copy_data,                                /* copy_data */
371         curves_apply                                     /* apply */
372 };
373
374 /* **** Hue Correct Modifier **** */
375
376 static void hue_correct_init_data(SequenceModifierData *smd)
377 {
378         HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
379         int c;
380
381         curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
382         hcmd->curve_mapping.preset = CURVE_PRESET_MID9;
383
384         for (c = 0; c < 3; c++) {
385                 CurveMap *cuma = &hcmd->curve_mapping.cm[c];
386
387                 curvemap_reset(cuma, &hcmd->curve_mapping.clipr, hcmd->curve_mapping.preset, CURVEMAP_SLOPE_POSITIVE);
388         }
389
390         /* default to showing Saturation */
391         hcmd->curve_mapping.cur = 1;
392 }
393
394 static void hue_correct_free_data(SequenceModifierData *smd)
395 {
396         HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
397
398         curvemapping_free_data(&hcmd->curve_mapping);
399 }
400
401 static void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
402 {
403         HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
404         HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target;
405
406         curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping);
407 }
408
409 static void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
410                                 unsigned char *mask_rect, float *mask_rect_float, void *data_v)
411 {
412         CurveMapping *curve_mapping = (CurveMapping *) data_v;
413         int x, y;
414
415         for (y = 0; y < height; y++) {
416                 for (x = 0; x < width; x++) {
417                         int pixel_index = (y * width + x) * 4;
418                         float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f};
419                         float hsv[3], f;
420
421                         if (rect_float)
422                                 copy_v3_v3(pixel, rect_float + pixel_index);
423                         else
424                                 rgb_uchar_to_float(pixel, rect + pixel_index);
425
426                         rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2);
427
428                         /* adjust hue, scaling returned default 0.5 up to 1 */
429                         f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]);
430                         hsv[0] += f - 0.5f;
431
432                         /* adjust saturation, scaling returned default 0.5 up to 1 */
433                         f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]);
434                         hsv[1] *= (f * 2.0f);
435
436                         /* adjust value, scaling returned default 0.5 up to 1 */
437                         f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]);
438                         hsv[2] *= (f * 2.f);
439
440                         hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
441                         CLAMP(hsv[1], 0.0f, 1.0f);
442
443                         /* convert back to rgb */
444                         hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2);
445
446                         if (mask_rect_float)
447                                 copy_v3_v3(mask, mask_rect_float + pixel_index);
448                         else if (mask_rect)
449                                 rgb_uchar_to_float(mask, mask_rect + pixel_index);
450
451                         result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0];
452                         result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1];
453                         result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2];
454
455                         if (rect_float)
456                                 copy_v3_v3(rect_float + pixel_index, result);
457                         else
458                                 rgb_float_to_uchar(rect + pixel_index, result);
459                 }
460         }
461 }
462
463 static void hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
464 {
465         HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
466
467         curvemapping_initialize(&hcmd->curve_mapping);
468
469         modifier_apply_threaded(ibuf, mask, hue_correct_apply_threaded, &hcmd->curve_mapping);
470 }
471
472 static SequenceModifierTypeInfo seqModifier_HueCorrect = {
473         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Hue Correct"),    /* name */
474         "HueCorrectModifierData",                              /* struct_name */
475         sizeof(HueCorrectModifierData),                        /* struct_size */
476         hue_correct_init_data,                                 /* init_data */
477         hue_correct_free_data,                                 /* free_data */
478         hue_correct_copy_data,                                 /* copy_data */
479         hue_correct_apply                                      /* apply */
480 };
481
482 /* **** Bright/Contrast Modifier **** */
483
484 typedef struct BrightContrastThreadData {
485         float bright;
486         float contrast;
487 } BrightContrastThreadData;
488
489 static void brightcontrast_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
490                                           unsigned char *mask_rect, float *mask_rect_float, void *data_v)
491 {
492         BrightContrastThreadData *data = (BrightContrastThreadData *) data_v;
493         int x, y;
494
495         float i;
496         int c;
497         float a, b, v;
498         float brightness = data->bright / 100.0f;
499         float contrast = data->contrast;
500         float delta = contrast / 200.0f;
501
502         a = 1.0f - delta * 2.0f;
503         /*
504          * The algorithm is by Werner D. Streidt
505          * (http://visca.com/ffactory/archives/5-99/msg00021.html)
506          * Extracted of OpenCV demhist.c
507          */
508         if (contrast > 0) {
509                 a = 1.0f / a;
510                 b = a * (brightness - delta);
511         }
512         else {
513                 delta *= -1;
514                 b = a * (brightness + delta);
515         }
516
517         for (y = 0; y < height; y++) {
518                 for (x = 0; x < width; x++) {
519                         int pixel_index = (y * width + x) * 4;
520
521                         if (rect) {
522                                 unsigned char *pixel = rect + pixel_index;
523
524                                 for (c = 0; c < 3; c++) {
525                                         i = (float) pixel[c] / 255.0f;
526                                         v = a * i + b;
527
528                                         if (mask_rect) {
529                                                 unsigned char *m = mask_rect + pixel_index;
530                                                 float t = (float) m[c] / 255.0f;
531
532                                                 v = (float) pixel[c] / 255.0f * (1.0f - t) + v * t;
533                                         }
534
535                                         pixel[c] = unit_float_to_uchar_clamp(v);
536                                 }
537                         }
538                         else if (rect_float) {
539                                 float *pixel = rect_float + pixel_index;
540
541                                 for (c = 0; c < 3; c++) {
542                                         i = pixel[c];
543                                         v = a * i + b;
544
545                                         if (mask_rect_float) {
546                                                 const float *m = mask_rect_float + pixel_index;
547
548                                                 pixel[c] = pixel[c] * (1.0f - m[c]) + v * m[c];
549                                         }
550                                         else
551                                                 pixel[c] = v;
552                                 }
553                         }
554                 }
555         }
556 }
557
558 static void brightcontrast_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
559 {
560         BrightContrastModifierData *bcmd = (BrightContrastModifierData *) smd;
561         BrightContrastThreadData data;
562
563         data.bright = bcmd->bright;
564         data.contrast = bcmd->contrast;
565
566         modifier_apply_threaded(ibuf, mask, brightcontrast_apply_threaded, &data);
567 }
568
569 static SequenceModifierTypeInfo seqModifier_BrightContrast = {
570         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Bright/Contrast"),   /* name */
571         "BrightContrastModifierData",                             /* struct_name */
572         sizeof(BrightContrastModifierData),                       /* struct_size */
573         NULL,                                                     /* init_data */
574         NULL,                                                     /* free_data */
575         NULL,                                                     /* copy_data */
576         brightcontrast_apply                                      /* apply */
577 };
578
579 /* **** Mask Modifier **** */
580
581 static void maskmodifier_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
582                                         unsigned char *mask_rect, float *mask_rect_float, void *UNUSED(data_v))
583 {
584         int x, y;
585
586         if (rect && !mask_rect)
587                 return;
588
589         if (rect_float && !mask_rect_float)
590                 return;
591
592         for (y = 0; y < height; y++) {
593                 for (x = 0; x < width; x++) {
594                         int pixel_index = (y * width + x) * 4;
595
596                         if (rect) {
597                                 unsigned char *pixel = rect + pixel_index;
598                                 unsigned char *mask_pixel = mask_rect + pixel_index;
599                                 unsigned char mask = min_iii(mask_pixel[0], mask_pixel[1], mask_pixel[2]);
600
601                                 /* byte buffer is straight, so only affect on alpha itself,
602                                  * this is the only way to alpha-over byte strip after
603                                  * applying mask modifier.
604                                  */
605                                 pixel[3] = (float)(pixel[3] * mask) / 255.0f;
606                         }
607                         else if (rect_float) {
608                                 int c;
609                                 float *pixel = rect_float + pixel_index;
610                                 const float *mask_pixel = mask_rect_float + pixel_index;
611                                 float mask = min_fff(mask_pixel[0], mask_pixel[1], mask_pixel[2]);
612
613                                 /* float buffers are premultiplied, so need to premul color
614                                  * as well to make it easy to alpha-over masted strip.
615                                  */
616                                 for (c = 0; c < 4; c++)
617                                         pixel[c] = pixel[c] * mask;
618                         }
619                 }
620         }
621 }
622
623 static void maskmodifier_apply(struct SequenceModifierData *UNUSED(smd), ImBuf *ibuf, ImBuf *mask)
624 {
625         // SequencerMaskModifierData *bcmd = (SequencerMaskModifierData *)smd;
626
627         modifier_apply_threaded(ibuf, mask, maskmodifier_apply_threaded, NULL);
628 }
629
630 static SequenceModifierTypeInfo seqModifier_Mask = {
631         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Mask"), /* name */
632         "SequencerMaskModifierData",                 /* struct_name */
633         sizeof(SequencerMaskModifierData),           /* struct_size */
634         NULL,                                        /* init_data */
635         NULL,                                        /* free_data */
636         NULL,                                        /* copy_data */
637         maskmodifier_apply                           /* apply */
638 };
639
640 /* **** Tonemap Modifier **** */
641
642 typedef struct AvgLogLum {
643         SequencerTonemapModifierData *tmmd;
644         struct ColorSpace *colorspace;
645         float al;
646         float auto_key;
647         float lav;
648         float cav[4];
649         float igm;
650 } AvgLogLum;
651
652 static void tonemapmodifier_init_data(SequenceModifierData *smd)
653 {
654         SequencerTonemapModifierData *tmmd = (SequencerTonemapModifierData *) smd;
655         /* Same as tonemap compositor node. */
656         tmmd->type = SEQ_TONEMAP_RD_PHOTORECEPTOR;
657         tmmd->key = 0.18f;
658         tmmd->offset = 1.0f;
659         tmmd->gamma = 1.0f;
660         tmmd->intensity = 0.0f;
661         tmmd->contrast = 0.0f;
662         tmmd->adaptation = 1.0f;
663         tmmd->correction = 0.0f;
664 }
665
666 static void tonemapmodifier_apply_threaded_simple(int width,
667                                                   int height,
668                                                   unsigned char *rect,
669                                                   float *rect_float,
670                                                   unsigned char *mask_rect,
671                                                   float *mask_rect_float,
672                                                   void *data_v)
673 {
674         AvgLogLum *avg = (AvgLogLum *)data_v;
675         for (int y = 0; y < height; y++) {
676                 for (int x = 0; x < width; x++) {
677                         int pixel_index = (y * width + x) * 4;
678                         float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f};
679                         /* Get input value. */
680                         if (rect_float) {
681                                 copy_v4_v4(input, &rect_float[pixel_index]);
682                         }
683                         else {
684                                 straight_uchar_to_premul_float(input, &rect[pixel_index]);
685                         }
686                         IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace);
687                         copy_v4_v4(output, input);
688                         /* Get mask value. */
689                         if (mask_rect_float) {
690                                 copy_v3_v3(mask, mask_rect_float + pixel_index);
691                         }
692                         else if (mask_rect) {
693                                 rgb_uchar_to_float(mask, mask_rect + pixel_index);
694                         }
695                         /* Apply correction. */
696                         mul_v3_fl(output, avg->al);
697                         float dr = output[0] + avg->tmmd->offset;
698                         float dg = output[1] + avg->tmmd->offset;
699                         float db = output[2] + avg->tmmd->offset;
700                         output[0] /= ((dr == 0.0f) ? 1.0f : dr);
701                         output[1] /= ((dg == 0.0f) ? 1.0f : dg);
702                         output[2] /= ((db == 0.0f) ? 1.0f : db);
703                         const float igm = avg->igm;
704                         if (igm != 0.0f) {
705                                 output[0] = powf(max_ff(output[0], 0.0f), igm);
706                                 output[1] = powf(max_ff(output[1], 0.0f), igm);
707                                 output[2] = powf(max_ff(output[2], 0.0f), igm);
708                         }
709                         /* Apply mask. */
710                         output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0];
711                         output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1];
712                         output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2];
713                         /* Copy result back. */
714                         IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace);
715                         if (rect_float) {
716                                 copy_v4_v4(&rect_float[pixel_index], output);
717                         }
718                         else {
719                                 premul_float_to_straight_uchar(&rect[pixel_index], output);
720                         }
721                 }
722         }
723 }
724
725 static void tonemapmodifier_apply_threaded_photoreceptor(int width,
726                                                          int height,
727                                                          unsigned char *rect,
728                                                          float *rect_float,
729                                                          unsigned char *mask_rect,
730                                                          float *mask_rect_float,
731                                                          void *data_v)
732 {
733         AvgLogLum *avg = (AvgLogLum *)data_v;
734         const float f = expf(-avg->tmmd->intensity);
735         const float m = (avg->tmmd->contrast > 0.0f) ? avg->tmmd->contrast : (0.3f + 0.7f * powf(avg->auto_key, 1.4f));
736         const float ic = 1.0f - avg->tmmd->correction, ia = 1.0f - avg->tmmd->adaptation;
737         for (int y = 0; y < height; y++) {
738                 for (int x = 0; x < width; x++) {
739                         int pixel_index = (y * width + x) * 4;
740                         float input[4], output[4], mask[3] = {1.0f, 1.0f, 1.0f};
741                         /* Get input value. */
742                         if (rect_float) {
743                                 copy_v4_v4(input, &rect_float[pixel_index]);
744                         }
745                         else {
746                                 straight_uchar_to_premul_float(input, &rect[pixel_index]);
747                         }
748                         IMB_colormanagement_colorspace_to_scene_linear_v3(input, avg->colorspace);
749                         copy_v4_v4(output, input);
750                         /* Get mask value. */
751                         if (mask_rect_float) {
752                                 copy_v3_v3(mask, mask_rect_float + pixel_index);
753                         }
754                         else if (mask_rect) {
755                                 rgb_uchar_to_float(mask, mask_rect + pixel_index);
756                         }
757                         /* Apply correction. */
758                         const float L = IMB_colormanagement_get_luminance(output);
759                         float I_l = output[0] + ic * (L - output[0]);
760                         float I_g = avg->cav[0] + ic * (avg->lav - avg->cav[0]);
761                         float I_a = I_l + ia * (I_g - I_l);
762                         output[0] /= (output[0] + powf(f * I_a, m));
763                         I_l = output[1] + ic * (L - output[1]);
764                         I_g = avg->cav[1] + ic * (avg->lav - avg->cav[1]);
765                         I_a = I_l + ia * (I_g - I_l);
766                         output[1] /= (output[1] + powf(f * I_a, m));
767                         I_l = output[2] + ic * (L - output[2]);
768                         I_g = avg->cav[2] + ic * (avg->lav - avg->cav[2]);
769                         I_a = I_l + ia * (I_g - I_l);
770                         output[2] /= (output[2] + powf(f * I_a, m));
771                         /* Apply mask. */
772                         output[0] = input[0] * (1.0f - mask[0]) + output[0] * mask[0];
773                         output[1] = input[1] * (1.0f - mask[1]) + output[1] * mask[1];
774                         output[2] = input[2] * (1.0f - mask[2]) + output[2] * mask[2];
775                         /* Copy result back. */
776                         IMB_colormanagement_scene_linear_to_colorspace_v3(output, avg->colorspace);
777                         if (rect_float) {
778                                 copy_v4_v4(&rect_float[pixel_index], output);
779                         }
780                         else {
781                                 premul_float_to_straight_uchar(&rect[pixel_index], output);
782                         }
783                 }
784         }
785 }
786
787 static void tonemapmodifier_apply(struct SequenceModifierData *smd,
788                                   ImBuf *ibuf,
789                                   ImBuf *mask)
790 {
791         SequencerTonemapModifierData *tmmd = (SequencerTonemapModifierData *) smd;
792         AvgLogLum data;
793         data.tmmd = tmmd;
794         data.colorspace = (ibuf->rect_float != NULL)
795                               ? ibuf->float_colorspace
796                               : ibuf->rect_colorspace;
797         float lsum = 0.0f;
798         int p = ibuf->x * ibuf->y;
799         float *fp = ibuf->rect_float;
800         unsigned char *cp = (unsigned char *)ibuf->rect;
801         float avl, maxl = -FLT_MAX, minl = FLT_MAX;
802         const float sc = 1.0f / p;
803         float Lav = 0.f;
804         float cav[4] = {0.0f, 0.0f, 0.0f, 0.0f};
805         while (p--) {
806                 float pixel[4];
807                 if (fp != NULL) {
808                         copy_v4_v4(pixel, fp);
809                 }
810                 else {
811                         straight_uchar_to_premul_float(pixel, cp);
812                 }
813                 IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, data.colorspace);
814                 float L = IMB_colormanagement_get_luminance(pixel);
815                 Lav += L;
816                 add_v3_v3(cav, pixel);
817                 lsum += logf(max_ff(L, 0.0f) + 1e-5f);
818                 maxl = (L > maxl) ? L : maxl;
819                 minl = (L < minl) ? L : minl;
820                 if (fp != NULL) {
821                         fp += 4;
822                 }
823                 else {
824                         cp += 4;
825                 }
826         }
827         data.lav = Lav * sc;
828         mul_v3_v3fl(data.cav, cav, sc);
829         maxl = logf(maxl + 1e-5f);
830         minl = logf(minl + 1e-5f);
831         avl = lsum * sc;
832         data.auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.0f;
833         float al = expf(avl);
834         data.al = (al == 0.0f) ? 0.0f : (tmmd->key / al);
835         data.igm = (tmmd->gamma == 0.0f) ? 1.0f : (1.0f / tmmd->gamma);
836
837         if (tmmd->type == SEQ_TONEMAP_RD_PHOTORECEPTOR) {
838                 modifier_apply_threaded(ibuf,
839                                         mask,
840                                         tonemapmodifier_apply_threaded_photoreceptor,
841                                         &data);
842         }
843         else /* if (tmmd->type == SEQ_TONEMAP_RD_SIMPLE) */ {
844                 modifier_apply_threaded(ibuf,
845                                         mask,
846                                         tonemapmodifier_apply_threaded_simple,
847                                         &data);
848         }
849 }
850
851 static SequenceModifierTypeInfo seqModifier_Tonemap = {
852         CTX_N_(BLT_I18NCONTEXT_ID_SEQUENCE, "Tonemap"), /* name */
853         "SequencerTonemapModifierData",                 /* struct_name */
854         sizeof(SequencerTonemapModifierData),           /* struct_size */
855         tonemapmodifier_init_data,                      /* init_data */
856         NULL,                                           /* free_data */
857         NULL,                                           /* copy_data */
858         tonemapmodifier_apply                           /* apply */
859 };
860
861 /*********************** Modifier functions *************************/
862
863 static void sequence_modifier_type_info_init(void)
864 {
865 #define INIT_TYPE(typeName) (modifiersTypes[seqModifierType_##typeName] = &seqModifier_##typeName)
866
867         INIT_TYPE(ColorBalance);
868         INIT_TYPE(Curves);
869         INIT_TYPE(HueCorrect);
870         INIT_TYPE(BrightContrast);
871         INIT_TYPE(Mask);
872         INIT_TYPE(WhiteBalance);
873         INIT_TYPE(Tonemap);
874
875 #undef INIT_TYPE
876 }
877
878 const SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
879 {
880         if (!modifierTypesInit) {
881                 sequence_modifier_type_info_init();
882                 modifierTypesInit = true;
883         }
884
885         return modifiersTypes[type];
886 }
887
888 SequenceModifierData *BKE_sequence_modifier_new(Sequence *seq, const char *name, int type)
889 {
890         SequenceModifierData *smd;
891         const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
892
893         smd = MEM_callocN(smti->struct_size, "sequence modifier");
894
895         smd->type = type;
896         smd->flag |= SEQUENCE_MODIFIER_EXPANDED;
897
898         if (!name || !name[0])
899                 BLI_strncpy(smd->name, smti->name, sizeof(smd->name));
900         else
901                 BLI_strncpy(smd->name, name, sizeof(smd->name));
902
903         BLI_addtail(&seq->modifiers, smd);
904
905         BKE_sequence_modifier_unique_name(seq, smd);
906
907         if (smti->init_data)
908                 smti->init_data(smd);
909
910         return smd;
911 }
912
913 bool BKE_sequence_modifier_remove(Sequence *seq, SequenceModifierData *smd)
914 {
915         if (BLI_findindex(&seq->modifiers, smd) == -1)
916                 return false;
917
918         BLI_remlink(&seq->modifiers, smd);
919         BKE_sequence_modifier_free(smd);
920
921         return true;
922 }
923
924 void BKE_sequence_modifier_clear(Sequence *seq)
925 {
926         SequenceModifierData *smd, *smd_next;
927
928         for (smd = seq->modifiers.first; smd; smd = smd_next) {
929                 smd_next = smd->next;
930                 BKE_sequence_modifier_free(smd);
931         }
932
933         BLI_listbase_clear(&seq->modifiers);
934 }
935
936 void BKE_sequence_modifier_free(SequenceModifierData *smd)
937 {
938         const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
939
940         if (smti && smti->free_data) {
941                 smti->free_data(smd);
942         }
943
944         MEM_freeN(smd);
945 }
946
947 void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd)
948 {
949         const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
950
951         BLI_uniquename(&seq->modifiers, smd, CTX_DATA_(BLT_I18NCONTEXT_ID_SEQUENCE, smti->name), '.',
952                        offsetof(SequenceModifierData, name), sizeof(smd->name));
953 }
954
955 SequenceModifierData *BKE_sequence_modifier_find_by_name(Sequence *seq, const char *name)
956 {
957         return BLI_findstring(&(seq->modifiers), name, offsetof(SequenceModifierData, name));
958 }
959
960 ImBuf *BKE_sequence_modifier_apply_stack(const SeqRenderData *context, Sequence *seq, ImBuf *ibuf, int cfra)
961 {
962         SequenceModifierData *smd;
963         ImBuf *processed_ibuf = ibuf;
964
965         if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
966                 processed_ibuf = IMB_dupImBuf(ibuf);
967                 BKE_sequencer_imbuf_from_sequencer_space(context->scene, processed_ibuf);
968         }
969
970         for (smd = seq->modifiers.first; smd; smd = smd->next) {
971                 const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
972
973                 /* could happen if modifier is being removed or not exists in current version of blender */
974                 if (!smti)
975                         continue;
976
977                 /* modifier is muted, do nothing */
978                 if (smd->flag & SEQUENCE_MODIFIER_MUTE)
979                         continue;
980
981                 if (smti->apply) {
982                         int frame_offset;
983                         if (smd->mask_time == SEQUENCE_MASK_TIME_RELATIVE) {
984                                 frame_offset = seq->start;
985                         }
986                         else /*if (smd->mask_time == SEQUENCE_MASK_TIME_ABSOLUTE)*/ {
987                                 frame_offset = 0;
988                         }
989
990                         ImBuf *mask = modifier_mask_get(smd,
991                                                         context,
992                                                         cfra,
993                                                         frame_offset,
994                                                         ibuf->rect_float != NULL);
995
996                         if (processed_ibuf == ibuf)
997                                 processed_ibuf = IMB_dupImBuf(ibuf);
998
999                         smti->apply(smd, processed_ibuf, mask);
1000
1001                         if (mask)
1002                                 IMB_freeImBuf(mask);
1003                 }
1004         }
1005
1006         if (seq->modifiers.first && (seq->flag & SEQ_USE_LINEAR_MODIFIERS)) {
1007                 BKE_sequencer_imbuf_to_sequencer_space(context->scene, processed_ibuf, false);
1008         }
1009
1010         return processed_ibuf;
1011 }
1012
1013 void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq)
1014 {
1015         SequenceModifierData *smd;
1016
1017         for (smd = seq->modifiers.first; smd; smd = smd->next) {
1018                 SequenceModifierData *smdn;
1019                 const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
1020
1021                 smdn = MEM_dupallocN(smd);
1022
1023                 if (smti && smti->copy_data)
1024                         smti->copy_data(smdn, smd);
1025
1026                 smdn->next = smdn->prev = NULL;
1027                 BLI_addtail(&seqn->modifiers, smdn);
1028         }
1029 }
1030
1031 int BKE_sequence_supports_modifiers(Sequence *seq)
1032 {
1033         return !ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD);
1034 }