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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_heap.h"
27 #include "BLI_math.h"
28 #include "BLI_math_color.h"
29 #include "BLI_utildefines.h"
30 
31 #include "DNA_key_types.h"
32 #include "DNA_texture_types.h"
33 
34 #include "BKE_colorband.h"
35 #include "BKE_key.h"
36 #include "BKE_material.h"
37 
BKE_colorband_init(ColorBand * coba,bool rangetype)38 void BKE_colorband_init(ColorBand *coba, bool rangetype)
39 {
40   int a;
41 
42   coba->data[0].pos = 0.0;
43   coba->data[1].pos = 1.0;
44 
45   if (rangetype == 0) {
46     coba->data[0].r = 0.0;
47     coba->data[0].g = 0.0;
48     coba->data[0].b = 0.0;
49     coba->data[0].a = 0.0;
50 
51     coba->data[1].r = 1.0;
52     coba->data[1].g = 1.0;
53     coba->data[1].b = 1.0;
54     coba->data[1].a = 1.0;
55   }
56   else {
57     coba->data[0].r = 0.0;
58     coba->data[0].g = 0.0;
59     coba->data[0].b = 0.0;
60     coba->data[0].a = 1.0;
61 
62     coba->data[1].r = 1.0;
63     coba->data[1].g = 1.0;
64     coba->data[1].b = 1.0;
65     coba->data[1].a = 1.0;
66   }
67 
68   for (a = 2; a < MAXCOLORBAND; a++) {
69     coba->data[a].r = 0.5;
70     coba->data[a].g = 0.5;
71     coba->data[a].b = 0.5;
72     coba->data[a].a = 1.0;
73     coba->data[a].pos = 0.5;
74   }
75 
76   coba->tot = 2;
77   coba->cur = 0;
78   coba->color_mode = COLBAND_BLEND_RGB;
79   coba->ipotype = COLBAND_INTERP_LINEAR;
80 }
81 
colorband_init_from_table_rgba_simple(ColorBand * coba,const float (* array)[4],const int array_len)82 static void colorband_init_from_table_rgba_simple(ColorBand *coba,
83                                                   const float (*array)[4],
84                                                   const int array_len)
85 {
86   /* No Re-sample, just de-duplicate. */
87   const float eps = (1.0f / 255.0f) + 1e-6f;
88   BLI_assert(array_len < MAXCOLORBAND);
89   int stops = min_ii(MAXCOLORBAND, array_len);
90   if (stops) {
91     const float step_size = 1.0f / (float)max_ii(stops - 1, 1);
92     int i_curr = -1;
93     for (int i_step = 0; i_step < stops; i_step++) {
94       if ((i_curr != -1) && compare_v4v4(&coba->data[i_curr].r, array[i_step], eps)) {
95         continue;
96       }
97       i_curr += 1;
98       copy_v4_v4(&coba->data[i_curr].r, array[i_step]);
99       coba->data[i_curr].pos = i_step * step_size;
100       coba->data[i_curr].cur = i_curr;
101     }
102     coba->tot = i_curr + 1;
103     coba->cur = 0;
104   }
105   else {
106     /* coba is empty, set 1 black stop */
107     zero_v3(&coba->data[0].r);
108     coba->data[0].a = 1.0f;
109     coba->cur = 0;
110     coba->tot = 1;
111   }
112 }
113 
114 /* -------------------------------------------------------------------- */
115 /** \name Color Ramp Re-Sample
116  *
117  * Local functions for #BKE_colorband_init_from_table_rgba
118  * \{ */
119 
120 /**
121  * Used for calculating which samples of a color-band to remove (when simplifying).
122  */
123 struct ColorResampleElem {
124   struct ColorResampleElem *next, *prev;
125   HeapNode *node;
126   float rgba[4];
127   float pos;
128 };
129 
130 /**
131  * Measure the 'area' of each channel and combine to use as a cost for this samples removal.
132  */
color_sample_remove_cost(const struct ColorResampleElem * c)133 static float color_sample_remove_cost(const struct ColorResampleElem *c)
134 {
135   if (c->next == NULL || c->prev == NULL) {
136     return -1.0f;
137   }
138   float area = 0.0f;
139 #if 0
140   float xy_prev[2], xy_curr[2], xy_next[2];
141   xy_prev[0] = c->prev->pos;
142   xy_curr[0] = c->pos;
143   xy_next[0] = c->next->pos;
144   for (int i = 0; i < 4; i++) {
145     xy_prev[1] = c->prev->rgba[i];
146     xy_curr[1] = c->rgba[i];
147     xy_next[1] = c->next->rgba[i];
148     area += fabsf(cross_tri_v2(xy_prev, xy_curr, xy_next));
149   }
150 #else
151   /* Above logic, optimized (p: previous, c: current, n: next). */
152   const float xpc = c->prev->pos - c->pos;
153   const float xnc = c->next->pos - c->pos;
154   for (int i = 0; i < 4; i++) {
155     const float ycn = c->rgba[i] - c->next->rgba[i];
156     const float ypc = c->prev->rgba[i] - c->rgba[i];
157     area += fabsf((xpc * ycn) + (ypc * xnc));
158   }
159 #endif
160   return area;
161 }
162 
163 /* TODO(campbell): create BLI_math_filter? */
filter_gauss(float x)164 static float filter_gauss(float x)
165 {
166   const float gaussfac = 1.6f;
167   const float two_gaussfac2 = 2.0f * gaussfac * gaussfac;
168   x *= 3.0f * gaussfac;
169   return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x * x / two_gaussfac2);
170 }
171 
colorband_init_from_table_rgba_resample(ColorBand * coba,const float (* array)[4],const int array_len,bool filter_samples)172 static void colorband_init_from_table_rgba_resample(ColorBand *coba,
173                                                     const float (*array)[4],
174                                                     const int array_len,
175                                                     bool filter_samples)
176 {
177   BLI_assert(array_len >= 2);
178   const float eps_2x = ((1.0f / 255.0f) + 1e-6f);
179   struct ColorResampleElem *c, *carr = MEM_mallocN(sizeof(*carr) * array_len, __func__);
180   int carr_len = array_len;
181   c = carr;
182   {
183     const float step_size = 1.0f / (float)(array_len - 1);
184     for (int i = 0; i < array_len; i++, c++) {
185       copy_v4_v4(carr[i].rgba, array[i]);
186       c->next = c + 1;
187       c->prev = c - 1;
188       c->pos = i * step_size;
189     }
190   }
191   carr[0].prev = NULL;
192   carr[array_len - 1].next = NULL;
193 
194   /* -2 to remove endpoints. */
195   Heap *heap = BLI_heap_new_ex(array_len - 2);
196   c = carr;
197   for (int i = 0; i < array_len; i++, c++) {
198     float cost = color_sample_remove_cost(c);
199     if (cost != -1.0f) {
200       c->node = BLI_heap_insert(heap, cost, c);
201     }
202     else {
203       c->node = NULL;
204     }
205   }
206 
207   while ((carr_len > 1 && !BLI_heap_is_empty(heap)) &&
208          ((carr_len >= MAXCOLORBAND) || (BLI_heap_top_value(heap) <= eps_2x))) {
209     c = BLI_heap_pop_min(heap);
210     struct ColorResampleElem *c_next = c->next, *c_prev = c->prev;
211     c_prev->next = c_next;
212     c_next->prev = c_prev;
213     /* Clear data (not essential, avoid confusion). */
214     c->prev = c->next = NULL;
215     c->node = NULL;
216 
217     /* Update adjacent */
218     for (int i = 0; i < 2; i++) {
219       struct ColorResampleElem *c_other = i ? c_next : c_prev;
220       if (c_other->node != NULL) {
221         const float cost = color_sample_remove_cost(c_other);
222         if (cost != -1.0) {
223           BLI_heap_node_value_update(heap, c_other->node, cost);
224         }
225         else {
226           BLI_heap_remove(heap, c_other->node);
227           c_other->node = NULL;
228         }
229       }
230     }
231     carr_len -= 1;
232   }
233   BLI_heap_free(heap, NULL);
234 
235   /* First member is never removed. */
236   int i = 0;
237   BLI_assert(carr_len < MAXCOLORBAND);
238   if (filter_samples == false) {
239     for (c = carr; c != NULL; c = c->next, i++) {
240       copy_v4_v4(&coba->data[i].r, c->rgba);
241       coba->data[i].pos = c->pos;
242       coba->data[i].cur = i;
243     }
244   }
245   else {
246     for (c = carr; c != NULL; c = c->next, i++) {
247       const int steps_prev = c->prev ? (c - c->prev) - 1 : 0;
248       const int steps_next = c->next ? (c->next - c) - 1 : 0;
249       if (steps_prev == 0 && steps_next == 0) {
250         copy_v4_v4(&coba->data[i].r, c->rgba);
251       }
252       else {
253         float rgba[4];
254         float rgba_accum = 1;
255         copy_v4_v4(rgba, c->rgba);
256 
257         if (steps_prev) {
258           const float step_size = 1.0 / (float)(steps_prev + 1);
259           int j = steps_prev;
260           for (struct ColorResampleElem *c_other = c - 1; c_other != c->prev; c_other--, j--) {
261             const float step_pos = (float)j * step_size;
262             BLI_assert(step_pos > 0.0f && step_pos < 1.0f);
263             const float f = filter_gauss(step_pos);
264             madd_v4_v4fl(rgba, c_other->rgba, f);
265             rgba_accum += f;
266           }
267         }
268         if (steps_next) {
269           const float step_size = 1.0 / (float)(steps_next + 1);
270           int j = steps_next;
271           for (struct ColorResampleElem *c_other = c + 1; c_other != c->next; c_other++, j--) {
272             const float step_pos = (float)j * step_size;
273             BLI_assert(step_pos > 0.0f && step_pos < 1.0f);
274             const float f = filter_gauss(step_pos);
275             madd_v4_v4fl(rgba, c_other->rgba, f);
276             rgba_accum += f;
277           }
278         }
279 
280         mul_v4_v4fl(&coba->data[i].r, rgba, 1.0f / rgba_accum);
281       }
282       coba->data[i].pos = c->pos;
283       coba->data[i].cur = i;
284     }
285   }
286   BLI_assert(i == carr_len);
287   coba->tot = i;
288   coba->cur = 0;
289 
290   MEM_freeN(carr);
291 }
292 
BKE_colorband_init_from_table_rgba(ColorBand * coba,const float (* array)[4],const int array_len,bool filter_samples)293 void BKE_colorband_init_from_table_rgba(ColorBand *coba,
294                                         const float (*array)[4],
295                                         const int array_len,
296                                         bool filter_samples)
297 {
298   /* Note, we could use MAXCOLORBAND here, but results of re-sampling are nicer,
299    * avoid different behavior when limit is hit. */
300   if (array_len < 2) {
301     /* No Re-sample, just de-duplicate. */
302     colorband_init_from_table_rgba_simple(coba, array, array_len);
303   }
304   else {
305     /* Re-sample */
306     colorband_init_from_table_rgba_resample(coba, array, array_len, filter_samples);
307   }
308 }
309 
310 /** \} */
311 
BKE_colorband_add(bool rangetype)312 ColorBand *BKE_colorband_add(bool rangetype)
313 {
314   ColorBand *coba;
315 
316   coba = MEM_callocN(sizeof(ColorBand), "colorband");
317   BKE_colorband_init(coba, rangetype);
318 
319   return coba;
320 }
321 
322 /* ------------------------------------------------------------------------- */
323 
colorband_hue_interp(const int ipotype_hue,const float mfac,const float fac,float h1,float h2)324 static float colorband_hue_interp(
325     const int ipotype_hue, const float mfac, const float fac, float h1, float h2)
326 {
327   float h_interp;
328   int mode = 0;
329 
330 #define HUE_INTERP(h_a, h_b) ((mfac * (h_a)) + (fac * (h_b)))
331 #define HUE_MOD(h) (((h) < 1.0f) ? (h) : (h)-1.0f)
332 
333   h1 = HUE_MOD(h1);
334   h2 = HUE_MOD(h2);
335 
336   BLI_assert(h1 >= 0.0f && h1 < 1.0f);
337   BLI_assert(h2 >= 0.0f && h2 < 1.0f);
338 
339   switch (ipotype_hue) {
340     case COLBAND_HUE_NEAR: {
341       if ((h1 < h2) && (h2 - h1) > +0.5f) {
342         mode = 1;
343       }
344       else if ((h1 > h2) && (h2 - h1) < -0.5f) {
345         mode = 2;
346       }
347       else {
348         mode = 0;
349       }
350       break;
351     }
352     case COLBAND_HUE_FAR: {
353       /* Do full loop in Hue space in case both stops are the same... */
354       if (h1 == h2) {
355         mode = 1;
356       }
357       else if ((h1 < h2) && (h2 - h1) < +0.5f) {
358         mode = 1;
359       }
360       else if ((h1 > h2) && (h2 - h1) > -0.5f) {
361         mode = 2;
362       }
363       else {
364         mode = 0;
365       }
366       break;
367     }
368     case COLBAND_HUE_CCW: {
369       if (h1 > h2) {
370         mode = 2;
371       }
372       else {
373         mode = 0;
374       }
375       break;
376     }
377     case COLBAND_HUE_CW: {
378       if (h1 < h2) {
379         mode = 1;
380       }
381       else {
382         mode = 0;
383       }
384       break;
385     }
386   }
387 
388   switch (mode) {
389     case 0:
390       h_interp = HUE_INTERP(h1, h2);
391       break;
392     case 1:
393       h_interp = HUE_INTERP(h1 + 1.0f, h2);
394       h_interp = HUE_MOD(h_interp);
395       break;
396     case 2:
397       h_interp = HUE_INTERP(h1, h2 + 1.0f);
398       h_interp = HUE_MOD(h_interp);
399       break;
400   }
401 
402   BLI_assert(h_interp >= 0.0f && h_interp < 1.0f);
403 
404 #undef HUE_INTERP
405 #undef HUE_MOD
406 
407   return h_interp;
408 }
409 
BKE_colorband_evaluate(const ColorBand * coba,float in,float out[4])410 bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
411 {
412   const CBData *cbd1, *cbd2, *cbd0, *cbd3;
413   float fac;
414   int ipotype;
415   int a;
416 
417   if (coba == NULL || coba->tot == 0) {
418     return false;
419   }
420 
421   cbd1 = coba->data;
422 
423   /* Note: when ipotype >= COLBAND_INTERP_B_SPLINE,
424    * we cannot do early-out with a constant color before first color stop and after last one,
425    * because interpolation starts before and ends after those... */
426   ipotype = (coba->color_mode == COLBAND_BLEND_RGB) ? coba->ipotype : COLBAND_INTERP_LINEAR;
427 
428   if (coba->tot == 1) {
429     out[0] = cbd1->r;
430     out[1] = cbd1->g;
431     out[2] = cbd1->b;
432     out[3] = cbd1->a;
433   }
434   else if ((in <= cbd1->pos) &&
435            ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE, COLBAND_INTERP_CONSTANT)) {
436     /* We are before first color stop. */
437     out[0] = cbd1->r;
438     out[1] = cbd1->g;
439     out[2] = cbd1->b;
440     out[3] = cbd1->a;
441   }
442   else {
443     CBData left, right;
444 
445     /* we're looking for first pos > in */
446     for (a = 0; a < coba->tot; a++, cbd1++) {
447       if (cbd1->pos > in) {
448         break;
449       }
450     }
451 
452     if (a == coba->tot) {
453       cbd2 = cbd1 - 1;
454       right = *cbd2;
455       right.pos = 1.0f;
456       cbd1 = &right;
457     }
458     else if (a == 0) {
459       left = *cbd1;
460       left.pos = 0.0f;
461       cbd2 = &left;
462     }
463     else {
464       cbd2 = cbd1 - 1;
465     }
466 
467     if ((a == coba->tot) &&
468         ELEM(ipotype, COLBAND_INTERP_LINEAR, COLBAND_INTERP_EASE, COLBAND_INTERP_CONSTANT)) {
469       /* We are after last color stop. */
470       out[0] = cbd2->r;
471       out[1] = cbd2->g;
472       out[2] = cbd2->b;
473       out[3] = cbd2->a;
474     }
475     else if (ipotype == COLBAND_INTERP_CONSTANT) {
476       /* constant */
477       out[0] = cbd2->r;
478       out[1] = cbd2->g;
479       out[2] = cbd2->b;
480       out[3] = cbd2->a;
481     }
482     else {
483       if (cbd2->pos != cbd1->pos) {
484         fac = (in - cbd1->pos) / (cbd2->pos - cbd1->pos);
485       }
486       else {
487         /* was setting to 0.0 in 2.56 & previous, but this
488          * is incorrect for the last element, see T26732. */
489         fac = (a != coba->tot) ? 0.0f : 1.0f;
490       }
491 
492       if (ELEM(ipotype, COLBAND_INTERP_B_SPLINE, COLBAND_INTERP_CARDINAL)) {
493         /* ipo from right to left: 3 2 1 0 */
494         float t[4];
495 
496         if (a >= coba->tot - 1) {
497           cbd0 = cbd1;
498         }
499         else {
500           cbd0 = cbd1 + 1;
501         }
502         if (a < 2) {
503           cbd3 = cbd2;
504         }
505         else {
506           cbd3 = cbd2 - 1;
507         }
508 
509         CLAMP(fac, 0.0f, 1.0f);
510 
511         if (ipotype == COLBAND_INTERP_CARDINAL) {
512           key_curve_position_weights(fac, t, KEY_CARDINAL);
513         }
514         else {
515           key_curve_position_weights(fac, t, KEY_BSPLINE);
516         }
517 
518         out[0] = t[3] * cbd3->r + t[2] * cbd2->r + t[1] * cbd1->r + t[0] * cbd0->r;
519         out[1] = t[3] * cbd3->g + t[2] * cbd2->g + t[1] * cbd1->g + t[0] * cbd0->g;
520         out[2] = t[3] * cbd3->b + t[2] * cbd2->b + t[1] * cbd1->b + t[0] * cbd0->b;
521         out[3] = t[3] * cbd3->a + t[2] * cbd2->a + t[1] * cbd1->a + t[0] * cbd0->a;
522         clamp_v4(out, 0.0f, 1.0f);
523       }
524       else {
525         if (ipotype == COLBAND_INTERP_EASE) {
526           const float fac2 = fac * fac;
527           fac = 3.0f * fac2 - 2.0f * fac2 * fac;
528         }
529         const float mfac = 1.0f - fac;
530 
531         if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSV)) {
532           float col1[3], col2[3];
533 
534           rgb_to_hsv_v(&cbd1->r, col1);
535           rgb_to_hsv_v(&cbd2->r, col2);
536 
537           out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
538           out[1] = mfac * col1[1] + fac * col2[1];
539           out[2] = mfac * col1[2] + fac * col2[2];
540           out[3] = mfac * cbd1->a + fac * cbd2->a;
541 
542           hsv_to_rgb_v(out, out);
543         }
544         else if (UNLIKELY(coba->color_mode == COLBAND_BLEND_HSL)) {
545           float col1[3], col2[3];
546 
547           rgb_to_hsl_v(&cbd1->r, col1);
548           rgb_to_hsl_v(&cbd2->r, col2);
549 
550           out[0] = colorband_hue_interp(coba->ipotype_hue, mfac, fac, col1[0], col2[0]);
551           out[1] = mfac * col1[1] + fac * col2[1];
552           out[2] = mfac * col1[2] + fac * col2[2];
553           out[3] = mfac * cbd1->a + fac * cbd2->a;
554 
555           hsl_to_rgb_v(out, out);
556         }
557         else {
558           /* COLBAND_BLEND_RGB */
559           out[0] = mfac * cbd1->r + fac * cbd2->r;
560           out[1] = mfac * cbd1->g + fac * cbd2->g;
561           out[2] = mfac * cbd1->b + fac * cbd2->b;
562           out[3] = mfac * cbd1->a + fac * cbd2->a;
563         }
564       }
565     }
566   }
567 
568   return true; /* OK */
569 }
570 
BKE_colorband_evaluate_table_rgba(const ColorBand * coba,float ** array,int * size)571 void BKE_colorband_evaluate_table_rgba(const ColorBand *coba, float **array, int *size)
572 {
573   int a;
574 
575   *size = CM_TABLE + 1;
576   *array = MEM_callocN(sizeof(float) * (*size) * 4, "ColorBand");
577 
578   for (a = 0; a < *size; a++) {
579     BKE_colorband_evaluate(coba, (float)a / (float)CM_TABLE, &(*array)[a * 4]);
580   }
581 }
582 
vergcband(const void * a1,const void * a2)583 static int vergcband(const void *a1, const void *a2)
584 {
585   const CBData *x1 = a1, *x2 = a2;
586 
587   if (x1->pos > x2->pos) {
588     return 1;
589   }
590   if (x1->pos < x2->pos) {
591     return -1;
592   }
593   return 0;
594 }
595 
BKE_colorband_update_sort(ColorBand * coba)596 void BKE_colorband_update_sort(ColorBand *coba)
597 {
598   int a;
599 
600   if (coba->tot < 2) {
601     return;
602   }
603 
604   for (a = 0; a < coba->tot; a++) {
605     coba->data[a].cur = a;
606   }
607 
608   qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
609 
610   for (a = 0; a < coba->tot; a++) {
611     if (coba->data[a].cur == coba->cur) {
612       coba->cur = a;
613       break;
614     }
615   }
616 }
617 
BKE_colorband_element_add(struct ColorBand * coba,float position)618 CBData *BKE_colorband_element_add(struct ColorBand *coba, float position)
619 {
620   if (coba->tot == MAXCOLORBAND) {
621     return NULL;
622   }
623 
624   CBData *xnew;
625 
626   xnew = &coba->data[coba->tot];
627   xnew->pos = position;
628 
629   if (coba->tot != 0) {
630     BKE_colorband_evaluate(coba, position, &xnew->r);
631   }
632   else {
633     zero_v4(&xnew->r);
634   }
635 
636   coba->tot++;
637   coba->cur = coba->tot - 1;
638 
639   BKE_colorband_update_sort(coba);
640 
641   return coba->data + coba->cur;
642 }
643 
BKE_colorband_element_remove(struct ColorBand * coba,int index)644 bool BKE_colorband_element_remove(struct ColorBand *coba, int index)
645 {
646   if (coba->tot < 2) {
647     return false;
648   }
649 
650   if (index < 0 || index >= coba->tot) {
651     return false;
652   }
653 
654   coba->tot--;
655   for (int a = index; a < coba->tot; a++) {
656     coba->data[a] = coba->data[a + 1];
657   }
658   if (coba->cur) {
659     coba->cur--;
660   }
661   return true;
662 }
663