static void load_frame_image_sequence(VoxelData *vd, Tex *tex) { ImBuf *ibuf; Image *ima = tex->ima; ImageUser *tiuser = &tex->iuser; ImageUser iuser = *(tiuser); int x=0, y=0, z=0; float *rf; if (!ima || !tiuser) return; if (iuser.frames == 0) return; ima->source = IMA_SRC_SEQUENCE; iuser.framenr = 1 + iuser.offset; /* find the first valid ibuf and use it to initialise the resolution of the data set */ /* need to do this in advance so we know how much memory to allocate */ ibuf= BKE_image_get_ibuf(ima, &iuser); while (!ibuf && (iuser.framenr < iuser.frames)) { iuser.framenr++; ibuf= BKE_image_get_ibuf(ima, &iuser); } if (!ibuf) return; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); vd->flag |= TEX_VD_STILL; vd->resol[0] = ibuf->x; vd->resol[1] = ibuf->y; vd->resol[2] = iuser.frames; vd->dataset = MEM_mapallocN(sizeof(float)*vd_resol_size(vd), "voxel dataset"); for (z=0; z < iuser.frames; z++) { /* get a new ibuf for each frame */ if (z > 0) { iuser.framenr++; ibuf= BKE_image_get_ibuf(ima, &iuser); if (!ibuf) break; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); } rf = ibuf->rect_float; for (y=0; y < ibuf->y; y++) { for (x=0; x < ibuf->x; x++) { /* currently averaged to monchrome */ vd->dataset[ V_I(x, y, z, vd->resol) ] = (rf[0] + rf[1] + rf[2])*0.333f; rf +=4; } } BKE_image_free_anim_ibufs(ima, iuser.framenr); } vd->ok = 1; return; }
static unsigned char *get_alpha_clone_image(Scene *scene, int *width, int *height) { Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint); ImBuf *ibuf; unsigned int size, alpha; unsigned char *rect, *cp; if(!brush || !brush->clone.image) return NULL; ibuf= BKE_image_get_ibuf(brush->clone.image, NULL); if(!ibuf || !ibuf->rect) return NULL; rect= MEM_dupallocN(ibuf->rect); if(!rect) return NULL; *width= ibuf->x; *height= ibuf->y; size= (*width)*(*height); alpha= (unsigned char)255*brush->clone.alpha; cp= rect; while(size-- > 0) { cp[3]= alpha; cp += 4; } return rect; }
static void bake_images(MultiresBakeRender *bkr) { LinkData *link; for(link= bkr->image.first; link; link= link->next) { Image *ima= (Image*)link->data; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf->x>0 && ibuf->y>0) { ibuf->userdata= MEM_callocN(ibuf->y*ibuf->x, "MultiresBake imbuf mask"); switch(bkr->mode) { case RE_BAKE_NORMALS: do_multires_bake(bkr, ima, apply_tangmat_callback, init_normal_data, NULL, free_normal_data); break; case RE_BAKE_DISPLACEMENT: do_multires_bake(bkr, ima, apply_heights_callback, init_heights_data, apply_heights_data, free_heights_data); break; } } ima->id.flag|= LIB_DOIT; } }
void BL_Texture::SplitEnvMap(EnvMap *map) { if (!map || !map->ima || (map->ima && !map->ima->ok)) return; ImBuf *ibuf= BKE_image_get_ibuf(map->ima, NULL); if (ibuf) my_envmap_split_ima(map, ibuf); }
static void apply_heights_data(void *bake_data) { MHeightBakeData *height_data= (MHeightBakeData*)bake_data; ImBuf *ibuf= BKE_image_get_ibuf(height_data->ima, NULL); int x, y, i; float height, *heights= height_data->heights; float min= height_data->height_min, max= height_data->height_max; for(x= 0; x<ibuf->x; x++) { for(y =0; y<ibuf->y; y++) { i= ibuf->x*y + x; if(((char*)ibuf->userdata)[i] != FILTER_MASK_USED) continue; if(ibuf->rect_float) { float *rrgbf= ibuf->rect_float + i*4; if(max-min > 1e-5f) height= (heights[i]-min)/(max-min); else height= 0; rrgbf[0]=rrgbf[1]=rrgbf[2]= height; } else { char *rrgb= (char*)ibuf->rect + i*4; if(max-min > 1e-5f) height= (heights[i]-min)/(max-min); else height= 0; rrgb[0]=rrgb[1]=rrgb[2]= FTOCHAR(height); } } } ibuf->userflags= IB_RECT_INVALID; }
static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) { MHeightBakeData *height_data; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); DerivedMesh *lodm= bkr->lores_dm; height_data= MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); height_data->ima= ima; height_data->heights= MEM_callocN(sizeof(float)*ibuf->x*ibuf->y, "MultiresBake heights"); height_data->height_max= -FLT_MAX; height_data->height_min= FLT_MAX; if(!bkr->use_lores_mesh) { SubsurfModifierData smd= {{NULL}}; int ss_lvl= bkr->tot_lvl - bkr->lvl; CLAMP(ss_lvl, 0, 6); smd.levels= smd.renderLevels= ss_lvl; smd.flags|= eSubsurfModifierFlag_SubsurfUv; if(bkr->simple) smd.subdivType= ME_SIMPLE_SUBSURF; height_data->ssdm= subsurf_make_derived_from_derived(bkr->lores_dm, &smd, 0, NULL, 0, 0, 0); } height_data->origindex= lodm->getFaceDataArray(lodm, CD_ORIGINDEX); return (void*)height_data; }
bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) { ImBuf *ibuf; if (!img || img->ok==0) { mOk = false; return mOk; } ibuf= BKE_image_get_ibuf(img, NULL); if (ibuf==NULL) { img->ok = 0; mOk = false; return mOk; } mTexture = img->bindcode; mType = GL_TEXTURE_2D; mUnit = unit; ActivateUnit(mUnit); if (mTexture != 0) { glBindTexture(GL_TEXTURE_2D, mTexture ); Validate(); return mOk; } // look for an existing gl image BL_TextureMap::iterator mapLook = g_textureManager.find(img->id.name); if (mapLook != g_textureManager.end()) { if (mapLook->second.gl_texture != 0) { mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_2D, mTexture); mOk = IsValid(); return mOk; } } mNeedsDeleted = 1; glGenTextures(1, (GLuint*)&mTexture); InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); // track created units BL_TextureObject obj; obj.gl_texture = mTexture; obj.ref_buffer = img; g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)img->id.name, obj)); glDisable(GL_TEXTURE_2D); ActivateUnit(0); Validate(); return mOk; }
static void rna_Image_save(Image *image, ReportList *reports) { ImBuf *ibuf= BKE_image_get_ibuf(image, NULL); if(ibuf) { char filename[FILE_MAXDIR + FILE_MAXFILE]; BLI_strncpy(filename, image->name, sizeof(filename)); BLI_path_abs(filename, G.main->name); if(image->packedfile) { if (writePackedFile(reports, image->name, image->packedfile, 0) != RET_OK) { BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could saved packed file to \"%s\"", image->id.name+2, image->name); } } else if (IMB_saveiff(ibuf, filename, ibuf->flags)) { image->type= IMA_TYPE_IMAGE; if(image->source==IMA_SRC_GENERATED) image->source= IMA_SRC_FILE; ibuf->userflags &= ~IB_BITMAPDIRTY; } else { BKE_reportf(reports, RPT_ERROR, "Image \"%s\" could not be saved to \"%s\"", image->id.name+2, image->name); } } else { BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name+2); } }
static void finish_images(MultiresBakeRender *bkr) { LinkData *link; for(link= bkr->image.first; link; link= link->next) { Image *ima= (Image*)link->data; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf->x<=0 || ibuf->y<=0) continue; RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); ibuf->userflags|= IB_BITMAPDIRTY; if(ibuf->rect_float) ibuf->userflags|= IB_RECT_INVALID; if(ibuf->mipmap[0]) { ibuf->userflags|= IB_MIPMAP_INVALID; imb_freemipmapImBuf(ibuf); } if(ibuf->userdata) { MEM_freeN(ibuf->userdata); ibuf->userdata= NULL; } } }
/* note: this function is used for multilayer too, to ensure uniform handling with BKE_image_get_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { ImBuf *ibuf; CompBuf *stackbuf; int type; float *rect; int alloc= FALSE; ibuf= BKE_image_get_ibuf(ima, iuser); if(ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { return NULL; } if (ibuf->rect_float == NULL) { IMB_float_from_rect(ibuf); } /* now we need a float buffer from the image with matching color management */ /* XXX weak code, multilayer is excluded from this */ rect= ibuf->rect_float; /* done coercing into the correct color management */ type= ibuf->channels; if(rd->scemode & R_COMP_CROP) { stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type); if(alloc) MEM_freeN(rect); } else { /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE); stackbuf->rect= rect; stackbuf->malloc= alloc; } /*code to respect the premul flag of images; I'm not sure if this is a good idea for multilayer images, since it never worked before for them. if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { //premul the image int i; float *pixel = stackbuf->rect; for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { pixel[0] *= pixel[3]; pixel[1] *= pixel[3]; pixel[2] *= pixel[3]; } } */ return stackbuf; }
static void rna_Image_update(Image *image, ReportList *reports) { ImBuf *ibuf= BKE_image_get_ibuf(image, NULL); if(ibuf == NULL) { BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name+2); return; } IMB_rect_from_float(ibuf); }
/* MultiresBake callback for normals' baking general idea: - find coord and normal of point with specified UV in hi-res mesh - multiply it by tangmat - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *UNUSED(bake_data), const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y) { MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; Image *ima= mtface[face_index].tpage; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); float uv[2], *st0, *st1, *st2, *st3; int pixel= ibuf->x*y + x; float n[3], vec[3], tmp[3]= {0.5, 0.5, 0.5}; lores_dm->getFace(lores_dm, face_index, &mface); st0= mtface[face_index].uv[0]; st1= mtface[face_index].uv[1]; st2= mtface[face_index].uv[2]; if(mface.v4) { st3= mtface[face_index].uv[3]; resolve_quad_uv(uv, st, st0, st1, st2, st3); } else resolve_tri_uv(uv, st, st0, st1, st2); CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, lvl, face_index, uv[0], uv[1], NULL, n); mul_v3_m3v3(vec, tangmat, n); normalize_v3(vec); mul_v3_fl(vec, 0.5); add_v3_v3(vec, tmp); if(ibuf->rect_float) { float *rrgbf= ibuf->rect_float + pixel*4; rrgbf[0]= vec[0]; rrgbf[1]= vec[1]; rrgbf[2]= vec[2]; rrgbf[3]= 1.0f; ibuf->userflags= IB_RECT_INVALID; } else { char *rrgb= (char*)ibuf->rect + pixel*4; rrgb[0]= FTOCHAR(vec[0]); rrgb[1]= FTOCHAR(vec[1]); rrgb[2]= FTOCHAR(vec[2]); rrgb[3]= 255; } }
static void rna_Image_pack(Image *image, ReportList *reports, int as_png) { ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { BKE_reportf(reports, RPT_ERROR, "Can't pack edited image from disk, only as internal PNG"); } else { if(as_png) { BKE_image_memorypack(image); } else { image->packedfile= newPackedFile(reports, image->name); } } }
static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); CompBuf *zbuf= NULL; if(ibuf && ibuf->zbuf_float) { if(rd->scemode & R_COMP_CROP) { zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL); } else { zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0); zbuf->rect= ibuf->zbuf_float; } } return zbuf; }
/* TODO: should probably be unified with BrushPainter stuff? */ unsigned int *brush_gen_texture_cache(Brush *br, int half_side) { unsigned int *texcache = NULL; MTex *mtex = &br->mtex; TexResult texres= {0}; int hasrgb, ix, iy; int side = half_side * 2; if(mtex->tex) { float x, y, step = 2.0 / side, co[3]; texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); BKE_image_get_ibuf(mtex->tex->ima, NULL); /*do normalized cannonical view coords for texture*/ for (y=-1.0, iy=0; iy<side; iy++, y += step) { for (x=-1.0, ix=0; ix<side; ix++, x += step) { co[0]= x; co[1]= y; co[2]= 0.0f; /* This is copied from displace modifier code */ hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). * if the texture didn't give an RGB value, copy the intensity across */ if(hasrgb & TEX_RGB) texres.tin = (0.35f * texres.tr + 0.45f * texres.tg + 0.2f * texres.tb); texres.tin = texres.tin * 255.0f; ((char*)texcache)[(iy*side+ix)*4] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+1] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+2] = (char)texres.tin; ((char*)texcache)[(iy*side+ix)*4+3] = (char)texres.tin; } } } return texcache; }
static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(in), short UNUSED(thread)) { float x = p->co[0]; float y = p->co[1]; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; if( ima ) { ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); if( ibuf ) { float xsize, ysize; float xoff, yoff; int px, py; float *result; xsize = ibuf->x / 2; ysize = ibuf->y / 2; xoff = yoff = -1; px = (int)( (x-xoff) * xsize ); py = (int)( (y-yoff) * ysize ); if( (!xsize) || (!ysize) ) return; if( !ibuf->rect_float ) { BLI_lock_thread(LOCK_IMAGE); if( !ibuf->rect_float ) IMB_float_from_rect(ibuf); BLI_unlock_thread(LOCK_IMAGE); } while( px < 0 ) px += ibuf->x; while( py < 0 ) py += ibuf->y; while( px >= ibuf->x ) px -= ibuf->x; while( py >= ibuf->y ) py -= ibuf->y; result = ibuf->rect_float + py*ibuf->x*4 + px*4; QUATCOPY( out, result ); } } }
static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int mag) { ImBuf *ibuf; unsigned int *bind = &image->bindcode; int error = GL_NO_ERROR; if(*bind) return error; ibuf= BKE_image_get_ibuf(image, NULL); if(ibuf == NULL || ibuf->rect == NULL ) { BKE_reportf(reports, RPT_ERROR, "Image \"%s\" does not have any image data", image->id.name+2); return (int)GL_INVALID_OPERATION; } /* could be made into a function? */ glGenTextures(1, (GLuint*)bind); glBindTexture(GL_TEXTURE_2D, *bind); if (filter != GL_NEAREST && filter != GL_LINEAR) error = (int)gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_INT, ibuf->rect); if (!error) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, image->tpageflag & IMA_CLAMP_U ? GL_CLAMP : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, image->tpageflag & IMA_CLAMP_V ? GL_CLAMP : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ibuf->x, ibuf->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); error = (int)glGetError(); } if (error) { glDeleteTextures(1, (GLuint*)bind); image->bindcode = 0; } return error; }
static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Main *bmain= CTX_data_main(C); Image *ima; ImBuf *ibuf; // first check for dirty images for(ima=bmain->image.first; ima; ima=ima->id.next) { if(ima->ibufs.first) { /* XXX FIX */ ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) break; } } if(ima) { uiPupMenuOkee(C, "FILE_OT_pack_all", "Some images are painted on. These changes will be lost. Continue?"); return OPERATOR_CANCELLED; } return pack_all_exec(C, op); }
static void icon_preview_startjob(void *customdata, short *stop, short *do_update) { ShaderPreview *sp= customdata; ID *id= sp->id; short idtype= GS(id->name); if(idtype == ID_IM) { Image *ima= (Image*)id; ImBuf *ibuf= NULL; ImageUser iuser= {NULL}; /* ima->ok is zero when Image cannot load */ if(ima==NULL || ima->ok==0) return; /* setup dummy image user */ iuser.ok= iuser.framenr= 1; iuser.scene= sp->scene; /* elubie: this needs to be changed: here image is always loaded if not already there. Very expensive for large images. Need to find a way to only get existing ibuf */ ibuf = BKE_image_get_ibuf(ima, &iuser); if(ibuf==NULL || ibuf->rect==NULL) return; icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update= 1; } else if(idtype == ID_BR) { Brush *br= (Brush*)id; br->icon_imbuf= get_brush_icon(br); memset(sp->pr_rect, 0x888888, sp->sizex*sp->sizey*sizeof(unsigned int)); if(!(br->icon_imbuf) || !(br->icon_imbuf->rect)) return; icon_copy_rect(br->icon_imbuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update= 1; } else { /* re-use shader job */ shader_preview_startjob(customdata, stop, do_update); /* world is rendered with alpha=0, so it wasn't displayed this could be render option for sky to, for later */ if(idtype == ID_WO) { set_alpha((char*)sp->pr_rect, sp->sizex, sp->sizey, 255); } else if(idtype == ID_MA) { Material* ma = (Material*)id; if(ma->material_type == MA_TYPE_HALO) set_alpha((char*)sp->pr_rect, sp->sizex, sp->sizey, 255); } } }
static int rna_Image_file_format_get(PointerRNA *ptr) { Image *image= (Image*)ptr->data; ImBuf *ibuf= BKE_image_get_ibuf(image, NULL); return BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); }
/* note: this function is used for multilayer too, to ensure uniform handling with BKE_image_get_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { ImBuf *ibuf; CompBuf *stackbuf; int type; ibuf= BKE_image_get_ibuf(ima, iuser); if(ibuf==NULL) return NULL; if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { if (ibuf->profile == IB_PROFILE_NONE) { /* if float buffer already exists = already linear */ /* else ... */ if (ibuf->rect_float == NULL) { imb_freerectfloatImBuf(ibuf); ibuf->profile = IB_PROFILE_SRGB; IMB_float_from_rect(ibuf); } else { ibuf->profile = IB_PROFILE_LINEAR_RGB; } } } else { if (ibuf->profile == IB_PROFILE_SRGB) { if (ibuf->rect_float != NULL) { imb_freerectfloatImBuf(ibuf); } ibuf->profile = IB_PROFILE_NONE; IMB_float_from_rect(ibuf); } } if (ibuf->rect_float == NULL) { IMB_float_from_rect(ibuf); } type= ibuf->channels; if(rd->scemode & R_COMP_CROP) { stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type); } else { /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0); stackbuf->rect= ibuf->rect_float; } /*code to respect the premul flag of images; I'm not sure if this is a good idea for multilayer images, since it never worked before for them. if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { //premul the image int i; float *pixel = stackbuf->rect; for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { pixel[0] *= pixel[3]; pixel[1] *= pixel[3]; pixel[2] *= pixel[3]; } } */ return stackbuf; };
static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: image image */ if(in[0]->data==NULL || in[1]->data==NULL) return; if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ Image *ima= (Image *)node->id; RenderData *rd= data; ImBuf *ibuf; CompBuf *cbuf, *buf1, *buf2, *mask; int x, y; float offset; buf1= typecheck_compbuf(in[0]->data, CB_RGBA); buf2= typecheck_compbuf(in[1]->data, CB_RGBA); BKE_image_user_calc_imanr(node->storage, rd->cfra, 0); /* always returns for viewer image, but we check nevertheless */ ibuf= BKE_image_get_ibuf(ima, node->storage); if(ibuf==NULL) { printf("node_composit_exec_viewer error\n"); return; } /* free all in ibuf */ imb_freerectImBuf(ibuf); imb_freerectfloatImBuf(ibuf); IMB_freezbuffloatImBuf(ibuf); /* make ibuf, and connect to ima */ ibuf->x= buf1->x; ibuf->y= buf1->y; imb_addrectfloatImBuf(ibuf); ima->ok= IMA_OK_LOADED; /* output buf */ cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0); /* no alloc*/ cbuf->rect= ibuf->rect_float; /* mask buf */ mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1); /* Check which offset mode is selected and limit offset if needed */ if(node->custom2 == 0) { offset = buf1->x / 100.0f * node->custom1; CLAMP(offset, 0, buf1->x); } else { offset = buf1->y / 100.0f * node->custom1; CLAMP(offset, 0, buf1->y); } if(node->custom2 == 0) { for(y=0; y<buf1->y; y++) { float *fac= mask->rect + y*buf1->x; for(x=offset; x>0; x--, fac++) *fac= 1.0f; } } else { for(y=0; y<offset; y++) { float *fac= mask->rect + y*buf1->x; for(x=buf1->x; x>0; x--, fac++) *fac= 1.0f; } } composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL); generate_preview(data, node, cbuf); free_compbuf(cbuf); free_compbuf(mask); if(in[0]->data != buf1) free_compbuf(buf1); if(in[1]->data != buf2) free_compbuf(buf2); } }
static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData, MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm= bkr->lores_dm; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); const int lvl= bkr->lvl; const int tot_face= dm->getNumFaces(dm); MVert *mvert= dm->getVertArray(dm); MFace *mface= dm->getFaceArray(dm); MTFace *mtface= dm->getFaceDataArray(dm, CD_MTFACE); float *pvtangent= NULL; if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) DM_add_tangent_layer(dm); pvtangent= DM_get_face_data_layer(dm, CD_TANGENT); if(tot_face > 0) { /* sanity check */ int f= 0; MBakeRast bake_rast; MResolvePixelData data={NULL}; data.mface= mface; data.mvert= mvert; data.mtface= mtface; data.pvtangent= pvtangent; data.precomputed_normals= dm->getFaceDataArray(dm, CD_NORMAL); /* don't strictly need this */ data.w= ibuf->x; data.h= ibuf->y; data.lores_dm= dm; data.hires_dm= bkr->hires_dm; data.lvl= lvl; data.pass_data= passKnownData; if(initBakeData) data.bake_data= initBakeData(bkr, ima); init_bake_rast(&bake_rast, ibuf, &data, flush_pixel); for(f= 0; f<tot_face; f++) { MTFace *mtfate= &mtface[f]; int verts[3][2], nr_tris, t; if(multiresbake_test_break(bkr)) break; if(mtfate->tpage!=ima) continue; data.face_index= f; /* might support other forms of diagonal splits later on such as split by shortest diagonal.*/ verts[0][0]=0; verts[1][0]=1; verts[2][0]=2; verts[0][1]=0; verts[1][1]=2; verts[2][1]=3; nr_tris= mface[f].v4!=0 ? 2 : 1; for(t= 0; t<nr_tris; t++) { data.i0= verts[0][t]; data.i1= verts[1][t]; data.i2 =verts[2][t]; bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]); } bkr->baked_faces++; if(bkr->do_update) *bkr->do_update= 1; if(bkr->progress) *bkr->progress= ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj; } if(applyBakeData) applyBakeData(data.bake_data); if(freeBakeData) freeBakeData(data.bake_data); } }
/* MultiresBake callback for heights baking general idea: - find coord of point with specified UV in hi-res mesh (let's call it p1) - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res mesh to make texture smoother) let's call this point p0 and n. - height wound be dot(n, p1-p0) */ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, const int face_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; Image *ima= mtface[face_index].tpage; ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); MHeightBakeData *height_data= (MHeightBakeData*)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel= ibuf->x*y + x; float vec[3], p0[3], p1[3], n[3], len; lores_dm->getFace(lores_dm, face_index, &mface); st0= mtface[face_index].uv[0]; st1= mtface[face_index].uv[1]; st2= mtface[face_index].uv[2]; if(mface.v4) { st3= mtface[face_index].uv[3]; resolve_quad_uv(uv, st, st0, st1, st2, st3); } else resolve_tri_uv(uv, st, st0, st1, st2); CLAMP(uv[0], 0.0f, 1.0f); CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, height_data->origindex, lvl, face_index, uv[0], uv[1], p1, 0); if(height_data->ssdm) { get_ccgdm_data(lores_dm, height_data->ssdm, height_data->origindex, 0, face_index, uv[0], uv[1], p0, n); } else { lores_dm->getFace(lores_dm, face_index, &mface); if(mface.v4) { interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n); } else { interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n); } } sub_v3_v3v3(vec, p1, p0); len= dot_v3v3(n, vec); height_data->heights[pixel]= len; if(len<height_data->height_min) height_data->height_min= len; if(len>height_data->height_max) height_data->height_max= len; if(ibuf->rect_float) { float *rrgbf= ibuf->rect_float + pixel*4; rrgbf[3]= 1.0f; ibuf->userflags= IB_RECT_INVALID; } else { char *rrgb= (char*)ibuf->rect + pixel*4; rrgb[3]= 255; } }
bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap) { if (!GLEW_ARB_texture_cube_map) { spit("cubemaps not supported"); mOk = false; return mOk; } else if (!cubemap || cubemap->ima->ok==0) { mOk = false; return mOk; } ImBuf *ibuf= BKE_image_get_ibuf(cubemap->ima, NULL); if (ibuf==0) { cubemap->ima->ok = 0; mOk = false; return mOk; } mNeedsDeleted = 1; mType = GL_TEXTURE_CUBE_MAP_ARB; mTexture = 0; mUnit = unit; ActivateUnit(mUnit); BL_TextureMap::iterator mapLook = g_textureManager.find(cubemap->ima->id.name); if (mapLook != g_textureManager.end()) { if (mapLook->second.gl_texture != 0 && mapLook->second.ref_buffer == cubemap->ima) { mTexture = mapLook->second.gl_texture; glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); mOk = IsValid(); return mOk; } } glGenTextures(1, (GLuint*)&mTexture); glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture); // track created units BL_TextureObject obj; obj.gl_texture = mTexture; obj.ref_buffer = cubemap->ima; g_textureManager.insert(std::pair<char*, BL_TextureObject>((char*)cubemap->ima->id.name, obj)); bool needs_split = false; if (!cubemap->cube[0]) { needs_split = true; spit ("Re-Generating texture buffer"); } if (needs_split) my_envmap_split_ima(cubemap, ibuf); if (!is_pow2(cubemap->cube[0]->x) || !is_pow2(cubemap->cube[0]->y)) { spit("invalid envmap size please render with CubeRes @ power of two"); my_free_envmapdata(cubemap); mOk = false; return mOk; } #define SetCubeMapFace(face, num) \ glTexImage2D(face, 0,GL_RGBA, \ cubemap->cube[num]->x, \ cubemap->cube[num]->y, \ 0, GL_RGBA, GL_UNSIGNED_BYTE, \ cubemap->cube[num]->rect) SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2); SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); if(GLEW_VERSION_1_2) glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); if (needs_split) my_free_envmapdata(cubemap); glDisable(GL_TEXTURE_CUBE_MAP_ARB); ActivateUnit(0); mOk = IsValid(); return mOk; }
static int multiresbake_check(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); Object *ob; Mesh *me; MultiresModifierData *mmd; int ok= 1, a; CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { ob= base->object; if(ob->type != OB_MESH) { BKE_report(op->reports, RPT_ERROR, "Basking of multires data only works with active object which is a mesh"); ok= 0; break; } me= (Mesh*)ob->data; mmd= get_multires_modifier(scene, ob, 0); /* Multi-resolution should be and be last in the stack */ if(ok && mmd) { ModifierData *md; ok= mmd->totlvl>0; for(md = (ModifierData*)mmd->modifier.next; md && ok; md = md->next) { if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { ok= 0; } } } else ok= 0; if(!ok) { BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object"); break; } if(!me->mtface) { BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); ok= 0; } else { a= me->totface; while (ok && a--) { Image *ima= me->mtface[a].tpage; if(!ima) { BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker"); ok= 0; } else { ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(!ibuf) { BKE_report(op->reports, RPT_ERROR, "Baking should happend to image with image buffer"); ok= 0; } else { if(ibuf->rect==NULL && ibuf->rect_float==NULL) ok= 0; if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) ok= 0; if(!ok) BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type"); } } } } if(!ok) break; }
static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: col, alpha */ if(node->id) { RenderData *rd= data; Image *ima= (Image *)node->id; ImageUser *iuser= (ImageUser *)node->storage; CompBuf *stackbuf= NULL; /* first set the right frame number in iuser */ BKE_image_user_calc_frame(iuser, rd->cfra, 0); /* force a load, we assume iuser index will be set OK anyway */ if(ima->type==IMA_TYPE_MULTILAYER) BKE_image_get_ibuf(ima, iuser); if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); if(rl) { out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED); /* go over all layers */ outputs_multilayer_get(rd, rl, out, ima, iuser); } } else { stackbuf= node_composit_get_image(rd, ima, iuser); if (stackbuf) { /*respect image premul option*/ if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { int i; float *pixel; /*first duplicate stackbuf->rect, since it's just a pointer to the source imbuf, and we don't want to change that.*/ stackbuf->rect = MEM_dupallocN(stackbuf->rect); /* since stackbuf now has allocated memory, rather than just a pointer, * mark it as allocated so it can be freed properly */ stackbuf->malloc=1; /*premul the image*/ pixel = stackbuf->rect; for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { pixel[0] *= pixel[3]; pixel[1] *= pixel[3]; pixel[2] *= pixel[3]; } } /* put image on stack */ out[0]->data= stackbuf; if(out[2]->hasoutput) out[2]->data= node_composit_get_zimage(node, rd); } } /* alpha and preview for both types */ if(stackbuf) { if(out[1]->hasoutput) out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); generate_preview(data, node, stackbuf); } } }