|
Blender
V2.59
|
00001 /* 00002 * $Id: CMP_util.c 38344 2011-07-12 18:59:54Z jbakker $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2006 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): none yet. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include "CMP_util.h" 00036 00037 CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc) 00038 { 00039 CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf"); 00040 00041 cbuf->x= sizex; 00042 cbuf->y= sizey; 00043 cbuf->xrad= sizex/2; 00044 cbuf->yrad= sizey/2; 00045 00046 cbuf->type= type; 00047 if(alloc) { 00048 if(cbuf->type==CB_RGBA) 00049 cbuf->rect= MEM_mapallocN(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect"); 00050 else if(cbuf->type==CB_VEC3) 00051 cbuf->rect= MEM_mapallocN(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect"); 00052 else if(cbuf->type==CB_VEC2) 00053 cbuf->rect= MEM_mapallocN(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect"); 00054 else 00055 cbuf->rect= MEM_mapallocN(sizeof(float)*sizex*sizey, "compbuf Fac rect"); 00056 cbuf->malloc= 1; 00057 } 00058 cbuf->disprect.xmin= 0; 00059 cbuf->disprect.ymin= 0; 00060 cbuf->disprect.xmax= sizex; 00061 cbuf->disprect.ymax= sizey; 00062 00063 return cbuf; 00064 } 00065 00066 CompBuf *dupalloc_compbuf(CompBuf *cbuf) 00067 { 00068 CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); 00069 if(dupbuf) { 00070 memmove(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y); 00071 00072 dupbuf->xof= cbuf->xof; 00073 dupbuf->yof= cbuf->yof; 00074 } 00075 return dupbuf; 00076 } 00077 00078 /* instead of reference counting, we create a list */ 00079 CompBuf *pass_on_compbuf(CompBuf *cbuf) 00080 { 00081 CompBuf *dupbuf= (cbuf)? alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0): NULL; 00082 CompBuf *lastbuf; 00083 00084 if(dupbuf) { 00085 dupbuf->rect= cbuf->rect; 00086 dupbuf->xof= cbuf->xof; 00087 dupbuf->yof= cbuf->yof; 00088 dupbuf->malloc= 0; 00089 00090 /* get last buffer in list, and append dupbuf */ 00091 for(lastbuf= cbuf; lastbuf; lastbuf= lastbuf->next) 00092 if(lastbuf->next==NULL) 00093 break; 00094 lastbuf->next= dupbuf; 00095 dupbuf->prev= lastbuf; 00096 } 00097 return dupbuf; 00098 } 00099 00100 00101 void free_compbuf(CompBuf *cbuf) 00102 { 00103 /* check referencing, then remove from list and set malloc tag */ 00104 if(cbuf->prev || cbuf->next) { 00105 if(cbuf->prev) 00106 cbuf->prev->next= cbuf->next; 00107 if(cbuf->next) 00108 cbuf->next->prev= cbuf->prev; 00109 if(cbuf->malloc) { 00110 if(cbuf->prev) 00111 cbuf->prev->malloc= 1; 00112 else 00113 cbuf->next->malloc= 1; 00114 cbuf->malloc= 0; 00115 } 00116 } 00117 00118 if(cbuf->malloc && cbuf->rect) 00119 MEM_freeN(cbuf->rect); 00120 00121 MEM_freeN(cbuf); 00122 } 00123 00124 void print_compbuf(char *str, CompBuf *cbuf) 00125 { 00126 printf("Compbuf %s %d %d %p\n", str, cbuf->x, cbuf->y, (void *)cbuf->rect); 00127 00128 } 00129 00130 void compbuf_set_node(CompBuf *cbuf, bNode *node) 00131 { 00132 if (cbuf) cbuf->node = node; 00133 } 00134 00135 /* used for disabling node (similar code in node_draw.c for disable line and node_edit for untangling nodes) */ 00136 void node_compo_pass_on(bNode *node, bNodeStack **nsin, bNodeStack **nsout) 00137 { 00138 CompBuf *valbuf= NULL, *colbuf= NULL, *vecbuf= NULL; 00139 bNodeSocket *sock; 00140 int a; 00141 00142 /* connect the first value buffer in with first value out */ 00143 /* connect the first RGBA buffer in with first RGBA out */ 00144 00145 /* test the inputs */ 00146 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { 00147 if(nsin[a]->data) { 00148 CompBuf *cbuf= nsin[a]->data; 00149 if(cbuf->type==1 && valbuf==NULL) valbuf= cbuf; 00150 if(cbuf->type==3 && vecbuf==NULL) vecbuf= cbuf; 00151 if(cbuf->type==4 && colbuf==NULL) colbuf= cbuf; 00152 } 00153 } 00154 00155 /* outputs */ 00156 if(valbuf || colbuf || vecbuf) { 00157 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { 00158 if(nsout[a]->hasoutput) { 00159 if(sock->type==SOCK_VALUE && valbuf) { 00160 nsout[a]->data= pass_on_compbuf(valbuf); 00161 valbuf= NULL; 00162 } 00163 if(sock->type==SOCK_VECTOR && vecbuf) { 00164 nsout[a]->data= pass_on_compbuf(vecbuf); 00165 vecbuf= NULL; 00166 } 00167 if(sock->type==SOCK_RGBA && colbuf) { 00168 nsout[a]->data= pass_on_compbuf(colbuf); 00169 colbuf= NULL; 00170 } 00171 } 00172 } 00173 } 00174 } 00175 00176 00177 CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type) 00178 { 00179 CompBuf *cbuf; 00180 rcti disprect= *drect; 00181 float *outfp; 00182 int dx, y; 00183 00184 if(disprect.xmax>rectx) disprect.xmax= rectx; 00185 if(disprect.ymax>recty) disprect.ymax= recty; 00186 if(disprect.xmin>= disprect.xmax) return NULL; 00187 if(disprect.ymin>= disprect.ymax) return NULL; 00188 00189 cbuf= alloc_compbuf(disprect.xmax-disprect.xmin, disprect.ymax-disprect.ymin, type, 1); 00190 outfp= cbuf->rect; 00191 rectf += type*(disprect.ymin*rectx + disprect.xmin); 00192 dx= type*cbuf->x; 00193 for(y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx) 00194 memcpy(outfp, rectf, sizeof(float)*dx); 00195 00196 return cbuf; 00197 } 00198 00199 CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy) 00200 { 00201 CompBuf *outbuf; 00202 float *rectf, *newrectf, *rf; 00203 int x, y, c, pixsize= inbuf->type; 00204 int ofsx, ofsy, stepx, stepy; 00205 00206 if(inbuf->x==newx && inbuf->y==newy) 00207 return dupalloc_compbuf(inbuf); 00208 00209 outbuf= alloc_compbuf(newx, newy, inbuf->type, 1); 00210 newrectf= outbuf->rect; 00211 00212 stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5; 00213 stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5; 00214 ofsy = 32768; 00215 00216 for (y = newy; y > 0 ; y--){ 00217 rectf = inbuf->rect; 00218 rectf += pixsize * (ofsy >> 16) * inbuf->x; 00219 00220 ofsy += stepy; 00221 ofsx = 32768; 00222 00223 for (x = newx ; x>0 ; x--) { 00224 00225 rf= rectf + pixsize*(ofsx >> 16); 00226 for(c=0; c<pixsize; c++) 00227 newrectf[c] = rf[c]; 00228 00229 newrectf+= pixsize; 00230 00231 ofsx += stepx; 00232 } 00233 } 00234 00235 return outbuf; 00236 } 00237 00238 void typecheck_compbuf_color(float *out, float *in, int outtype, int intype) 00239 { 00240 if(intype == outtype) { 00241 memcpy(out, in, sizeof(float)*outtype); 00242 } 00243 else if(outtype==CB_VAL) { 00244 if(intype==CB_VEC2) { 00245 *out= 0.5f*(in[0]+in[1]); 00246 } 00247 else if(intype==CB_VEC3) { 00248 *out= 0.333333f*(in[0]+in[1]+in[2]); 00249 } 00250 else if(intype==CB_RGBA) { 00251 *out= in[0]*0.35f + in[1]*0.45f + in[2]*0.2f; 00252 } 00253 } 00254 else if(outtype==CB_VEC2) { 00255 if(intype==CB_VAL) { 00256 out[0]= in[0]; 00257 out[1]= in[0]; 00258 } 00259 else if(intype==CB_VEC3) { 00260 out[0]= in[0]; 00261 out[1]= in[1]; 00262 } 00263 else if(intype==CB_RGBA) { 00264 out[0]= in[0]; 00265 out[1]= in[1]; 00266 } 00267 } 00268 else if(outtype==CB_VEC3) { 00269 if(intype==CB_VAL) { 00270 out[0]= in[0]; 00271 out[1]= in[0]; 00272 out[2]= in[0]; 00273 } 00274 else if(intype==CB_VEC2) { 00275 out[0]= in[0]; 00276 out[1]= in[1]; 00277 out[2]= 0.0f; 00278 } 00279 else if(intype==CB_RGBA) { 00280 out[0]= in[0]; 00281 out[1]= in[1]; 00282 out[2]= in[2]; 00283 } 00284 } 00285 else if(outtype==CB_RGBA) { 00286 if(intype==CB_VAL) { 00287 out[0]= in[0]; 00288 out[1]= in[0]; 00289 out[2]= in[0]; 00290 out[3]= 1.0f; 00291 } 00292 else if(intype==CB_VEC2) { 00293 out[0]= in[0]; 00294 out[1]= in[1]; 00295 out[2]= 0.0f; 00296 out[3]= 1.0f; 00297 } 00298 else if(intype==CB_VEC3) { 00299 out[0]= in[0]; 00300 out[1]= in[1]; 00301 out[2]= in[2]; 00302 out[3]= 1.0f; 00303 } 00304 } 00305 } 00306 00307 CompBuf *typecheck_compbuf(CompBuf *inbuf, int type) 00308 { 00309 if(inbuf && inbuf->type!=type) { 00310 CompBuf *outbuf; 00311 float *inrf, *outrf; 00312 int x; 00313 00314 outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1); 00315 00316 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ 00317 outbuf->xof= inbuf->xof; 00318 outbuf->yof= inbuf->yof; 00319 00320 if(inbuf->rect_procedural) { 00321 outbuf->rect_procedural= inbuf->rect_procedural; 00322 VECCOPY(outbuf->procedural_size, inbuf->procedural_size); 00323 VECCOPY(outbuf->procedural_offset, inbuf->procedural_offset); 00324 outbuf->procedural_type= inbuf->procedural_type; 00325 outbuf->node= inbuf->node; 00326 return outbuf; 00327 } 00328 00329 inrf= inbuf->rect; 00330 outrf= outbuf->rect; 00331 x= inbuf->x*inbuf->y; 00332 00333 if(type==CB_VAL) { 00334 if(inbuf->type==CB_VEC2) { 00335 for(; x>0; x--, outrf+= 1, inrf+= 2) 00336 *outrf= 0.5f*(inrf[0]+inrf[1]); 00337 } 00338 else if(inbuf->type==CB_VEC3) { 00339 for(; x>0; x--, outrf+= 1, inrf+= 3) 00340 *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]); 00341 } 00342 else if(inbuf->type==CB_RGBA) { 00343 for(; x>0; x--, outrf+= 1, inrf+= 4) 00344 *outrf= inrf[0]*0.35f + inrf[1]*0.45f + inrf[2]*0.2f; 00345 } 00346 } 00347 else if(type==CB_VEC2) { 00348 if(inbuf->type==CB_VAL) { 00349 for(; x>0; x--, outrf+= 2, inrf+= 1) { 00350 outrf[0]= inrf[0]; 00351 outrf[1]= inrf[0]; 00352 } 00353 } 00354 else if(inbuf->type==CB_VEC3) { 00355 for(; x>0; x--, outrf+= 2, inrf+= 3) { 00356 outrf[0]= inrf[0]; 00357 outrf[1]= inrf[1]; 00358 } 00359 } 00360 else if(inbuf->type==CB_RGBA) { 00361 for(; x>0; x--, outrf+= 2, inrf+= 4) { 00362 outrf[0]= inrf[0]; 00363 outrf[1]= inrf[1]; 00364 } 00365 } 00366 } 00367 else if(type==CB_VEC3) { 00368 if(inbuf->type==CB_VAL) { 00369 for(; x>0; x--, outrf+= 3, inrf+= 1) { 00370 outrf[0]= inrf[0]; 00371 outrf[1]= inrf[0]; 00372 outrf[2]= inrf[0]; 00373 } 00374 } 00375 else if(inbuf->type==CB_VEC2) { 00376 for(; x>0; x--, outrf+= 3, inrf+= 2) { 00377 outrf[0]= inrf[0]; 00378 outrf[1]= inrf[1]; 00379 outrf[2]= 0.0f; 00380 } 00381 } 00382 else if(inbuf->type==CB_RGBA) { 00383 for(; x>0; x--, outrf+= 3, inrf+= 4) { 00384 outrf[0]= inrf[0]; 00385 outrf[1]= inrf[1]; 00386 outrf[2]= inrf[2]; 00387 } 00388 } 00389 } 00390 else if(type==CB_RGBA) { 00391 if(inbuf->type==CB_VAL) { 00392 for(; x>0; x--, outrf+= 4, inrf+= 1) { 00393 outrf[0]= inrf[0]; 00394 outrf[1]= inrf[0]; 00395 outrf[2]= inrf[0]; 00396 outrf[3]= 1.0f; 00397 } 00398 } 00399 else if(inbuf->type==CB_VEC2) { 00400 for(; x>0; x--, outrf+= 4, inrf+= 2) { 00401 outrf[0]= inrf[0]; 00402 outrf[1]= inrf[1]; 00403 outrf[2]= 0.0f; 00404 outrf[3]= 1.0f; 00405 } 00406 } 00407 else if(inbuf->type==CB_VEC3) { 00408 for(; x>0; x--, outrf+= 4, inrf+= 3) { 00409 outrf[0]= inrf[0]; 00410 outrf[1]= inrf[1]; 00411 outrf[2]= inrf[2]; 00412 outrf[3]= 1.0f; 00413 } 00414 } 00415 } 00416 00417 return outbuf; 00418 } 00419 return inbuf; 00420 } 00421 00422 static float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad) 00423 { 00424 if(cbuf) { 00425 if(cbuf->rect_procedural) { 00426 cbuf->rect_procedural(cbuf, use, (float)x/(float)xrad, (float)y/(float)yrad); 00427 return use; 00428 } 00429 else { 00430 static float col[4]= {0.0f, 0.0f, 0.0f, 0.0f}; 00431 00432 /* map coords */ 00433 x-= cbuf->xof; 00434 y-= cbuf->yof; 00435 00436 if(y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col; 00437 if(x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col; 00438 00439 return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) ); 00440 } 00441 } 00442 else return defcol; 00443 } 00444 00445 /* **************************************************** */ 00446 00447 /* Pixel-to-Pixel operation, 1 Image in, 1 out */ 00448 void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, 00449 void (*func)(bNode *, float *, float *), 00450 int src_type) 00451 { 00452 CompBuf *src_use; 00453 float *outfp=out->rect, *srcfp; 00454 float color[4]; /* local color if compbuf is procedural */ 00455 int xrad, yrad, x, y; 00456 00457 src_use= typecheck_compbuf(src_buf, src_type); 00458 00459 xrad= out->xrad; 00460 yrad= out->yrad; 00461 00462 for(y= -yrad; y<-yrad+out->y; y++) { 00463 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { 00464 srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad); 00465 func(node, outfp, srcfp); 00466 } 00467 } 00468 00469 if(src_use!=src_buf) 00470 free_compbuf(src_use); 00471 } 00472 00473 /* Pixel-to-Pixel operation, 2 Images in, 1 out */ 00474 void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, 00475 CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), 00476 int src_type, int fac_type) 00477 { 00478 CompBuf *src_use, *fac_use; 00479 float *outfp=out->rect, *srcfp, *facfp; 00480 float color[4]; /* local color if compbuf is procedural */ 00481 int xrad, yrad, x, y; 00482 00483 src_use= typecheck_compbuf(src_buf, src_type); 00484 fac_use= typecheck_compbuf(fac_buf, fac_type); 00485 00486 xrad= out->xrad; 00487 yrad= out->yrad; 00488 00489 for(y= -yrad; y<-yrad+out->y; y++) { 00490 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { 00491 srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad); 00492 facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad); 00493 00494 func(node, outfp, srcfp, facfp); 00495 } 00496 } 00497 if(src_use!=src_buf) 00498 free_compbuf(src_use); 00499 if(fac_use!=fac_buf) 00500 free_compbuf(fac_use); 00501 } 00502 00503 /* Pixel-to-Pixel operation, 3 Images in, 1 out */ 00504 void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, 00505 CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), 00506 int src1_type, int src2_type, int fac_type) 00507 { 00508 CompBuf *src1_use, *src2_use, *fac_use; 00509 float *outfp=out->rect, *src1fp, *src2fp, *facfp; 00510 float color[4]; /* local color if compbuf is procedural */ 00511 int xrad, yrad, x, y; 00512 00513 src1_use= typecheck_compbuf(src1_buf, src1_type); 00514 src2_use= typecheck_compbuf(src2_buf, src2_type); 00515 fac_use= typecheck_compbuf(fac_buf, fac_type); 00516 00517 xrad= out->xrad; 00518 yrad= out->yrad; 00519 00520 for(y= -yrad; y<-yrad+out->y; y++) { 00521 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { 00522 src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad); 00523 src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad); 00524 facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad); 00525 00526 func(node, outfp, src1fp, src2fp, facfp); 00527 } 00528 } 00529 00530 if(src1_use!=src1_buf) 00531 free_compbuf(src1_use); 00532 if(src2_use!=src2_buf) 00533 free_compbuf(src2_use); 00534 if(fac_use!=fac_buf) 00535 free_compbuf(fac_use); 00536 } 00537 00538 /* Pixel-to-Pixel operation, 4 Images in, 1 out */ 00539 void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, 00540 CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, 00541 void (*func)(bNode *, float *, float *, float *, float *, float *), 00542 int src1_type, int fac1_type, int src2_type, int fac2_type) 00543 { 00544 CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use; 00545 float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp; 00546 float color[4]; /* local color if compbuf is procedural */ 00547 int xrad, yrad, x, y; 00548 00549 src1_use= typecheck_compbuf(src1_buf, src1_type); 00550 src2_use= typecheck_compbuf(src2_buf, src2_type); 00551 fac1_use= typecheck_compbuf(fac1_buf, fac1_type); 00552 fac2_use= typecheck_compbuf(fac2_buf, fac2_type); 00553 00554 xrad= out->xrad; 00555 yrad= out->yrad; 00556 00557 for(y= -yrad; y<-yrad+out->y; y++) { 00558 for(x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { 00559 src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad); 00560 src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad); 00561 fac1fp= compbuf_get_pixel(fac1_use, fac1, color, x, y, xrad, yrad); 00562 fac2fp= compbuf_get_pixel(fac2_use, fac2, color, x, y, xrad, yrad); 00563 00564 func(node, outfp, src1fp, fac1fp, src2fp, fac2fp); 00565 } 00566 } 00567 00568 if(src1_use!=src1_buf) 00569 free_compbuf(src1_use); 00570 if(src2_use!=src2_buf) 00571 free_compbuf(src2_use); 00572 if(fac1_use!=fac1_buf) 00573 free_compbuf(fac1_use); 00574 if(fac2_use!=fac2_buf) 00575 free_compbuf(fac2_use); 00576 } 00577 00578 00579 CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel) 00580 { 00581 CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); 00582 float *valf, *rectf; 00583 int tot; 00584 00585 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ 00586 valbuf->xof= cbuf->xof; 00587 valbuf->yof= cbuf->yof; 00588 00589 valf= valbuf->rect; 00590 00591 /* defaults to returning alpha channel */ 00592 if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A; 00593 00594 rectf= cbuf->rect + channel; 00595 00596 for(tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) 00597 *valf= *rectf; 00598 00599 return valbuf; 00600 } 00601 00602 static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy) 00603 { 00604 CompBuf *outbuf; 00605 float *outfp; 00606 int xrad, yrad, x, y; 00607 00608 outbuf= alloc_compbuf(newx, newy, CB_RGBA, 1); 00609 00610 outfp= outbuf->rect; 00611 xrad= outbuf->xrad; 00612 yrad= outbuf->yrad; 00613 00614 for(y= -yrad; y<-yrad+outbuf->y; y++) 00615 for(x= -xrad; x<-xrad+outbuf->x; x++, outfp+=outbuf->type) 00616 cbuf->rect_procedural(cbuf, outfp, (float)x/(float)xrad, (float)y/(float)yrad); 00617 00618 return outbuf; 00619 } 00620 00621 void generate_preview(void *data, bNode *node, CompBuf *stackbuf) 00622 { 00623 RenderData *rd= data; 00624 bNodePreview *preview= node->preview; 00625 int xsize, ysize; 00626 int color_manage= rd->color_mgt_flag & R_COLOR_MANAGEMENT; 00627 unsigned char *rect; 00628 00629 if(preview && stackbuf) { 00630 CompBuf *cbuf, *stackbuf_use; 00631 00632 if(stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return; 00633 00634 stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA); 00635 00636 if(stackbuf->x > stackbuf->y) { 00637 xsize= 140; 00638 ysize= (140*stackbuf->y)/stackbuf->x; 00639 } 00640 else { 00641 ysize= 140; 00642 xsize= (140*stackbuf->x)/stackbuf->y; 00643 } 00644 00645 if(stackbuf_use->rect_procedural) 00646 cbuf= generate_procedural_preview(stackbuf_use, xsize, ysize); 00647 else 00648 cbuf= scalefast_compbuf(stackbuf_use, xsize, ysize); 00649 00650 /* convert to byte for preview */ 00651 rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect"); 00652 00653 if(color_manage) 00654 floatbuf_to_srgb_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); 00655 else 00656 floatbuf_to_byte(cbuf->rect, rect, 0, xsize, 0, ysize, xsize); 00657 00658 free_compbuf(cbuf); 00659 if(stackbuf_use!=stackbuf) 00660 free_compbuf(stackbuf_use); 00661 00662 BLI_lock_thread(LOCK_PREVIEW); 00663 00664 if(preview->rect) 00665 MEM_freeN(preview->rect); 00666 preview->xsize= xsize; 00667 preview->ysize= ysize; 00668 preview->rect= rect; 00669 00670 BLI_unlock_thread(LOCK_PREVIEW); 00671 } 00672 } 00673 00674 void do_rgba_to_yuva(bNode *UNUSED(node), float *out, float *in) 00675 { 00676 rgb_to_yuv(in[0],in[1],in[2], &out[0], &out[1], &out[2]); 00677 out[3]=in[3]; 00678 } 00679 00680 void do_rgba_to_hsva(bNode *UNUSED(node), float *out, float *in) 00681 { 00682 rgb_to_hsv(in[0],in[1],in[2], &out[0], &out[1], &out[2]); 00683 out[3]=in[3]; 00684 } 00685 00686 void do_rgba_to_ycca(bNode *UNUSED(node), float *out, float *in) 00687 { 00688 rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); 00689 out[3]=in[3]; 00690 } 00691 00692 void do_yuva_to_rgba(bNode *UNUSED(node), float *out, float *in) 00693 { 00694 yuv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]); 00695 out[3]=in[3]; 00696 } 00697 00698 void do_hsva_to_rgba(bNode *UNUSED(node), float *out, float *in) 00699 { 00700 hsv_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]); 00701 out[3]=in[3]; 00702 } 00703 00704 void do_ycca_to_rgba(bNode *UNUSED(node), float *out, float *in) 00705 { 00706 ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); 00707 out[3]=in[3]; 00708 } 00709 00710 void do_copy_rgba(bNode *UNUSED(node), float *out, float *in) 00711 { 00712 QUATCOPY(out, in); 00713 } 00714 00715 void do_copy_rgb(bNode *UNUSED(node), float *out, float *in) 00716 { 00717 VECCOPY(out, in); 00718 out[3]= 1.0f; 00719 } 00720 00721 void do_copy_value(bNode *UNUSED(node), float *out, float *in) 00722 { 00723 out[0]= in[0]; 00724 } 00725 00726 void do_copy_a_rgba(bNode *UNUSED(node), float *out, float *in, float *fac) 00727 { 00728 VECCOPY(out, in); 00729 out[3]= *fac; 00730 } 00731 00732 /* only accepts RGBA buffers */ 00733 void gamma_correct_compbuf(CompBuf *img, int inversed) 00734 { 00735 float *drect; 00736 int x; 00737 00738 if(img->type!=CB_RGBA) return; 00739 00740 drect= img->rect; 00741 if(inversed) { 00742 for(x=img->x*img->y; x>0; x--, drect+=4) { 00743 if(drect[0]>0.0f) drect[0]= sqrt(drect[0]); else drect[0]= 0.0f; 00744 if(drect[1]>0.0f) drect[1]= sqrt(drect[1]); else drect[1]= 0.0f; 00745 if(drect[2]>0.0f) drect[2]= sqrt(drect[2]); else drect[2]= 0.0f; 00746 } 00747 } 00748 else { 00749 for(x=img->x*img->y; x>0; x--, drect+=4) { 00750 if(drect[0]>0.0f) drect[0]*= drect[0]; else drect[0]= 0.0f; 00751 if(drect[1]>0.0f) drect[1]*= drect[1]; else drect[1]= 0.0f; 00752 if(drect[2]>0.0f) drect[2]*= drect[2]; else drect[2]= 0.0f; 00753 } 00754 } 00755 } 00756 00757 void premul_compbuf(CompBuf *img, int inversed) 00758 { 00759 float *drect; 00760 int x; 00761 00762 if(img->type!=CB_RGBA) return; 00763 00764 drect= img->rect; 00765 if(inversed) { 00766 for(x=img->x*img->y; x>0; x--, drect+=4) { 00767 if(fabs(drect[3]) < 1e-5f) { 00768 drect[0]= 0.0f; 00769 drect[1]= 0.0f; 00770 drect[2]= 0.0f; 00771 } 00772 else { 00773 drect[0] /= drect[3]; 00774 drect[1] /= drect[3]; 00775 drect[2] /= drect[3]; 00776 } 00777 } 00778 } 00779 else { 00780 for(x=img->x*img->y; x>0; x--, drect+=4) { 00781 drect[0] *= drect[3]; 00782 drect[1] *= drect[3]; 00783 drect[2] *= drect[3]; 00784 } 00785 } 00786 } 00787 00788 00789 00790 /* 00791 * 2D Fast Hartley Transform, used for convolution 00792 */ 00793 00794 typedef float fREAL; 00795 00796 // returns next highest power of 2 of x, as well it's log2 in L2 00797 static unsigned int nextPow2(unsigned int x, unsigned int* L2) 00798 { 00799 unsigned int pw, x_notpow2 = x & (x-1); 00800 *L2 = 0; 00801 while (x>>=1) ++(*L2); 00802 pw = 1 << (*L2); 00803 if (x_notpow2) { (*L2)++; pw<<=1; } 00804 return pw; 00805 } 00806 00807 //------------------------------------------------------------------------------ 00808 00809 // from FXT library by Joerg Arndt, faster in order bitreversal 00810 // use: r = revbin_upd(r, h) where h = N>>1 00811 static unsigned int revbin_upd(unsigned int r, unsigned int h) 00812 { 00813 while (!((r^=h)&h)) h >>= 1; 00814 return r; 00815 } 00816 //------------------------------------------------------------------------------ 00817 static void FHT(fREAL* data, unsigned int M, unsigned int inverse) 00818 { 00819 double tt, fc, dc, fs, ds, a = M_PI; 00820 fREAL t1, t2; 00821 int n2, bd, bl, istep, k, len = 1 << M, n = 1; 00822 00823 int i, j = 0; 00824 unsigned int Nh = len >> 1; 00825 for (i=1;i<(len-1);++i) { 00826 j = revbin_upd(j, Nh); 00827 if (j>i) { 00828 t1 = data[i]; 00829 data[i] = data[j]; 00830 data[j] = t1; 00831 } 00832 } 00833 00834 do { 00835 fREAL* data_n = &data[n]; 00836 00837 istep = n << 1; 00838 for (k=0; k<len; k+=istep) { 00839 t1 = data_n[k]; 00840 data_n[k] = data[k] - t1; 00841 data[k] += t1; 00842 } 00843 00844 n2 = n >> 1; 00845 if (n>2) { 00846 fc = dc = cos(a); 00847 fs = ds = sqrt(1.0 - fc*fc); //sin(a); 00848 bd = n-2; 00849 for (bl=1; bl<n2; bl++) { 00850 fREAL* data_nbd = &data_n[bd]; 00851 fREAL* data_bd = &data[bd]; 00852 for (k=bl; k<len; k+=istep) { 00853 t1 = fc*data_n[k] + fs*data_nbd[k]; 00854 t2 = fs*data_n[k] - fc*data_nbd[k]; 00855 data_n[k] = data[k] - t1; 00856 data_nbd[k] = data_bd[k] - t2; 00857 data[k] += t1; 00858 data_bd[k] += t2; 00859 } 00860 tt = fc*dc - fs*ds; 00861 fs = fs*dc + fc*ds; 00862 fc = tt; 00863 bd -= 2; 00864 } 00865 } 00866 00867 if (n>1) { 00868 for (k=n2; k<len; k+=istep) { 00869 t1 = data_n[k]; 00870 data_n[k] = data[k] - t1; 00871 data[k] += t1; 00872 } 00873 } 00874 00875 n = istep; 00876 a *= 0.5; 00877 } while (n<len); 00878 00879 if (inverse) { 00880 fREAL sc = (fREAL)1 / (fREAL)len; 00881 for (k=0; k<len; ++k) 00882 data[k] *= sc; 00883 } 00884 } 00885 //------------------------------------------------------------------------------ 00886 /* 2D Fast Hartley Transform, Mx/My -> log2 of width/height, 00887 nzp -> the row where zero pad data starts, 00888 inverse -> see above */ 00889 static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My, 00890 unsigned int nzp, unsigned int inverse) 00891 { 00892 unsigned int i, j, Nx, Ny, maxy; 00893 fREAL t; 00894 00895 Nx = 1 << Mx; 00896 Ny = 1 << My; 00897 00898 // rows (forward transform skips 0 pad data) 00899 maxy = inverse ? Ny : nzp; 00900 for (j=0; j<maxy; ++j) 00901 FHT(&data[Nx*j], Mx, inverse); 00902 00903 // transpose data 00904 if (Nx==Ny) { // square 00905 for (j=0; j<Ny; ++j) 00906 for (i=j+1; i<Nx; ++i) { 00907 unsigned int op = i + (j << Mx), np = j + (i << My); 00908 t=data[op], data[op]=data[np], data[np]=t; 00909 } 00910 } 00911 else { // rectangular 00912 unsigned int k, Nym = Ny-1, stm = 1 << (Mx + My); 00913 for (i=0; stm>0; i++) { 00914 #define pred(k) (((k & Nym) << Mx) + (k >> My)) 00915 for (j=pred(i); j>i; j=pred(j)); 00916 if (j < i) continue; 00917 for (k=i, j=pred(i); j!=i; k=j, j=pred(j), stm--) 00918 { t=data[j], data[j]=data[k], data[k]=t; } 00919 #undef pred 00920 stm--; 00921 } 00922 } 00923 // swap Mx/My & Nx/Ny 00924 i = Nx, Nx = Ny, Ny = i; 00925 i = Mx, Mx = My, My = i; 00926 00927 // now columns == transposed rows 00928 for (j=0; j<Ny; ++j) 00929 FHT(&data[Nx*j], Mx, inverse); 00930 00931 // finalize 00932 for (j=0; j<=(Ny >> 1); j++) { 00933 unsigned int jm = (Ny - j) & (Ny-1); 00934 unsigned int ji = j << Mx; 00935 unsigned int jmi = jm << Mx; 00936 for (i=0; i<=(Nx >> 1); i++) { 00937 unsigned int im = (Nx - i) & (Nx-1); 00938 fREAL A = data[ji + i]; 00939 fREAL B = data[jmi + i]; 00940 fREAL C = data[ji + im]; 00941 fREAL D = data[jmi + im]; 00942 fREAL E = (fREAL)0.5*((A + D) - (B + C)); 00943 data[ji + i] = A - E; 00944 data[jmi + i] = B + E; 00945 data[ji + im] = C + E; 00946 data[jmi + im] = D - E; 00947 } 00948 } 00949 00950 } 00951 00952 //------------------------------------------------------------------------------ 00953 00954 /* 2D convolution calc, d1 *= d2, M/N - > log2 of width/height */ 00955 static void fht_convolve(fREAL* d1, fREAL* d2, unsigned int M, unsigned int N) 00956 { 00957 fREAL a, b; 00958 unsigned int i, j, k, L, mj, mL; 00959 unsigned int m = 1 << M, n = 1 << N; 00960 unsigned int m2 = 1 << (M-1), n2 = 1 << (N-1); 00961 unsigned int mn2 = m << (N-1); 00962 00963 d1[0] *= d2[0]; 00964 d1[mn2] *= d2[mn2]; 00965 d1[m2] *= d2[m2]; 00966 d1[m2 + mn2] *= d2[m2 + mn2]; 00967 for (i=1; i<m2; i++) { 00968 k = m - i; 00969 a = d1[i]*d2[i] - d1[k]*d2[k]; 00970 b = d1[k]*d2[i] + d1[i]*d2[k]; 00971 d1[i] = (b + a)*(fREAL)0.5; 00972 d1[k] = (b - a)*(fREAL)0.5; 00973 a = d1[i + mn2]*d2[i + mn2] - d1[k + mn2]*d2[k + mn2]; 00974 b = d1[k + mn2]*d2[i + mn2] + d1[i + mn2]*d2[k + mn2]; 00975 d1[i + mn2] = (b + a)*(fREAL)0.5; 00976 d1[k + mn2] = (b - a)*(fREAL)0.5; 00977 } 00978 for (j=1; j<n2; j++) { 00979 L = n - j; 00980 mj = j << M; 00981 mL = L << M; 00982 a = d1[mj]*d2[mj] - d1[mL]*d2[mL]; 00983 b = d1[mL]*d2[mj] + d1[mj]*d2[mL]; 00984 d1[mj] = (b + a)*(fREAL)0.5; 00985 d1[mL] = (b - a)*(fREAL)0.5; 00986 a = d1[m2 + mj]*d2[m2 + mj] - d1[m2 + mL]*d2[m2 + mL]; 00987 b = d1[m2 + mL]*d2[m2 + mj] + d1[m2 + mj]*d2[m2 + mL]; 00988 d1[m2 + mj] = (b + a)*(fREAL)0.5; 00989 d1[m2 + mL] = (b - a)*(fREAL)0.5; 00990 } 00991 for (i=1; i<m2; i++) { 00992 k = m - i; 00993 for (j=1; j<n2; j++) { 00994 L = n - j; 00995 mj = j << M; 00996 mL = L << M; 00997 a = d1[i + mj]*d2[i + mj] - d1[k + mL]*d2[k + mL]; 00998 b = d1[k + mL]*d2[i + mj] + d1[i + mj]*d2[k + mL]; 00999 d1[i + mj] = (b + a)*(fREAL)0.5; 01000 d1[k + mL] = (b - a)*(fREAL)0.5; 01001 a = d1[i + mL]*d2[i + mL] - d1[k + mj]*d2[k + mj]; 01002 b = d1[k + mj]*d2[i + mL] + d1[i + mL]*d2[k + mj]; 01003 d1[i + mL] = (b + a)*(fREAL)0.5; 01004 d1[k + mj] = (b - a)*(fREAL)0.5; 01005 } 01006 } 01007 } 01008 01009 //------------------------------------------------------------------------------ 01010 01011 void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2) 01012 { 01013 fREAL *data1, *data2, *fp; 01014 unsigned int w2, h2, hw, hh, log2_w, log2_h; 01015 fRGB wt, *colp; 01016 int x, y, ch; 01017 int xbl, ybl, nxb, nyb, xbsz, ybsz; 01018 int in2done = 0; 01019 01020 CompBuf* rdst = alloc_compbuf(in1->x, in1->y, in1->type, 1); 01021 01022 // convolution result width & height 01023 w2 = 2*in2->x - 1; 01024 h2 = 2*in2->y - 1; 01025 // FFT pow2 required size & log2 01026 w2 = nextPow2(w2, &log2_w); 01027 h2 = nextPow2(h2, &log2_h); 01028 01029 // alloc space 01030 data1 = (fREAL*)MEM_callocN(3*w2*h2*sizeof(fREAL), "convolve_fast FHT data1"); 01031 data2 = (fREAL*)MEM_callocN(w2*h2*sizeof(fREAL), "convolve_fast FHT data2"); 01032 01033 // normalize convolutor 01034 wt[0] = wt[1] = wt[2] = 0.f; 01035 for (y=0; y<in2->y; y++) { 01036 colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; 01037 for (x=0; x<in2->x; x++) 01038 fRGB_add(wt, colp[x]); 01039 } 01040 if (wt[0] != 0.f) wt[0] = 1.f/wt[0]; 01041 if (wt[1] != 0.f) wt[1] = 1.f/wt[1]; 01042 if (wt[2] != 0.f) wt[2] = 1.f/wt[2]; 01043 for (y=0; y<in2->y; y++) { 01044 colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; 01045 for (x=0; x<in2->x; x++) 01046 fRGB_colormult(colp[x], wt); 01047 } 01048 01049 // copy image data, unpacking interleaved RGBA into separate channels 01050 // only need to calc data1 once 01051 01052 // block add-overlap 01053 hw = in2->x >> 1; 01054 hh = in2->y >> 1; 01055 xbsz = (w2 + 1) - in2->x; 01056 ybsz = (h2 + 1) - in2->y; 01057 nxb = in1->x / xbsz; 01058 if (in1->x % xbsz) nxb++; 01059 nyb = in1->y / ybsz; 01060 if (in1->y % ybsz) nyb++; 01061 for (ybl=0; ybl<nyb; ybl++) { 01062 for (xbl=0; xbl<nxb; xbl++) { 01063 01064 // each channel one by one 01065 for (ch=0; ch<3; ch++) { 01066 fREAL* data1ch = &data1[ch*w2*h2]; 01067 01068 // only need to calc fht data from in2 once, can re-use for every block 01069 if (!in2done) { 01070 // in2, channel ch -> data1 01071 for (y=0; y<in2->y; y++) { 01072 fp = &data1ch[y*w2]; 01073 colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; 01074 for (x=0; x<in2->x; x++) 01075 fp[x] = colp[x][ch]; 01076 } 01077 } 01078 01079 // in1, channel ch -> data2 01080 memset(data2, 0, w2*h2*sizeof(fREAL)); 01081 for (y=0; y<ybsz; y++) { 01082 int yy = ybl*ybsz + y; 01083 if (yy >= in1->y) continue; 01084 fp = &data2[y*w2]; 01085 colp = (fRGB*)&in1->rect[yy*in1->x*in1->type]; 01086 for (x=0; x<xbsz; x++) { 01087 int xx = xbl*xbsz + x; 01088 if (xx >= in1->x) continue; 01089 fp[x] = colp[xx][ch]; 01090 } 01091 } 01092 01093 // forward FHT 01094 // zero pad data start is different for each == height+1 01095 if (!in2done) FHT2D(data1ch, log2_w, log2_h, in2->y+1, 0); 01096 FHT2D(data2, log2_w, log2_h, in2->y+1, 0); 01097 01098 // FHT2D transposed data, row/col now swapped 01099 // convolve & inverse FHT 01100 fht_convolve(data2, data1ch, log2_h, log2_w); 01101 FHT2D(data2, log2_h, log2_w, 0, 1); 01102 // data again transposed, so in order again 01103 01104 // overlap-add result 01105 for (y=0; y<(int)h2; y++) { 01106 const int yy = ybl*ybsz + y - hh; 01107 if ((yy < 0) || (yy >= in1->y)) continue; 01108 fp = &data2[y*w2]; 01109 colp = (fRGB*)&rdst->rect[yy*in1->x*in1->type]; 01110 for (x=0; x<(int)w2; x++) { 01111 const int xx = xbl*xbsz + x - hw; 01112 if ((xx < 0) || (xx >= in1->x)) continue; 01113 colp[xx][ch] += fp[x]; 01114 } 01115 } 01116 01117 } 01118 in2done = 1; 01119 } 01120 } 01121 01122 MEM_freeN(data2); 01123 MEM_freeN(data1); 01124 memcpy(dst->rect, rdst->rect, sizeof(float)*dst->x*dst->y*dst->type); 01125 free_compbuf(rdst); 01126 } 01127 01128 01129 /* 01130 * 01131 * Utility functions qd_* should probably be intergrated better with other functions here. 01132 * 01133 */ 01134 // sets fcol to pixelcolor at (x, y) 01135 void qd_getPixel(CompBuf* src, int x, int y, float* col) 01136 { 01137 if(src->rect_procedural) { 01138 float bc[4]; 01139 src->rect_procedural(src, bc, (float)x/(float)src->xrad, (float)y/(float)src->yrad); 01140 01141 switch(src->type){ 01142 /* these fallthrough to get all the channels */ 01143 case CB_RGBA: col[3]=bc[3]; 01144 case CB_VEC3: col[2]=bc[2]; 01145 case CB_VEC2: col[1]=bc[1]; 01146 case CB_VAL: col[0]=bc[0]; 01147 } 01148 } 01149 else if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { 01150 float* bc = &src->rect[(x + y*src->x)*src->type]; 01151 switch(src->type){ 01152 /* these fallthrough to get all the channels */ 01153 case CB_RGBA: col[3]=bc[3]; 01154 case CB_VEC3: col[2]=bc[2]; 01155 case CB_VEC2: col[1]=bc[1]; 01156 case CB_VAL: col[0]=bc[0]; 01157 } 01158 } 01159 else { 01160 switch(src->type){ 01161 /* these fallthrough to get all the channels */ 01162 case CB_RGBA: col[3]=0.0; 01163 case CB_VEC3: col[2]=0.0; 01164 case CB_VEC2: col[1]=0.0; 01165 case CB_VAL: col[0]=0.0; 01166 } 01167 } 01168 } 01169 01170 // sets pixel (x, y) to color col 01171 void qd_setPixel(CompBuf* src, int x, int y, float* col) 01172 { 01173 if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { 01174 float* bc = &src->rect[(x + y*src->x)*src->type]; 01175 switch(src->type){ 01176 /* these fallthrough to get all the channels */ 01177 case CB_RGBA: bc[3]=col[3]; 01178 case CB_VEC3: bc[2]=col[2]; 01179 case CB_VEC2: bc[1]=col[1]; 01180 case CB_VAL: bc[0]=col[0]; 01181 } 01182 } 01183 } 01184 01185 // adds fcol to pixelcolor (x, y) 01186 void qd_addPixel(CompBuf* src, int x, int y, float* col) 01187 { 01188 if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { 01189 float* bc = &src->rect[(x + y*src->x)*src->type]; 01190 bc[0] += col[0], bc[1] += col[1], bc[2] += col[2]; 01191 } 01192 } 01193 01194 // multiplies pixel by factor value f 01195 void qd_multPixel(CompBuf* src, int x, int y, float f) 01196 { 01197 if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { 01198 float* bc = &src->rect[(x + y*src->x)*src->type]; 01199 bc[0] *= f, bc[1] *= f, bc[2] *= f; 01200 } 01201 } 01202 01203 // bilinear interpolation with wraparound 01204 void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col) 01205 { 01206 const float ufl = floor(u), vfl = floor(v); 01207 const int nx = (int)ufl % src->x, ny = (int)vfl % src->y; 01208 const int x1 = (nx < 0) ? (nx + src->x) : nx; 01209 const int y1 = (ny < 0) ? (ny + src->y) : ny; 01210 const int x2 = (x1 + 1) % src->x, y2 = (y1 + 1) % src->y; 01211 const float* c00 = &src->rect[(x1 + y1*src->x)*src->type]; 01212 const float* c10 = &src->rect[(x2 + y1*src->x)*src->type]; 01213 const float* c01 = &src->rect[(x1 + y2*src->x)*src->type]; 01214 const float* c11 = &src->rect[(x2 + y2*src->x)*src->type]; 01215 const float uf = u - ufl, vf = v - vfl; 01216 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; 01217 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; 01218 if (src->type != CB_VAL) { 01219 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1]; 01220 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2]; 01221 col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3]; 01222 } 01223 } 01224 01225 // as above, without wrap around 01226 void qd_getPixelLerp(CompBuf* src, float u, float v, float* col) 01227 { 01228 const float ufl = floor(u), vfl = floor(v); 01229 const int x1 = (int)ufl, y1 = (int)vfl; 01230 const int x2 = (int)ceil(u), y2 = (int)ceil(v); 01231 if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) { 01232 const float B[4] = {0,0,0,0}; 01233 const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y); 01234 const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type]; 01235 const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type]; 01236 const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type]; 01237 const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type]; 01238 const float uf = u - ufl, vf = v - vfl; 01239 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; 01240 col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; 01241 if (src->type != CB_VAL) { 01242 col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1]; 01243 col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2]; 01244 col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3]; 01245 } 01246 } 01247 else col[0] = col[1] = col[2] = col[3] = 0.f; 01248 } 01249 01250 // as above, sampling only one channel 01251 void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out) 01252 { 01253 const float ufl = floor(u), vfl = floor(v); 01254 const int x1 = (int)ufl, y1 = (int)vfl; 01255 const int x2 = (int)ceil(u), y2 = (int)ceil(v); 01256 if (chan >= src->type) chan = 0; 01257 if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) { 01258 const float B[4] = {0,0,0,0}; 01259 const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y); 01260 const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type + chan]; 01261 const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type + chan]; 01262 const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type + chan]; 01263 const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type + chan]; 01264 const float uf = u - ufl, vf = v - vfl; 01265 const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; 01266 out[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; 01267 } 01268 else *out = 0.f; 01269 } 01270 01271 01272 CompBuf* qd_downScaledCopy(CompBuf* src, int scale) 01273 { 01274 CompBuf* fbuf; 01275 if (scale <= 1) 01276 fbuf = dupalloc_compbuf(src); 01277 else { 01278 int nw = src->x/scale, nh = src->y/scale; 01279 if ((2*(src->x % scale)) > scale) nw++; 01280 if ((2*(src->y % scale)) > scale) nh++; 01281 fbuf = alloc_compbuf(nw, nh, src->type, 1); 01282 { 01283 int x, y, xx, yy, sx, sy, mx, my; 01284 float colsum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; 01285 float fscale = 1.f/(float)(scale*scale); 01286 for (y=0; y<nh; y++) { 01287 fRGB* fcolp = (fRGB*)&fbuf->rect[y*fbuf->x*fbuf->type]; 01288 yy = y*scale; 01289 my = yy + scale; 01290 if (my > src->y) my = src->y; 01291 for (x=0; x<nw; x++) { 01292 xx = x*scale; 01293 mx = xx + scale; 01294 if (mx > src->x) mx = src->x; 01295 colsum[0] = colsum[1] = colsum[2] = 0.f; 01296 for (sy=yy; sy<my; sy++) { 01297 fRGB* scolp = (fRGB*)&src->rect[sy*src->x*src->type]; 01298 for (sx=xx; sx<mx; sx++) 01299 fRGB_add(colsum, scolp[sx]); 01300 } 01301 fRGB_mult(colsum, fscale); 01302 fRGB_copy(fcolp[x], colsum); 01303 } 01304 } 01305 } 01306 } 01307 return fbuf; 01308 } 01309 01310 // fast g.blur, per channel 01311 // xy var. bits 1 & 2 ca be used to blur in x or y direction separately 01312 void IIR_gauss(CompBuf* src, float sigma, int chan, int xy) 01313 { 01314 double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3]; 01315 double *X, *Y, *W; 01316 int i, x, y, sz; 01317 01318 // <0.5 not valid, though can have a possibly useful sort of sharpening effect 01319 if (sigma < 0.5) return; 01320 01321 if ((xy < 1) || (xy > 3)) xy = 3; 01322 01323 // XXX The YVV macro defined below explicitely expects sources of at least 3x3 pixels, 01324 // so just skiping blur along faulty direction if src's def is below that limit! 01325 if (src->x < 3) xy &= ~(int) 1; 01326 if (src->y < 3) xy &= ~(int) 2; 01327 if (xy < 1) return; 01328 01329 // see "Recursive Gabor Filtering" by Young/VanVliet 01330 // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200 01331 if (sigma >= 3.556) 01332 q = 0.9804*(sigma - 3.556) + 2.5091; 01333 else // sigma >= 0.5 01334 q = (0.0561*sigma + 0.5784)*sigma - 0.2568; 01335 q2 = q*q; 01336 sc = (1.1668 + q)*(3.203729649 + (2.21566 + q)*q); 01337 // no gabor filtering here, so no complex multiplies, just the regular coefs. 01338 // all negated here, so as not to have to recalc Triggs/Sdika matrix 01339 cf[1] = q*(5.788961737 + (6.76492 + 3.0*q)*q)/ sc; 01340 cf[2] = -q2*(3.38246 + 3.0*q)/sc; 01341 // 0 & 3 unchanged 01342 cf[3] = q2*q/sc; 01343 cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; 01344 01345 // Triggs/Sdika border corrections, 01346 // it seems to work, not entirely sure if it is actually totally correct, 01347 // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark), 01348 // found one other implementation by Cristoph Lampert, 01349 // but neither seem to be quite the same, result seems to be ok sofar anyway. 01350 // Extra scale factor here to not have to do it in filter, 01351 // though maybe this had something to with the precision errors 01352 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])); 01353 tsM[0] = sc*(-cf[3]*cf[1] + 1.0 - cf[3]*cf[3] - cf[2]); 01354 tsM[1] = sc*((cf[3] + cf[1])*(cf[2] + cf[3]*cf[1])); 01355 tsM[2] = sc*(cf[3]*(cf[1] + cf[3]*cf[2])); 01356 tsM[3] = sc*(cf[1] + cf[3]*cf[2]); 01357 tsM[4] = sc*(-(cf[2] - 1.0)*(cf[2] + cf[3]*cf[1])); 01358 tsM[5] = sc*(-(cf[3]*cf[1] + cf[3]*cf[3] + cf[2] - 1.0)*cf[3]); 01359 tsM[6] = sc*(cf[3]*cf[1] + cf[2] + cf[1]*cf[1] - cf[2]*cf[2]); 01360 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]); 01361 tsM[8] = sc*(cf[3]*(cf[1] + cf[3]*cf[2])); 01362 01363 #define YVV(L)\ 01364 {\ 01365 W[0] = cf[0]*X[0] + cf[1]*X[0] + cf[2]*X[0] + cf[3]*X[0];\ 01366 W[1] = cf[0]*X[1] + cf[1]*W[0] + cf[2]*X[0] + cf[3]*X[0];\ 01367 W[2] = cf[0]*X[2] + cf[1]*W[1] + cf[2]*W[0] + cf[3]*X[0];\ 01368 for (i=3; i<L; i++)\ 01369 W[i] = cf[0]*X[i] + cf[1]*W[i-1] + cf[2]*W[i-2] + cf[3]*W[i-3];\ 01370 tsu[0] = W[L-1] - X[L-1];\ 01371 tsu[1] = W[L-2] - X[L-1];\ 01372 tsu[2] = W[L-3] - X[L-1];\ 01373 tsv[0] = tsM[0]*tsu[0] + tsM[1]*tsu[1] + tsM[2]*tsu[2] + X[L-1];\ 01374 tsv[1] = tsM[3]*tsu[0] + tsM[4]*tsu[1] + tsM[5]*tsu[2] + X[L-1];\ 01375 tsv[2] = tsM[6]*tsu[0] + tsM[7]*tsu[1] + tsM[8]*tsu[2] + X[L-1];\ 01376 Y[L-1] = cf[0]*W[L-1] + cf[1]*tsv[0] + cf[2]*tsv[1] + cf[3]*tsv[2];\ 01377 Y[L-2] = cf[0]*W[L-2] + cf[1]*Y[L-1] + cf[2]*tsv[0] + cf[3]*tsv[1];\ 01378 Y[L-3] = cf[0]*W[L-3] + cf[1]*Y[L-2] + cf[2]*Y[L-1] + cf[3]*tsv[0];\ 01379 for (i=L-4; i>=0; i--)\ 01380 Y[i] = cf[0]*W[i] + cf[1]*Y[i+1] + cf[2]*Y[i+2] + cf[3]*Y[i+3];\ 01381 } 01382 01383 // intermediate buffers 01384 sz = MAX2(src->x, src->y); 01385 X = MEM_callocN(sz*sizeof(double), "IIR_gauss X buf"); 01386 Y = MEM_callocN(sz*sizeof(double), "IIR_gauss Y buf"); 01387 W = MEM_callocN(sz*sizeof(double), "IIR_gauss W buf"); 01388 if (xy & 1) { // H 01389 for (y=0; y<src->y; ++y) { 01390 const int yx = y*src->x; 01391 for (x=0; x<src->x; ++x) 01392 X[x] = src->rect[(x + yx)*src->type + chan]; 01393 YVV(src->x); 01394 for (x=0; x<src->x; ++x) 01395 src->rect[(x + yx)*src->type + chan] = Y[x]; 01396 } 01397 } 01398 if (xy & 2) { // V 01399 for (x=0; x<src->x; ++x) { 01400 for (y=0; y<src->y; ++y) 01401 X[y] = src->rect[(x + y*src->x)*src->type + chan]; 01402 YVV(src->y); 01403 for (y=0; y<src->y; ++y) 01404 src->rect[(x + y*src->x)*src->type + chan] = Y[y]; 01405 } 01406 } 01407 01408 MEM_freeN(X); 01409 MEM_freeN(W); 01410 MEM_freeN(Y); 01411 #undef YVV 01412 } 01413