Bugfix #6469
[blender.git] / source / blender / nodes / intern / CMP_util.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (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  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "CMP_util.h"
31
32
33
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= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0);
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, cbuf->rect);
125         
126 }
127
128 CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type)
129 {
130         CompBuf *cbuf;
131         rcti disprect= *drect;
132         float *outfp;
133         int dx, y;
134         
135         if(disprect.xmax>rectx) disprect.xmax= rectx;
136         if(disprect.ymax>recty) disprect.ymax= recty;
137         if(disprect.xmin>= disprect.xmax) return NULL;
138         if(disprect.ymin>= disprect.ymax) return NULL;
139         
140         cbuf= alloc_compbuf(disprect.xmax-disprect.xmin, disprect.ymax-disprect.ymin, type, 1);
141         outfp= cbuf->rect;
142         rectf += type*(disprect.ymin*rectx + disprect.xmin);
143         dx= type*cbuf->x;
144         for(y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx)
145                 memcpy(outfp, rectf, sizeof(float)*dx);
146         
147         return cbuf;
148 }
149
150 CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy)
151 {
152         CompBuf *outbuf; 
153         float *rectf, *newrectf, *rf;
154         int x, y, c, pixsize= inbuf->type;
155         int ofsx, ofsy, stepx, stepy;
156         
157         if(inbuf->x==newx && inbuf->y==newy)
158                 return dupalloc_compbuf(inbuf);
159         
160         outbuf= alloc_compbuf(newx, newy, inbuf->type, 1);
161         newrectf= outbuf->rect;
162         
163         stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5;
164         stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5;
165         ofsy = 32768;
166         
167         for (y = newy; y > 0 ; y--){
168                 rectf = inbuf->rect;
169                 rectf += pixsize * (ofsy >> 16) * inbuf->x;
170
171                 ofsy += stepy;
172                 ofsx = 32768;
173                 
174                 for (x = newx ; x>0 ; x--) {
175                         
176                         rf= rectf + pixsize*(ofsx >> 16);
177                         for(c=0; c<pixsize; c++)
178                                 newrectf[c] = rf[c];
179                         
180                         newrectf+= pixsize;
181                         
182                         ofsx += stepx;
183                 }
184         }
185         
186         return outbuf;
187 }
188
189 CompBuf *typecheck_compbuf(CompBuf *inbuf, int type)
190 {
191         if(inbuf && inbuf->type!=type && inbuf->rect_procedural==NULL) {
192                 CompBuf *outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1); 
193                 float *inrf= inbuf->rect;
194                 float *outrf= outbuf->rect;
195                 int x= inbuf->x*inbuf->y;
196                 
197                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
198                 outbuf->xof= inbuf->xof;
199                 outbuf->yof= inbuf->yof;
200                 
201                 if(type==CB_VAL) {
202                         if(inbuf->type==CB_VEC2) {
203                                 for(; x>0; x--, outrf+= 1, inrf+= 2)
204                                         *outrf= 0.5f*(inrf[0]+inrf[1]);
205                         }
206                         else if(inbuf->type==CB_VEC3) {
207                                 for(; x>0; x--, outrf+= 1, inrf+= 3)
208                                         *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]);
209                         }
210                         else if(inbuf->type==CB_RGBA) {
211                                 for(; x>0; x--, outrf+= 1, inrf+= 4)
212                                         *outrf= inrf[0]*0.35f + inrf[1]*0.45f + inrf[2]*0.2f;
213                         }
214                 }
215                 else if(type==CB_VEC2) {
216                         if(inbuf->type==CB_VAL) {
217                                 for(; x>0; x--, outrf+= 2, inrf+= 1) {
218                                         outrf[0]= inrf[0];
219                                         outrf[1]= inrf[0];
220                                 }
221                         }
222                         else if(inbuf->type==CB_VEC3) {
223                                 for(; x>0; x--, outrf+= 2, inrf+= 3) {
224                                         outrf[0]= inrf[0];
225                                         outrf[1]= inrf[1];
226                                 }
227                         }
228                         else if(inbuf->type==CB_RGBA) {
229                                 for(; x>0; x--, outrf+= 2, inrf+= 4) {
230                                         outrf[0]= inrf[0];
231                                         outrf[1]= inrf[1];
232                                 }
233                         }
234                 }
235                 else if(type==CB_VEC3) {
236                         if(inbuf->type==CB_VAL) {
237                                 for(; x>0; x--, outrf+= 3, inrf+= 1) {
238                                         outrf[0]= inrf[0];
239                                         outrf[1]= inrf[0];
240                                         outrf[2]= inrf[0];
241                                 }
242                         }
243                         else if(inbuf->type==CB_VEC2) {
244                                 for(; x>0; x--, outrf+= 3, inrf+= 2) {
245                                         outrf[0]= inrf[0];
246                                         outrf[1]= inrf[1];
247                                         outrf[2]= 0.0f;
248                                 }
249                         }
250                         else if(inbuf->type==CB_RGBA) {
251                                 for(; x>0; x--, outrf+= 3, inrf+= 4) {
252                                         outrf[0]= inrf[0];
253                                         outrf[1]= inrf[1];
254                                         outrf[2]= inrf[2];
255                                 }
256                         }
257                 }
258                 else if(type==CB_RGBA) {
259                         if(inbuf->type==CB_VAL) {
260                                 for(; x>0; x--, outrf+= 4, inrf+= 1) {
261                                         outrf[0]= inrf[0];
262                                         outrf[1]= inrf[0];
263                                         outrf[2]= inrf[0];
264                                         outrf[3]= 1.0f;
265                                 }
266                         }
267                         else if(inbuf->type==CB_VEC2) {
268                                 for(; x>0; x--, outrf+= 4, inrf+= 2) {
269                                         outrf[0]= inrf[0];
270                                         outrf[1]= inrf[1];
271                                         outrf[2]= 0.0f;
272                                         outrf[3]= 1.0f;
273                                 }
274                         }
275                         else if(inbuf->type==CB_VEC3) {
276                                 for(; x>0; x--, outrf+= 4, inrf+= 3) {
277                                         outrf[0]= inrf[0];
278                                         outrf[1]= inrf[1];
279                                         outrf[2]= inrf[2];
280                                         outrf[3]= 1.0f;
281                                 }
282                         }
283                 }
284                 
285                 return outbuf;
286         }
287         return inbuf;
288 }
289
290 float *compbuf_get_pixel(CompBuf *cbuf, float *rectf, int x, int y, int xrad, int yrad)
291 {
292         if(cbuf) {
293                 if(cbuf->rect_procedural) {
294                         cbuf->rect_procedural(cbuf, rectf, (float)x/(float)xrad, (float)y/(float)yrad);
295                         return rectf;
296                 }
297                 else {
298                         static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f};
299                         
300                         /* map coords */
301                         x-= cbuf->xof;
302                         y-= cbuf->yof;
303                         
304                         if(y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col;
305                         if(x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col;
306                         
307                         return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) );
308                 }
309         }
310         else return rectf;
311 }
312
313 /* **************************************************** */
314
315 /* Pixel-to-Pixel operation, 1 Image in, 1 out */
316 void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
317                                                                           void (*func)(bNode *, float *, float *), 
318                                                                           int src_type)
319 {
320         CompBuf *src_use;
321         float *outfp=out->rect, *srcfp;
322         int xrad, yrad, x, y;
323         
324         src_use= typecheck_compbuf(src_buf, src_type);
325         
326         xrad= out->xrad;
327         yrad= out->yrad;
328         
329         for(y= -yrad; y<-yrad+out->y; y++) {
330                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
331                         srcfp= compbuf_get_pixel(src_use, src_col, x, y, xrad, yrad);
332                         func(node, outfp, srcfp);
333                 }
334         }
335         
336         if(src_use!=src_buf)
337                 free_compbuf(src_use);
338 }
339
340 /* Pixel-to-Pixel operation, 2 Images in, 1 out */
341 void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col,
342                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), 
343                                                                           int src_type, int fac_type)
344 {
345         CompBuf *src_use, *fac_use;
346         float *outfp=out->rect, *srcfp, *facfp;
347         int xrad, yrad, x, y;
348         
349         src_use= typecheck_compbuf(src_buf, src_type);
350         fac_use= typecheck_compbuf(fac_buf, fac_type);
351
352         xrad= out->xrad;
353         yrad= out->yrad;
354         
355         for(y= -yrad; y<-yrad+out->y; y++) {
356                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
357                         srcfp= compbuf_get_pixel(src_use, src_col, x, y, xrad, yrad);
358                         facfp= compbuf_get_pixel(fac_use, fac, x, y, xrad, yrad);
359                         
360                         func(node, outfp, srcfp, facfp);
361                 }
362         }
363         if(src_use!=src_buf)
364                 free_compbuf(src_use);
365         if(fac_use!=fac_buf)
366                 free_compbuf(fac_use);
367 }
368
369 /* Pixel-to-Pixel operation, 3 Images in, 1 out */
370 void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, 
371                                                                           CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), 
372                                                                           int src1_type, int src2_type, int fac_type)
373 {
374         CompBuf *src1_use, *src2_use, *fac_use;
375         float *outfp=out->rect, *src1fp, *src2fp, *facfp;
376         int xrad, yrad, x, y;
377         
378         src1_use= typecheck_compbuf(src1_buf, src1_type);
379         src2_use= typecheck_compbuf(src2_buf, src2_type);
380         fac_use= typecheck_compbuf(fac_buf, fac_type);
381         
382         xrad= out->xrad;
383         yrad= out->yrad;
384         
385         for(y= -yrad; y<-yrad+out->y; y++) {
386                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
387                         src1fp= compbuf_get_pixel(src1_use, src1_col, x, y, xrad, yrad);
388                         src2fp= compbuf_get_pixel(src2_use, src2_col, x, y, xrad, yrad);
389                         facfp= compbuf_get_pixel(fac_use, fac, x, y, xrad, yrad);
390                         
391                         func(node, outfp, src1fp, src2fp, facfp);
392                 }
393         }
394         
395         if(src1_use!=src1_buf)
396                 free_compbuf(src1_use);
397         if(src2_use!=src2_buf)
398                 free_compbuf(src2_use);
399         if(fac_use!=fac_buf)
400                 free_compbuf(fac_use);
401 }
402
403 /* Pixel-to-Pixel operation, 4 Images in, 1 out */
404 void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, 
405                                                                           CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, 
406                                                                           void (*func)(bNode *, float *, float *, float *, float *, float *), 
407                                                                           int src1_type, int fac1_type, int src2_type, int fac2_type)
408 {
409         CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use;
410         float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp;
411         int xrad, yrad, x, y;
412         
413         src1_use= typecheck_compbuf(src1_buf, src1_type);
414         src2_use= typecheck_compbuf(src2_buf, src2_type);
415         fac1_use= typecheck_compbuf(fac1_buf, fac1_type);
416         fac2_use= typecheck_compbuf(fac2_buf, fac2_type);
417         
418         xrad= out->xrad;
419         yrad= out->yrad;
420         
421         for(y= -yrad; y<-yrad+out->y; y++) {
422                 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) {
423                         src1fp= compbuf_get_pixel(src1_use, src1_col, x, y, xrad, yrad);
424                         src2fp= compbuf_get_pixel(src2_use, src2_col, x, y, xrad, yrad);
425                         fac1fp= compbuf_get_pixel(fac1_use, fac1, x, y, xrad, yrad);
426                         fac2fp= compbuf_get_pixel(fac2_use, fac2, x, y, xrad, yrad);
427                         
428                         func(node, outfp, src1fp, fac1fp, src2fp, fac2fp);
429                 }
430         }
431         
432         if(src1_use!=src1_buf)
433                 free_compbuf(src1_use);
434         if(src2_use!=src2_buf)
435                 free_compbuf(src2_use);
436         if(fac1_use!=fac1_buf)
437                 free_compbuf(fac1_use);
438         if(fac2_use!=fac2_buf)
439                 free_compbuf(fac2_use);
440 }
441
442
443 CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel)
444 {
445         CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
446         float *valf, *rectf;
447         int tot;
448         
449         /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
450         valbuf->xof= cbuf->xof;
451         valbuf->yof= cbuf->yof;
452         
453         valf= valbuf->rect;
454         
455         /* defaults to returning alpha channel */
456         if ((channel < CHAN_R) && (channel > CHAN_A)) channel = CHAN_A;
457
458         rectf= cbuf->rect + channel;
459         
460         for(tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4)
461                 *valf= *rectf;
462         
463         return valbuf;
464 }
465
466 void generate_preview(bNode *node, CompBuf *stackbuf)
467 {
468         bNodePreview *preview= node->preview;
469         
470         if(preview && stackbuf) {
471                 CompBuf *cbuf, *stackbuf_use;
472                 
473                 if(stackbuf->rect==NULL) return;
474                 
475                 stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA);
476                 
477                 if(stackbuf->x > stackbuf->y) {
478                         preview->xsize= 140;
479                         preview->ysize= (140*stackbuf->y)/stackbuf->x;
480                 }
481                 else {
482                         preview->ysize= 140;
483                         preview->xsize= (140*stackbuf->x)/stackbuf->y;
484                 }
485                 
486                 cbuf= scalefast_compbuf(stackbuf_use, preview->xsize, preview->ysize);
487                 
488                 /* this ensures free-compbuf does the right stuff */
489                 SWAP(float *, cbuf->rect, node->preview->rect);
490                 
491                 free_compbuf(cbuf);
492                 if(stackbuf_use!=stackbuf)
493                         free_compbuf(stackbuf_use);
494
495         }
496 }
497
498 void do_rgba_to_yuva(bNode *node, float *out, float *in)
499 {
500    rgb_to_yuv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
501    out[3]=in[3];
502 }
503
504 void do_rgba_to_hsva(bNode *node, float *out, float *in)
505 {
506    rgb_to_hsv(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
507    out[3]=in[3];
508 }
509
510 void do_rgba_to_ycca(bNode *node, float *out, float *in)
511 {
512    rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
513    out[3]=in[3];
514 }
515
516 void do_yuva_to_rgba(bNode *node, float *out, float *in)
517 {
518    yuv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
519    out[3]=in[3];
520 }
521
522 void do_hsva_to_rgba(bNode *node, float *out, float *in)
523 {
524    hsv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
525    out[3]=in[3];
526 }
527
528 void do_ycca_to_rgba(bNode *node, float *out, float *in)
529 {
530    ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
531    out[3]=in[3];
532 }
533
534 void do_copy_rgba(bNode *node, float *out, float *in)
535 {
536    QUATCOPY(out, in);
537 }
538
539 void do_copy_rgb(bNode *node, float *out, float *in)
540 {
541    VECCOPY(out, in);
542    out[3]= 1.0f;
543 }
544
545 void do_copy_value(bNode *node, float *out, float *in)
546 {
547    out[0]= in[0];
548 }
549
550 void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac)
551 {
552    VECCOPY(out, in);
553    out[3]= *fac;
554 }
555
556 /* only accepts RGBA buffers */
557 void gamma_correct_compbuf(CompBuf *img, int inversed)
558 {
559    float *drect;
560    int x;
561
562    if(img->type!=CB_RGBA) return;
563
564    drect= img->rect;
565    if(inversed) {
566       for(x=img->x*img->y; x>0; x--, drect+=4) {
567          if(drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f;
568          if(drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f;
569          if(drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f;
570       }
571    }
572    else {
573       for(x=img->x*img->y; x>0; x--, drect+=4) {
574          if(drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f;
575          if(drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f;
576          if(drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f;
577       }
578    }
579 }