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