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