Blender  V2.93
colortools.c
Go to the documentation of this file.
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) 2005 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <float.h>
25 #include <math.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "DNA_color_types.h"
32 #include "DNA_curve_types.h"
33 
34 #include "BLI_blenlib.h"
35 #include "BLI_math.h"
36 #include "BLI_task.h"
37 #include "BLI_threads.h"
38 #include "BLI_utildefines.h"
39 
40 #include "BKE_colortools.h"
41 #include "BKE_curve.h"
42 #include "BKE_fcurve.h"
43 
44 #include "IMB_colormanagement.h"
45 #include "IMB_imbuf_types.h"
46 
47 #include "BLO_read_write.h"
48 
49 /* ********************************* color curve ********************* */
50 
51 /* ***************** operations on full struct ************* */
52 
54  CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
55 {
56  int a;
57  float clipminx, clipminy, clipmaxx, clipmaxy;
58 
60  if (tot == 4) {
61  cumap->cur = 3; /* rhms, hack for 'col' curve? */
62  }
63 
64  clipminx = min_ff(minx, maxx);
65  clipminy = min_ff(miny, maxy);
66  clipmaxx = max_ff(minx, maxx);
67  clipmaxy = max_ff(miny, maxy);
68 
69  BLI_rctf_init(&cumap->curr, clipminx, clipmaxx, clipminy, clipmaxy);
70  cumap->clipr = cumap->curr;
71 
72  cumap->white[0] = cumap->white[1] = cumap->white[2] = 1.0f;
73  cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f;
74 
75  for (a = 0; a < tot; a++) {
76  cumap->cm[a].totpoint = 2;
77  cumap->cm[a].curve = MEM_callocN(2 * sizeof(CurveMapPoint), "curve points");
78 
79  cumap->cm[a].curve[0].x = minx;
80  cumap->cm[a].curve[0].y = miny;
81  cumap->cm[a].curve[1].x = maxx;
82  cumap->cm[a].curve[1].y = maxy;
83  }
84 
85  cumap->changed_timestamp = 0;
86 }
87 
88 CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
89 {
90  CurveMapping *cumap;
91 
92  cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
93 
94  BKE_curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy);
95 
96  return cumap;
97 }
98 
100 {
101  int a;
102 
103  for (a = 0; a < CM_TOT; a++) {
104  if (cumap->cm[a].curve) {
105  MEM_freeN(cumap->cm[a].curve);
106  cumap->cm[a].curve = NULL;
107  }
108  if (cumap->cm[a].table) {
109  MEM_freeN(cumap->cm[a].table);
110  cumap->cm[a].table = NULL;
111  }
112  if (cumap->cm[a].premultable) {
113  MEM_freeN(cumap->cm[a].premultable);
114  cumap->cm[a].premultable = NULL;
115  }
116  }
117 }
118 
120 {
121  if (cumap) {
123  MEM_freeN(cumap);
124  }
125 }
126 
128 {
129  int a;
130 
131  *target = *cumap;
132 
133  for (a = 0; a < CM_TOT; a++) {
134  if (cumap->cm[a].curve) {
135  target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
136  }
137  if (cumap->cm[a].table) {
138  target->cm[a].table = MEM_dupallocN(cumap->cm[a].table);
139  }
140  if (cumap->cm[a].premultable) {
141  target->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable);
142  }
143  }
144 }
145 
147 {
148  if (cumap) {
149  CurveMapping *cumapn = MEM_dupallocN(cumap);
150  BKE_curvemapping_copy_data(cumapn, cumap);
151  return cumapn;
152  }
153  return NULL;
154 }
155 
156 void BKE_curvemapping_set_black_white_ex(const float black[3],
157  const float white[3],
158  float r_bwmul[3])
159 {
160  int a;
161 
162  for (a = 0; a < 3; a++) {
163  const float delta = max_ff(white[a] - black[a], 1e-5f);
164  r_bwmul[a] = 1.0f / delta;
165  }
166 }
167 
169  const float black[3],
170  const float white[3])
171 {
172  if (white) {
173  copy_v3_v3(cumap->white, white);
174  }
175  if (black) {
176  copy_v3_v3(cumap->black, black);
177  }
178 
179  BKE_curvemapping_set_black_white_ex(cumap->black, cumap->white, cumap->bwmul);
180  cumap->changed_timestamp++;
181 }
182 
183 /* ***************** operations on single curve ************* */
184 /* ********** NOTE: requires BKE_curvemapping_changed() call after ******** */
185 
186 /* remove specified point */
188 {
189  CurveMapPoint *cmp;
190  int a, b, removed = 0;
191 
192  /* must have 2 points minimum */
193  if (cuma->totpoint <= 2) {
194  return false;
195  }
196 
197  cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points");
198 
199  /* well, lets keep the two outer points! */
200  for (a = 0, b = 0; a < cuma->totpoint; a++) {
201  if (&cuma->curve[a] != point) {
202  cmp[b] = cuma->curve[a];
203  b++;
204  }
205  else {
206  removed++;
207  }
208  }
209 
210  MEM_freeN(cuma->curve);
211  cuma->curve = cmp;
212  cuma->totpoint -= removed;
213  return (removed != 0);
214 }
215 
216 /* removes with flag set */
217 void BKE_curvemap_remove(CurveMap *cuma, const short flag)
218 {
219  CurveMapPoint *cmp = MEM_mallocN((cuma->totpoint) * sizeof(CurveMapPoint), "curve points");
220  int a, b, removed = 0;
221 
222  /* well, lets keep the two outer points! */
223  cmp[0] = cuma->curve[0];
224  for (a = 1, b = 1; a < cuma->totpoint - 1; a++) {
225  if (!(cuma->curve[a].flag & flag)) {
226  cmp[b] = cuma->curve[a];
227  b++;
228  }
229  else {
230  removed++;
231  }
232  }
233  cmp[b] = cuma->curve[a];
234 
235  MEM_freeN(cuma->curve);
236  cuma->curve = cmp;
237  cuma->totpoint -= removed;
238 }
239 
241 {
242  CurveMapPoint *cmp = MEM_callocN((cuma->totpoint + 1) * sizeof(CurveMapPoint), "curve points");
243  CurveMapPoint *newcmp = NULL;
244  int a, b;
245  bool foundloc = false;
246 
247  /* insert fragments of the old one and the new point to the new curve */
248  cuma->totpoint++;
249  for (a = 0, b = 0; a < cuma->totpoint; a++) {
250  if ((foundloc == false) && ((a + 1 == cuma->totpoint) || (x < cuma->curve[a].x))) {
251  cmp[a].x = x;
252  cmp[a].y = y;
253  cmp[a].flag = CUMA_SELECT;
254  foundloc = true;
255  newcmp = &cmp[a];
256  }
257  else {
258  cmp[a].x = cuma->curve[b].x;
259  cmp[a].y = cuma->curve[b].y;
260  /* make sure old points don't remain selected */
261  cmp[a].flag = cuma->curve[b].flag & ~CUMA_SELECT;
262  cmp[a].shorty = cuma->curve[b].shorty;
263  b++;
264  }
265  }
266 
267  /* free old curve and replace it with new one */
268  MEM_freeN(cuma->curve);
269  cuma->curve = cmp;
270 
271  return newcmp;
272 }
273 
274 void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
275 {
276  if (cuma->curve) {
277  MEM_freeN(cuma->curve);
278  }
279 
280  switch (preset) {
281  case CURVE_PRESET_LINE:
282  cuma->totpoint = 2;
283  break;
284  case CURVE_PRESET_SHARP:
285  cuma->totpoint = 4;
286  break;
287  case CURVE_PRESET_SMOOTH:
288  cuma->totpoint = 4;
289  break;
290  case CURVE_PRESET_MAX:
291  cuma->totpoint = 2;
292  break;
293  case CURVE_PRESET_MID9:
294  cuma->totpoint = 9;
295  break;
296  case CURVE_PRESET_ROUND:
297  cuma->totpoint = 4;
298  break;
299  case CURVE_PRESET_ROOT:
300  cuma->totpoint = 4;
301  break;
302  case CURVE_PRESET_GAUSS:
303  cuma->totpoint = 7;
304  break;
305  case CURVE_PRESET_BELL:
306  cuma->totpoint = 3;
307  break;
308  }
309 
310  cuma->curve = MEM_callocN(cuma->totpoint * sizeof(CurveMapPoint), "curve points");
311 
312  switch (preset) {
313  case CURVE_PRESET_LINE:
314  cuma->curve[0].x = clipr->xmin;
315  cuma->curve[0].y = clipr->ymax;
316  cuma->curve[1].x = clipr->xmax;
317  cuma->curve[1].y = clipr->ymin;
318  if (slope == CURVEMAP_SLOPE_POS_NEG) {
319  cuma->curve[0].flag |= CUMA_HANDLE_VECTOR;
320  cuma->curve[1].flag |= CUMA_HANDLE_VECTOR;
321  }
322  break;
323  case CURVE_PRESET_SHARP:
324  cuma->curve[0].x = 0;
325  cuma->curve[0].y = 1;
326  cuma->curve[1].x = 0.25;
327  cuma->curve[1].y = 0.50;
328  cuma->curve[2].x = 0.75;
329  cuma->curve[2].y = 0.04;
330  cuma->curve[3].x = 1;
331  cuma->curve[3].y = 0;
332  break;
333  case CURVE_PRESET_SMOOTH:
334  cuma->curve[0].x = 0;
335  cuma->curve[0].y = 1;
336  cuma->curve[1].x = 0.25;
337  cuma->curve[1].y = 0.94;
338  cuma->curve[2].x = 0.75;
339  cuma->curve[2].y = 0.06;
340  cuma->curve[3].x = 1;
341  cuma->curve[3].y = 0;
342  break;
343  case CURVE_PRESET_MAX:
344  cuma->curve[0].x = 0;
345  cuma->curve[0].y = 1;
346  cuma->curve[1].x = 1;
347  cuma->curve[1].y = 1;
348  break;
349  case CURVE_PRESET_MID9: {
350  for (int i = 0; i < cuma->totpoint; i++) {
351  cuma->curve[i].x = i / ((float)cuma->totpoint - 1);
352  cuma->curve[i].y = 0.5;
353  }
354  break;
355  }
356  case CURVE_PRESET_ROUND:
357  cuma->curve[0].x = 0;
358  cuma->curve[0].y = 1;
359  cuma->curve[1].x = 0.5;
360  cuma->curve[1].y = 0.90;
361  cuma->curve[2].x = 0.86;
362  cuma->curve[2].y = 0.5;
363  cuma->curve[3].x = 1;
364  cuma->curve[3].y = 0;
365  break;
366  case CURVE_PRESET_ROOT:
367  cuma->curve[0].x = 0;
368  cuma->curve[0].y = 1;
369  cuma->curve[1].x = 0.25;
370  cuma->curve[1].y = 0.95;
371  cuma->curve[2].x = 0.75;
372  cuma->curve[2].y = 0.44;
373  cuma->curve[3].x = 1;
374  cuma->curve[3].y = 0;
375  break;
376  case CURVE_PRESET_GAUSS:
377  cuma->curve[0].x = 0;
378  cuma->curve[0].y = 0.025f;
379  cuma->curve[1].x = 0.16f;
380  cuma->curve[1].y = 0.135f;
381  cuma->curve[2].x = 0.298f;
382  cuma->curve[2].y = 0.36f;
383 
384  cuma->curve[3].x = 0.50f;
385  cuma->curve[3].y = 1.0f;
386 
387  cuma->curve[4].x = 0.70f;
388  cuma->curve[4].y = 0.36f;
389  cuma->curve[5].x = 0.84f;
390  cuma->curve[5].y = 0.135f;
391  cuma->curve[6].x = 1.0f;
392  cuma->curve[6].y = 0.025f;
393  break;
394  case CURVE_PRESET_BELL:
395  cuma->curve[0].x = 0.0f;
396  cuma->curve[0].y = 0.025f;
397 
398  cuma->curve[1].x = 0.50f;
399  cuma->curve[1].y = 1.0f;
400 
401  cuma->curve[2].x = 1.0f;
402  cuma->curve[2].y = 0.025f;
403  break;
404  }
405 
406  /* mirror curve in x direction to have positive slope
407  * rather than default negative slope */
408  if (slope == CURVEMAP_SLOPE_POSITIVE) {
409  int i, last = cuma->totpoint - 1;
410  CurveMapPoint *newpoints = MEM_dupallocN(cuma->curve);
411 
412  for (i = 0; i < cuma->totpoint; i++) {
413  newpoints[i].y = cuma->curve[last - i].y;
414  }
415 
416  MEM_freeN(cuma->curve);
417  cuma->curve = newpoints;
418  }
419  else if (slope == CURVEMAP_SLOPE_POS_NEG) {
420  const int num_points = cuma->totpoint * 2 - 1;
421  CurveMapPoint *new_points = MEM_mallocN(num_points * sizeof(CurveMapPoint),
422  "curve symmetric points");
423  for (int i = 0; i < cuma->totpoint; i++) {
424  const int src_last_point = cuma->totpoint - i - 1;
425  const int dst_last_point = num_points - i - 1;
426  new_points[i] = cuma->curve[src_last_point];
427  new_points[i].x = (1.0f - cuma->curve[src_last_point].x) * 0.5f;
428  new_points[dst_last_point] = new_points[i];
429  new_points[dst_last_point].x = 0.5f + cuma->curve[src_last_point].x * 0.5f;
430  }
431  cuma->totpoint = num_points;
432  MEM_freeN(cuma->curve);
433  cuma->curve = new_points;
434  }
435 
436  if (cuma->table) {
437  MEM_freeN(cuma->table);
438  cuma->table = NULL;
439  }
440 }
441 
446 {
447  int a;
448 
449  for (a = 0; a < cuma->totpoint; a++) {
450  if (cuma->curve[a].flag & CUMA_SELECT) {
452  if (type == HD_VECT) {
453  cuma->curve[a].flag |= CUMA_HANDLE_VECTOR;
454  }
455  else if (type == HD_AUTO_ANIM) {
456  cuma->curve[a].flag |= CUMA_HANDLE_AUTO_ANIM;
457  }
458  else {
459  /* pass */
460  }
461  }
462  }
463 }
464 
465 /* *********************** Making the tables and display ************** */
466 
470 static void calchandle_curvemap(BezTriple *bezt, const BezTriple *prev, const BezTriple *next)
471 {
472  /* defines to avoid confusion */
473 #define p2_h1 ((p2)-3)
474 #define p2_h2 ((p2) + 3)
475 
476  const float *p1, *p3;
477  float *p2;
478  float pt[3];
479  float len, len_a, len_b;
480  float dvec_a[2], dvec_b[2];
481 
482  if (bezt->h1 == 0 && bezt->h2 == 0) {
483  return;
484  }
485 
486  p2 = bezt->vec[1];
487 
488  if (prev == NULL) {
489  p3 = next->vec[1];
490  pt[0] = 2.0f * p2[0] - p3[0];
491  pt[1] = 2.0f * p2[1] - p3[1];
492  p1 = pt;
493  }
494  else {
495  p1 = prev->vec[1];
496  }
497 
498  if (next == NULL) {
499  p1 = prev->vec[1];
500  pt[0] = 2.0f * p2[0] - p1[0];
501  pt[1] = 2.0f * p2[1] - p1[1];
502  p3 = pt;
503  }
504  else {
505  p3 = next->vec[1];
506  }
507 
508  sub_v2_v2v2(dvec_a, p2, p1);
509  sub_v2_v2v2(dvec_b, p3, p2);
510 
511  len_a = len_v2(dvec_a);
512  len_b = len_v2(dvec_b);
513 
514  if (len_a == 0.0f) {
515  len_a = 1.0f;
516  }
517  if (len_b == 0.0f) {
518  len_b = 1.0f;
519  }
520 
521  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) || ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) { /* auto */
522  float tvec[2];
523  tvec[0] = dvec_b[0] / len_b + dvec_a[0] / len_a;
524  tvec[1] = dvec_b[1] / len_b + dvec_a[1] / len_a;
525 
526  len = len_v2(tvec) * 2.5614f;
527  if (len != 0.0f) {
528 
529  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
530  len_a /= len;
531  madd_v2_v2v2fl(p2_h1, p2, tvec, -len_a);
532 
533  if ((bezt->h1 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
534  const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
535  const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
536  if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
537  bezt->vec[0][1] = bezt->vec[1][1];
538  }
539  else { /* handles should not be beyond y coord of two others */
540  if (ydiff1 <= 0.0f) {
541  if (prev->vec[1][1] > bezt->vec[0][1]) {
542  bezt->vec[0][1] = prev->vec[1][1];
543  }
544  }
545  else {
546  if (prev->vec[1][1] < bezt->vec[0][1]) {
547  bezt->vec[0][1] = prev->vec[1][1];
548  }
549  }
550  }
551  }
552  }
553  if (ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {
554  len_b /= len;
555  madd_v2_v2v2fl(p2_h2, p2, tvec, len_b);
556 
557  if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
558  const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
559  const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
560  if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
561  bezt->vec[2][1] = bezt->vec[1][1];
562  }
563  else { /* handles should not be beyond y coord of two others */
564  if (ydiff1 <= 0.0f) {
565  if (next->vec[1][1] < bezt->vec[2][1]) {
566  bezt->vec[2][1] = next->vec[1][1];
567  }
568  }
569  else {
570  if (next->vec[1][1] > bezt->vec[2][1]) {
571  bezt->vec[2][1] = next->vec[1][1];
572  }
573  }
574  }
575  }
576  }
577  }
578  }
579 
580  if (bezt->h1 == HD_VECT) { /* vector */
581  madd_v2_v2v2fl(p2_h1, p2, dvec_a, -1.0f / 3.0f);
582  }
583  if (bezt->h2 == HD_VECT) {
584  madd_v2_v2v2fl(p2_h2, p2, dvec_b, 1.0f / 3.0f);
585  }
586 
587 #undef p2_h1
588 #undef p2_h2
589 }
590 
591 /* in X, out Y.
592  * X is presumed to be outside first or last */
593 static float curvemap_calc_extend(const CurveMapping *cumap,
594  const CurveMap *cuma,
595  float x,
596  const float first[2],
597  const float last[2])
598 {
599  if (x <= first[0]) {
600  if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
601  /* extrapolate horizontally */
602  return first[1];
603  }
604 
605  if (cuma->ext_in[0] == 0.0f) {
606  return first[1] + cuma->ext_in[1] * 10000.0f;
607  }
608 
609  return first[1] + cuma->ext_in[1] * (x - first[0]) / cuma->ext_in[0];
610  }
611  if (x >= last[0]) {
612  if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) {
613  /* extrapolate horizontally */
614  return last[1];
615  }
616 
617  if (cuma->ext_out[0] == 0.0f) {
618  return last[1] - cuma->ext_out[1] * 10000.0f;
619  }
620 
621  return last[1] + cuma->ext_out[1] * (x - last[0]) / cuma->ext_out[0];
622  }
623  return 0.0f;
624 }
625 
626 /* only creates a table for a single channel in CurveMapping */
627 static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma)
628 {
629  const rctf *clipr = &cumap->clipr;
630  CurveMapPoint *cmp = cuma->curve;
631  BezTriple *bezt;
632 
633  if (cuma->curve == NULL) {
634  return;
635  }
636 
637  /* default rect also is table range */
638  cuma->mintable = clipr->xmin;
639  cuma->maxtable = clipr->xmax;
640 
641  /* hrmf... we now rely on blender ipo beziers, these are more advanced */
642  bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr");
643 
644  for (int a = 0; a < cuma->totpoint; a++) {
645  cuma->mintable = min_ff(cuma->mintable, cmp[a].x);
646  cuma->maxtable = max_ff(cuma->maxtable, cmp[a].x);
647  bezt[a].vec[1][0] = cmp[a].x;
648  bezt[a].vec[1][1] = cmp[a].y;
649  if (cmp[a].flag & CUMA_HANDLE_VECTOR) {
650  bezt[a].h1 = bezt[a].h2 = HD_VECT;
651  }
652  else if (cmp[a].flag & CUMA_HANDLE_AUTO_ANIM) {
653  bezt[a].h1 = bezt[a].h2 = HD_AUTO_ANIM;
654  }
655  else {
656  bezt[a].h1 = bezt[a].h2 = HD_AUTO;
657  }
658  }
659 
660  const BezTriple *bezt_prev = NULL;
661  for (int a = 0; a < cuma->totpoint; a++) {
662  const BezTriple *bezt_next = (a != cuma->totpoint - 1) ? &bezt[a + 1] : NULL;
663  calchandle_curvemap(&bezt[a], bezt_prev, bezt_next);
664  bezt_prev = &bezt[a];
665  }
666 
667  /* first and last handle need correction, instead of pointing to center of next/prev,
668  * we let it point to the closest handle */
669  if (cuma->totpoint > 2) {
670  float hlen, nlen, vec[3];
671 
672  if (bezt[0].h2 == HD_AUTO) {
673 
674  hlen = len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
675  /* clip handle point */
676  copy_v3_v3(vec, bezt[1].vec[0]);
677  if (vec[0] < bezt[0].vec[1][0]) {
678  vec[0] = bezt[0].vec[1][0];
679  }
680 
681  sub_v3_v3(vec, bezt[0].vec[1]);
682  nlen = len_v3(vec);
683  if (nlen > FLT_EPSILON) {
684  mul_v3_fl(vec, hlen / nlen);
685  add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
686  sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
687  }
688  }
689  int a = cuma->totpoint - 1;
690  if (bezt[a].h2 == HD_AUTO) {
691 
692  hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
693  /* clip handle point */
694  copy_v3_v3(vec, bezt[a - 1].vec[2]);
695  if (vec[0] > bezt[a].vec[1][0]) {
696  vec[0] = bezt[a].vec[1][0];
697  }
698 
699  sub_v3_v3(vec, bezt[a].vec[1]);
700  nlen = len_v3(vec);
701  if (nlen > FLT_EPSILON) {
702  mul_v3_fl(vec, hlen / nlen);
703  add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
704  sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
705  }
706  }
707  }
708  /* make the bezier curve */
709  if (cuma->table) {
710  MEM_freeN(cuma->table);
711  }
712 
713  int totpoint = (cuma->totpoint - 1) * CM_RESOL;
714  float *allpoints = MEM_callocN(totpoint * 2 * sizeof(float), "table");
715  float *point = allpoints;
716 
717  for (int a = 0; a < cuma->totpoint - 1; a++, point += 2 * CM_RESOL) {
719  bezt[a].vec[1], bezt[a].vec[2], bezt[a + 1].vec[0], bezt[a + 1].vec[1]);
720  BKE_curve_forward_diff_bezier(bezt[a].vec[1][0],
721  bezt[a].vec[2][0],
722  bezt[a + 1].vec[0][0],
723  bezt[a + 1].vec[1][0],
724  point,
725  CM_RESOL - 1,
726  sizeof(float[2]));
727  BKE_curve_forward_diff_bezier(bezt[a].vec[1][1],
728  bezt[a].vec[2][1],
729  bezt[a + 1].vec[0][1],
730  bezt[a + 1].vec[1][1],
731  point + 1,
732  CM_RESOL - 1,
733  sizeof(float[2]));
734  }
735 
736  /* store first and last handle for extrapolation, unit length */
737  cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0];
738  cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1];
739  float ext_in_range = sqrtf(cuma->ext_in[0] * cuma->ext_in[0] +
740  cuma->ext_in[1] * cuma->ext_in[1]);
741  cuma->ext_in[0] /= ext_in_range;
742  cuma->ext_in[1] /= ext_in_range;
743 
744  int out_a = cuma->totpoint - 1;
745  cuma->ext_out[0] = bezt[out_a].vec[1][0] - bezt[out_a].vec[2][0];
746  cuma->ext_out[1] = bezt[out_a].vec[1][1] - bezt[out_a].vec[2][1];
747  float ext_out_range = sqrtf(cuma->ext_out[0] * cuma->ext_out[0] +
748  cuma->ext_out[1] * cuma->ext_out[1]);
749  cuma->ext_out[0] /= ext_out_range;
750  cuma->ext_out[1] /= ext_out_range;
751 
752  /* cleanup */
753  MEM_freeN(bezt);
754 
755  float range = CM_TABLEDIV * (cuma->maxtable - cuma->mintable);
756  cuma->range = 1.0f / range;
757 
758  /* now make a table with CM_TABLE equal x distances */
759  float *firstpoint = allpoints;
760  float *lastpoint = allpoints + 2 * (totpoint - 1);
761  point = allpoints;
762 
763  cmp = MEM_callocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "dist table");
764 
765  for (int a = 0; a <= CM_TABLE; a++) {
766  float cur_x = cuma->mintable + range * (float)a;
767  cmp[a].x = cur_x;
768 
769  /* Get the first point with x coordinate larger than cur_x. */
770  while (cur_x >= point[0] && point != lastpoint) {
771  point += 2;
772  }
773 
774  /* Check if we are on or outside the start or end point. */
775  if (point == firstpoint || (point == lastpoint && cur_x >= point[0])) {
776  if (compare_ff(cur_x, point[0], 1e-6f)) {
777  /* When on the point exactly, use the value directly to avoid precision
778  * issues with extrapolation of extreme slopes. */
779  cmp[a].y = point[1];
780  }
781  else {
782  /* Extrapolate values that lie outside the start and end point. */
783  cmp[a].y = curvemap_calc_extend(cumap, cuma, cur_x, firstpoint, lastpoint);
784  }
785  }
786  else {
787  float fac1 = point[0] - point[-2];
788  float fac2 = point[0] - cur_x;
789  if (fac1 > FLT_EPSILON) {
790  fac1 = fac2 / fac1;
791  }
792  else {
793  fac1 = 0.0f;
794  }
795  cmp[a].y = fac1 * point[-1] + (1.0f - fac1) * point[1];
796  }
797  }
798 
799  MEM_freeN(allpoints);
800  cuma->table = cmp;
801 }
802 
803 /* call when you do images etc, needs restore too. also verifies tables */
804 /* it uses a flag to prevent premul or free to happen twice */
806 {
807  int a;
808 
809  if (restore) {
810  if (cumap->flag & CUMA_PREMULLED) {
811  for (a = 0; a < 3; a++) {
812  MEM_freeN(cumap->cm[a].table);
813  cumap->cm[a].table = cumap->cm[a].premultable;
814  cumap->cm[a].premultable = NULL;
815 
816  copy_v2_v2(cumap->cm[a].ext_in, cumap->cm[a].premul_ext_in);
817  copy_v2_v2(cumap->cm[a].ext_out, cumap->cm[a].premul_ext_out);
818  zero_v2(cumap->cm[a].premul_ext_in);
819  zero_v2(cumap->cm[a].premul_ext_out);
820  }
821 
822  cumap->flag &= ~CUMA_PREMULLED;
823  }
824  }
825  else {
826  if ((cumap->flag & CUMA_PREMULLED) == 0) {
827  /* verify and copy */
828  for (a = 0; a < 3; a++) {
829  if (cumap->cm[a].table == NULL) {
830  curvemap_make_table(cumap, cumap->cm + a);
831  }
832  cumap->cm[a].premultable = cumap->cm[a].table;
833  cumap->cm[a].table = MEM_mallocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "premul table");
834  memcpy(
835  cumap->cm[a].table, cumap->cm[a].premultable, (CM_TABLE + 1) * sizeof(CurveMapPoint));
836  }
837 
838  if (cumap->cm[3].table == NULL) {
839  curvemap_make_table(cumap, cumap->cm + 3);
840  }
841 
842  /* premul */
843  for (a = 0; a < 3; a++) {
844  int b;
845  for (b = 0; b <= CM_TABLE; b++) {
846  cumap->cm[a].table[b].y = BKE_curvemap_evaluateF(
847  cumap, cumap->cm + 3, cumap->cm[a].table[b].y);
848  }
849 
850  copy_v2_v2(cumap->cm[a].premul_ext_in, cumap->cm[a].ext_in);
851  copy_v2_v2(cumap->cm[a].premul_ext_out, cumap->cm[a].ext_out);
852  mul_v2_v2(cumap->cm[a].ext_in, cumap->cm[3].ext_in);
853  mul_v2_v2(cumap->cm[a].ext_out, cumap->cm[3].ext_out);
854  }
855 
856  cumap->flag |= CUMA_PREMULLED;
857  }
858  }
859 }
860 
861 static int sort_curvepoints(const void *a1, const void *a2)
862 {
863  const struct CurveMapPoint *x1 = a1, *x2 = a2;
864 
865  if (x1->x > x2->x) {
866  return 1;
867  }
868  if (x1->x < x2->x) {
869  return -1;
870  }
871  return 0;
872 }
873 
874 /* ************************ more CurveMapping calls *************** */
875 
876 /* note; only does current curvemap! */
877 void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
878 {
879  CurveMap *cuma = cumap->cm + cumap->cur;
880  CurveMapPoint *cmp = cuma->curve;
881  rctf *clipr = &cumap->clipr;
882  float thresh = 0.01f * BLI_rctf_size_x(clipr);
883  float dx = 0.0f, dy = 0.0f;
884  int a;
885 
886  cumap->changed_timestamp++;
887 
888  /* clamp with clip */
889  if (cumap->flag & CUMA_DO_CLIP) {
890  for (a = 0; a < cuma->totpoint; a++) {
891  if (cmp[a].flag & CUMA_SELECT) {
892  if (cmp[a].x < clipr->xmin) {
893  dx = min_ff(dx, cmp[a].x - clipr->xmin);
894  }
895  else if (cmp[a].x > clipr->xmax) {
896  dx = max_ff(dx, cmp[a].x - clipr->xmax);
897  }
898  if (cmp[a].y < clipr->ymin) {
899  dy = min_ff(dy, cmp[a].y - clipr->ymin);
900  }
901  else if (cmp[a].y > clipr->ymax) {
902  dy = max_ff(dy, cmp[a].y - clipr->ymax);
903  }
904  }
905  }
906  for (a = 0; a < cuma->totpoint; a++) {
907  if (cmp[a].flag & CUMA_SELECT) {
908  cmp[a].x -= dx;
909  cmp[a].y -= dy;
910  }
911  }
912 
913  /* ensure zoom-level respects clipping */
914  if (BLI_rctf_size_x(&cumap->curr) > BLI_rctf_size_x(&cumap->clipr)) {
915  cumap->curr.xmin = cumap->clipr.xmin;
916  cumap->curr.xmax = cumap->clipr.xmax;
917  }
918  if (BLI_rctf_size_y(&cumap->curr) > BLI_rctf_size_y(&cumap->clipr)) {
919  cumap->curr.ymin = cumap->clipr.ymin;
920  cumap->curr.ymax = cumap->clipr.ymax;
921  }
922  }
923 
924  qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints);
925 
926  /* remove doubles, threshold set on 1% of default range */
927  if (rem_doubles && cuma->totpoint > 2) {
928  for (a = 0; a < cuma->totpoint - 1; a++) {
929  dx = cmp[a].x - cmp[a + 1].x;
930  dy = cmp[a].y - cmp[a + 1].y;
931  if (sqrtf(dx * dx + dy * dy) < thresh) {
932  if (a == 0) {
933  cmp[a + 1].flag |= CUMA_HANDLE_VECTOR;
934  if (cmp[a + 1].flag & CUMA_SELECT) {
935  cmp[a].flag |= CUMA_SELECT;
936  }
937  }
938  else {
939  cmp[a].flag |= CUMA_HANDLE_VECTOR;
940  if (cmp[a].flag & CUMA_SELECT) {
941  cmp[a + 1].flag |= CUMA_SELECT;
942  }
943  }
944  break; /* we assume 1 deletion per edit is ok */
945  }
946  }
947  if (a != cuma->totpoint - 1) {
948  BKE_curvemap_remove(cuma, 2);
949  }
950  }
951  curvemap_make_table(cumap, cuma);
952 }
953 
955 {
956  int a, cur = cumap->cur;
957 
958  for (a = 0; a < CM_TOT; a++) {
959  if (cumap->cm[a].curve) {
960  cumap->cur = a;
961  BKE_curvemapping_changed(cumap, false);
962  }
963  }
964 
965  cumap->cur = cur;
966 }
967 
968 /* Reset the view for current curve. */
970 {
971  cumap->curr = cumap->clipr;
972 }
973 
974 /* table should be verified */
975 float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value)
976 {
977  /* index in table */
978  float fi = (value - cuma->mintable) * cuma->range;
979  int i = (int)fi;
980 
981  /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */
982  if (fi < 0.0f || fi > CM_TABLE) {
983  return curvemap_calc_extend(cumap, cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x);
984  }
985 
986  if (i < 0) {
987  return cuma->table[0].y;
988  }
989  if (i >= CM_TABLE) {
990  return cuma->table[CM_TABLE].y;
991  }
992 
993  fi = fi - (float)i;
994  return (1.0f - fi) * cuma->table[i].y + (fi)*cuma->table[i + 1].y;
995 }
996 
997 /* works with curve 'cur' */
998 float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
999 {
1000  const CurveMap *cuma = cumap->cm + cur;
1001  float val = BKE_curvemap_evaluateF(cumap, cuma, value);
1002 
1003  /* account for clipping */
1004  if (cumap->flag & CUMA_DO_CLIP) {
1005  if (val < cumap->curr.ymin) {
1006  val = cumap->curr.ymin;
1007  }
1008  else if (val > cumap->curr.ymax) {
1009  val = cumap->curr.ymax;
1010  }
1011  }
1012 
1013  return val;
1014 }
1015 
1016 /* vector case */
1017 void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3])
1018 {
1019  vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], vecin[0]);
1020  vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], vecin[1]);
1021  vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], vecin[2]);
1022 }
1023 
1024 /* RGB case, no black/white points, no premult */
1026  float vecout[3],
1027  const float vecin[3])
1028 {
1029  vecout[0] = BKE_curvemap_evaluateF(
1030  cumap, &cumap->cm[0], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[0]));
1031  vecout[1] = BKE_curvemap_evaluateF(
1032  cumap, &cumap->cm[1], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[1]));
1033  vecout[2] = BKE_curvemap_evaluateF(
1034  cumap, &cumap->cm[2], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[2]));
1035 }
1036 
1038  float vecout[3],
1039  const float vecin[3],
1040  const int channel_offset[3])
1041 {
1042  const float v0in = vecin[channel_offset[0]];
1043  const float v1in = vecin[channel_offset[1]];
1044  const float v2in = vecin[channel_offset[2]];
1045 
1046  const float v0 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[0]], v0in);
1047  const float v2 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[2]], v2in);
1048  const float v1 = v2 + ((v0 - v2) * (v1in - v2in) / (v0in - v2in));
1049 
1050  vecout[channel_offset[0]] = v0;
1051  vecout[channel_offset[1]] = v1;
1052  vecout[channel_offset[2]] = v2;
1053 }
1054 
1066  float vecout[3],
1067  const float vecin[3],
1068  const float black[3],
1069  const float bwmul[3])
1070 {
1071  const float r = (vecin[0] - black[0]) * bwmul[0];
1072  const float g = (vecin[1] - black[1]) * bwmul[1];
1073  const float b = (vecin[2] - black[2]) * bwmul[2];
1074 
1075  switch (cumap->tone) {
1076  default:
1077  case CURVE_TONE_STANDARD: {
1078  vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r);
1079  vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g);
1080  vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], b);
1081  break;
1082  }
1083  case CURVE_TONE_FILMLIKE: {
1084  if (r >= g) {
1085  if (g > b) {
1086  /* Case 1: r >= g > b */
1087  const int shuffeled_channels[] = {0, 1, 2};
1088  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1089  }
1090  else if (b > r) {
1091  /* Case 2: b > r >= g */
1092  const int shuffeled_channels[] = {2, 0, 1};
1093  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1094  }
1095  else if (b > g) {
1096  /* Case 3: r >= b > g */
1097  const int shuffeled_channels[] = {0, 2, 1};
1098  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1099  }
1100  else {
1101  /* Case 4: r >= g == b */
1102  copy_v2_fl2(vecout,
1103  BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r),
1104  BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g));
1105  vecout[2] = vecout[1];
1106  }
1107  }
1108  else {
1109  if (r >= b) {
1110  /* Case 5: g > r >= b */
1111  const int shuffeled_channels[] = {1, 0, 2};
1112  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1113  }
1114  else if (b > g) {
1115  /* Case 6: b > g > r */
1116  const int shuffeled_channels[] = {2, 1, 0};
1117  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1118  }
1119  else {
1120  /* Case 7: g >= b > r */
1121  const int shuffeled_channels[] = {1, 2, 0};
1122  curvemapping_evaluateRGBF_filmlike(cumap, vecout, vecin, shuffeled_channels);
1123  }
1124  }
1125  break;
1126  }
1127  }
1128 }
1129 
1130 /* RGB with black/white points and premult. tables are checked */
1132  float vecout[3],
1133  const float vecin[3])
1134 {
1135  BKE_curvemapping_evaluate_premulRGBF_ex(cumap, vecout, vecin, cumap->black, cumap->bwmul);
1136 }
1137 
1138 /* same as above, byte version */
1140  unsigned char vecout_byte[3],
1141  const unsigned char vecin_byte[3])
1142 {
1143  float vecin[3], vecout[3];
1144 
1145  vecin[0] = (float)vecin_byte[0] / 255.0f;
1146  vecin[1] = (float)vecin_byte[1] / 255.0f;
1147  vecin[2] = (float)vecin_byte[2] / 255.0f;
1148 
1149  BKE_curvemapping_evaluate_premulRGBF(cumap, vecout, vecin);
1150 
1151  vecout_byte[0] = unit_float_to_uchar_clamp(vecout[0]);
1152  vecout_byte[1] = unit_float_to_uchar_clamp(vecout[1]);
1153  vecout_byte[2] = unit_float_to_uchar_clamp(vecout[2]);
1154 }
1155 
1157 {
1158  if (cumap->black[0] != 0.0f) {
1159  return true;
1160  }
1161  if (cumap->black[1] != 0.0f) {
1162  return true;
1163  }
1164  if (cumap->black[2] != 0.0f) {
1165  return true;
1166  }
1167  if (cumap->white[0] != 1.0f) {
1168  return true;
1169  }
1170  if (cumap->white[1] != 1.0f) {
1171  return true;
1172  }
1173  if (cumap->white[2] != 1.0f) {
1174  return true;
1175  }
1176 
1177  for (int a = 0; a < CM_TOT; a++) {
1178  if (cumap->cm[a].curve) {
1179  if (cumap->cm[a].totpoint != 2) {
1180  return true;
1181  }
1182 
1183  if (cumap->cm[a].curve[0].x != 0.0f) {
1184  return true;
1185  }
1186  if (cumap->cm[a].curve[0].y != 0.0f) {
1187  return true;
1188  }
1189  if (cumap->cm[a].curve[1].x != 1.0f) {
1190  return true;
1191  }
1192  if (cumap->cm[a].curve[1].y != 1.0f) {
1193  return true;
1194  }
1195  }
1196  }
1197  return false;
1198 }
1199 
1201 {
1202  int a;
1203 
1204  if (cumap == NULL) {
1205  return;
1206  }
1207 
1208  for (a = 0; a < CM_TOT; a++) {
1209  if (cumap->cm[a].table == NULL) {
1210  curvemap_make_table(cumap, cumap->cm + a);
1211  }
1212  }
1213 }
1214 
1215 void BKE_curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size)
1216 {
1217  int a;
1218 
1219  *size = CM_TABLE + 1;
1220  *array = MEM_callocN(sizeof(float) * (*size) * 4, "CurveMapping");
1221 
1222  for (a = 0; a < *size; a++) {
1223  if (cumap->cm[0].table) {
1224  (*array)[a * 4 + 0] = cumap->cm[0].table[a].y;
1225  }
1226  if (cumap->cm[1].table) {
1227  (*array)[a * 4 + 1] = cumap->cm[1].table[a].y;
1228  }
1229  if (cumap->cm[2].table) {
1230  (*array)[a * 4 + 2] = cumap->cm[2].table[a].y;
1231  }
1232  if (cumap->cm[3].table) {
1233  (*array)[a * 4 + 3] = cumap->cm[3].table[a].y;
1234  }
1235  }
1236 }
1237 
1239 {
1240  BLO_write_struct(writer, CurveMapping, cumap);
1241  BKE_curvemapping_curves_blend_write(writer, cumap);
1242 }
1243 
1245 {
1246  for (int a = 0; a < CM_TOT; a++) {
1247  BLO_write_struct_array(writer, CurveMapPoint, cumap->cm[a].totpoint, cumap->cm[a].curve);
1248  }
1249 }
1250 
1251 /* cumap itself has been read already. */
1253 {
1254  /* flag seems to be able to hang? Maybe old files... not bad to clear anyway */
1255  cumap->flag &= ~CUMA_PREMULLED;
1256 
1257  for (int a = 0; a < CM_TOT; a++) {
1258  BLO_read_data_address(reader, &cumap->cm[a].curve);
1259  cumap->cm[a].table = NULL;
1260  cumap->cm[a].premultable = NULL;
1261  }
1262 }
1263 
1264 /* ***************** Histogram **************** */
1265 
1266 #define INV_255 (1.0f / 255.0f)
1267 
1269 {
1270  int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */
1271 
1272  /* note: clamp integer instead of float to avoid problems with NaN */
1273  CLAMP(bin, 0, 255);
1274 
1275  return bin;
1276 }
1277 
1278 static void save_sample_line(
1279  Scopes *scopes, const int idx, const float fx, const float rgb[3], const float ycc[3])
1280 {
1281  float yuv[3];
1282 
1283  /* vectorscope*/
1284  rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv[0], &yuv[1], &yuv[2], BLI_YUV_ITU_BT709);
1285  scopes->vecscope[idx + 0] = yuv[1];
1286  scopes->vecscope[idx + 1] = yuv[2];
1287 
1288  /* waveform */
1289  switch (scopes->wavefrm_mode) {
1290  case SCOPES_WAVEFRM_RGB:
1292  scopes->waveform_1[idx + 0] = fx;
1293  scopes->waveform_1[idx + 1] = rgb[0];
1294  scopes->waveform_2[idx + 0] = fx;
1295  scopes->waveform_2[idx + 1] = rgb[1];
1296  scopes->waveform_3[idx + 0] = fx;
1297  scopes->waveform_3[idx + 1] = rgb[2];
1298  break;
1299  case SCOPES_WAVEFRM_LUMA:
1300  scopes->waveform_1[idx + 0] = fx;
1301  scopes->waveform_1[idx + 1] = ycc[0];
1302  break;
1306  scopes->waveform_1[idx + 0] = fx;
1307  scopes->waveform_1[idx + 1] = ycc[0];
1308  scopes->waveform_2[idx + 0] = fx;
1309  scopes->waveform_2[idx + 1] = ycc[1];
1310  scopes->waveform_3[idx + 0] = fx;
1311  scopes->waveform_3[idx + 1] = ycc[2];
1312  break;
1313  }
1314 }
1315 
1317  ImBuf *ibuf,
1318  const ColorManagedViewSettings *view_settings,
1319  const ColorManagedDisplaySettings *display_settings)
1320 {
1321  int i, x, y;
1322  const float *fp;
1323  unsigned char *cp;
1324 
1325  int x1 = roundf(hist->co[0][0] * ibuf->x);
1326  int x2 = roundf(hist->co[1][0] * ibuf->x);
1327  int y1 = roundf(hist->co[0][1] * ibuf->y);
1328  int y2 = roundf(hist->co[1][1] * ibuf->y);
1329 
1330  struct ColormanageProcessor *cm_processor = NULL;
1331 
1332  hist->channels = 3;
1333  hist->x_resolution = 256;
1334  hist->xmax = 1.0f;
1335  /* hist->ymax = 1.0f; */ /* now do this on the operator _only_ */
1336 
1337  if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
1338  return;
1339  }
1340 
1341  if (ibuf->rect_float) {
1342  cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
1343  }
1344 
1345  for (i = 0; i < 256; i++) {
1346  x = (int)(0.5f + x1 + (float)i * (x2 - x1) / 255.0f);
1347  y = (int)(0.5f + y1 + (float)i * (y2 - y1) / 255.0f);
1348 
1349  if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) {
1350  hist->data_luma[i] = hist->data_r[i] = hist->data_g[i] = hist->data_b[i] = hist->data_a[i] =
1351  0.0f;
1352  }
1353  else {
1354  if (ibuf->rect_float) {
1355  float rgba[4];
1356  fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x));
1357 
1358  switch (ibuf->channels) {
1359  case 4:
1360  copy_v4_v4(rgba, fp);
1361  IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
1362  break;
1363  case 3:
1364  copy_v3_v3(rgba, fp);
1365  IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
1366  rgba[3] = 1.0f;
1367  break;
1368  case 2:
1369  copy_v3_fl(rgba, fp[0]);
1370  rgba[3] = fp[1];
1371  break;
1372  case 1:
1373  copy_v3_fl(rgba, fp[0]);
1374  rgba[3] = 1.0f;
1375  break;
1376  default:
1378  }
1379 
1381  hist->data_r[i] = rgba[0];
1382  hist->data_g[i] = rgba[1];
1383  hist->data_b[i] = rgba[2];
1384  hist->data_a[i] = rgba[3];
1385  }
1386  else if (ibuf->rect) {
1387  cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x);
1388  hist->data_luma[i] = (float)IMB_colormanagement_get_luminance_byte(cp) / 255.0f;
1389  hist->data_r[i] = (float)cp[0] / 255.0f;
1390  hist->data_g[i] = (float)cp[1] / 255.0f;
1391  hist->data_b[i] = (float)cp[2] / 255.0f;
1392  hist->data_a[i] = (float)cp[3] / 255.0f;
1393  }
1394  }
1395  }
1396 
1397  if (cm_processor) {
1398  IMB_colormanagement_processor_free(cm_processor);
1399  }
1400 }
1401 
1402 /* if view_settings, it also applies this to byte buffers */
1403 typedef struct ScopesUpdateData {
1405  const ImBuf *ibuf;
1407  const unsigned char *display_buffer;
1408  const int ycc_mode;
1410 
1411 typedef struct ScopesUpdateDataChunk {
1412  unsigned int bin_lum[256];
1413  unsigned int bin_r[256];
1414  unsigned int bin_g[256];
1415  unsigned int bin_b[256];
1416  unsigned int bin_a[256];
1417  float min[3], max[3];
1419 
1420 static void scopes_update_cb(void *__restrict userdata,
1421  const int y,
1422  const TaskParallelTLS *__restrict tls)
1423 {
1424  const ScopesUpdateData *data = userdata;
1425 
1426  Scopes *scopes = data->scopes;
1427  const ImBuf *ibuf = data->ibuf;
1428  struct ColormanageProcessor *cm_processor = data->cm_processor;
1429  const unsigned char *display_buffer = data->display_buffer;
1430  const int ycc_mode = data->ycc_mode;
1431 
1432  ScopesUpdateDataChunk *data_chunk = tls->userdata_chunk;
1433  unsigned int *bin_lum = data_chunk->bin_lum;
1434  unsigned int *bin_r = data_chunk->bin_r;
1435  unsigned int *bin_g = data_chunk->bin_g;
1436  unsigned int *bin_b = data_chunk->bin_b;
1437  unsigned int *bin_a = data_chunk->bin_a;
1438  float *min = data_chunk->min;
1439  float *max = data_chunk->max;
1440 
1441  const float *rf = NULL;
1442  const unsigned char *rc = NULL;
1443  const int rows_per_sample_line = ibuf->y / scopes->sample_lines;
1444  const int savedlines = y / rows_per_sample_line;
1445  const bool do_sample_line = (savedlines < scopes->sample_lines) &&
1446  (y % rows_per_sample_line) == 0;
1447  const bool is_float = (ibuf->rect_float != NULL);
1448 
1449  if (is_float) {
1450  rf = ibuf->rect_float + ((size_t)y) * ibuf->x * ibuf->channels;
1451  }
1452  else {
1453  rc = display_buffer + ((size_t)y) * ibuf->x * ibuf->channels;
1454  }
1455 
1456  for (int x = 0; x < ibuf->x; x++) {
1457  float rgba[4], ycc[3], luma;
1458 
1459  if (is_float) {
1460  switch (ibuf->channels) {
1461  case 4:
1462  copy_v4_v4(rgba, rf);
1463  IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
1464  break;
1465  case 3:
1466  copy_v3_v3(rgba, rf);
1467  IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
1468  rgba[3] = 1.0f;
1469  break;
1470  case 2:
1471  copy_v3_fl(rgba, rf[0]);
1472  rgba[3] = rf[1];
1473  break;
1474  case 1:
1475  copy_v3_fl(rgba, rf[0]);
1476  rgba[3] = 1.0f;
1477  break;
1478  default:
1480  }
1481  }
1482  else {
1483  for (int c = 4; c--;) {
1484  rgba[c] = rc[c] * INV_255;
1485  }
1486  }
1487 
1488  /* we still need luma for histogram */
1489  luma = IMB_colormanagement_get_luminance(rgba);
1490 
1491  /* check for min max */
1492  if (ycc_mode == -1) {
1493  minmax_v3v3_v3(min, max, rgba);
1494  }
1495  else {
1496  rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode);
1497  mul_v3_fl(ycc, INV_255);
1498  minmax_v3v3_v3(min, max, ycc);
1499  }
1500  /* increment count for histo*/
1501  bin_lum[get_bin_float(luma)]++;
1502  bin_r[get_bin_float(rgba[0])]++;
1503  bin_g[get_bin_float(rgba[1])]++;
1504  bin_b[get_bin_float(rgba[2])]++;
1505  bin_a[get_bin_float(rgba[3])]++;
1506 
1507  /* save sample if needed */
1508  if (do_sample_line) {
1509  const float fx = (float)x / (float)ibuf->x;
1510  const int idx = 2 * (ibuf->x * savedlines + x);
1511  save_sample_line(scopes, idx, fx, rgba, ycc);
1512  }
1513 
1514  rf += ibuf->channels;
1515  rc += ibuf->channels;
1516  }
1517 }
1518 
1519 static void scopes_update_reduce(const void *__restrict UNUSED(userdata),
1520  void *__restrict chunk_join,
1521  void *__restrict chunk)
1522 {
1523  ScopesUpdateDataChunk *join_chunk = chunk_join;
1524  const ScopesUpdateDataChunk *data_chunk = chunk;
1525 
1526  unsigned int *bin_lum = join_chunk->bin_lum;
1527  unsigned int *bin_r = join_chunk->bin_r;
1528  unsigned int *bin_g = join_chunk->bin_g;
1529  unsigned int *bin_b = join_chunk->bin_b;
1530  unsigned int *bin_a = join_chunk->bin_a;
1531  const unsigned int *bin_lum_c = data_chunk->bin_lum;
1532  const unsigned int *bin_r_c = data_chunk->bin_r;
1533  const unsigned int *bin_g_c = data_chunk->bin_g;
1534  const unsigned int *bin_b_c = data_chunk->bin_b;
1535  const unsigned int *bin_a_c = data_chunk->bin_a;
1536 
1537  const float *min = data_chunk->min;
1538  const float *max = data_chunk->max;
1539 
1540  for (int b = 256; b--;) {
1541  bin_lum[b] += bin_lum_c[b];
1542  bin_r[b] += bin_r_c[b];
1543  bin_g[b] += bin_g_c[b];
1544  bin_b[b] += bin_b_c[b];
1545  bin_a[b] += bin_a_c[b];
1546  }
1547 
1548  for (int c = 3; c--;) {
1549  if (min[c] < join_chunk->min[c]) {
1550  join_chunk->min[c] = min[c];
1551  }
1552  if (max[c] > join_chunk->max[c]) {
1553  join_chunk->max[c] = max[c];
1554  }
1555  }
1556 }
1557 
1559  ImBuf *ibuf,
1560  const ColorManagedViewSettings *view_settings,
1561  const ColorManagedDisplaySettings *display_settings)
1562 {
1563  int a;
1564  unsigned int nl, na, nr, ng, nb;
1565  double divl, diva, divr, divg, divb;
1566  const unsigned char *display_buffer = NULL;
1567  int ycc_mode = -1;
1568  void *cache_handle = NULL;
1569  struct ColormanageProcessor *cm_processor = NULL;
1570 
1571  if (ibuf->rect == NULL && ibuf->rect_float == NULL) {
1572  return;
1573  }
1574 
1575  if (scopes->ok == 1) {
1576  return;
1577  }
1578 
1579  if (scopes->hist.ymax == 0.0f) {
1580  scopes->hist.ymax = 1.0f;
1581  }
1582 
1583  /* hmmmm */
1584  if (!(ELEM(ibuf->channels, 3, 4))) {
1585  return;
1586  }
1587 
1588  scopes->hist.channels = 3;
1589  scopes->hist.x_resolution = 256;
1590 
1591  switch (scopes->wavefrm_mode) {
1592  case SCOPES_WAVEFRM_RGB:
1593  /* fall-through */
1595  ycc_mode = -1;
1596  break;
1597  case SCOPES_WAVEFRM_LUMA:
1599  ycc_mode = BLI_YCC_JFIF_0_255;
1600  break;
1602  ycc_mode = BLI_YCC_ITU_BT601;
1603  break;
1605  ycc_mode = BLI_YCC_ITU_BT709;
1606  break;
1607  }
1608 
1609  /* convert to number of lines with logarithmic scale */
1610  scopes->sample_lines = (scopes->accuracy * 0.01f) * (scopes->accuracy * 0.01f) * ibuf->y;
1611  CLAMP_MIN(scopes->sample_lines, 1);
1612 
1613  if (scopes->sample_full) {
1614  scopes->sample_lines = ibuf->y;
1615  }
1616 
1617  /* scan the image */
1618  for (a = 0; a < 3; a++) {
1619  scopes->minmax[a][0] = 25500.0f;
1620  scopes->minmax[a][1] = -25500.0f;
1621  }
1622 
1623  scopes->waveform_tot = ibuf->x * scopes->sample_lines;
1624 
1625  if (scopes->waveform_1) {
1626  MEM_freeN(scopes->waveform_1);
1627  }
1628  if (scopes->waveform_2) {
1629  MEM_freeN(scopes->waveform_2);
1630  }
1631  if (scopes->waveform_3) {
1632  MEM_freeN(scopes->waveform_3);
1633  }
1634  if (scopes->vecscope) {
1635  MEM_freeN(scopes->vecscope);
1636  }
1637 
1638  scopes->waveform_1 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float),
1639  "waveform point channel 1");
1640  scopes->waveform_2 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float),
1641  "waveform point channel 2");
1642  scopes->waveform_3 = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float),
1643  "waveform point channel 3");
1644  scopes->vecscope = MEM_callocN(scopes->waveform_tot * 2 * sizeof(float),
1645  "vectorscope point channel");
1646 
1647  if (ibuf->rect_float) {
1648  cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
1649  }
1650  else {
1651  display_buffer = (const unsigned char *)IMB_display_buffer_acquire(
1652  ibuf, view_settings, display_settings, &cache_handle);
1653  }
1654 
1655  /* Keep number of threads in sync with the merge parts below. */
1657  .scopes = scopes,
1658  .ibuf = ibuf,
1659  .cm_processor = cm_processor,
1660  .display_buffer = display_buffer,
1661  .ycc_mode = ycc_mode,
1662  };
1663  ScopesUpdateDataChunk data_chunk = {{0}};
1664  INIT_MINMAX(data_chunk.min, data_chunk.max);
1665 
1666  TaskParallelSettings settings;
1668  settings.use_threading = (ibuf->y > 256);
1669  settings.userdata_chunk = &data_chunk;
1670  settings.userdata_chunk_size = sizeof(data_chunk);
1671  settings.func_reduce = scopes_update_reduce;
1672  BLI_task_parallel_range(0, ibuf->y, &data, scopes_update_cb, &settings);
1673 
1674  /* convert hist data to float (proportional to max count) */
1675  nl = na = nr = nb = ng = 0;
1676  for (a = 0; a < 256; a++) {
1677  if (data_chunk.bin_lum[a] > nl) {
1678  nl = data_chunk.bin_lum[a];
1679  }
1680  if (data_chunk.bin_r[a] > nr) {
1681  nr = data_chunk.bin_r[a];
1682  }
1683  if (data_chunk.bin_g[a] > ng) {
1684  ng = data_chunk.bin_g[a];
1685  }
1686  if (data_chunk.bin_b[a] > nb) {
1687  nb = data_chunk.bin_b[a];
1688  }
1689  if (data_chunk.bin_a[a] > na) {
1690  na = data_chunk.bin_a[a];
1691  }
1692  }
1693  divl = nl ? 1.0 / (double)nl : 1.0;
1694  diva = na ? 1.0 / (double)na : 1.0;
1695  divr = nr ? 1.0 / (double)nr : 1.0;
1696  divg = ng ? 1.0 / (double)ng : 1.0;
1697  divb = nb ? 1.0 / (double)nb : 1.0;
1698 
1699  for (a = 0; a < 256; a++) {
1700  scopes->hist.data_luma[a] = data_chunk.bin_lum[a] * divl;
1701  scopes->hist.data_r[a] = data_chunk.bin_r[a] * divr;
1702  scopes->hist.data_g[a] = data_chunk.bin_g[a] * divg;
1703  scopes->hist.data_b[a] = data_chunk.bin_b[a] * divb;
1704  scopes->hist.data_a[a] = data_chunk.bin_a[a] * diva;
1705  }
1706 
1707  if (cm_processor) {
1708  IMB_colormanagement_processor_free(cm_processor);
1709  }
1710  if (cache_handle) {
1711  IMB_display_buffer_release(cache_handle);
1712  }
1713 
1714  scopes->ok = 1;
1715 }
1716 
1718 {
1719  if (scopes->waveform_1) {
1720  MEM_freeN(scopes->waveform_1);
1721  scopes->waveform_1 = NULL;
1722  }
1723  if (scopes->waveform_2) {
1724  MEM_freeN(scopes->waveform_2);
1725  scopes->waveform_2 = NULL;
1726  }
1727  if (scopes->waveform_3) {
1728  MEM_freeN(scopes->waveform_3);
1729  scopes->waveform_3 = NULL;
1730  }
1731  if (scopes->vecscope) {
1732  MEM_freeN(scopes->vecscope);
1733  scopes->vecscope = NULL;
1734  }
1735 }
1736 
1737 void BKE_scopes_new(Scopes *scopes)
1738 {
1739  scopes->accuracy = 30.0;
1740  scopes->hist.mode = HISTO_MODE_RGB;
1741  scopes->wavefrm_alpha = 0.3;
1742  scopes->vecscope_alpha = 0.3;
1743  scopes->wavefrm_height = 100;
1744  scopes->vecscope_height = 100;
1745  scopes->hist.height = 100;
1746  scopes->ok = 0;
1747  scopes->waveform_1 = NULL;
1748  scopes->waveform_2 = NULL;
1749  scopes->waveform_3 = NULL;
1750  scopes->vecscope = NULL;
1751 }
1752 
1754 {
1755  const char *display_name = IMB_colormanagement_display_get_default_name();
1756 
1757  BLI_strncpy(settings->display_device, display_name, sizeof(settings->display_device));
1758 }
1759 
1761  const ColorManagedDisplaySettings *settings)
1762 {
1763  BLI_strncpy(new_settings->display_device,
1764  settings->display_device,
1765  sizeof(new_settings->display_device));
1766 }
1767 
1769  ColorManagedViewSettings *view_settings,
1770  const ColorManagedDisplaySettings *display_settings,
1771  const char *view_transform)
1772 {
1774  display_settings->display_device);
1775 
1776  if (!view_transform) {
1778  }
1779 
1780  /* TODO(sergey): Find a way to make look query more reliable with non
1781  * default configuration. */
1782  STRNCPY(view_settings->view_transform, view_transform);
1783  STRNCPY(view_settings->look, "None");
1784 
1785  view_settings->flag = 0;
1786  view_settings->gamma = 1.0f;
1787  view_settings->exposure = 0.0f;
1788  view_settings->curve_mapping = NULL;
1789 
1790  IMB_colormanagement_validate_settings(display_settings, view_settings);
1791 }
1792 
1794  struct ColorManagedViewSettings *view_settings,
1795  const struct ColorManagedDisplaySettings *display_settings)
1796 {
1797  IMB_colormanagement_init_default_view_settings(view_settings, display_settings);
1798 }
1799 
1801  const ColorManagedViewSettings *settings)
1802 {
1803  BLI_strncpy(new_settings->look, settings->look, sizeof(new_settings->look));
1804  BLI_strncpy(new_settings->view_transform,
1805  settings->view_transform,
1806  sizeof(new_settings->view_transform));
1807 
1808  new_settings->flag = settings->flag;
1809  new_settings->exposure = settings->exposure;
1810  new_settings->gamma = settings->gamma;
1811 
1812  if (settings->curve_mapping) {
1813  new_settings->curve_mapping = BKE_curvemapping_copy(settings->curve_mapping);
1814  }
1815  else {
1816  new_settings->curve_mapping = NULL;
1817  }
1818 }
1819 
1821 {
1822  if (settings->curve_mapping) {
1824  settings->curve_mapping = NULL;
1825  }
1826 }
1827 
1829  ColorManagedViewSettings *settings)
1830 {
1831  if (settings->curve_mapping) {
1832  BKE_curvemapping_blend_write(writer, settings->curve_mapping);
1833  }
1834 }
1835 
1837  ColorManagedViewSettings *settings)
1838 {
1839  BLO_read_data_address(reader, &settings->curve_mapping);
1840 
1841  if (settings->curve_mapping) {
1842  BKE_curvemapping_blend_read(reader, settings->curve_mapping);
1843  }
1844 }
1845 
1847  ColorManagedColorspaceSettings *colorspace_settings)
1848 {
1849  BLI_strncpy(colorspace_settings->name, "", sizeof(colorspace_settings->name));
1850 }
1851 
1853  ColorManagedColorspaceSettings *colorspace_settings,
1854  const ColorManagedColorspaceSettings *settings)
1855 {
1856  BLI_strncpy(colorspace_settings->name, settings->name, sizeof(colorspace_settings->name));
1857 }
1858 
1860  const ColorManagedColorspaceSettings *settings2)
1861 {
1862  return STREQ(settings1->name, settings2->name);
1863 }
typedef float(TangentPoint)[2]
@ CURVEMAP_SLOPE_POS_NEG
@ CURVEMAP_SLOPE_POSITIVE
void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
Definition: curve.c:5559
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.c:1804
#define BLI_assert_unreachable()
Definition: BLI_assert.h:96
#define BLI_INLINE
MINLINE float max_ff(float a, float b)
MINLINE int compare_ff(float a, float b, const float max_diff)
MINLINE float min_ff(float a, float b)
#define BLI_YUV_ITU_BT709
#define BLI_YCC_JFIF_0_255
#define BLI_YCC_ITU_BT601
void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, int colorspace)
Definition: math_color.c:130
void rgb_to_yuv(float r, float g, float b, float *r_y, float *r_u, float *r_v, int colorspace)
Definition: math_color.c:79
#define BLI_YCC_ITU_BT709
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE void copy_v2_fl2(float v[2], float x, float y)
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void mul_v2_v2(float r[2], const float a[2])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void zero_v2(float r[2])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:436
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:161
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#define INIT_MINMAX(min, max)
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
typedef double(DMatrix)[4][4]
#define CM_TOT
@ CUMA_PREMULLED
@ CUMA_EXTEND_EXTRAPOLATE
@ CUMA_DO_CLIP
#define SCOPES_WAVEFRM_RGB_PARADE
#define SCOPES_WAVEFRM_YCC_JPEG
@ CUMA_HANDLE_AUTO_ANIM
@ CUMA_SELECT
@ CUMA_HANDLE_VECTOR
@ HISTO_MODE_RGB
#define SCOPES_WAVEFRM_RGB
#define CM_TABLEDIV
#define SCOPES_WAVEFRM_YCC_601
#define SCOPES_WAVEFRM_YCC_709
#define SCOPES_WAVEFRM_LUMA
@ CURVE_TONE_STANDARD
@ CURVE_TONE_FILMLIKE
#define CM_RESOL
#define CM_TABLE
@ CURVE_PRESET_ROOT
@ CURVE_PRESET_GAUSS
@ CURVE_PRESET_SMOOTH
@ CURVE_PRESET_ROUND
@ CURVE_PRESET_LINE
@ CURVE_PRESET_SHARP
@ CURVE_PRESET_MID9
@ CURVE_PRESET_BELL
@ CURVE_PRESET_MAX
@ HD_AUTO_ANIM
@ HD_VECT
@ HD_AUTO
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3])
BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3])
void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor)
void IMB_colormanagement_validate_settings(const struct ColorManagedDisplaySettings *display_settings, struct ColorManagedViewSettings *view_settings)
void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor, float pixel[4])
void IMB_display_buffer_release(void *cache_handle)
struct ColormanageProcessor * IMB_colormanagement_display_processor_new(const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings)
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
void IMB_colormanagement_init_default_view_settings(struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings)
unsigned char * IMB_display_buffer_acquire(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, void **cache_handle)
const char * IMB_colormanagement_display_get_default_name(void)
struct ColorManagedDisplay * IMB_colormanagement_display_get_named(const char *name)
const char * IMB_colormanagement_display_get_default_view_transform_name(struct ColorManagedDisplay *display)
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
ATTR_WARN_UNUSED_RESULT const BMVert * v2
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
struct ScopesUpdateData ScopesUpdateData
void BKE_curvemapping_evaluate_premulRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3])
Definition: colortools.c:1131
void BKE_color_managed_colorspace_settings_init(ColorManagedColorspaceSettings *colorspace_settings)
Definition: colortools.c:1846
static int sort_curvepoints(const void *a1, const void *a2)
Definition: colortools.c:861
struct ScopesUpdateDataChunk ScopesUpdateDataChunk
static void calchandle_curvemap(BezTriple *bezt, const BezTriple *prev, const BezTriple *next)
Definition: colortools.c:470
static void scopes_update_cb(void *__restrict userdata, const int y, const TaskParallelTLS *__restrict tls)
Definition: colortools.c:1420
CurveMapPoint * BKE_curvemap_insert(CurveMap *cuma, float x, float y)
Definition: colortools.c:240
static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma)
Definition: colortools.c:627
void BKE_curvemapping_free_data(CurveMapping *cumap)
Definition: colortools.c:99
void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, float vecout[3], const float vecin[3], const float black[3], const float bwmul[3])
Definition: colortools.c:1065
void BKE_curvemapping_set_black_white(CurveMapping *cumap, const float black[3], const float white[3])
Definition: colortools.c:168
#define INV_255
Definition: colortools.c:1266
void BKE_color_managed_view_settings_init_default(struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings)
Definition: colortools.c:1793
void BKE_color_managed_view_settings_blend_read_data(BlendDataReader *reader, ColorManagedViewSettings *settings)
Definition: colortools.c:1836
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
Definition: colortools.c:998
void BKE_curvemapping_changed_all(CurveMapping *cumap)
Definition: colortools.c:954
void BKE_curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
Definition: colortools.c:53
void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping *cumap)
Definition: colortools.c:1244
CurveMapping * BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
Definition: colortools.c:88
bool BKE_curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point)
Definition: colortools.c:187
void BKE_curvemapping_blend_read(BlendDataReader *reader, CurveMapping *cumap)
Definition: colortools.c:1252
static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap, float vecout[3], const float vecin[3], const int channel_offset[3])
Definition: colortools.c:1037
static float curvemap_calc_extend(const CurveMapping *cumap, const CurveMap *cuma, float x, const float first[2], const float last[2])
Definition: colortools.c:593
void BKE_curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3])
Definition: colortools.c:1025
void BKE_color_managed_display_settings_copy(ColorManagedDisplaySettings *new_settings, const ColorManagedDisplaySettings *settings)
Definition: colortools.c:1760
void BKE_curvemapping_evaluate_premulRGB(const CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3])
Definition: colortools.c:1139
void BKE_color_managed_display_settings_init(ColorManagedDisplaySettings *settings)
Definition: colortools.c:1753
void BKE_curvemapping_set_black_white_ex(const float black[3], const float white[3], float r_bwmul[3])
Definition: colortools.c:156
BLI_INLINE int get_bin_float(float f)
Definition: colortools.c:1268
void BKE_color_managed_view_settings_free(ColorManagedViewSettings *settings)
Definition: colortools.c:1820
void BKE_curvemapping_reset_view(CurveMapping *cumap)
Definition: colortools.c:969
void BKE_curvemap_remove(CurveMap *cuma, const short flag)
Definition: colortools.c:217
void BKE_scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
Definition: colortools.c:1558
void BKE_curvemapping_init(CurveMapping *cumap)
Definition: colortools.c:1200
void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
Definition: colortools.c:1316
void BKE_color_managed_view_settings_copy(ColorManagedViewSettings *new_settings, const ColorManagedViewSettings *settings)
Definition: colortools.c:1800
#define p2_h1
void BKE_color_managed_view_settings_init_render(ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const char *view_transform)
Definition: colortools.c:1768
void BKE_color_managed_view_settings_blend_write(BlendWriter *writer, ColorManagedViewSettings *settings)
Definition: colortools.c:1828
static void save_sample_line(Scopes *scopes, const int idx, const float fx, const float rgb[3], const float ycc[3])
Definition: colortools.c:1278
void BKE_curvemap_reset(CurveMap *cuma, const rctf *clipr, int preset, int slope)
Definition: colortools.c:274
void BKE_curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size)
Definition: colortools.c:1215
void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore)
Definition: colortools.c:805
void BKE_curvemapping_free(CurveMapping *cumap)
Definition: colortools.c:119
void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap)
Definition: colortools.c:1238
CurveMapping * BKE_curvemapping_copy(const CurveMapping *cumap)
Definition: colortools.c:146
static void scopes_update_reduce(const void *__restrict UNUSED(userdata), void *__restrict chunk_join, void *__restrict chunk)
Definition: colortools.c:1519
void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3])
Definition: colortools.c:1017
#define p2_h2
void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
Definition: colortools.c:877
void BKE_curvemap_handle_set(CurveMap *cuma, int type)
Definition: colortools.c:445
float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value)
Definition: colortools.c:975
void BKE_scopes_new(Scopes *scopes)
Definition: colortools.c:1737
void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
Definition: colortools.c:127
void BKE_scopes_free(Scopes *scopes)
Definition: colortools.c:1717
void BKE_color_managed_colorspace_settings_copy(ColorManagedColorspaceSettings *colorspace_settings, const ColorManagedColorspaceSettings *settings)
Definition: colortools.c:1852
bool BKE_color_managed_colorspace_settings_equals(const ColorManagedColorspaceSettings *settings1, const ColorManagedColorspaceSettings *settings2)
Definition: colortools.c:1859
bool BKE_curvemapping_RGBA_does_something(const CurveMapping *cumap)
Definition: colortools.c:1156
Curve curve
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
static ulong * next
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
#define min(a, b)
Definition: sort.c:51
float vec[3][3]
struct CurveMapping * curve_mapping
CurveMapPoint * table
float maxtable
short totpoint
CurveMapPoint * curve
CurveMapPoint * premultable
float mintable
float ext_out[2]
float ext_in[2]
float premul_ext_out[2]
float premul_ext_in[2]
float bwmul[3]
float white[3]
CurveMap cm[4]
float black[3]
float data_a[256]
float data_luma[256]
float data_r[256]
float co[2][2]
float data_b[256]
float data_g[256]
int channels
unsigned int * rect
float * rect_float
unsigned int bin_g[256]
Definition: colortools.c:1414
unsigned int bin_a[256]
Definition: colortools.c:1416
unsigned int bin_r[256]
Definition: colortools.c:1413
unsigned int bin_b[256]
Definition: colortools.c:1415
unsigned int bin_lum[256]
Definition: colortools.c:1412
const ImBuf * ibuf
Definition: colortools.c:1405
const int ycc_mode
Definition: colortools.c:1408
struct ColormanageProcessor * cm_processor
Definition: colortools.c:1406
const unsigned char * display_buffer
Definition: colortools.c:1407
int waveform_tot
int wavefrm_height
int wavefrm_mode
float * waveform_3
float * waveform_2
int sample_full
int vecscope_height
float wavefrm_alpha
float minmax[3][2]
float vecscope_alpha
float * waveform_1
int sample_lines
float * vecscope
float accuracy
struct Histogram hist
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:158
size_t userdata_chunk_size
Definition: BLI_task.h:150
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
float max
uint len