style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / nodes / composite / node_composite_util.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/node_composite_util.c
29  *  \ingroup nodes
30  */
31
32
33 #include "node_composite_util.h"
34
35 CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc)
36 {
37         CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf");
38         
39         cbuf->x= sizex;
40         cbuf->y= sizey;
41         cbuf->xrad= sizex/2;
42         cbuf->yrad= sizey/2;
43         
44         cbuf->type= type;
45         if (alloc) {
46                 if (cbuf->type==CB_RGBA)
47                         cbuf->rect= MEM_mapallocN(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect");
48                 else if (cbuf->type==CB_VEC3)
49                         cbuf->rect= MEM_mapallocN(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect");
50                 else if (cbuf->type==CB_VEC2)
51                         cbuf->rect= MEM_mapallocN(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect");
52                 else
53                         cbuf->rect= MEM_mapallocN(sizeof(float)*sizex*sizey, "compbuf Fac rect");
54                 cbuf->malloc= 1;
55         }
56         cbuf->disprect.xmin = 0;
57         cbuf->disprect.ymin = 0;
58         cbuf->disprect.xmax = sizex;
59         cbuf->disprect.ymax = sizey;
60         
61         return cbuf;
62 }
63
64 CompBuf *dupalloc_compbuf(CompBuf *cbuf)
65 {
66         CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1);
67         if (dupbuf) {
68                 memcpy(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y);
69         
70                 dupbuf->xof= cbuf->xof;
71                 dupbuf->yof= cbuf->yof;
72         }       
73         return dupbuf;
74 }
75
76 /* instead of reference counting, we create a list */
77 CompBuf *pass_on_compbuf(CompBuf *cbuf)
78 {
79         CompBuf *dupbuf= (cbuf)? alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0): NULL;
80         CompBuf *lastbuf;
81         
82         if (dupbuf) {
83                 dupbuf->rect= cbuf->rect;
84                 dupbuf->xof= cbuf->xof;
85                 dupbuf->yof= cbuf->yof;
86                 dupbuf->malloc= 0;
87                 
88                 /* get last buffer in list, and append dupbuf */
89                 for (lastbuf= cbuf; lastbuf; lastbuf= lastbuf->next)
90                         if (lastbuf->next==NULL)
91                                 break;
92                 lastbuf->next= dupbuf;
93                 dupbuf->prev= lastbuf;
94         }       
95         return dupbuf;
96 }
97
98
99 void free_compbuf(CompBuf *cbuf)
100 {
101         /* check referencing, then remove from list and set malloc tag */
102         if (cbuf->prev || cbuf->next) {
103                 if (cbuf->prev)
104                         cbuf->prev->next= cbuf->next;
105                 if (cbuf->next)
106                         cbuf->next->prev= cbuf->prev;
107                 if (cbuf->malloc) {
108                         if (cbuf->prev)
109                                 cbuf->prev->malloc= 1;
110                         else
111                                 cbuf->next->malloc= 1;
112                         cbuf->malloc= 0;
113                 }
114         }
115         
116         if (cbuf->malloc && cbuf->rect)
117                 MEM_freeN(cbuf->rect);
118
119         MEM_freeN(cbuf);
120 }
121
122 void print_compbuf(char *str, CompBuf *cbuf)
123 {
124         printf("Compbuf %s %d %d %p\n", str, cbuf->x, cbuf->y, (void *)cbuf->rect);
125         
126 }
127
128 void compbuf_set_node(CompBuf *cbuf, bNode *node)
129 {
130         if (cbuf) cbuf->node = node;
131 }
132
133
134 CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type)
135 {
136         CompBuf *cbuf;
137         rcti disprect= *drect;
138         float *outfp;
139         int dx, y;
140         
141         if (disprect.xmax>rectx) disprect.xmax = rectx;
142         if (disprect.ymax>recty) disprect.ymax = recty;
143         if (disprect.xmin>= disprect.xmax) return NULL;
144         if (disprect.ymin>= disprect.ymax) return NULL;
145         
146         cbuf= alloc_compbuf(disprect.xmax-disprect.xmin, disprect.ymax-disprect.ymin, type, 1);
147         outfp= cbuf->rect;
148         rectf += type*(disprect.ymin*rectx + disprect.xmin);
149         dx= type*cbuf->x;
150         for (y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx)
151                 memcpy(outfp, rectf, sizeof(float)*dx);
152         
153         return cbuf;
154 }
155
156 CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
157 {
158         CompBuf *outbuf; 
159         float *rectf, *newrectf, *rf;
160         int x, y, c, pixsize= inbuf->type;
161         int ofsx, ofsy, stepx, stepy;
162         
163         if (inbuf->x==newx && inbuf->y==newy)
164                 return dupalloc_compbuf(inbuf);
165         
166         outbuf= alloc_compbuf(newx, newy, inbuf->type, 1);
167         newrectf= outbuf->rect;
168         
169         stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5;
170         stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5;
171         ofsy = 32768;
172         
173         for (y = newy; y > 0 ; y--) {
174                 rectf = inbuf->rect;
175                 rectf += pixsize * (ofsy >> 16) * inbuf->x;
176
177                 ofsy += stepy;
178                 ofsx = 32768;
179                 
180                 for (x = newx ; x>0 ; x--) {
181                         
182                         rf= rectf + pixsize*(ofsx >> 16);
183                         for (c=0; c<pixsize; c++)
184                                 newrectf[c] = rf[c];
185                         
186                         newrectf+= pixsize;
187                         
188                         ofsx += stepx;
189                 }
190         }
191         
192         return outbuf;
193 }
194
195 void typecheck_compbuf_color(float *out, float *in, int outtype, int intype)
196 {
197         if (intype == outtype) {
198                 memcpy(out, in, sizeof(float)*outtype);
199         }
200         else if (outtype==CB_VAL) {
201                 if (intype==CB_VEC2) {
202                         *out= 0.5f*(in[0]+in[1]);
203                 }
204                 else if (intype==CB_VEC3) {
205                         *out= 0.333333f*(in[0]+in[1]+in[2]);
206                 }
207                 else if (intype==CB_RGBA) {
208                         *out= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f;
209                 }
210         }
211         else if (outtype==CB_VEC2) {
212                 if (intype==CB_VAL) {
213                         out[0]= in[0];
214                         out[1]= in[0];
215                 }
216                 else if (intype==CB_VEC3) {
217                         out[0]= in[0];
218                         out[1]= in[1];
219                 }
220                 else if (intype==CB_RGBA) {
221                         out[0]= in[0];
222                         out[1]= in[1];
223                 }
224         }
225         else if (outtype==CB_VEC3) {
226                 if (intype==CB_VAL) {
227                         out[0]= in[0];
228                         out[1]= in[0];
229                         out[2]= in[0];
230                 }
231                 else if (intype==CB_VEC2) {
232                         out[0]= in[0];
233                         out[1]= in[1];
234                         out[2]= 0.0f;
235                 }
236                 else if (intype==CB_RGBA) {
237                         out[0]= in[0];
238                         out[1]= in[1];
239                         out[2]= in[2];
240                 }
241         }
242         else if (outtype==CB_RGBA) {
243                 if (intype==CB_VAL) {
244                         out[0]= in[0];
245                         out[1]= in[0];
246                         out[2]= in[0];
247                         out[3]= 1.0f;
248                 }
249                 else if (intype==CB_VEC2) {
250                         out[0]= in[0];
251                         out[1]= in[1];
252                         out[2]= 0.0f;
253                         out[3]= 1.0f;
254                 }
255                 else if (intype==CB_VEC3) {
256                         out[0]= in[0];
257                         out[1]= in[1];
258                         out[2]= in[2];
259                         out[3]= 1.0f;
260                 }
261         }
262 }
263
264 CompBuf *typecheck_compbuf(CompBuf *inbuf, int type)
265 {
266         if (inbuf && inbuf->type!=type) {
267                 CompBuf *outbuf;
268                 float *inrf, *outrf;
269                 int x;
270
271                 outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1); 
272
273                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
274                 outbuf->xof= inbuf->xof;
275                 outbuf->yof= inbuf->yof;
276
277                 if (inbuf->rect_procedural) {
278                         outbuf->rect_procedural= inbuf->rect_procedural;
279                         copy_v3_v3(outbuf->procedural_size, inbuf->procedural_size);
280                         copy_v3_v3(outbuf->procedural_offset, inbuf->procedural_offset);
281                         outbuf->procedural_type= inbuf->procedural_type;
282                         outbuf->node= inbuf->node;
283                         return outbuf;
284                 }
285
286                 inrf= inbuf->rect;
287                 outrf= outbuf->rect;
288                 x= inbuf->x*inbuf->y;
289                 
290                 if (type==CB_VAL) {
291                         if (inbuf->type==CB_VEC2) {
292                                 for (; x>0; x--, outrf+= 1, inrf+= 2)
293                                         *outrf= 0.5f*(inrf[0]+inrf[1]);
294                         }
295                         else if (inbuf->type==CB_VEC3) {
296                                 for (; x>0; x--, outrf+= 1, inrf+= 3)
297                                         *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]);
298                         }
299                         else if (inbuf->type==CB_RGBA) {
300                                 for (; x>0; x--, outrf+= 1, inrf+= 4)
301                                         *outrf= inrf[0]*0.35f + inrf[1]*0.45f + inrf[2]*0.2f;
302                         }
303                 }
304                 else if (type==CB_VEC2) {
305                         if (inbuf->type==CB_VAL) {
306                                 for (; x>0; x--, outrf+= 2, inrf+= 1) {
307                                         outrf[0]= inrf[0];
308                                         outrf[1]= inrf[0];
309                                 }
310                         }
311                         else if (inbuf->type==CB_VEC3) {
312                                 for (; x>0; x--, outrf+= 2, inrf+= 3) {
313                                         outrf[0]= inrf[0];
314                                         outrf[1]= inrf[1];
315                                 }
316                         }
317                         else if (inbuf->type==CB_RGBA) {
318                                 for (; x>0; x--, outrf+= 2, inrf+= 4) {
319                                         outrf[0]= inrf[0];
320                                         outrf[1]= inrf[1];
321                                 }
322                         }
323                 }
324                 else if (type==CB_VEC3) {
325                         if (inbuf->type==CB_VAL) {
326                                 for (; x>0; x--, outrf+= 3, inrf+= 1) {
327                                         outrf[0]= inrf[0];
328                                         outrf[1]= inrf[0];
329                                         outrf[2]= inrf[0];
330                                 }
331                         }
332                         else if (inbuf->type==CB_VEC2) {
333                                 for (; x>0; x--, outrf+= 3, inrf+= 2) {
334                                         outrf[0]= inrf[0];
335                                         outrf[1]= inrf[1];
336                                         outrf[2]= 0.0f;
337                                 }
338                         }
339                         else if (inbuf->type==CB_RGBA) {
340                                 for (; x>0; x--, outrf+= 3, inrf+= 4) {
341                                         outrf[0]= inrf[0];
342                                         outrf[1]= inrf[1];
343                                         outrf[2]= inrf[2];
344                                 }
345                         }
346                 }
347                 else if (type==CB_RGBA) {
348                         if (inbuf->type==CB_VAL) {
349                                 for (; x>0; x--, outrf+= 4, inrf+= 1) {
350                                         outrf[0]= inrf[0];
351                                         outrf[1]= inrf[0];
352                                         outrf[2]= inrf[0];
353                                         outrf[3]= 1.0f;
354                                 }
355                         }
356                         else if (inbuf->type==CB_VEC2) {
357                                 for (; x>0; x--, outrf+= 4, inrf+= 2) {
358                                         outrf[0]= inrf[0];
359                                         outrf[1]= inrf[1];
360                                         outrf[2]= 0.0f;
361                                         outrf[3]= 1.0f;
362                                 }
363                         }
364                         else if (inbuf->type==CB_VEC3) {
365                                 for (; x>0; x--, outrf+= 4, inrf+= 3) {
366                                         outrf[0]= inrf[0];
367                                         outrf[1]= inrf[1];
368                                         outrf[2]= inrf[2];
369                                         outrf[3]= 1.0f;
370                                 }
371                         }
372                 }
373                 
374                 return outbuf;
375         }
376         return inbuf;
377 }
378
379 float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad)
380 {
381         if (cbuf) {
382                 if (cbuf->rect_procedural) {
383                         cbuf->rect_procedural(cbuf, use, (float)x/(float)xrad, (float)y/(float)yrad);
384                         return use;
385                 }
386                 else {
387                         static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
388                         
389                         /* map coords */
390                         x-= cbuf->xof;
391                         y-= cbuf->yof;
392                         
393                         if (y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col;
394                         if (x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col;
395                         
396                         return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) );
397                 }
398         }
399         else return defcol;
400 }
401
402 /* **************************************************** */
403
404 static CompBuf *composit_check_compbuf(CompBuf *cbuf, int type, CompBuf *outbuf)
405 {
406         /* check type */
407         CompBuf *dbuf= typecheck_compbuf(cbuf, type);
408
409         /* if same as output and translated, duplicate so pixels don't interfere */
410         if (dbuf == outbuf && !dbuf->rect_procedural && (dbuf->xof || dbuf->yof))
411                 dbuf= dupalloc_compbuf(dbuf);
412         
413         return dbuf;
414 }
415
416 /* Pixel-to-Pixel operation, 1 Image in, 1 out */
417 void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
418                                                                           void (*func)(bNode *, float *, float *), 
419                                                                           int src_type)
420 {
421         CompBuf *src_use;
422         float *outfp=out->rect, *srcfp;
423         float color[4]; /* local color if compbuf is procedural */
424         int xrad, yrad, x, y;
425         
426         src_use= composit_check_compbuf(src_buf, src_type, out);
427         
428         xrad= out->xrad;
429         yrad= out->yrad;
430         
431         for (y= -yrad; y<-yrad+out->y; y++) {
432                 for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
433                         srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad);
434                         func(node, outfp, srcfp);
435                 }
436         }
437         
438         if (src_use!=src_buf)
439                 free_compbuf(src_use);
440 }
441
442 /* Pixel-to-Pixel operation, 2 Images in, 1 out */
443 void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
444                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), 
445                                                                           int src_type, int fac_type)
446 {
447         CompBuf *src_use, *fac_use;
448         float *outfp=out->rect, *srcfp, *facfp;
449         float color[4]; /* local color if compbuf is procedural */
450         int xrad, yrad, x, y;
451         
452         src_use= composit_check_compbuf(src_buf, src_type, out);
453         fac_use= composit_check_compbuf(fac_buf, fac_type, out);
454
455         xrad= out->xrad;
456         yrad= out->yrad;
457         
458         for (y= -yrad; y<-yrad+out->y; y++) {
459                 for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
460                         srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad);
461                         facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad);
462                         
463                         func(node, outfp, srcfp, facfp);
464                 }
465         }
466         if (src_use!=src_buf)
467                 free_compbuf(src_use);
468         if (fac_use!=fac_buf)
469                 free_compbuf(fac_use);
470 }
471
472 /* Pixel-to-Pixel operation, 3 Images in, 1 out */
473 void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, 
474                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), 
475                                                                           int src1_type, int src2_type, int fac_type)
476 {
477         CompBuf *src1_use, *src2_use, *fac_use;
478         float *outfp=out->rect, *src1fp, *src2fp, *facfp;
479         float color[4]; /* local color if compbuf is procedural */
480         int xrad, yrad, x, y;
481         
482         src1_use= composit_check_compbuf(src1_buf, src1_type, out);
483         src2_use= composit_check_compbuf(src2_buf, src2_type, out);
484         fac_use= composit_check_compbuf(fac_buf, fac_type, out);
485         
486         xrad= out->xrad;
487         yrad= out->yrad;
488         
489         for (y= -yrad; y<-yrad+out->y; y++) {
490                 for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
491                         src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad);
492                         src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad);
493                         facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad);
494                         
495                         func(node, outfp, src1fp, src2fp, facfp);
496                 }
497         }
498         
499         if (src1_use!=src1_buf)
500                 free_compbuf(src1_use);
501         if (src2_use!=src2_buf)
502                 free_compbuf(src2_use);
503         if (fac_use!=fac_buf)
504                 free_compbuf(fac_use);
505 }
506
507 /* Pixel-to-Pixel operation, 4 Images in, 1 out */
508 void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, 
509                                                                           CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, 
510                                                                           void (*func)(bNode *, float *, float *, float *, float *, float *), 
511                                                                           int src1_type, int fac1_type, int src2_type, int fac2_type)
512 {
513         CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use;
514         float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp;
515         float color[4]; /* local color if compbuf is procedural */
516         int xrad, yrad, x, y;
517         
518         src1_use= composit_check_compbuf(src1_buf, src1_type, out);
519         src2_use= composit_check_compbuf(src2_buf, src2_type, out);
520         fac1_use= composit_check_compbuf(fac1_buf, fac1_type, out);
521         fac2_use= composit_check_compbuf(fac2_buf, fac2_type, out);
522         
523         xrad= out->xrad;
524         yrad= out->yrad;
525         
526         for (y= -yrad; y<-yrad+out->y; y++) {
527                 for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
528                         src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad);
529                         src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad);
530                         fac1fp= compbuf_get_pixel(fac1_use, fac1, color, x, y, xrad, yrad);
531                         fac2fp= compbuf_get_pixel(fac2_use, fac2, color, x, y, xrad, yrad);
532                         
533                         func(node, outfp, src1fp, fac1fp, src2fp, fac2fp);
534                 }
535         }
536         
537         if (src1_use!=src1_buf)
538                 free_compbuf(src1_use);
539         if (src2_use!=src2_buf)
540                 free_compbuf(src2_use);
541         if (fac1_use!=fac1_buf)
542                 free_compbuf(fac1_use);
543         if (fac2_use!=fac2_buf)
544                 free_compbuf(fac2_use);
545 }
546
547
548 CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
549 {
550         CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
551         float *valf, *rectf;
552         int tot;
553         
554         /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
555         valbuf->xof= cbuf->xof;
556         valbuf->yof= cbuf->yof;
557         
558         valf= valbuf->rect;
559
560         /* defaults to returning alpha channel */
561         if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A;
562
563         rectf= cbuf->rect + channel;
564         
565         for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
566                 *valf= *rectf;
567         
568         return valbuf;
569 }
570
571 static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy)
572 {
573         CompBuf *outbuf;
574         float *outfp;
575         int xrad, yrad, x, y;
576         
577         outbuf= alloc_compbuf(newx, newy, CB_RGBA, 1);
578
579         outfp= outbuf->rect;
580         xrad= outbuf->xrad;
581         yrad= outbuf->yrad;
582         
583         for (y= -yrad; y<-yrad+outbuf->y; y++)
584                 for (x= -xrad; x<-xrad+outbuf->x; x++, outfp+=outbuf->type)
585                         cbuf->rect_procedural(cbuf, outfp, (float)x/(float)xrad, (float)y/(float)yrad);
586
587         return outbuf;
588 }
589
590 void generate_preview(void *data, bNode *node, CompBuf *stackbuf)
591 {
592         RenderData *rd= data;
593         bNodePreview *preview= node->preview;
594         int xsize, ysize;
595         int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB;
596         int predivide= (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
597         int dither= 0;
598         unsigned char *rect;
599         
600         if (preview && stackbuf) {
601                 CompBuf *cbuf, *stackbuf_use;
602                 
603                 if (stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return;
604                 
605                 stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA);
606
607                 if (stackbuf->x > stackbuf->y) {
608                         xsize= 140;
609                         ysize= (140*stackbuf->y)/stackbuf->x;
610                 }
611                 else {
612                         ysize= 140;
613                         xsize= (140*stackbuf->x)/stackbuf->y;
614                 }
615                 
616                 if (stackbuf_use->rect_procedural)
617                         cbuf= generate_procedural_preview(stackbuf_use, xsize, ysize);
618                 else
619                         cbuf= scalefast_compbuf(stackbuf_use, xsize, ysize);
620
621                 /* convert to byte for preview */
622                 rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect");
623
624                 IMB_buffer_byte_from_float(rect, cbuf->rect,
625                         4, dither, IB_PROFILE_SRGB, profile_from, predivide, 
626                         xsize, ysize, xsize, xsize);
627                 
628                 free_compbuf(cbuf);
629                 if (stackbuf_use!=stackbuf)
630                         free_compbuf(stackbuf_use);
631
632                 BLI_lock_thread(LOCK_PREVIEW);
633
634                 if (preview->rect)
635                         MEM_freeN(preview->rect);
636                 preview->xsize= xsize;
637                 preview->ysize= ysize;
638                 preview->rect= rect;
639
640                 BLI_unlock_thread(LOCK_PREVIEW);
641         }
642 }
643
644 void do_rgba_to_yuva(bNode *UNUSED(node), float *out, float *in)
645 {
646         rgb_to_yuv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
647         out[3]=in[3];
648 }
649
650 void do_rgba_to_hsva(bNode *UNUSED(node), float *out, float *in)
651 {
652         rgb_to_hsv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
653         out[3]=in[3];
654 }
655
656 void do_rgba_to_ycca(bNode *UNUSED(node), float *out, float *in)
657 {
658         rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
659         out[3]=in[3];
660 }
661
662 void do_yuva_to_rgba(bNode *UNUSED(node), float *out, float *in)
663 {
664         yuv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
665         out[3]=in[3];
666 }
667
668 void do_hsva_to_rgba(bNode *UNUSED(node), float *out, float *in)
669 {
670         hsv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
671         out[3]=in[3];
672 }
673
674 void do_ycca_to_rgba(bNode *UNUSED(node), float *out, float *in)
675 {
676         ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
677         out[3]=in[3];
678 }
679
680 void do_copy_rgba(bNode *UNUSED(node), float *out, float *in)
681 {
682         copy_v4_v4(out, in);
683 }
684
685 void do_copy_rgb(bNode *UNUSED(node), float *out, float *in)
686 {
687         copy_v3_v3(out, in);
688         out[3]= 1.0f;
689 }
690
691 void do_copy_value(bNode *UNUSED(node), float *out, float *in)
692 {
693         out[0]= in[0];
694 }
695
696 void do_copy_a_rgba(bNode *UNUSED(node), float *out, float *in, float *fac)
697 {
698         copy_v3_v3(out, in);
699         out[3]= *fac;
700 }
701
702 /* only accepts RGBA buffers */
703 void gamma_correct_compbuf(CompBuf *img, int inversed)
704 {
705         float *drect;
706         int x;
707
708         if (img->type!=CB_RGBA) return;
709
710         drect= img->rect;
711         if (inversed) {
712                 for (x=img->x*img->y; x>0; x--, drect+=4) {
713                         if (drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f;
714                         if (drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f;
715                         if (drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f;
716                 }
717         }
718         else {
719                 for (x=img->x*img->y; x>0; x--, drect+=4) {
720                         if (drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f;
721                         if (drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f;
722                         if (drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f;
723                 }
724         }
725 }
726
727 void premul_compbuf(CompBuf *img, int inversed)
728 {
729         float *drect;
730         int x;
731
732         if (img->type!=CB_RGBA) return;
733
734         drect= img->rect;
735         if (inversed) {
736                 for (x=img->x*img->y; x>0; x--, drect+=4) {
737                         if (fabsf(drect[3]) < 1e-5f) {
738                                 drect[0]= 0.0f;
739                                 drect[1]= 0.0f;
740                                 drect[2]= 0.0f;
741                         }
742                         else {
743                                 drect[0] /= drect[3];
744                                 drect[1] /= drect[3];
745                                 drect[2] /= drect[3];
746                         }
747                 }
748         }
749         else {
750                 for (x=img->x*img->y; x>0; x--, drect+=4) {
751                         drect[0] *= drect[3];
752                         drect[1] *= drect[3];
753                         drect[2] *= drect[3];
754                 }
755         }
756 }
757
758
759
760 /*
761  *  2D Fast Hartley Transform, used for convolution
762  */
763
764 typedef float fREAL;
765
766 // returns next highest power of 2 of x, as well it's log2 in L2
767 static unsigned int nextPow2(unsigned int x, unsigned int* L2)
768 {
769         unsigned int pw, x_notpow2 = x & (x-1);
770         *L2 = 0;
771         while (x>>=1) ++(*L2);
772         pw = 1 << (*L2);
773         if (x_notpow2) { (*L2)++;  pw<<=1; }
774         return pw;
775 }
776
777 //------------------------------------------------------------------------------
778
779 // from FXT library by Joerg Arndt, faster in order bitreversal
780 // use: r = revbin_upd(r, h) where h = N>>1
781 static unsigned int revbin_upd(unsigned int r, unsigned int h)
782 {
783         while (!((r^=h)&h)) h >>= 1;
784         return r;
785 }
786 //------------------------------------------------------------------------------
787 static void FHT(fREAL* data, unsigned int M, unsigned int inverse)
788 {
789         double tt, fc, dc, fs, ds, a = M_PI;
790         fREAL t1, t2;
791         int n2, bd, bl, istep, k, len = 1 << M, n = 1;
792
793         int i, j = 0;
794         unsigned int Nh = len >> 1;
795         for (i=1;i<(len-1);++i) {
796                 j = revbin_upd(j, Nh);
797                 if (j>i) {
798                         t1 = data[i];
799                         data[i] = data[j];
800                         data[j] = t1;
801                 }
802         }
803
804         do {
805                 fREAL* data_n = &data[n];
806
807                 istep = n << 1;
808                 for (k=0; k<len; k+=istep) {
809                         t1 = data_n[k];
810                         data_n[k] = data[k] - t1;
811                         data[k] += t1;
812                 }
813
814                 n2 = n >> 1;
815                 if (n>2) {
816                         fc = dc = cos(a);
817                         fs = ds = sqrt(1.0 - fc*fc); //sin(a);
818                         bd = n-2;
819                         for (bl=1; bl<n2; bl++) {
820                                 fREAL* data_nbd = &data_n[bd];
821                                 fREAL* data_bd = &data[bd];
822                                 for (k=bl; k<len; k+=istep) {
823                                         t1 = fc*data_n[k] + fs*data_nbd[k];
824                                         t2 = fs*data_n[k] - fc*data_nbd[k];
825                                         data_n[k] = data[k] - t1;
826                                         data_nbd[k] = data_bd[k] - t2;
827                                         data[k] += t1;
828                                         data_bd[k] += t2;
829                                 }
830                                 tt = fc*dc - fs*ds;
831                                 fs = fs*dc + fc*ds;
832                                 fc = tt;
833                                 bd -= 2;
834                         }
835                 }
836
837                 if (n>1) {
838                         for (k=n2; k<len; k+=istep) {
839                                 t1 = data_n[k];
840                                 data_n[k] = data[k] - t1;
841                                 data[k] += t1;
842                         }
843                 }
844
845                 n = istep;
846                 a *= 0.5;
847         } while (n<len);
848
849         if (inverse) {
850                 fREAL sc = (fREAL)1 / (fREAL)len;
851                 for (k=0; k<len; ++k)
852                         data[k] *= sc;
853         }
854 }
855 //------------------------------------------------------------------------------
856 /* 2D Fast Hartley Transform, Mx/My -> log2 of width/height,
857         nzp -> the row where zero pad data starts,
858         inverse -> see above */
859 static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My,
860                 unsigned int nzp, unsigned int inverse)
861 {
862         unsigned int i, j, Nx, Ny, maxy;
863         fREAL t;
864
865         Nx = 1 << Mx;
866         Ny = 1 << My;
867
868         // rows (forward transform skips 0 pad data)
869         maxy = inverse ? Ny : nzp;
870         for (j=0; j<maxy; ++j)
871                 FHT(&data[Nx*j], Mx, inverse);
872
873         // transpose data
874         if (Nx==Ny) {  // square
875                 for (j=0; j<Ny; ++j)
876                         for (i=j+1; i<Nx; ++i) {
877                                 unsigned int op = i + (j << Mx), np = j + (i << My);
878                                 t=data[op], data[op]=data[np], data[np]=t;
879                         }
880         }
881         else {  // rectangular
882                 unsigned int k, Nym = Ny-1, stm = 1 << (Mx + My);
883                 for (i=0; stm>0; i++) {
884                         #define pred(k) (((k & Nym) << Mx) + (k >> My))
885                         for (j=pred(i); j>i; j=pred(j));
886                         if (j < i) continue;
887                         for (k=i, j=pred(i); j!=i; k=j, j=pred(j), stm--)
888                                 { t=data[j], data[j]=data[k], data[k]=t; }
889                         #undef pred
890                         stm--;
891                 }
892         }
893         // swap Mx/My & Nx/Ny
894         i = Nx, Nx = Ny, Ny = i;
895         i = Mx, Mx = My, My = i;
896
897         // now columns == transposed rows
898         for (j=0; j<Ny; ++j)
899                 FHT(&data[Nx*j], Mx, inverse);
900
901         // finalize
902         for (j=0; j<=(Ny >> 1); j++) {
903                 unsigned int jm = (Ny - j) & (Ny-1);
904                 unsigned int ji = j << Mx;
905                 unsigned int jmi = jm << Mx;
906                 for (i=0; i<=(Nx >> 1); i++) {
907                         unsigned int im = (Nx - i) & (Nx-1);
908                         fREAL A = data[ji + i];
909                         fREAL B = data[jmi + i];
910                         fREAL C = data[ji + im];
911                         fREAL D = data[jmi + im];
912                         fREAL E = (fREAL)0.5*((A + D) - (B + C));
913                         data[ji + i] = A - E;
914                         data[jmi + i] = B + E;
915                         data[ji + im] = C + E;
916                         data[jmi + im] = D - E;
917                 }
918         }
919
920 }
921
922 //------------------------------------------------------------------------------
923
924 /* 2D convolution calc, d1 *= d2, M/N - > log2 of width/height */
925 static void fht_convolve(fREAL* d1, fREAL* d2, unsigned int M, unsigned int N)
926 {
927         fREAL a, b;
928         unsigned int i, j, k, L, mj, mL;
929         unsigned int m = 1 << M, n = 1 << N;
930         unsigned int m2 = 1 << (M-1), n2 = 1 << (N-1);
931         unsigned int mn2 = m << (N-1);
932
933         d1[0] *= d2[0];
934         d1[mn2] *= d2[mn2];
935         d1[m2] *= d2[m2];
936         d1[m2 + mn2] *= d2[m2 + mn2];
937         for (i=1; i<m2; i++) {
938                 k = m - i;
939                 a = d1[i]*d2[i] - d1[k]*d2[k];
940                 b = d1[k]*d2[i] + d1[i]*d2[k];
941                 d1[i] = (b + a)*(fREAL)0.5;
942                 d1[k] = (b - a)*(fREAL)0.5;
943                 a = d1[i + mn2]*d2[i + mn2] - d1[k + mn2]*d2[k + mn2];
944                 b = d1[k + mn2]*d2[i + mn2] + d1[i + mn2]*d2[k + mn2];
945                 d1[i + mn2] = (b + a)*(fREAL)0.5;
946                 d1[k + mn2] = (b - a)*(fREAL)0.5;
947         }
948         for (j=1; j<n2; j++) {
949                 L = n - j;
950                 mj = j << M;
951                 mL = L << M;
952                 a = d1[mj]*d2[mj] - d1[mL]*d2[mL];
953                 b = d1[mL]*d2[mj] + d1[mj]*d2[mL];
954                 d1[mj] = (b + a)*(fREAL)0.5;
955                 d1[mL] = (b - a)*(fREAL)0.5;
956                 a = d1[m2 + mj]*d2[m2 + mj] - d1[m2 + mL]*d2[m2 + mL];
957                 b = d1[m2 + mL]*d2[m2 + mj] + d1[m2 + mj]*d2[m2 + mL];
958                 d1[m2 + mj] = (b + a)*(fREAL)0.5;
959                 d1[m2 + mL] = (b - a)*(fREAL)0.5;
960         }
961         for (i=1; i<m2; i++) {
962                 k = m - i;
963                 for (j=1; j<n2; j++) {
964                         L = n - j;
965                         mj = j << M;
966                         mL = L << M;
967                         a = d1[i + mj]*d2[i + mj] - d1[k + mL]*d2[k + mL];
968                         b = d1[k + mL]*d2[i + mj] + d1[i + mj]*d2[k + mL];
969                         d1[i + mj] = (b + a)*(fREAL)0.5;
970                         d1[k + mL] = (b - a)*(fREAL)0.5;
971                         a = d1[i + mL]*d2[i + mL] - d1[k + mj]*d2[k + mj];
972                         b = d1[k + mj]*d2[i + mL] + d1[i + mL]*d2[k + mj];
973                         d1[i + mL] = (b + a)*(fREAL)0.5;
974                         d1[k + mj] = (b - a)*(fREAL)0.5;
975                 }
976         }
977 }
978
979 //------------------------------------------------------------------------------
980
981 void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2)
982 {
983         fREAL *data1, *data2, *fp;
984         unsigned int w2, h2, hw, hh, log2_w, log2_h;
985         fRGB wt, *colp;
986         int x, y, ch;
987         int xbl, ybl, nxb, nyb, xbsz, ybsz;
988         int in2done = 0;
989
990         CompBuf* rdst = alloc_compbuf(in1->x, in1->y, in1->type, 1);
991
992         // convolution result width & height
993         w2 = 2*in2->x - 1;
994         h2 = 2*in2->y - 1;
995         // FFT pow2 required size & log2
996         w2 = nextPow2(w2, &log2_w);
997         h2 = nextPow2(h2, &log2_h);
998
999         // alloc space
1000         data1 = (fREAL*)MEM_callocN(3*w2*h2*sizeof(fREAL), "convolve_fast FHT data1");
1001         data2 = (fREAL*)MEM_callocN(w2*h2*sizeof(fREAL), "convolve_fast FHT data2");
1002
1003         // normalize convolutor
1004         wt[0] = wt[1] = wt[2] = 0.f;
1005         for (y=0; y<in2->y; y++) {
1006                 colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
1007                 for (x=0; x<in2->x; x++)
1008                         fRGB_add(wt, colp[x]);
1009         }
1010         if (wt[0] != 0.f) wt[0] = 1.f/wt[0];
1011         if (wt[1] != 0.f) wt[1] = 1.f/wt[1];
1012         if (wt[2] != 0.f) wt[2] = 1.f/wt[2];
1013         for (y=0; y<in2->y; y++) {
1014                 colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
1015                 for (x=0; x<in2->x; x++)
1016                         fRGB_colormult(colp[x], wt);
1017         }
1018
1019         // copy image data, unpacking interleaved RGBA into separate channels
1020         // only need to calc data1 once
1021
1022         // block add-overlap
1023         hw = in2->x >> 1;
1024         hh = in2->y >> 1;
1025         xbsz = (w2 + 1) - in2->x;
1026         ybsz = (h2 + 1) - in2->y;
1027         nxb = in1->x / xbsz;
1028         if (in1->x % xbsz) nxb++;
1029         nyb = in1->y / ybsz;
1030         if (in1->y % ybsz) nyb++;
1031         for (ybl=0; ybl<nyb; ybl++) {
1032                 for (xbl=0; xbl<nxb; xbl++) {
1033
1034                         // each channel one by one
1035                         for (ch=0; ch<3; ch++) {
1036                                 fREAL* data1ch = &data1[ch*w2*h2];
1037
1038                                 // only need to calc fht data from in2 once, can re-use for every block
1039                                 if (!in2done) {
1040                                         // in2, channel ch -> data1
1041                                         for (y=0; y<in2->y; y++) {
1042                                                 fp = &data1ch[y*w2];
1043                                                 colp = (fRGB*)&in2->rect[y*in2->x*in2->type];
1044                                                 for (x=0; x<in2->x; x++)
1045                                                         fp[x] = colp[x][ch];
1046                                         }
1047                                 }
1048
1049                                 // in1, channel ch -> data2
1050                                 memset(data2, 0, w2*h2*sizeof(fREAL));
1051                                 for (y=0; y<ybsz; y++) {
1052                                         int yy = ybl*ybsz + y;
1053                                         if (yy >= in1->y) continue;
1054                                         fp = &data2[y*w2];
1055                                         colp = (fRGB*)&in1->rect[yy*in1->x*in1->type];
1056                                         for (x=0; x<xbsz; x++) {
1057                                                 int xx = xbl*xbsz + x;
1058                                                 if (xx >= in1->x) continue;
1059                                                 fp[x] = colp[xx][ch];
1060                                         }
1061                                 }
1062
1063                                 // forward FHT
1064                                 // zero pad data start is different for each == height+1
1065                                 if (!in2done) FHT2D(data1ch, log2_w, log2_h, in2->y+1, 0);
1066                                 FHT2D(data2, log2_w, log2_h, in2->y+1, 0);
1067
1068                                 // FHT2D transposed data, row/col now swapped
1069                                 // convolve & inverse FHT
1070                                 fht_convolve(data2, data1ch, log2_h, log2_w);
1071                                 FHT2D(data2, log2_h, log2_w, 0, 1);
1072                                 // data again transposed, so in order again
1073
1074                                 // overlap-add result
1075                                 for (y=0; y<(int)h2; y++) {
1076                                         const int yy = ybl*ybsz + y - hh;
1077                                         if ((yy < 0) || (yy >= in1->y)) continue;
1078                                         fp = &data2[y*w2];
1079                                         colp = (fRGB*)&rdst->rect[yy*in1->x*in1->type];
1080                                         for (x=0; x<(int)w2; x++) {
1081                                                 const int xx = xbl*xbsz + x - hw;
1082                                                 if ((xx < 0) || (xx >= in1->x)) continue;
1083                                                 colp[xx][ch] += fp[x];
1084                                         }
1085                                 }
1086
1087                         }
1088                         in2done = 1;
1089                 }
1090         }
1091
1092         MEM_freeN(data2);
1093         MEM_freeN(data1);
1094         memcpy(dst->rect, rdst->rect, sizeof(float)*dst->x*dst->y*dst->type);
1095         free_compbuf(rdst);
1096 }
1097
1098
1099 /*
1100  *
1101  * Utility functions qd_* should probably be intergrated better with other functions here.
1102  *
1103  */
1104 // sets fcol to pixelcolor at (x, y)
1105 void qd_getPixel(CompBuf* src, int x, int y, float* col)
1106 {
1107         if (src->rect_procedural) {
1108                 float bc[4];
1109                 src->rect_procedural(src, bc, (float)x/(float)src->xrad, (float)y/(float)src->yrad);
1110
1111                 switch(src->type) {
1112                         /* these fallthrough to get all the channels */
1113                         case CB_RGBA: col[3]=bc[3]; 
1114                         case CB_VEC3: col[2]=bc[2];
1115                         case CB_VEC2: col[1]=bc[1];
1116                         case CB_VAL: col[0]=bc[0];
1117                 }
1118         }
1119         else if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
1120                 float* bc = &src->rect[(x + y*src->x)*src->type];
1121                 switch(src->type) {
1122                         /* these fallthrough to get all the channels */
1123                         case CB_RGBA: col[3]=bc[3]; 
1124                         case CB_VEC3: col[2]=bc[2];
1125                         case CB_VEC2: col[1]=bc[1];
1126                         case CB_VAL: col[0]=bc[0];
1127                 }
1128         }
1129         else {
1130                 switch(src->type) {
1131                         /* these fallthrough to get all the channels */
1132                         case CB_RGBA: col[3]=0.0; 
1133                         case CB_VEC3: col[2]=0.0; 
1134                         case CB_VEC2: col[1]=0.0; 
1135                         case CB_VAL: col[0]=0.0; 
1136                 }
1137         }
1138 }
1139
1140 // sets pixel (x, y) to color col
1141 void qd_setPixel(CompBuf* src, int x, int y, float* col)
1142 {
1143         if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
1144                 float* bc = &src->rect[(x + y*src->x)*src->type];
1145                 switch(src->type) {
1146                         /* these fallthrough to get all the channels */
1147                         case CB_RGBA: bc[3]=col[3]; 
1148                         case CB_VEC3: bc[2]=col[2];
1149                         case CB_VEC2: bc[1]=col[1];
1150                         case CB_VAL: bc[0]=col[0];
1151                 }
1152         }
1153 }
1154
1155 // adds fcol to pixelcolor (x, y)
1156 void qd_addPixel(CompBuf* src, int x, int y, float* col)
1157 {
1158         if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
1159                 float* bc = &src->rect[(x + y*src->x)*src->type];
1160                 bc[0] += col[0], bc[1] += col[1], bc[2] += col[2];
1161         }
1162 }
1163
1164 // multiplies pixel by factor value f
1165 void qd_multPixel(CompBuf* src, int x, int y, float f)
1166 {
1167         if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) {
1168                 float* bc = &src->rect[(x + y*src->x)*src->type];
1169                 bc[0] *= f, bc[1] *= f, bc[2] *= f;
1170         }
1171 }
1172
1173 // bilinear interpolation with wraparound
1174 void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col)
1175 {
1176         const float ufl = floor(u), vfl = floor(v);
1177         const int nx = (int)ufl % src->x, ny = (int)vfl % src->y;
1178         const int x1 = (nx < 0) ? (nx + src->x) : nx;
1179         const int y1 = (ny < 0) ? (ny + src->y) : ny;
1180         const int x2 = (x1 + 1) % src->x, y2 = (y1 + 1) % src->y;
1181         const float* c00 = &src->rect[(x1 + y1*src->x)*src->type];
1182         const float* c10 = &src->rect[(x2 + y1*src->x)*src->type];
1183         const float* c01 = &src->rect[(x1 + y2*src->x)*src->type];
1184         const float* c11 = &src->rect[(x2 + y2*src->x)*src->type];
1185         const float uf = u - ufl, vf = v - vfl;
1186         const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
1187         col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
1188         if (src->type != CB_VAL) {
1189                 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
1190                 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
1191                 col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
1192         }
1193 }
1194
1195 // as above, without wrap around
1196 void qd_getPixelLerp(CompBuf* src, float u, float v, float* col)
1197 {
1198         const float ufl = floor(u), vfl = floor(v);
1199         const int x1 = (int)ufl, y1 = (int)vfl;
1200         const int x2 = (int)ceil(u), y2 = (int)ceil(v);
1201         if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) {
1202                 const float B[4] = {0,0,0,0};
1203                 const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y);
1204                 const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type];
1205                 const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type];
1206                 const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type];
1207                 const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type];
1208                 const float uf = u - ufl, vf = v - vfl;
1209                 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
1210                 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
1211                 if (src->type != CB_VAL) {
1212                         col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1];
1213                         col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2];
1214                         col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3];
1215                 }
1216         }
1217         else col[0] = col[1] = col[2] = col[3] = 0.f;
1218 }
1219
1220 // as above, sampling only one channel
1221 void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out)
1222 {
1223         const float ufl = floor(u), vfl = floor(v);
1224         const int x1 = (int)ufl, y1 = (int)vfl;
1225         const int x2 = (int)ceil(u), y2 = (int)ceil(v);
1226         if (chan >= src->type) chan = 0;
1227         if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) {
1228                 const float B[4] = {0,0,0,0};
1229                 const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y);
1230                 const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type + chan];
1231                 const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type + chan];
1232                 const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type + chan];
1233                 const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type + chan];
1234                 const float uf = u - ufl, vf = v - vfl;
1235                 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf;
1236                 out[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0];
1237         }
1238         else *out = 0.f;
1239 }
1240
1241
1242 CompBuf* qd_downScaledCopy(CompBuf* src, int scale)
1243 {
1244         CompBuf* fbuf;
1245         if (scale <= 1)
1246                 fbuf = dupalloc_compbuf(src);
1247         else {
1248                 int nw = src->x/scale, nh = src->y/scale;
1249                 if ((2*(src->x % scale)) > scale) nw++;
1250                 if ((2*(src->y % scale)) > scale) nh++;
1251                 fbuf = alloc_compbuf(nw, nh, src->type, 1);
1252                 {
1253                         int x, y, xx, yy, sx, sy, mx, my;
1254                         float colsum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1255                         float fscale = 1.f/(float)(scale*scale);
1256                         for (y=0; y<nh; y++) {
1257                                 fRGB* fcolp = (fRGB*)&fbuf->rect[y*fbuf->x*fbuf->type];
1258                                 yy = y*scale;
1259                                 my = yy + scale;
1260                                 if (my > src->y) my = src->y;
1261                                 for (x=0; x<nw; x++) {
1262                                         xx = x*scale;
1263                                         mx = xx + scale;
1264                                         if (mx > src->x) mx = src->x;
1265                                         colsum[0] = colsum[1] = colsum[2] = 0.f;
1266                                         for (sy=yy; sy<my; sy++) {
1267                                                 fRGB* scolp = (fRGB*)&src->rect[sy*src->x*src->type];
1268                                                 for (sx=xx; sx<mx; sx++)
1269                                                         fRGB_add(colsum, scolp[sx]);
1270                                         }
1271                                         fRGB_mult(colsum, fscale);
1272                                         fRGB_copy(fcolp[x], colsum);
1273                                 }
1274                         }
1275                 }
1276         }
1277         return fbuf;
1278 }
1279
1280 // fast g.blur, per channel
1281 // xy var. bits 1 & 2 ca be used to blur in x or y direction separately
1282 void IIR_gauss(CompBuf* src, float sigma, int chan, int xy)
1283 {
1284         double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3];
1285         double *X, *Y, *W;
1286         int i, x, y, sz;
1287
1288         // <0.5 not valid, though can have a possibly useful sort of sharpening effect
1289         if (sigma < 0.5f) return;
1290         
1291         if ((xy < 1) || (xy > 3)) xy = 3;
1292         
1293         // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels,
1294         //     so just skiping blur along faulty direction if src's def is below that limit!
1295         if (src->x < 3) xy &= ~(int) 1;
1296         if (src->y < 3) xy &= ~(int) 2;
1297         if (xy < 1) return;
1298
1299         // see "Recursive Gabor Filtering" by Young/VanVliet
1300         // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200
1301         if (sigma >= 3.556f)
1302                 q = 0.9804f*(sigma - 3.556f) + 2.5091f;
1303         else // sigma >= 0.5
1304                 q = (0.0561f*sigma + 0.5784f)*sigma - 0.2568f;
1305         q2 = q*q;
1306         sc = (1.1668 + q)*(3.203729649  + (2.21566 + q)*q);
1307         // no gabor filtering here, so no complex multiplies, just the regular coefs.
1308         // all negated here, so as not to have to recalc Triggs/Sdika matrix
1309         cf[1] = q*(5.788961737 + (6.76492 + 3.0*q)*q)/ sc;
1310         cf[2] = -q2*(3.38246 + 3.0*q)/sc;
1311         // 0 & 3 unchanged
1312         cf[3] = q2*q/sc;
1313         cf[0] = 1.0 - cf[1] - cf[2] - cf[3];
1314
1315         // Triggs/Sdika border corrections,
1316         // it seems to work, not entirely sure if it is actually totally correct,
1317         // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark),
1318         // found one other implementation by Cristoph Lampert,
1319         // but neither seem to be quite the same, result seems to be ok so far anyway.
1320         // Extra scale factor here to not have to do it in filter,
1321         // though maybe this had something to with the precision errors
1322         sc = cf[0]/((1.0 + cf[1] - cf[2] + cf[3])*(1.0 - cf[1] - cf[2] - cf[3])*(1.0 + cf[2] + (cf[1] - cf[3])*cf[3]));
1323         tsM[0] = sc*(-cf[3]*cf[1] + 1.0 - cf[3]*cf[3] - cf[2]);
1324         tsM[1] = sc*((cf[3] + cf[1])*(cf[2] + cf[3]*cf[1]));
1325         tsM[2] = sc*(cf[3]*(cf[1] + cf[3]*cf[2]));
1326         tsM[3] = sc*(cf[1] + cf[3]*cf[2]);
1327         tsM[4] = sc*(-(cf[2] - 1.0)*(cf[2] + cf[3]*cf[1]));
1328         tsM[5] = sc*(-(cf[3]*cf[1] + cf[3]*cf[3] + cf[2] - 1.0)*cf[3]);
1329         tsM[6] = sc*(cf[3]*cf[1] + cf[2] + cf[1]*cf[1] - cf[2]*cf[2]);
1330         tsM[7] = sc*(cf[1]*cf[2] + cf[3]*cf[2]*cf[2] - cf[1]*cf[3]*cf[3] - cf[3]*cf[3]*cf[3] - cf[3]*cf[2] + cf[3]);
1331         tsM[8] = sc*(cf[3]*(cf[1] + cf[3]*cf[2]));
1332
1333 #define YVV(L)                                                                \
1334 {                                                                             \
1335         W[0] = cf[0]*X[0] + cf[1]*X[0] + cf[2]*X[0] + cf[3]*X[0];                 \
1336         W[1] = cf[0]*X[1] + cf[1]*W[0] + cf[2]*X[0] + cf[3]*X[0];                 \
1337         W[2] = cf[0]*X[2] + cf[1]*W[1] + cf[2]*W[0] + cf[3]*X[0];                 \
1338         for (i=3; i<L; i++)                                                       \
1339                 W[i] = cf[0]*X[i] + cf[1]*W[i-1] + cf[2]*W[i-2] + cf[3]*W[i-3];       \
1340         tsu[0] = W[L-1] - X[L-1];                                                 \
1341         tsu[1] = W[L-2] - X[L-1];                                                 \
1342         tsu[2] = W[L-3] - X[L-1];                                                 \
1343         tsv[0] = tsM[0]*tsu[0] + tsM[1]*tsu[1] + tsM[2]*tsu[2] + X[L-1];          \
1344         tsv[1] = tsM[3]*tsu[0] + tsM[4]*tsu[1] + tsM[5]*tsu[2] + X[L-1];          \
1345         tsv[2] = tsM[6]*tsu[0] + tsM[7]*tsu[1] + tsM[8]*tsu[2] + X[L-1];          \
1346         Y[L-1] = cf[0]*W[L-1] + cf[1]*tsv[0] + cf[2]*tsv[1] + cf[3]*tsv[2];       \
1347         Y[L-2] = cf[0]*W[L-2] + cf[1]*Y[L-1] + cf[2]*tsv[0] + cf[3]*tsv[1];       \
1348         Y[L-3] = cf[0]*W[L-3] + cf[1]*Y[L-2] + cf[2]*Y[L-1] + cf[3]*tsv[0];       \
1349         for (i=L-4; i>=0; i--)                                                    \
1350                 Y[i] = cf[0]*W[i] + cf[1]*Y[i+1] + cf[2]*Y[i+2] + cf[3]*Y[i+3];       \
1351 }
1352
1353         // intermediate buffers
1354         sz = MAX2(src->x, src->y);
1355         X = MEM_callocN(sz*sizeof(double), "IIR_gauss X buf");
1356         Y = MEM_callocN(sz*sizeof(double), "IIR_gauss Y buf");
1357         W = MEM_callocN(sz*sizeof(double), "IIR_gauss W buf");
1358         if (xy & 1) {   // H
1359                 for (y=0; y<src->y; ++y) {
1360                         const int yx = y*src->x;
1361                         for (x=0; x<src->x; ++x)
1362                                 X[x] = src->rect[(x + yx)*src->type + chan];
1363                         YVV(src->x);
1364                         for (x=0; x<src->x; ++x)
1365                                 src->rect[(x + yx)*src->type + chan] = Y[x];
1366                 }
1367         }
1368         if (xy & 2) {   // V
1369                 for (x=0; x<src->x; ++x) {
1370                         for (y=0; y<src->y; ++y)
1371                                 X[y] = src->rect[(x + y*src->x)*src->type + chan];
1372                         YVV(src->y);
1373                         for (y=0; y<src->y; ++y)
1374                                 src->rect[(x + y*src->x)*src->type + chan] = Y[y];
1375                 }
1376         }
1377
1378         MEM_freeN(X);
1379         MEM_freeN(W);
1380         MEM_freeN(Y);
1381 #undef YVV
1382 }
1383