|
Blender
V2.59
|
00001 /* 00002 * $Id: CMP_image.c 38092 2011-07-04 19:22:37Z 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 00038 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ 00039 00040 static bNodeSocketType cmp_node_rlayers_out[]= { 00041 { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 00042 { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00043 { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00044 { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00045 { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00046 { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00047 { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00048 { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00049 { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00050 { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00051 { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00052 { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00053 { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00054 { SOCK_RGBA, 0, "Indirect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00055 { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00056 { SOCK_VALUE, 0, "IndexMA", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00057 { SOCK_VALUE, 0, "Mist", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00058 { SOCK_RGBA, 0, "Emit", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00059 { SOCK_RGBA, 0, "Environment",0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, 00060 { -1, 0, "" } 00061 }; 00062 00063 00064 /* note: this function is used for multilayer too, to ensure uniform 00065 handling with BKE_image_get_ibuf() */ 00066 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) 00067 { 00068 ImBuf *ibuf; 00069 CompBuf *stackbuf; 00070 int type; 00071 00072 float *rect; 00073 int alloc= FALSE; 00074 00075 ibuf= BKE_image_get_ibuf(ima, iuser); 00076 if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { 00077 return NULL; 00078 } 00079 00080 if (ibuf->rect_float == NULL) { 00081 IMB_float_from_rect(ibuf); 00082 } 00083 00084 /* now we need a float buffer from the image with matching color management */ 00085 /* XXX weak code, multilayer is excluded from this */ 00086 if(ibuf->channels == 4 && ima->rr==NULL) { 00087 if(rd->color_mgt_flag & R_COLOR_MANAGEMENT) { 00088 if(ibuf->profile != IB_PROFILE_NONE) { 00089 rect= ibuf->rect_float; 00090 } 00091 else { 00092 rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); 00093 srgb_to_linearrgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); 00094 alloc= TRUE; 00095 } 00096 } 00097 else { 00098 if(ibuf->profile == IB_PROFILE_NONE) { 00099 rect= ibuf->rect_float; 00100 } 00101 else { 00102 rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); 00103 linearrgb_to_srgb_rgba_rgba_buf(rect, ibuf->rect_float, ibuf->x * ibuf->y); 00104 alloc= TRUE; 00105 } 00106 } 00107 } 00108 else { 00109 /* non-rgba passes can't use color profiles */ 00110 rect= ibuf->rect_float; 00111 } 00112 /* done coercing into the correct color management */ 00113 00114 00115 type= ibuf->channels; 00116 00117 if(rd->scemode & R_COMP_CROP) { 00118 stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type); 00119 if(alloc) 00120 MEM_freeN(rect); 00121 } 00122 else { 00123 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ 00124 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE); 00125 stackbuf->rect= rect; 00126 stackbuf->malloc= alloc; 00127 } 00128 00129 /*code to respect the premul flag of images; I'm 00130 not sure if this is a good idea for multilayer images, 00131 since it never worked before for them. 00132 if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { 00133 //premul the image 00134 int i; 00135 float *pixel = stackbuf->rect; 00136 00137 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { 00138 pixel[0] *= pixel[3]; 00139 pixel[1] *= pixel[3]; 00140 pixel[2] *= pixel[3]; 00141 } 00142 } 00143 */ 00144 return stackbuf; 00145 } 00146 00147 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) 00148 { 00149 ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); 00150 CompBuf *zbuf= NULL; 00151 00152 if(ibuf && ibuf->zbuf_float) { 00153 if(rd->scemode & R_COMP_CROP) { 00154 zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL); 00155 } 00156 else { 00157 zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0); 00158 zbuf->rect= ibuf->zbuf_float; 00159 } 00160 } 00161 return zbuf; 00162 } 00163 00164 /* check if layer is available, returns pass buffer */ 00165 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype) 00166 { 00167 RenderPass *rpass; 00168 short index; 00169 00170 for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++) 00171 if(rpass->passtype==passtype) 00172 break; 00173 00174 if(rpass) { 00175 CompBuf *cbuf; 00176 00177 iuser->pass= index; 00178 BKE_image_multilayer_index(ima->rr, iuser); 00179 cbuf= node_composit_get_image(rd, ima, iuser); 00180 00181 return cbuf; 00182 } 00183 return NULL; 00184 } 00185 00186 static void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser) 00187 { 00188 if(out[RRES_OUT_Z]->hasoutput) 00189 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z); 00190 if(out[RRES_OUT_VEC]->hasoutput) 00191 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR); 00192 if(out[RRES_OUT_NORMAL]->hasoutput) 00193 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL); 00194 if(out[RRES_OUT_UV]->hasoutput) 00195 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV); 00196 00197 if(out[RRES_OUT_RGBA]->hasoutput) 00198 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA); 00199 if(out[RRES_OUT_DIFF]->hasoutput) 00200 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE); 00201 if(out[RRES_OUT_SPEC]->hasoutput) 00202 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC); 00203 if(out[RRES_OUT_SHADOW]->hasoutput) 00204 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW); 00205 if(out[RRES_OUT_AO]->hasoutput) 00206 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO); 00207 if(out[RRES_OUT_REFLECT]->hasoutput) 00208 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT); 00209 if(out[RRES_OUT_REFRACT]->hasoutput) 00210 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT); 00211 if(out[RRES_OUT_INDIRECT]->hasoutput) 00212 out[RRES_OUT_INDIRECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDIRECT); 00213 if(out[RRES_OUT_INDEXOB]->hasoutput) 00214 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); 00215 if(out[RRES_OUT_INDEXMA]->hasoutput) 00216 out[RRES_OUT_INDEXMA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXMA); 00217 if(out[RRES_OUT_MIST]->hasoutput) 00218 out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST); 00219 if(out[RRES_OUT_EMIT]->hasoutput) 00220 out[RRES_OUT_EMIT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_EMIT); 00221 if(out[RRES_OUT_ENV]->hasoutput) 00222 out[RRES_OUT_ENV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_ENVIRONMENT); 00223 } 00224 00225 00226 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) 00227 { 00228 00229 /* image assigned to output */ 00230 /* stack order input sockets: col, alpha */ 00231 if(node->id) { 00232 RenderData *rd= data; 00233 Image *ima= (Image *)node->id; 00234 ImageUser *iuser= (ImageUser *)node->storage; 00235 CompBuf *stackbuf= NULL; 00236 00237 /* first set the right frame number in iuser */ 00238 BKE_image_user_calc_frame(iuser, rd->cfra, 0); 00239 00240 /* force a load, we assume iuser index will be set OK anyway */ 00241 if(ima->type==IMA_TYPE_MULTILAYER) 00242 BKE_image_get_ibuf(ima, iuser); 00243 00244 if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { 00245 RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); 00246 00247 if(rl) { 00248 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED); 00249 00250 /* go over all layers */ 00251 outputs_multilayer_get(rd, rl, out, ima, iuser); 00252 } 00253 } 00254 else { 00255 stackbuf= node_composit_get_image(rd, ima, iuser); 00256 00257 if (stackbuf) { 00258 /*respect image premul option*/ 00259 if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { 00260 int i; 00261 float *pixel; 00262 00263 /*first duplicate stackbuf->rect, since it's just a pointer 00264 to the source imbuf, and we don't want to change that.*/ 00265 stackbuf->rect = MEM_dupallocN(stackbuf->rect); 00266 00267 /* since stackbuf now has allocated memory, rather than just a pointer, 00268 * mark it as allocated so it can be freed properly */ 00269 stackbuf->malloc=1; 00270 00271 /*premul the image*/ 00272 pixel = stackbuf->rect; 00273 for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { 00274 pixel[0] *= pixel[3]; 00275 pixel[1] *= pixel[3]; 00276 pixel[2] *= pixel[3]; 00277 } 00278 } 00279 00280 /* put image on stack */ 00281 out[0]->data= stackbuf; 00282 00283 if(out[2]->hasoutput) 00284 out[2]->data= node_composit_get_zimage(node, rd); 00285 } 00286 } 00287 00288 /* alpha and preview for both types */ 00289 if(stackbuf) { 00290 if(out[1]->hasoutput) 00291 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); 00292 00293 generate_preview(data, node, stackbuf); 00294 } 00295 } 00296 } 00297 00298 static void node_composit_init_image(bNode* node) 00299 { 00300 ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); 00301 node->storage= iuser; 00302 iuser->frames= 1; 00303 iuser->sfra= 1; 00304 iuser->fie_ima= 2; 00305 iuser->ok= 1; 00306 } 00307 00308 void register_node_type_cmp_image(ListBase *lb) 00309 { 00310 static bNodeType ntype; 00311 00312 node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS, 00313 NULL, cmp_node_rlayers_out); 00314 node_type_size(&ntype, 120, 80, 300); 00315 node_type_init(&ntype, node_composit_init_image); 00316 node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); 00317 node_type_exec(&ntype, node_composit_exec_image); 00318 00319 nodeRegisterType(lb, &ntype); 00320 } 00321 00322 00323 /* **************** RENDER RESULT ******************** */ 00324 00325 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode) 00326 { 00327 float *fp= RE_RenderLayerGetPass(rl, passcode); 00328 if(fp) { 00329 CompBuf *buf; 00330 int buftype= CB_VEC3; 00331 00332 if(ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA)) 00333 buftype= CB_VAL; 00334 else if(passcode==SCE_PASS_VECTOR) 00335 buftype= CB_VEC4; 00336 else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA)) 00337 buftype= CB_RGBA; 00338 00339 if(rd->scemode & R_COMP_CROP) 00340 buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype); 00341 else { 00342 buf= alloc_compbuf(rectx, recty, buftype, 0); 00343 buf->rect= fp; 00344 } 00345 return buf; 00346 } 00347 return NULL; 00348 } 00349 00350 static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty) 00351 { 00352 if(out[RRES_OUT_Z]->hasoutput) 00353 out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z); 00354 if(out[RRES_OUT_VEC]->hasoutput) 00355 out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR); 00356 if(out[RRES_OUT_NORMAL]->hasoutput) 00357 out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL); 00358 if(out[RRES_OUT_UV]->hasoutput) 00359 out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV); 00360 00361 if(out[RRES_OUT_RGBA]->hasoutput) 00362 out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA); 00363 if(out[RRES_OUT_DIFF]->hasoutput) 00364 out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE); 00365 if(out[RRES_OUT_SPEC]->hasoutput) 00366 out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC); 00367 if(out[RRES_OUT_SHADOW]->hasoutput) 00368 out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW); 00369 if(out[RRES_OUT_AO]->hasoutput) 00370 out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO); 00371 if(out[RRES_OUT_REFLECT]->hasoutput) 00372 out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT); 00373 if(out[RRES_OUT_REFRACT]->hasoutput) 00374 out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT); 00375 if(out[RRES_OUT_INDIRECT]->hasoutput) 00376 out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT); 00377 if(out[RRES_OUT_INDEXOB]->hasoutput) 00378 out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); 00379 if(out[RRES_OUT_INDEXMA]->hasoutput) 00380 out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA); 00381 if(out[RRES_OUT_MIST]->hasoutput) 00382 out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST); 00383 if(out[RRES_OUT_EMIT]->hasoutput) 00384 out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT); 00385 if(out[RRES_OUT_ENV]->hasoutput) 00386 out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT); 00387 } 00388 00389 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) 00390 { 00391 Scene *sce= (Scene *)node->id; 00392 Render *re= (sce)? RE_GetRender(sce->id.name): NULL; 00393 RenderData *rd= data; 00394 RenderResult *rr= NULL; 00395 00396 if(re) 00397 rr= RE_AcquireResultRead(re); 00398 00399 if(rr) { 00400 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); 00401 if(srl) { 00402 RenderLayer *rl= RE_GetRenderLayer(rr, srl->name); 00403 if(rl && rl->rectf) { 00404 CompBuf *stackbuf; 00405 00406 /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */ 00407 if(rd->scemode & R_COMP_CROP) 00408 stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA); 00409 else { 00410 stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0); 00411 stackbuf->rect= rl->rectf; 00412 } 00413 if(stackbuf==NULL) { 00414 printf("Error; Preview Panel in UV Window returns zero sized image\n"); 00415 } 00416 else { 00417 stackbuf->xof= rr->xof; 00418 stackbuf->yof= rr->yof; 00419 00420 /* put on stack */ 00421 out[RRES_OUT_IMAGE]->data= stackbuf; 00422 00423 if(out[RRES_OUT_ALPHA]->hasoutput) 00424 out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); 00425 00426 node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty); 00427 00428 generate_preview(data, node, stackbuf); 00429 } 00430 } 00431 } 00432 } 00433 00434 if(re) 00435 RE_ReleaseResult(re); 00436 } 00437 00438 00439 void register_node_type_cmp_rlayers(ListBase *lb) 00440 { 00441 static bNodeType ntype; 00442 00443 node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS, 00444 NULL, cmp_node_rlayers_out); 00445 node_type_size(&ntype, 150, 100, 300); 00446 node_type_exec(&ntype, node_composit_exec_rlayers); 00447 00448 nodeRegisterType(lb, &ntype); 00449 } 00450 00451 00452