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