Simplified the ntreeUpdate function by getting rid of the dependency list and limitin...
[blender-staging.git] / release / plugins / sequence / color-correction-hsv.c
1 /*
2  * Color Correction Plugin (YUV Version) 0.01
3  *
4  * Copyright (c) 2005 Peter Schlaile
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  */
17
18 #include "math.h"
19 #include "plugin.h"
20 #include <stdio.h>
21
22 char name[]= "Color Correction";
23
24 VarStruct varstr[]= {
25         { NUMSLI|FLO, "St Y:", 0.0,     -1.0,   1.0, "Setup Y"}, 
26         { NUMSLI|FLO, "Gn Y:",  1.0,    0.0,    10.0,"Gain Y"},
27         { NUMSLI|FLO, "Ga Y:", 1.0,     0.0,    10.0, "Gamma Y"},
28
29         { NUMSLI|FLO, "Lo S:",  1.0,    0.0,    10.0,"Saturation Shadows"},
30         { NUMSLI|FLO, "Md S:",  1.0,    0.0,    10.0,"Saturation Midtones"},
31         { NUMSLI|FLO, "Hi S:",  1.0,    0.0,    10.0,"Saturation Highlights"},
32
33         { NUMSLI|FLO, "MA S:",  1.0,    0.0,    10.0,"Master Saturation"}, 
34
35         { NUMSLI|FLO, "Lo T:",  0.25, 0.0, 1.0,
36           "Saturation Shadow Thres"}, 
37         { NUMSLI|FLO, "Hi T:",  0.75, 0.0, 1.0,
38           "Saturation Highlights Thres"}, 
39         { TOG|INT,      "Debug", 0.0,   0.0,    1.0,   
40           "Show curves as overlay"}, 
41 };
42
43 typedef struct Cast {
44         float setup_y;
45         float gain_y;
46         float gamma_y;
47         float sat_shadows;
48         float sat_midtones;
49         float sat_highlights;
50
51         float master_sat;
52         float lo_thres;
53         float hi_thres;
54         int debug;
55 } Cast;
56
57 float cfra;
58
59 void plugin_seq_doit(Cast *, float, float, int, int, ImBuf *, ImBuf *, ImBuf *, ImBuf *);
60
61 int plugin_seq_getversion(void) { return B_PLUGIN_VERSION;}
62 void plugin_but_changed(int but) {}
63 void plugin_init() {}
64
65 void plugin_getinfo(PluginInfo *info)
66 {
67         info->name= name;
68         info->nvars= sizeof(varstr)/sizeof(VarStruct);
69         info->cfra= &cfra;
70
71         info->varstr= varstr;
72
73         info->init= plugin_init;
74         info->seq_doit= (SeqDoit) plugin_seq_doit;
75         info->callback= plugin_but_changed;
76 }
77
78 static void hsv_to_rgb (double  h, double  s, double  v,
79                         double *r, double *g, double *b)
80 {
81         int i;
82         double f, w, q, t;
83
84         if (s == 0.0)
85                 s = 0.000001;
86         
87         if (h == -1.0)
88         {
89                 *r = v;
90                 *g = v;
91                 *b = v;
92         }
93         else
94         {
95                 if (h == 360.0)
96                         h = 0.0;
97                 h = h / 60.0;
98                 i = (int) h;
99                 f = h - i;
100                 w = v * (1.0 - s);
101                 q = v * (1.0 - (s * f));
102                 t = v * (1.0 - (s * (1.0 - f)));
103                 
104                 switch (i)
105                 {
106                 case 0:
107                         *r = v;
108                         *g = t;
109                         *b = w;
110                         break;
111                 case 1:
112                         *r = q;
113                         *g = v;
114                         *b = w;
115                         break;
116                 case 2:
117                         *r = w;
118                         *g = v;
119                         *b = t;
120                         break;
121                 case 3:
122                         *r = w;
123                         *g = q;
124                         *b = v;
125                         break;
126                 case 4:
127                         *r = t;
128                         *g = w;
129                         *b = v;
130                         break;
131                 case 5:
132                         *r = v;
133                         *g = w;
134                         *b = q;
135                         break;
136                 }
137         }
138 }
139
140 static void rgb_to_hsv (double  r, double  g, double  b,
141                         double *h, double *s, double *v)
142 {
143         double max, min, delta;
144
145         max = r;
146         if (g > max)
147                 max = g;
148         if (b > max)
149                 max = b;
150         
151         min = r;
152         if (g < min)
153                 min = g;
154         if (b < min)
155                 min = b;
156         
157         *v = max;
158         
159         if (max != 0.0)
160                 *s = (max - min) / max;
161         else
162                 *s = 0.0;
163         
164         if (*s == 0.0)
165                 *h = -1.0;
166         else
167         {
168                 delta = max - min;
169                 
170                 if (r == max)
171                         *h = (g - b) / delta;
172                 else if (g == max)
173                         *h = 2.0 + (b - r) / delta;
174                 else if (b == max)
175                         *h = 4.0 + (r - g) / delta;
176                 
177                 *h = *h * 60.0;
178                 
179                 if (*h < 0.0)
180                         *h = *h + 360;
181         }
182 }
183
184 void plugin_seq_doit(Cast *cast, float facf0, float facf1, int width, 
185         int height, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *out, ImBuf *use) {
186         char *dest, *src1;
187         int x, y, c;
188         double gamma_table[256];
189         double uv_table[256];
190         float *destf = out->rect_float;
191         float *src1f;
192         
193         if (!ibuf1) return;
194
195         dest= (char *) out->rect;
196         src1= (char *) ibuf1->rect;
197         src1f= ibuf1->rect_float;
198
199         for (y = 0; y < 256; y++) {
200                 float v = 1.0 * y / 255;
201                 v += cast->setup_y;
202                 v *= cast->gain_y;
203                 v = pow(v, cast->gamma_y);
204                 if ( v > 1.0) {
205                         v = 1.0;
206                 } else if (v < 0.0) {
207                         v = 0.0;
208                 }
209                 gamma_table[y] = v * 255;
210         }
211
212         for (y = 0; y < 256; y++) {
213                 float v = 1.0;
214                 v *= cast->master_sat;
215                 if (y < cast->lo_thres * 255) {
216                         v *= cast->sat_shadows;
217                 } else if (y > cast->hi_thres * 255) {
218                         v *= cast->sat_highlights;
219                 } else {
220                         v *= cast->sat_midtones;
221                 }
222                 uv_table[y] = v;
223         }
224
225
226         for (y = 0; y < height; y++) {
227                 for (x = 0; x < width; x++) {
228                         double h,s,v,r,g,b;
229                         double fac;
230
231                         if (ibuf1->rect_float) rgb_to_hsv(src1f[0], src1f[1],
232                                 src1f[2],&h,&s,&v);
233                         else rgb_to_hsv((double) src1[0]/255.0,
234                                    (double) src1[1]/255.0,
235                                    (double) src1[2]/255.0,
236                                    &h, &s, &v);
237                         v = gamma_table[(int) (v * 255.0)] / 255.0;
238
239                         fac = uv_table[(int) (255.0 * v)];
240
241                         s *= fac;
242                         if (s >= 1.0) {
243                                 s = 1.0;
244                         }
245                         hsv_to_rgb(h,s,v, &r, &g, &b);
246                         
247                         if (out->rect_float) {
248                                 destf[0] = r;
249                                 destf[1] = g;
250                                 destf[2] = b;
251                                 destf = destf + 4;
252                                 src1f +=4;
253                         } else {
254                                 dest[0] = r*255.0;
255                                 dest[1] = g*255.0;
256                                 dest[2] = b*255.0;
257                                 dest += 4;
258                         }
259
260                         src1 += 4;
261                 }
262         }
263
264         if (cast->debug) {
265                 dest= (char *) out->rect;
266                 for (c = 0; c < 10; c++) {
267                         x = 0;
268                         for (y = 0; y < 256; y++) {
269                                 char val = gamma_table[y];
270                                 while (x < y * width / 255) {
271                                         *dest++ = val;
272                                         *dest++ = val;
273                                         *dest++ = val;
274                                         dest++;
275                                         x++;
276                                 }
277                         }
278                 }
279                 for (c = 0; c < 10; c++) {
280                         x = 0;
281                         for (y = 0; y < 256; y++) {
282                                 char val = uv_table[y] * 255.0/10.0;
283                                 while (x < y * width / 255) {
284                                         *dest++ = val;
285                                         *dest++ = val;
286                                         *dest++ = val;
287                                         dest++;
288                                         x++;
289                                 }
290                         }
291                 }
292         }
293 }