diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_blender.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_colortools.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_image.h | 116 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_library.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_utildefines.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/colortools.c | 44 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 1376 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 61 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node_composite.c | 567 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/packedFile.c | 11 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/texture.c | 32 |
13 files changed, 1584 insertions, 668 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 71ede8820db..e7029a01c09 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 242 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 53097b915f0..e78882220a9 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -31,7 +31,7 @@ struct CurveMapping; struct CurveMap; -struct Image; +struct ImBuf; struct rctf; struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); @@ -53,7 +53,7 @@ float curvemapping_evaluateF(struct CurveMapping *cumap, int cur, float value void curvemapping_evaluate3F(struct CurveMapping *cumap, float *vecout, const float *vecin); void curvemapping_evaluateRGBF(struct CurveMapping *cumap, float *vecout, const float *vecin); void curvemapping_evaluate_premulRGBF(struct CurveMapping *cumap, float *vecout, const float *vecin); -void curvemapping_do_image(struct CurveMapping *cumap, struct Image *ima); +void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf); void curvemapping_premultiply(struct CurveMapping *cumap, int restore); int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 98a93611204..1acaf004fb9 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -43,28 +43,108 @@ struct ImBuf; struct Tex; struct anim; -void free_image(struct Image *me); -void free_image_preview(struct Image *ima); -void free_image_buffers(struct Image *ima); -struct Image *add_image(char *name); -void free_unused_animimages(void); -struct Image *new_image(int width, int height, char *name, short uvtestgrid); - -int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); -void BKE_makepicstring(char *string, char *base, int frame, int imtype); -void BKE_add_image_extension(char *string, int imtype); -int BKE_imtype_is_movie(int imtype); +/* call from library */ +void free_image(struct Image *me); + +int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); +void BKE_makepicstring(char *string, char *base, int frame, int imtype); +void BKE_add_image_extension(char *string, int imtype); +int BKE_ftype_to_imtype(int ftype); +int BKE_imtype_to_ftype(int imtype); +int BKE_imtype_is_movie(int imtype); struct anim *openanim(char * name, int flags); -void ima_ibuf_is_nul(struct Tex *tex, struct Image *ima); -void load_image(struct Image * ima, int flags, char *relabase, int framenum); -void converttopremul(struct ImBuf *ibuf); -void image_de_interlace(struct Image *ima, int odd); + +void converttopremul(struct ImBuf *ibuf); +void image_de_interlace(struct Image *ima, int odd); -void tag_image_time(struct Image *ima); -void free_old_images(void); +void tag_image_time(struct Image *ima); +void free_old_images(void); + +/* ********************************** NEW IMAGE API *********************** */ + +/* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ +/* should be used in conjunction with an ID * to Image. */ +struct ImageUser; +struct RenderPass; +struct RenderResult; + +/* ima->source; where image comes from */ +#define IMA_SRC_CHECK 0 +#define IMA_SRC_FILE 1 +#define IMA_SRC_SEQUENCE 2 +#define IMA_SRC_MOVIE 3 +#define IMA_SRC_GENERATED 4 +#define IMA_SRC_VIEWER 5 + +/* ima->type, how to handle/generate it */ +#define IMA_TYPE_IMAGE 0 +#define IMA_TYPE_MULTILAYER 1 + /* generated */ +#define IMA_TYPE_UV_TEST 2 +#define IMA_TYPE_VERSE 3 + /* viewers */ +#define IMA_TYPE_R_RESULT 4 +#define IMA_TYPE_COMPOSITE 5 + +/* ima->ok */ +#define IMA_OK 1 +#define IMA_OK_LOADED 2 + +/* signals */ + /* reload only frees, doesn't read until image_get_ibuf() called */ +#define IMA_SIGNAL_RELOAD 0 +#define IMA_SIGNAL_FREE 1 + /* pack signals are executed */ +#define IMA_SIGNAL_PACK 2 +#define IMA_SIGNAL_REPACK 3 +#define IMA_SIGNAL_UNPACK 4 + /* source changes, from image to sequence or movie, etc */ +#define IMA_SIGNAL_SRC_CHANGE 5 + /* image-user gets a new image, check settings */ +#define IMA_SIGNAL_USER_NEW_IMAGE 6 + +/* depending Image type, and (optional) ImageUser setting it returns ibuf */ +/* always call to make signals work */ +struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); + +/* returns existing Image when filename/type is same */ +struct Image *BKE_add_image_file(const char *name); + +/* adds image, adds ibuf, generates color or pattern */ +struct Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid); + +/* for reload, refresh, pack */ +void BKE_image_signal(struct Image *ima, struct ImageUser *iuser, int signal); + +/* ensures an Image exists for viewing nodes or render */ +struct Image *BKE_image_verify_viewer(int type, const char *name); + +/* force an ImBuf to become part of Image */ +void BKE_image_assign_ibuf(struct Image *ima, struct ImBuf *ibuf); + +/* called on frame change or before render */ +void BKE_image_user_calc_imanr(struct ImageUser *iuser, int cfra, int fieldnr); + +/* fix things in ImageUser when new image gets assigned */ +void BKE_image_user_new_image(struct Image *ima, struct ImageUser *iuser); + +/* sets index offset for multilayer files */ +struct RenderPass *BKE_image_multilayer_index(struct RenderResult *rr, struct ImageUser *iuser); + +/* for multilayer images as well as for render-viewer */ +struct RenderResult *BKE_image_get_renderresult(struct Image *ima); + +/* goes over all textures that use images */ +void BKE_image_free_all_textures(void); + +/* does one image! */ +void BKE_image_free_anim_ibufs(struct Image *ima, int except_frame); + +/* does all images with type MOVIE or SEQUENCE */ +void BKE_image_all_free_anim_ibufs(int except_frame); -void free_all_imagetextures(void); +void BKE_image_memorypack(struct Image *ima); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index c51ebe25226..cc6d15f7bcb 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -66,6 +66,7 @@ struct ID *find_id(char *type, char *name); void clear_id_newpoins(void); void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr); +void IMAnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID *link, short *nr); void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype); #endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index f5fe91920b7..232a2a2cd9e 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -42,10 +42,12 @@ #define TRUE 1 #endif -/* also fill in structs itself, dna cannot handle defines, duplicate in blendef.h still */ +/* these values need to be hardcoded in structs, dna does not recognize defines */ +/* also defined in DNA_space_types.h */ #ifndef FILE_MAXDIR #define FILE_MAXDIR 160 #define FILE_MAXFILE 80 +#define FILE_MAX 240 #endif #define ELEM(a, b, c) ( (a)==(b) || (a)==(c) ) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 93238137f95..6249bb2f21b 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -43,6 +43,7 @@ #include "BKE_curve.h" #include "BKE_global.h" #include "BKE_ipo.h" +#include "BKE_image.h" #include "BKE_main.h" #include "BKE_utildefines.h" @@ -623,30 +624,43 @@ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float *vecout, const #define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) -void curvemapping_do_image(CurveMapping *cumap, Image *ima) +void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf) { int pixel; - if(ima==NULL || ima->ibuf==NULL) + if(ibuf==NULL) return; - if(ima->ibuf->rect_float==NULL) - IMB_float_from_rect(ima->ibuf); - else if(ima->ibuf->rect==NULL) - imb_addrectImBuf(ima->ibuf); + if(ibuf->rect_float==NULL) + IMB_float_from_rect(ibuf); + else if(ibuf->rect==NULL) + imb_addrectImBuf(ibuf); curvemapping_premultiply(cumap, 0); - if(ima->ibuf->rect_float && ima->ibuf->rect) { - float *pixf= ima->ibuf->rect_float; + if(ibuf->rect_float && ibuf->rect) { + float *pixf= ibuf->rect_float; float col[3]; - char *pixc= (char *)ima->ibuf->rect; + int stride= 4; + char *pixc= (char *)ibuf->rect; - for(pixel= ima->ibuf->x*ima->ibuf->y; pixel>0; pixel--, pixf+=4, pixc+=4) { - curvemapping_evaluate_premulRGBF(cumap, col, pixf); - pixc[0]= FTOCHAR(col[0]); - pixc[1]= FTOCHAR(col[1]); - pixc[2]= FTOCHAR(col[2]); - pixc[3]= FTOCHAR(pixf[3]); + if(ibuf->channels) + stride= ibuf->channels; + + for(pixel= ibuf->x*ibuf->y; pixel>0; pixel--, pixf+=stride, pixc+=4) { + if(stride<3) { + col[0]= curvemap_evaluateF(cumap->cm, *pixf); + pixc[1]= pixc[2]= pixc[3]= pixc[0]= FTOCHAR(col[0]); + } + else { + curvemapping_evaluate_premulRGBF(cumap, col, pixf); + pixc[0]= FTOCHAR(col[0]); + pixc[1]= FTOCHAR(col[1]); + pixc[2]= FTOCHAR(col[2]); + if(stride>3) + pixc[3]= FTOCHAR(pixf[3]); + else + pixc[3]= 255; + } } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index cf19d64ca03..b8a6ebf8928 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2,15 +2,12 @@ * * $Id$ * - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -26,9 +23,9 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Blender Foundation, 2006 * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * ***** END GPL LICENSE BLOCK ***** */ #include <stdio.h> @@ -47,85 +44,278 @@ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "intern/openexr/openexr_multi.h" #include "DNA_image_types.h" -#include "DNA_texture_types.h" #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" +#include "DNA_texture_types.h" #include "DNA_userdef_types.h" -#include "BLI_blenlib.h" #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_threads.h" #include "BKE_bmfont.h" -#include "BKE_packedFile.h" -#include "BKE_library.h" #include "BKE_global.h" -#include "BKE_main.h" #include "BKE_icons.h" #include "BKE_image.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_packedFile.h" #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "PIL_time.h" +#include "RE_pipeline.h" + /* bad level; call to free_realtime_image */ #include "BKE_bad_level_calls.h" -void free_image_buffers(Image *ima) +/* max int, to indicate we don't store sequences in ibuf */ +#define IMA_NO_INDEX 0x7FEFEFEF + +/* quick lookup: supports 1 million frames, thousand passes */ +#define IMA_MAKE_INDEX(frame, index) ((frame)<<10)+index +#define IMA_INDEX_FRAME(index) (index>>10) + +/* ******** IMAGE PROCESSING ************* */ + +/* used by sequencer */ +void converttopremul(struct ImBuf *ibuf) { - unsigned int a; + int x, y, val; + char *cp; + + if(ibuf==0) return; + if(ibuf->depth==24) { /* put alpha at 255 */ + + cp= (char *)(ibuf->rect); + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + cp[3]= 255; + } + } + return; + } - if(ima->ibuf) { - if (ima->ibuf->userdata) { - MEM_freeN(ima->ibuf->userdata); - ima->ibuf->userdata = NULL; + cp= (char *)(ibuf->rect); + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + if(cp[3]==0) { + cp[0]= cp[1]= cp[2]= 0; + } + else if(cp[3]!=255) { + val= cp[3]; + cp[0]= (cp[0]*val)>>8; + cp[1]= (cp[1]*val)>>8; + cp[2]= (cp[2]*val)>>8; + } } - IMB_freeImBuf(ima->ibuf); - ima->ibuf= NULL; } - if(ima->anim) IMB_free_anim(ima->anim); - ima->anim= NULL; +} + +static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ +{ + struct ImBuf * tbuf1, * tbuf2; - for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - ima->mipmap[a]= NULL; + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* make copies */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + + ibuf->x *= 2; + + IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); + IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + + ibuf->x /= 2; + IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y); + IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); } + ibuf->y /= 2; +} + +static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ +{ + struct ImBuf * tbuf1, * tbuf2; - free_realtime_image(ima); + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* make copies */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + + ibuf->x *= 2; + + IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); + IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + + ibuf->x /= 2; + IMB_rectcpy(ibuf, tbuf2, 0, 0, 0, 0, tbuf2->x, tbuf2->y); + IMB_rectcpy(ibuf, tbuf1, 0, tbuf2->y, 0, 0, tbuf1->x, tbuf1->y); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); + } + ibuf->y /= 2; +} + +void image_de_interlace(Image *ima, int odd) +{ + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf) { + if(odd) + de_interlace_st(ibuf); + else + de_interlace_ng(ibuf); + } } -void free_image_preview(struct Image *ima) +/* ***************** ALLOC & FREE, DATA MANAGING *************** */ + +static void image_free_buffers(Image *ima) { + ImBuf *ibuf; + + while((ibuf = ima->ibufs.first)) { + BLI_remlink(&ima->ibufs, ibuf); + + if (ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata = NULL; + } + IMB_freeImBuf(ibuf); + } + + if(ima->anim) IMB_free_anim(ima->anim); + ima->anim= NULL; + if (ima->preview) { MEM_freeN(ima->preview->rect); MEM_freeN(ima->preview); - ima->preview = 0; + ima->preview = NULL; } + + if(ima->rr) { + RE_FreeRenderResult(ima->rr); + ima->rr= NULL; + } + + free_realtime_image(ima); + + ima->ok= IMA_OK; } +/* called by library too, do not free ima itself */ void free_image(Image *ima) { - free_image_buffers(ima); + image_free_buffers(ima); if (ima->packedfile) { freePackedFile(ima->packedfile); ima->packedfile = NULL; } - free_image_preview(ima); BKE_icon_delete(&ima->id); ima->id.icon_id = 0; } +/* only image block itself */ +static Image *image_alloc(const char *name, short source, short type) +{ + Image *ima; + + ima= alloc_libblock(&G.main->image, ID_IM, name); + if(ima) { + ima->ok= IMA_OK; + + ima->xrep= ima->yrep= 1; + ima->gen_x= 256; ima->gen_y= 256; + ima->gen_type= 1; /* no defines yet? */ + + ima->source= source; + ima->type= type; + } + return ima; +} + +/* get the ibuf from an image cache, local use here only */ +static ImBuf *image_get_ibuf(Image *ima, int index, int frame) +{ + if(index==IMA_NO_INDEX) + return ima->ibufs.first; + else { + ImBuf *ibuf; + + index= IMA_MAKE_INDEX(frame, index); + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) + if(ibuf->index==index) + return ibuf; + return NULL; + } +} + +/* no ima->ibuf anymore, but listbase */ +static void image_remove_ibuf(Image *ima, ImBuf *ibuf) +{ + if(ibuf) { + BLI_remlink(&ima->ibufs, ibuf); + IMB_freeImBuf(ibuf); + } +} + + +/* no ima->ibuf anymore, but listbase */ +static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) +{ + if(ibuf) { + ImBuf *link; + + if(index!=IMA_NO_INDEX) + index= IMA_MAKE_INDEX(frame, index); + + /* insert based on index */ + for(link= ima->ibufs.first; link; link= link->next) + if(link->index>=index) + break; + /* now we don't want copies? */ + if(link && ibuf->index==link->index) { + ImBuf *prev= ibuf->prev; + image_remove_ibuf(ima, link); + link= prev; + } + + /* this function accepts link==NULL */ + BLI_insertlinkbefore(&ima->ibufs, link, ibuf); + + ibuf->index= index; + } + +} -Image *add_image(char *name) +/* checks if image was already loaded, then returns same image */ +/* otherwise creates new. */ +/* does not load ibuf itself */ +Image *BKE_add_image_file(const char *name) { Image *ima; int file, len; - char *libname, str[256], strtest[256]; + const char *libname; + char str[FILE_MAX], strtest[FILE_MAX]; - strcpy(str, name); + BLI_strncpy(str, name, sizeof(str)); BLI_convertstringcode(str, G.sce, G.scene->r.cfra); file= open(str, O_BINARY|O_RDONLY); @@ -133,135 +323,188 @@ Image *add_image(char *name) close(file); /* first search an identical image */ - ima= G.main->image.first; - while(ima) { - strcpy(strtest, ima->name); - BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); - if( strcmp(strtest, str)==0 ) { - if(ima->anim==0 || ima->id.us==0) { - strcpy(ima->name, name); /* for stringcode */ - ima->id.us++; /* officially should not, it doesn't link here! */ - ima->ok= 1; - return ima; + for(ima= G.main->image.first; ima; ima= ima->id.next) { + if(ima->source!=IMA_SRC_VIEWER) { + BLI_strncpy(strtest, ima->name, sizeof(ima->name)); + BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); + + if( strcmp(strtest, str)==0 ) { + if(ima->anim==NULL || ima->id.us==0) { + BLI_strncpy(ima->name, name, sizeof(ima->name)); /* for stringcode */ + ima->id.us++; /* officially should not, it doesn't link here! */ + if(ima->ok==0) + ima->ok= IMA_OK; + /* RETURN! */ + return ima; + } } } - ima= ima->id.next; } - + /* add new image */ + + /* create a short library name */ len= strlen(name); while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--; libname= name+len; - ima= alloc_libblock(&G.main->image, ID_IM, libname); - strcpy(ima->name, name); - ima->ok= 1; + ima= image_alloc(libname, IMA_SRC_FILE, IMA_TYPE_IMAGE); + BLI_strncpy(ima->name, name, sizeof(ima->name)); - ima->xrep= ima->yrep= 1; + /* do a wild guess! */ + if(BLI_testextensie(name, ".avi") || BLI_testextensie(name, ".mov") + || BLI_testextensie(name, ".mpg") || BLI_testextensie(name, ".mp4")) + ima->source= IMA_SRC_MOVIE; return ima; } -Image *new_image(int width, int height, char *name, short uvtestgrid) +static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid) { - Image *ima; - - ima = alloc_libblock(&G.main->image, ID_IM, name); + ImBuf *ibuf; + float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b; + unsigned char *rect; + int x, y; + int checkerwidth=21, dark=1; - if (ima) - { - ImBuf *ibuf; - unsigned char *rect; - int x, y; - int checkerwidth=21, dark=1; - float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b; - - strcpy(ima->name, "Untitled"); - - ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); - strcpy(ibuf->name, "Untitled"); - ima->ibuf= ibuf; - ibuf->userflags |= IB_BITMAPDIRTY; - - rect= (unsigned char*)ibuf->rect; + ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); + strcpy(ibuf->name, "Untitled"); + ibuf->userflags |= IB_BITMAPDIRTY; + + rect= (unsigned char*)ibuf->rect; + + if (uvtestgrid) { + /* these two passes could be combined into one, but it's more readable and + * easy to tweak like this, speed isn't really that much of an issue in this situation... */ - if (uvtestgrid) { - /* these two passes could be combined into one, but it's more readable and - * easy to tweak like this, speed isn't really that much of an issue in this situation... */ - - /* checkers */ - for(y=0; y<ibuf->y; y++) { - dark = pow(-1, floor(y / checkerwidth)); + /* checkers */ + for(y=0; y<ibuf->y; y++) { + dark = pow(-1, floor(y / checkerwidth)); + + for(x=0; x<ibuf->x; x++, rect+=4) { + if (x % checkerwidth == 0) dark *= -1; - for(x=0; x<ibuf->x; x++, rect+=4) { - if (x % checkerwidth == 0) dark *= -1; - - if (dark > 0) { - rect[0] = rect[1] = rect[2] = 64; - rect[3] = 255; - } else { - rect[0] = rect[1] = rect[2] = 150; - rect[3] = 255; - } + if (dark > 0) { + rect[0] = rect[1] = rect[2] = 64; + rect[3] = 255; + } else { + rect[0] = rect[1] = rect[2] = 150; + rect[3] = 255; } } - - /* 2nd pass, coloured + */ - rect= (unsigned char*)ibuf->rect; + } + + /* 2nd pass, coloured + */ + rect= (unsigned char*)ibuf->rect; + + for(y=0; y<ibuf->y; y++) { + hoffs = 0.125 * floor(y / checkerwidth); - for(y=0; y<ibuf->y; y++) { - hoffs = 0.125 * floor(y / checkerwidth); + for(x=0; x<ibuf->x; x++, rect+=4) { + h = 0.125 * floor(x / checkerwidth); - for(x=0; x<ibuf->x; x++, rect+=4) { - h = 0.125 * floor(x / checkerwidth); - - if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) && - (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) { + if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) && + (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) { + + if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) || + (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) { - if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) || - (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) { + hue = fmod(fabs(h-hoffs), 1.0); + hsv_to_rgb(hue, s, v, &r, &g, &b); - hue = fmod(fabs(h-hoffs), 1.0); - hsv_to_rgb(hue, s, v, &r, &g, &b); - - rect[0]= (char)(r * 255.0); - rect[1]= (char)(g * 255.0); - rect[2]= (char)(b * 255.0); - rect[3]= 255; - } + rect[0]= (char)(r * 255.0); + rect[1]= (char)(g * 255.0); + rect[2]= (char)(b * 255.0); + rect[3]= 255; } - } + } - } else { /* blank image */ - for(y=0; y<ibuf->y; y++) { - for(x=0; x<ibuf->x; x++, rect+=4) { - rect[0]= rect[1]= rect[2]= 0; - rect[3]= 255; - } + } + } else { /* blank image */ + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, rect+=4) { + rect[0]= rect[1]= rect[2]= 0; + rect[3]= 255; } } + } + return ibuf; +} - ima->ok= 1; - ima->xrep= ima->yrep= 1; +/* adds new image block, creates ImBuf and initializes color */ +Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid) +{ + Image *ima; + + /* on save, type is changed to FILE in editsima.c */ + ima= image_alloc(name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST); + + if (ima) { + ImBuf *ibuf; + + BLI_strncpy(ima->name, name, FILE_MAX); + ima->gen_x= width; + ima->gen_y= height; + ima->gen_type= uvtestgrid; + + ibuf= add_ibuf_size(width, height, name, uvtestgrid); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + + ima->ok= IMA_OK_LOADED; } return ima; } +/* packs rect from memory as PNG */ +void BKE_image_memorypack(Image *ima) +{ + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + + if(ibuf==NULL) + return; + if (ima->packedfile) { + freePackedFile(ima->packedfile); + ima->packedfile = NULL; + } + + ibuf->ftype= PNG; + ibuf->depth= 32; + + IMB_saveiff(ibuf, ibuf->name, IB_rect | IB_mem); + if(ibuf->encodedbuffer==NULL) { + printf("memory save for pack error\n"); + } + else { + PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); + + pf->data = ibuf->encodedbuffer; + pf->size = ibuf->encodedsize; + ima->packedfile= pf; + ibuf->encodedbuffer= NULL; + ibuf->encodedsize= 0; + ibuf->userflags &= ~IB_BITMAPDIRTY; + + if(ima->source==IMA_SRC_GENERATED) + ima->source= IMA_SRC_FILE; + } +} + void tag_image_time(Image *ima) { if (ima) ima->lastused = (int)PIL_check_seconds_timer(); } -void tag_all_images_time() { +void tag_all_images_time() +{ Image *ima; int ctime = (int)PIL_check_seconds_timer(); ima= G.main->image.first; while(ima) { - if(ima->bindcode || ima->repbind || ima->ibuf) { + if(ima->bindcode || ima->repbind || ima->ibufs.first) { ima->lastused = ctime; } } @@ -294,29 +537,15 @@ void free_old_images() ima->lastused = ctime; } /* Otherwise, just kill the buffers */ - else if (ima->ibuf) { - free_image_buffers(ima); + else if (ima->ibufs.first) { + image_free_buffers(ima); } } ima = ima->id.next; } } -void free_unused_animimages() -{ - Image *ima, *nima; - - ima= G.main->image.first; - while(ima) { - nima= ima->id.next; - if(ima->id.us==0) { - if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima); - } - ima= nima; - } -} - -void free_all_imagetextures(void) +void BKE_image_free_all_textures(void) { Tex *tex; Image *ima; @@ -330,19 +559,116 @@ void free_all_imagetextures(void) tex->ima->id.flag |= LIB_DOIT; for(ima= G.main->image.first; ima; ima= ima->id.next) { - if(ima->ibuf && (ima->id.flag & LIB_DOIT)) { - if(ima->mipmap[0]) - totsize+= 1.33*ima->ibuf->x*ima->ibuf->y*4; - else - totsize+= ima->ibuf->x*ima->ibuf->y*4; - free_image_buffers(ima); + if(ima->ibufs.first && (ima->id.flag & LIB_DOIT)) { + ImBuf *ibuf; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { + if(ibuf->mipmap[0]) + totsize+= 1.33*ibuf->x*ibuf->y*4; + else + totsize+= ibuf->x*ibuf->y*4; + } + image_free_buffers(ima); } } - printf("freed total %d MB\n", totsize/(1024*1024)); + /* printf("freed total %d MB\n", totsize/(1024*1024)); */ } +/* except_frame is weak, only works for seqs without offset... */ +void BKE_image_free_anim_ibufs(Image *ima, int except_frame) +{ + ImBuf *ibuf, *nbuf; + + for(ibuf= ima->ibufs.first; ibuf; ibuf= nbuf) { + nbuf= ibuf->next; + if(ibuf->userflags & IB_BITMAPDIRTY) + continue; + if(ibuf->index==IMA_NO_INDEX) + continue; + if(except_frame!=IMA_INDEX_FRAME(ibuf->index)) { + BLI_remlink(&ima->ibufs, ibuf); + + if (ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata = NULL; + } + IMB_freeImBuf(ibuf); + } + } +} + +void BKE_image_all_free_anim_ibufs(int cfra) +{ + Image *ima; + + for(ima= G.main->image.first; ima; ima= ima->id.next) + if(ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) + BKE_image_free_anim_ibufs(ima, cfra); +} + + /* *********** READ AND WRITE ************** */ +int BKE_imtype_to_ftype(int imtype) +{ + if(imtype==0) + return TGA; + else if(imtype== R_IRIS) + return IMAGIC; + else if (imtype==R_RADHDR) + return RADHDR; + else if (imtype==R_PNG) + return PNG; + else if (imtype==R_BMP) + return BMP; + else if (imtype==R_TIFF) + return TIF; + else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) + return OPENEXR; + else if (imtype==R_CINEON) + return CINEON; + else if (imtype==R_DPX) + return DPX; + else if (imtype==R_TARGA) + return TGA; + else if(imtype==R_RAWTGA) + return RAWTGA; + else if(imtype==R_HAMX) + return AN_hamx; + else + return JPG|90; +} + +int BKE_ftype_to_imtype(int ftype) +{ + if(ftype==0) + return TGA; + else if(ftype == IMAGIC) + return R_IRIS; + else if (ftype & RADHDR) + return R_RADHDR; + else if (ftype & PNG) + return R_PNG; + else if (ftype & BMP) + return R_BMP; + else if (ftype & TIF) + return R_TIFF; + else if (ftype & OPENEXR) + return R_OPENEXR; + else if (ftype & CINEON) + return R_CINEON; + else if (ftype & DPX) + return R_DPX; + else if (ftype & TGA) + return R_TARGA; + else if(ftype & RAWTGA) + return R_RAWTGA; + else if(ftype == AN_hamx) + return R_HAMX; + else + return R_JPEG90; +} + + int BKE_imtype_is_movie(int imtype) { switch(imtype) { @@ -395,7 +721,7 @@ void BKE_add_image_extension(char *string, int imtype) extension= ".tif"; } #ifdef WITH_OPENEXR - else if(imtype==R_OPENEXR) { + else if( ELEM(imtype, R_OPENEXR, R_MULTILAYER)) { if(!BLI_testextensie(string, ".exr")) extension= ".exr"; } @@ -437,7 +763,7 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali ibuf->ftype= TIF; } #ifdef WITH_OPENEXR - else if (imtype==R_OPENEXR) { + else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) { ibuf->ftype= OPENEXR; if(subimtype & R_OPENEXR_HALF) ibuf->ftype |= OPENEXR_HALF; @@ -488,7 +814,7 @@ void BKE_makepicstring(char *string, char *base, int frame, int imtype) if (string==NULL) return; - BLI_strncpy(string, base, FILE_MAXDIR + FILE_MAXFILE - 10); /* weak assumption */ + BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ BLI_convertstringcode(string, G.sce, frame); len= strlen(string); @@ -506,43 +832,7 @@ void BKE_makepicstring(char *string, char *base, int frame, int imtype) } -/* ******** IMAGE WRAPPING INIT ************* */ - -/* used by sequencer, texture */ -void converttopremul(struct ImBuf *ibuf) -{ - int x, y, val; - char *cp; - - if(ibuf==0) return; - if(ibuf->depth==24) { /* put alpha at 255 */ - - cp= (char *)(ibuf->rect); - for(y=0; y<ibuf->y; y++) { - for(x=0; x<ibuf->x; x++, cp+=4) { - cp[3]= 255; - } - } - return; - } - - cp= (char *)(ibuf->rect); - for(y=0; y<ibuf->y; y++) { - for(x=0; x<ibuf->x; x++, cp+=4) { - if(cp[3]==0) { - cp[0]= cp[1]= cp[2]= 0; - } - else if(cp[3]!=255) { - val= cp[3]; - cp[0]= (cp[0]*val)>>8; - cp[1]= (cp[1]*val)>>8; - cp[2]= (cp[2]*val)>>8; - } - } - } -} - -/* used by sequencer, texture */ +/* used by sequencer too */ struct anim *openanim(char *name, int flags) { struct anim *anim; @@ -562,198 +852,656 @@ struct anim *openanim(char *name, int flags) return(anim); } +/* ************************* New Image API *************** */ + + +/* Notes about Image storage +- packedfile + -> written in .blend +- filename + -> written in .blend +- movie + -> comes from packedfile or filename +- renderresult + -> comes from packedfile or filename +- listbase + -> ibufs from exrhandle +- flipbook array + -> ibufs come from movie, temporary renderresult or sequence +- ibuf + -> comes from packedfile or filename or generated -/* -load_image handles reading the image from disk or from the packedfile. */ -void load_image(Image * ima, int flags, char *relabase, int framenum) -{ - char name[FILE_MAXDIR + FILE_MAXFILE]; - if(ima->id.lib) relabase= ima->id.lib->filename; +/* forces existance of 1 Image for renderout or nodes, returns Image */ +/* name is only for default, when making new one */ +Image *BKE_image_verify_viewer(int type, const char *name) +{ + Image *ima; - if (ima->ibuf == NULL) { - - // is there a PackedFile with this image ?; - if (ima->packedfile) { - ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags); - } else { - strcpy(name, ima->name); - BLI_convertstringcode(name, relabase, framenum); + for(ima=G.main->image.first; ima; ima= ima->id.next) + if(ima->source==IMA_SRC_VIEWER) + if(ima->type==type) + break; + + if(ima==NULL) + ima= image_alloc(name, IMA_SRC_VIEWER, type); + + /* happens on reload, imagewindow cannot be image user when hidden*/ + if(ima->id.us==0) + id_us_plus(&ima->id); - ima->ibuf = IMB_loadiffname(name , flags); - } - // check if the image is a font image... - // printf("Checking for font\n"); + return ima; +} - if (ima->ibuf) { - detectBitmapFont(ima->ibuf); - /* preview is NULL when it has never been used as an icon before */ - if(G.background==0 && ima->preview==NULL) - BKE_icon_changed(BKE_icon_getid(&ima->id)); +void BKE_image_assign_ibuf(Image *ima, ImBuf *ibuf) +{ + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); +} +void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) +{ + if(ima==NULL) + return; + + switch(signal) { + case IMA_SIGNAL_FREE: + image_free_buffers(ima); + if(iuser) + iuser->ok= 1; + break; + case IMA_SIGNAL_SRC_CHANGE: + if(ima->type==IMA_TYPE_MULTILAYER) + image_free_buffers(ima); + else if(ima->source==IMA_SRC_GENERATED) { + if(ima->gen_x==0 || ima->gen_y==0) { + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + if(ibuf) { + ima->gen_x= ibuf->x; + ima->gen_y= ibuf->y; + } + } + } + ima->ok= 1; + if(iuser) + iuser->ok= 1; + break; + + case IMA_SIGNAL_RELOAD: + /* try to repack file */ + if(ima->packedfile) { + PackedFile *pf; + pf = newPackedFile(ima->name); + if (pf) { + freePackedFile(ima->packedfile); + ima->packedfile = pf; + image_free_buffers(ima); + } else { + printf("ERROR: Image not available. Keeping packed image\n"); + } } + else + image_free_buffers(ima); + + if(iuser) + iuser->ok= 1; + + break; + case IMA_SIGNAL_USER_NEW_IMAGE: + if(iuser) { + iuser->ok= 1; + if(ima->source==IMA_SRC_FILE || ima->source==IMA_SRC_SEQUENCE) { + if(ima->type==IMA_TYPE_MULTILAYER) { + iuser->multi_index= 0; + iuser->layer= iuser->pass= 0; + } + } + } + break; } } - -static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ +/* if layer or pass changes, we need an index for the imbufs list */ +/* note it is called for rendered results, but it doesnt use the index! */ +/* and because rendered results use fake layer/passes, don't correct for wrong indices here */ +RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) { - struct ImBuf * tbuf1, * tbuf2; + RenderLayer *rl; + RenderPass *rpass= NULL; - if (ibuf == 0) return; - if (ibuf->flags & IB_fields) return; - ibuf->flags |= IB_fields; + if(rr==NULL) + return NULL; - if (ibuf->rect) { - /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + if(iuser) { + short index= 0, rl_index= 0, rp_index; - ibuf->x *= 2; + for(rl= rr->layers.first; rl; rl= rl->next, rl_index++) { + rp_index= 0; + for(rpass= rl->passes.first; rpass; rpass= rpass->next, index++, rp_index++) + if(iuser->layer==rl_index && iuser->pass==rp_index) + break; + if(rpass) + break; + } - IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); - IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + if(rpass) + iuser->multi_index= index; + else + iuser->multi_index= 0; + } + if(rpass==NULL) { + rl= rr->layers.first; + if(rl) + rpass= rl->passes.first; + } + + return rpass; +} + +RenderResult *BKE_image_get_renderresult(Image *ima) +{ + if(ima->rr) + return ima->rr; + if(ima->type==IMA_TYPE_R_RESULT) + return RE_GetResult(RE_GetRender(G.scene->id.name)); + return NULL; +} + +/* after imbuf load, openexr type can return with a exrhandle open */ +/* in that case we have to build a render-result */ +static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr) +{ + + ima->rr= RE_MultilayerConvert(ibuf->userdata, ibuf->x, ibuf->y); + IMB_exr_close(ibuf->userdata); + ibuf->userdata= NULL; + if(ima->rr) + ima->rr->framenr= framenr; +} + +/* common stuff to do with images after loading */ +static void image_initialize_after_load(Image *ima, ImBuf *ibuf) +{ + + + /* preview is NULL when it has never been used as an icon before */ + if(G.background==0 && ima->preview==NULL) + BKE_icon_changed(BKE_icon_getid(&ima->id)); + + /* stringcodes also in ibuf, ibuf->name is used to retrieve original (buttons) */ + BLI_strncpy(ibuf->name, ima->name, FILE_MAX); + + /* fields */ + if (ima->flag & IMA_FIELDS) { + if(ima->flag & IMA_STD_FIELD) de_interlace_st(ibuf); + else de_interlace_ng(ibuf); + } + /* timer */ + ima->lastused = clock() / CLOCKS_PER_SEC; + + ima->ok= IMA_OK_LOADED; + +} + +static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf; + unsigned short numlen; + char name[FILE_MAX], head[FILE_MAX], tail[FILE_MAX]; + + ima->lastframe= frame; + + BLI_stringdec(ima->name, head, tail, &numlen); + BLI_stringenc(ima->name, head, tail, numlen, frame); + BLI_strncpy(name, ima->name, sizeof(name)); + + if(ima->id.lib) + BLI_convertstringcode(name, ima->id.lib->filename, frame); + else + BLI_convertstringcode(name, G.sce, frame); + + /* read ibuf */ + ibuf = IMB_loadiffname(name, IB_rect|IB_multilayer); + printf("loaded %s\n", name); + + if (ibuf) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + if (ibuf->ftype==OPENEXR && ibuf->userdata) { + image_create_multilayer(ima, ibuf, frame); + ima->type= IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf= NULL; + } + else { + image_assign_ibuf(ima, ibuf, 0, frame); + image_initialize_after_load(ima, ibuf); + } + } + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; +} + +static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int frame) +{ + struct ImBuf *ibuf= NULL; + + /* either we load from RenderResult, or we have to load a new one */ + + /* check for new RenderResult */ + if(ima->rr==NULL || frame!=ima->rr->framenr) { + /* copy to survive not found multilayer image */ + RenderResult *oldrr= ima->rr; + + ima->rr= NULL; + ibuf = image_load_sequence_file(ima, iuser, frame); - ibuf->x /= 2; - IMB_rectcpy(ibuf, tbuf1, 0, 0, 0, 0, tbuf1->x, tbuf1->y); - IMB_rectcpy(ibuf, tbuf2, 0, tbuf2->y, 0, 0, tbuf2->x, tbuf2->y); + if(ibuf) { /* actually an error */ + ima->type= IMA_TYPE_IMAGE; + printf("error, multi is normal image\n"); + } + // printf("loaded new result %p\n", ima->rr); + /* free result if new one found */ + if(ima->rr) { + // if(oldrr) printf("freed previous result %p\n", oldrr); + if(oldrr) RE_FreeRenderResult(oldrr); + } + else + ima->rr= oldrr; + + } + if(ima->rr) { + RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser); - IMB_freeImBuf(tbuf1); - IMB_freeImBuf(tbuf2); + if(rpass) { + // printf("load from pass %s\n", rpass->name); + /* since we free render results, we copy the rect */ + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + ibuf->rect_float= MEM_dupallocN(rpass->rect); + ibuf->flags |= IB_rectfloat; + ibuf->mall= IB_rectfloat; + ibuf->channels= rpass->channels; + + image_assign_ibuf(ima, ibuf, iuser->multi_index, frame); + image_initialize_after_load(ima, ibuf); + + } + // else printf("pass not found\n"); } - ibuf->y /= 2; + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ + +static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) { - struct ImBuf * tbuf1, * tbuf2; + struct ImBuf *ibuf= NULL; - if (ibuf == 0) return; - if (ibuf->flags & IB_fields) return; - ibuf->flags |= IB_fields; + ima->lastframe= frame; - if (ibuf->rect) { - /* make copies */ - tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); - tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + if(ima->anim==NULL) { + char str[FILE_MAX]; - ibuf->x *= 2; + BLI_strncpy(str, ima->name, FILE_MAX); + if(ima->id.lib) + BLI_convertstringcode(str, ima->id.lib->filename, 0); + else + BLI_convertstringcode(str, G.sce, 0); - IMB_rectcpy(tbuf1, ibuf, 0, 0, 0, 0, ibuf->x, ibuf->y); - IMB_rectcpy(tbuf2, ibuf, 0, 0, tbuf2->x, 0, ibuf->x, ibuf->y); + ima->anim = openanim(str, IB_cmap | IB_rect); - ibuf->x /= 2; - IMB_rectcpy(ibuf, tbuf2, 0, 0, 0, 0, tbuf2->x, tbuf2->y); - IMB_rectcpy(ibuf, tbuf1, 0, tbuf2->y, 0, 0, tbuf1->x, tbuf1->y); + /* let's initialize this user */ + if(ima->anim && iuser && iuser->frames==0) + iuser->frames= IMB_anim_get_duration(ima->anim); + } + + if(ima->anim) { + int dur = IMB_anim_get_duration(ima->anim); + int fra= frame-1; - IMB_freeImBuf(tbuf1); - IMB_freeImBuf(tbuf2); + if(fra<0) fra = 0; + if(fra>(dur-1)) fra= dur-1; + ibuf = IMB_anim_absolute(ima->anim, fra); + + if(ibuf) { + image_assign_ibuf(ima, ibuf, 0, frame); + image_initialize_after_load(ima, ibuf); + } + else + ima->ok= 0; } - ibuf->y /= 2; + else + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -void image_de_interlace(Image *ima, int odd) +/* cfra used for # code, Image can only have this # for all its users */ +static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { - if(odd) - de_interlace_st(ima->ibuf); + struct ImBuf *ibuf; + char str[FILE_MAX]; + + /* always ensure clean ima */ + image_free_buffers(ima); + + /* is there a PackedFile with this image ? */ + if (ima->packedfile) { + ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, IB_rect|IB_multilayer); + } + else { + + /* get the right string */ + BLI_strncpy(str, ima->name, sizeof(str)); + if(ima->id.lib) + BLI_convertstringcode(str, ima->id.lib->filename, cfra); + else + BLI_convertstringcode(str, G.sce, cfra); + + /* read ibuf */ + ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer); + } + + if (ibuf) { + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + if (ibuf->ftype==OPENEXR && ibuf->userdata) { + image_create_multilayer(ima, ibuf, cfra); + ima->type= IMA_TYPE_MULTILAYER; + IMB_freeImBuf(ibuf); + ibuf= NULL; + } + else { + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + image_initialize_after_load(ima, ibuf); + + /* check if the image is a font image... */ + detectBitmapFont(ibuf); + + /* make packed file for autopack */ + if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) + ima->packedfile = newPackedFile(str); + } + } else - de_interlace_ng(ima->ibuf); + ima->ok= 0; + + if(iuser) + iuser->ok= ima->ok; + + return ibuf; } -void ima_ibuf_is_nul(Tex *tex, Image *ima) +static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser) { - void (*de_interlacefunc)(struct ImBuf *ibuf); - unsigned int a; - int fra, dur; - char str[FILE_MAXDIR+FILE_MAXFILE], *cp; + ImBuf *ibuf= NULL; - if(ima==0) return; + if(ima->rr==NULL) { + ibuf = image_load_image_file(ima, iuser, 0); + if(ibuf) { /* actually an error */ + ima->type= IMA_TYPE_IMAGE; + return ibuf; + } + } + if(ima->rr) { + RenderPass *rpass= BKE_image_multilayer_index(ima->rr, iuser); + + if(rpass) { + ibuf= IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0, 0); + + image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0); + image_initialize_after_load(ima, ibuf); + + ibuf->rect_float= rpass->rect; + ibuf->flags |= IB_rectfloat; + ibuf->channels= rpass->channels; + } + } - strcpy(str, ima->name); - if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, G.scene->r.cfra); - else - BLI_convertstringcode(str, G.sce, G.scene->r.cfra); + if(ibuf==NULL) + ima->ok= 0; + if(iuser) + iuser->ok= ima->ok; - if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st; - else de_interlacefunc= de_interlace_ng; + return ibuf; +} + + +/* showing RGBA result itself (from compo/sequence) or + like exr, using layers etc */ +static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) +{ + RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); - if(tex->imaflag & TEX_ANIM5) { + if(rr && iuser) { + RenderResult rres; + float *rectf; + unsigned int *rect; + int channels= 4, layer= iuser->layer; - if(ima->anim==NULL) ima->anim = openanim(str, IB_cmap | IB_rect); - if (ima->anim) { - dur = IMB_anim_get_duration(ima->anim); - - fra= ima->lastframe-1; - - if(fra<0) fra = 0; - if(fra>(dur-1)) fra= dur-1; - ima->ibuf = IMB_anim_absolute(ima->anim, fra); - - /* patch for textbutton with name ima (B_NAMEIMA) */ - if(ima->ibuf) { - strcpy(ima->ibuf->name, ima->name); - if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); + /* this gives active layer, composite or seqence result */ + RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); + rect= rres.rect32; + rectf= rres.rectf; + + /* get compo/seq result by default */ + if(rr->rectf && layer==0); + else if(rr->layers.first) { + RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer-(rr->rectf?1:0)); + if(rl) { + /* there's no combined pass, is in renderlayer itself */ + if(iuser->pass==0) { + rectf= rl->rectf; + } + else { + RenderPass *rpass= BLI_findlink(&rl->passes, iuser->pass-1); + if(rpass) { + channels= rpass->channels; + rectf= rpass->rect; + } + } } } - } else { - // create a packedfile for this image when autopack is on - // for performance (IMB_loadiffname uses mmap) we don't do this by default - if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) { - ima->packedfile = newPackedFile(str); + if(rectf || rect) { + ImBuf *ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + + /* make ibuf if needed, and initialize it */ + if(ibuf==NULL) { + ibuf= IMB_allocImBuf(rr->rectx, rr->recty, 32, 0, 0); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } + ibuf->x= rr->rectx; + ibuf->y= rr->recty; + + if(ibuf->rect_float!=rectf || rect) /* ensure correct redraw */ + imb_freerectImBuf(ibuf); + if(rect) + ibuf->rect= rect; + + ibuf->rect_float= rectf; + ibuf->flags |= IB_rectfloat; + ibuf->channels= channels; + + ima->ok= IMA_OK_LOADED; + return ibuf; } - - load_image(ima, IB_rect, G.sce, G.scene->r.cfra); - - if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); } - if(ima->ibuf) { + return NULL; +} + +/* Checks optional ImageUser and verifies/creates ImBuf. */ +/* returns ibuf */ +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + ImBuf *ibuf= NULL; + + /* quick reject tests */ + if(ima==NULL) + return NULL; + if(iuser) { + if(iuser->ok==0) + return NULL; + } + else if(ima->ok==0) + return NULL; + + BLI_lock_thread(LOCK_CUSTOM1); + + /* handle image source and types */ + if(ima->source==IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + int frame= iuser?iuser->framenr:ima->lastframe; - /* stringcodes also in ibuf. ibuf->name is used as 'undo' (buttons.c) */ - strcpy(ima->ibuf->name, ima->name); + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) + ibuf= image_load_movie_file(ima, iuser, frame); + } + else if(ima->source==IMA_SRC_SEQUENCE) { - if(ima->ibuf->cmap) { + if(ima->type==IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + int frame= iuser?iuser->framenr:ima->lastframe; - if(tex->imaflag & TEX_ANIM5) { - - if(tex->imaflag & TEX_MORKPATCH) { - /**** PATCH TO SET COLOR 2 RIGHT (neogeo..) */ - if(ima->ibuf->maxcol > 4) { - cp= (char *)(ima->ibuf->cmap+2); - cp[0]= 0x80; - } - } - - IMB_applycmap(ima->ibuf); - IMB_convert_rgba_to_abgr(ima->ibuf); - - } + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) + ibuf= image_load_sequence_file(ima, iuser, frame); + else + BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); + } + /* no else; on load the ima type can change */ + if(ima->type==IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + int frame= iuser?iuser->framenr:ima->lastframe; + int index= iuser?iuser->multi_index:IMA_NO_INDEX; - converttopremul(ima->ibuf); + ibuf= image_get_ibuf(ima, index, frame); + if(G.rt) printf("seq multi fra %d id %d ibuf %p %s\n", frame, index, ibuf, ima->id.name); + if(ibuf==NULL) + ibuf= image_load_sequence_multilayer(ima, iuser, frame); + else + BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); + } + + } + else if(ima->source==IMA_SRC_FILE) { + + if(ima->type==IMA_TYPE_IMAGE) { + ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); + if(ibuf==NULL) + ibuf= image_load_image_file(ima, iuser, G.scene->r.cfra); /* cfra only for '#', this global is OK */ } + /* no else; on load the ima type can change */ + if(ima->type==IMA_TYPE_MULTILAYER) { + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf= image_get_ibuf(ima, iuser?iuser->multi_index:IMA_NO_INDEX, 0); + if(ibuf==NULL) + ibuf= image_get_ibuf_multilayer(ima, iuser); + } + + } + else if(ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + ibuf= image_get_ibuf(ima, IMA_NO_INDEX, 0); - if(tex->imaflag & TEX_ANTISCALE) { - IMB_clever_double(ima->ibuf); - IMB_antialias(ima->ibuf); + if(ibuf==NULL) { + if(ima->type==IMA_TYPE_VERSE) { + /* todo */ + } + else { /* always fall back to IMA_TYPE_UV_TEST */ + /* UV testgrid or black or solid etc */ + if(ima->gen_x==0) ima->gen_x= 256; + if(ima->gen_y==0) ima->gen_y= 256; + ibuf= add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, ima->gen_type); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } } - else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf); } - - if(ima->ibuf) - ima->lastused = clock() / CLOCKS_PER_SEC; - else - ima->ok= 0; - - for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - ima->mipmap[a]= 0; + else if(ima->source == IMA_SRC_VIEWER) { + if(ima->type==IMA_TYPE_R_RESULT) { + /* always verify entirely */ + ibuf= image_get_render_result(ima, iuser); + } + else if(ima->type==IMA_TYPE_COMPOSITE) { + int frame= iuser?iuser->framenr:0; + + /* Composite Viewer, all handled in compositor */ + ibuf= image_get_ibuf(ima, 0, frame); + if(ibuf==NULL) { + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, 0, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } + } } + if(G.rendering==0) + tag_image_time(ima); + + BLI_unlock_thread(LOCK_CUSTOM1); + + return ibuf; } +void BKE_image_user_calc_imanr(ImageUser *iuser, int cfra, int fieldnr) +{ + int imanr, len; + + /* here (+fie_ima/2-1) makes sure that division happens correctly */ + len= (iuser->fie_ima*iuser->frames)/2; + + if(len==0) { + iuser->framenr= 0; + } + else { + cfra= cfra - iuser->sfra+1; + + /* cyclic */ + if(iuser->cycl) { + cfra= ( (cfra) % len ); + if(cfra < 0) cfra+= len; + if(cfra==0) cfra= len; + } + + if(cfra<1) cfra= 1; + else if(cfra>len) cfra= len; + + /* convert current frame to current field */ + cfra= 2*(cfra); + if(fieldnr) cfra++; + + /* transform to images space */ + imanr= (cfra+iuser->fie_ima-2)/iuser->fie_ima; + if(imanr>iuser->frames) imanr= iuser->frames; + imanr+= iuser->offset; + + if(iuser->cycl) { + imanr= ( (imanr) % len ); + while(imanr < 0) imanr+= len; + if(imanr==0) imanr= len; + } + + /* allows image users to handle redraws */ + if(iuser->flag & IMA_ANIM_ALWAYS) + if(imanr!=iuser->framenr) + iuser->flag |= IMA_ANIM_REFRESHED; + + iuser->framenr= imanr; + if(iuser->ok==0) iuser->ok= 1; + } +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index b5680f98940..ba19ba5d8b2 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -569,7 +569,9 @@ static void get_flags_for_id(ID *id, char *buf) sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' '); } -static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr) +#define IDPUP_NO_VIEWER 1 + +static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int hideflag) { int i, nids= BLI_countlist(lb); @@ -588,6 +590,10 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor if (U.uiflag & USER_HIDE_DOT && id->name[2]=='.') continue; + if (hideflag & IDPUP_NO_VIEWER) + if (GS(id->name)==ID_IM) + if ( ((Image *)id)->source==IMA_SRC_VIEWER ) + continue; get_flags_for_id(id, buf); @@ -681,12 +687,35 @@ void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, BLI_dynstr_append(pupds, "|"); } - IDnames_to_dyn_pupstring(pupds, lb, link, nr); + IDnames_to_dyn_pupstring(pupds, lb, link, nr, 0); *str= BLI_dynstr_get_cstring(pupds); BLI_dynstr_free(pupds); } +/* skips viewer images */ +void IMAnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr) +{ + DynStr *pupds= BLI_dynstr_new(); + + if (title) { + BLI_dynstr_append(pupds, title); + BLI_dynstr_append(pupds, "%t|"); + } + + if (extraops) { + BLI_dynstr_append(pupds, extraops); + if (BLI_dynstr_get_len(pupds)) + BLI_dynstr_append(pupds, "|"); + } + + IDnames_to_dyn_pupstring(pupds, lb, link, nr, IDPUP_NO_VIEWER); + + *str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); +} + + // only used by headerbuttons.c void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype) { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index bb6439d09fb..d10ff6c6d33 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -31,6 +31,7 @@ #include <string.h> #include "DNA_ID.h" +#include "DNA_image_types.h" #include "DNA_node_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" @@ -641,7 +642,7 @@ static void find_node_with_socket(bNodeTree *ntree, bNodeSocket *sock, bNode **n { bNode *node; bNodeSocket *tsock; - int index; + int index= 0; for(node= ntree->nodes.first; node; node= node->next) { for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) @@ -807,6 +808,13 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup) nbd->samples= 32; nbd->fac= 1.0f; } + else if(ELEM3(type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { + ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); + node->storage= iuser; + iuser->sfra= 1; + iuser->fie_ima= 2; + iuser->ok= 1; + } else if(type==CMP_NODE_HUE_SAT) { NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat"); node->storage= nhs; @@ -1488,10 +1496,10 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node) free_compbuf(sock->ns.data); sock->ns.data= NULL; - if(node->preview && node->preview->rect) { - MEM_freeN(node->preview->rect); - node->preview->rect= NULL; - } + //if(node->preview && node->preview->rect) { + // MEM_freeN(node->preview->rect); + // node->preview->rect= NULL; + //} } } @@ -1967,6 +1975,14 @@ static void *exec_composite_node(void *node_v) return 0; } +/* should become a type? these are nodes without input, only giving values */ +static int node_only_value(bNode *node) +{ + if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB)) + return 1; + return 0; +} + /* return total of executable nodes, for timecursor */ /* only compositor uses it */ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) @@ -1991,10 +2007,13 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) node_get_stack(node, thd->stack, nsin, nsout); /* test the outputs */ - for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { - if(nsout[a]->data==NULL && nsout[a]->hasoutput) { - node->need_exec= 1; - break; + /* skip value-only nodes (should be in type!) */ + if(!node_only_value(node)) { + for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { + if(nsout[a]->data==NULL && nsout[a]->hasoutput) { + node->need_exec= 1; + break; + } } } @@ -2008,7 +2027,7 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) bNodeLink *link= sock->link; /* this is the test for a cyclic case */ if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { - if(nsin[a]->data==NULL || sock->link->fromnode->need_exec) { + if(sock->link->fromnode->need_exec) { node->need_exec= 1; break; } @@ -2030,15 +2049,31 @@ static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) } } totnode++; - // printf("node needs exec %s\n", node->name); + /* printf("node needs exec %s\n", node->name); */ /* tag for getExecutableNode() */ node->exec= 0; } - else + else { /* tag for getExecutableNode() */ node->exec= NODE_READY|NODE_FINISHED; + + } } + + /* last step: set the stack values for only-value nodes */ + /* just does all now, compared to a full buffer exec this is nothing */ + if(totnode) { + for(node= ntree->nodes.first; node; node= node->next) { + if(node->need_exec==0 && node_only_value(node)) { + if(node->typeinfo->execfunc) { + node_get_stack(node, thd->stack, nsin, nsout); + node->typeinfo->execfunc(thd->rd, node, nsin, nsout); + } + } + } + } + return totnode; } @@ -2187,8 +2222,6 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeEndExecTree(ntree); - free_unused_animimages(); - } diff --git a/source/blender/blenkernel/intern/node_composite.c b/source/blender/blenkernel/intern/node_composite.c index b35bfba6b3e..9030b072b9d 100644 --- a/source/blender/blenkernel/intern/node_composite.c +++ b/source/blender/blenkernel/intern/node_composite.c @@ -600,10 +600,27 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, /* stack order input sockets: col, alpha, z */ if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ + RenderData *rd= data; Image *ima= (Image *)node->id; + ImBuf *ibuf; CompBuf *cbuf, *tbuf; int rectx, recty; + + 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); + + /* get size */ tbuf= in[0]->data?in[0]->data:(in[1]->data?in[1]->data:in[2]->data); if(tbuf==NULL) { rectx= 320; recty= 256; @@ -613,31 +630,16 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, recty= tbuf->y; } - if(ima->ibuf==NULL) - ima->ibuf= IMB_allocImBuf(rectx, recty, 32, 0, 0); - - /* cleanup of composit image */ - if(ima->ibuf->rect) { - MEM_freeN(ima->ibuf->rect); - ima->ibuf->rect= NULL; - ima->ibuf->mall &= ~IB_rect; - } - if(ima->ibuf->zbuf_float) { - MEM_freeN(ima->ibuf->zbuf_float); - ima->ibuf->zbuf_float= NULL; - ima->ibuf->mall &= ~IB_zbuffloat; - } - if(ima->ibuf->rect_float) - MEM_freeN(ima->ibuf->rect_float); - - ima->ibuf->x= rectx; - ima->ibuf->y= recty; - ima->ibuf->mall |= IB_rectfloat; - ima->ibuf->rect_float= MEM_mallocN(4*rectx*recty*sizeof(float), "viewer rect"); + /* make ibuf, and connect to ima */ + ibuf->x= rectx; + ibuf->y= recty; + imb_addrectfloatImBuf(ibuf); + ima->ok= IMA_OK_LOADED; + /* now we combine the input with ibuf */ cbuf= alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/ - cbuf->rect= ima->ibuf->rect_float; + cbuf->rect= ibuf->rect_float; /* when no alpha, we can simply copy */ if(in[1]->data==NULL) { @@ -646,10 +648,11 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, else composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); + /* zbuf option */ if(in[2]->data) { CompBuf *zbuf= alloc_compbuf(rectx, recty, CB_VAL, 1); - ima->ibuf->zbuf_float= zbuf->rect; - ima->ibuf->mall |= IB_zbuffloat; + ibuf->zbuf_float= zbuf->rect; + ibuf->mall |= IB_zbuffloat; composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); @@ -674,7 +677,7 @@ static bNodeType cmp_node_viewer= { /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW, /* input sock */ cmp_node_viewer_in, /* output sock */ NULL, - /* storage */ "", + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_viewer }; @@ -706,37 +709,38 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * 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; buf1= typecheck_compbuf(in[0]->data, CB_RGBA); buf2= typecheck_compbuf(in[1]->data, CB_RGBA); - if(ima->ibuf==NULL) - ima->ibuf= IMB_allocImBuf(buf1->x, buf1->y, 32, 0, 0); + BKE_image_user_calc_imanr(node->storage, rd->cfra, 0); - /* cleanup of viewer image */ - if(ima->ibuf->rect) { - MEM_freeN(ima->ibuf->rect); - ima->ibuf->rect= NULL; - ima->ibuf->mall &= ~IB_rect; - } - if(ima->ibuf->zbuf_float) { - MEM_freeN(ima->ibuf->zbuf_float); - ima->ibuf->zbuf_float= NULL; - ima->ibuf->mall &= ~IB_zbuffloat; + /* 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; } - if(ima->ibuf->rect_float) - MEM_freeN(ima->ibuf->rect_float); - ima->ibuf->x= buf1->x; - ima->ibuf->y= buf1->y; - ima->ibuf->mall |= IB_rectfloat; - ima->ibuf->rect_float= MEM_mallocN(4*buf1->x*buf1->y*sizeof(float), "viewer rect"); + /* 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= ima->ibuf->rect_float; + cbuf->rect= ibuf->rect_float; /* mask buf */ mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1); @@ -766,7 +770,7 @@ static bNodeType cmp_node_splitviewer= { /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW, /* input sock */ cmp_node_splitviewer_in, /* output sock */ NULL, - /* storage */ "", + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_splitviewer }; @@ -818,6 +822,8 @@ static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **i outbuf->malloc= 0; free_compbuf(outbuf); + /* signal for imageviewer to refresh (it converts to byte rects...) */ + BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); return; } } @@ -900,140 +906,69 @@ static bNodeType cmp_node_output_file= { }; -/* **************** IMAGE ******************** */ -static bNodeSocketType cmp_node_image_out[]= { +/* **************** IMAGE (and RenderResult, multilayer image) ******************** */ + +/* output socket defines */ +#define RRES_OUT_IMAGE 0 +#define RRES_OUT_ALPHA 1 +#define RRES_OUT_Z 2 +#define RRES_OUT_NORMAL 3 +#define RRES_OUT_UV 4 +#define RRES_OUT_VEC 5 +#define RRES_OUT_RGBA 6 +#define RRES_OUT_DIFF 7 +#define RRES_OUT_SPEC 8 +#define RRES_OUT_SHADOW 9 +#define RRES_OUT_AO 10 +#define RRES_OUT_REFLECT 11 +#define RRES_OUT_REFRACT 12 +#define RRES_OUT_RADIO 13 +#define RRES_OUT_INDEXOB 14 + +static bNodeSocketType cmp_node_rlayers_out[]= { { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, { -1, 0, "" } }; -static int calcimanr(int cfra, NodeImageAnim *nia) -{ - - if(nia->frames==0) return nia->nr; - - cfra= cfra - nia->sfra; - - /* cyclic */ - if(nia->cyclic) - cfra= (cfra % nia->frames); - else if(cfra>=nia->frames) - cfra= nia->frames-1; - else if(cfra<0) - cfra= 0; - - cfra+= nia->nr; - - if(cfra<1) cfra= 1; - - return cfra; -} - -static void animated_image(bNode *node, int cfra) +/* 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) { - Image *ima; - NodeImageAnim *nia; - int imanr; - - ima= (Image *)node->id; - nia= node->storage; - - if(nia && nia->frames && ima && ima->name) { /* frames anim or movie */ - - imanr= calcimanr(cfra, nia); - - if(nia->movie) { - char str[FILE_MAXDIR+FILE_MAXFILE]; - - strcpy(str, ima->name); - if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, cfra); - else - BLI_convertstringcode(str, G.sce, cfra); - - if(ima->anim==NULL) - ima->anim = openanim(str, IB_cmap | IB_rect); - - if (ima->anim) { - int dur = IMB_anim_get_duration(ima->anim); - - if(imanr < 0) imanr = 0; - if(imanr > (dur-1)) imanr= dur-1; - - BLI_lock_thread(LOCK_CUSTOM1); - if(ima->ibuf) IMB_freeImBuf(ima->ibuf); - ima->ibuf = IMB_anim_absolute(ima->anim, imanr); - BLI_unlock_thread(LOCK_CUSTOM1); - - /* patch for textbutton with name ima (B_NAMEIMA) */ - if(ima->ibuf) { - strcpy(ima->ibuf->name, ima->name); - ima->ok= 1; - } - } - } - else { - - if(imanr!=ima->lastframe) { - unsigned short numlen; - char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXDIR+FILE_MAXFILE], tail[FILE_MAXDIR+FILE_MAXFILE]; - - strcpy(name, ima->name); - - ima->lastframe= imanr; - - BLI_stringdec(name, head, tail, &numlen); - BLI_stringenc(name, head, tail, numlen, imanr); - - ima= add_image(name); - - if(ima) { - ima->flag |= IMA_FROMANIM; - if(node->id) node->id->us--; - node->id= (ID *)ima; - - ima->ok= 1; - } - } - } - } -} - -static CompBuf *node_composit_get_image(bNode *node, RenderData *rd) -{ - Image *ima; + ImBuf *ibuf; CompBuf *stackbuf; + int type; - /* animated image? */ - if(node->storage) - animated_image(node, rd->cfra); + ibuf= BKE_image_get_ibuf(ima, iuser); + if(ibuf==NULL) + return NULL; - ima= (Image *)node->id; + if(ibuf->rect_float==NULL) + IMB_float_from_rect(ibuf); - /* test if image is OK */ - if(ima->ok==0) return NULL; - - if(ima->ibuf==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - load_image(ima, IB_rect, G.sce, rd->cfra); /* G.sce is current .blend path */ - BLI_unlock_thread(LOCK_CUSTOM1); - if(ima->ibuf==NULL) { - ima->ok= 0; - return NULL; - } - } - if(ima->ibuf->rect_float==NULL) - IMB_float_from_rect(ima->ibuf); + type= ibuf->channels; if(rd->scemode & R_COMP_CROP) { - stackbuf= get_cropped_compbuf(&rd->disprect, ima->ibuf->rect_float, ima->ibuf->x, ima->ibuf->y, CB_RGBA); + 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(ima->ibuf->x, ima->ibuf->y, CB_RGBA, 0); - stackbuf->rect= ima->ibuf->rect_float; + stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0); + stackbuf->rect= ibuf->rect_float; } return stackbuf; @@ -1041,39 +976,119 @@ static CompBuf *node_composit_get_image(bNode *node, RenderData *rd) static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { - Image *ima= (Image *)node->id; + ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); CompBuf *zbuf= NULL; - if(ima->ibuf && ima->ibuf->zbuf_float) { + if(ibuf && ibuf->zbuf_float) { if(rd->scemode & R_COMP_CROP) { - zbuf= get_cropped_compbuf(&rd->disprect, ima->ibuf->zbuf_float, ima->ibuf->x, ima->ibuf->y, CB_VAL); + zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL); } else { - zbuf= alloc_compbuf(ima->ibuf->x, ima->ibuf->y, CB_VAL, 0); - zbuf->rect= ima->ibuf->zbuf_float; + zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0); + zbuf->rect= ibuf->zbuf_float; } } return zbuf; } +/* check if layer is available, returns pass buffer */ +static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype) +{ + RenderPass *rpass; + short index; + + for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++) + if(rpass->passtype==passtype) + break; + + if(rpass) { + CompBuf *cbuf; + + iuser->pass= index; + BKE_image_multilayer_index(ima->rr, iuser); + cbuf= node_composit_get_image(rd, ima, iuser); + + return cbuf; + } + return NULL; +} + +void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser) +{ + if(out[RRES_OUT_Z]->hasoutput) + out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z); + if(out[RRES_OUT_VEC]->hasoutput) + out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR); + if(out[RRES_OUT_NORMAL]->hasoutput) + out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL); + if(out[RRES_OUT_UV]->hasoutput) + out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV); + + if(out[RRES_OUT_RGBA]->hasoutput) + out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA); + if(out[RRES_OUT_DIFF]->hasoutput) + out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE); + if(out[RRES_OUT_SPEC]->hasoutput) + out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC); + if(out[RRES_OUT_SHADOW]->hasoutput) + out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW); + if(out[RRES_OUT_AO]->hasoutput) + out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO); + if(out[RRES_OUT_REFLECT]->hasoutput) + out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT); + if(out[RRES_OUT_REFRACT]->hasoutput) + out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT); + if(out[RRES_OUT_RADIO]->hasoutput) + out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO); + if(out[RRES_OUT_INDEXOB]->hasoutput) + out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB); + +} + + static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { /* image assigned to output */ /* stack order input sockets: col, alpha */ if(node->id) { - CompBuf *stackbuf= node_composit_get_image(node, data); + RenderData *rd= data; + Image *ima= (Image *)node->id; + ImageUser *iuser= (ImageUser *)node->storage; + CompBuf *stackbuf= NULL; - /* put ibuf on stack */ - out[0]->data= stackbuf; + /* first set the right frame number in iuser */ + BKE_image_user_calc_imanr(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); + + /* 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); - - if(out[2]->hasoutput) - out[2]->data= node_composit_get_zimage(node, data); - + generate_preview(node, stackbuf); } } @@ -1087,51 +1102,14 @@ static bNodeType cmp_node_image= { /* width+range */ 120, 80, 300, /* class+opts */ NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS, /* input sock */ NULL, - /* output sock */ cmp_node_image_out, - /* storage */ "NodeImageAnim", + /* output sock */ cmp_node_rlayers_out, + /* storage */ "ImageUser", /* execfunc */ node_composit_exec_image }; /* **************** RENDER RESULT ******************** */ -/* output socket defines */ -#define RRES_OUT_IMAGE 0 -#define RRES_OUT_ALPHA 1 -#define RRES_OUT_Z 2 -#define RRES_OUT_NORMAL 3 -#define RRES_OUT_UV 4 -#define RRES_OUT_VEC 5 -#define RRES_OUT_RGBA 6 -#define RRES_OUT_DIFF 7 -#define RRES_OUT_SPEC 8 -#define RRES_OUT_SHADOW 9 -#define RRES_OUT_AO 10 -#define RRES_OUT_REFLECT 11 -#define RRES_OUT_REFRACT 12 -#define RRES_OUT_RADIO 13 -#define RRES_OUT_INDEXOB 14 - -static bNodeSocketType cmp_node_rlayers_out[]= { - { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "Z", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "UV", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VECTOR, 0, "Speed", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Diffuse", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Specular", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Shadow", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "AO", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Reflect", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Refract", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_RGBA, 0, "Radio", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { SOCK_VALUE, 0, "IndexOB", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, - { -1, 0, "" } -}; - - static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode) { float *fp= RE_RenderLayerGetPass(rl, passcode); @@ -1143,9 +1121,9 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in buftype= CB_VAL; else if(passcode==SCE_PASS_VECTOR) buftype= CB_VEC4; - else if(passcode==SCE_PASS_RGBA) + else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA)) buftype= CB_RGBA; - + if(rd->scemode & R_COMP_CROP) buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype); else { @@ -1157,6 +1135,38 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in return NULL; } +void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty) +{ + if(out[RRES_OUT_Z]->hasoutput) + out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z); + if(out[RRES_OUT_VEC]->hasoutput) + out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR); + if(out[RRES_OUT_NORMAL]->hasoutput) + out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL); + if(out[RRES_OUT_UV]->hasoutput) + out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV); + + if(out[RRES_OUT_RGBA]->hasoutput) + out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA); + if(out[RRES_OUT_DIFF]->hasoutput) + out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE); + if(out[RRES_OUT_SPEC]->hasoutput) + out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC); + if(out[RRES_OUT_SHADOW]->hasoutput) + out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW); + if(out[RRES_OUT_AO]->hasoutput) + out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO); + if(out[RRES_OUT_REFLECT]->hasoutput) + out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT); + if(out[RRES_OUT_REFRACT]->hasoutput) + out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT); + if(out[RRES_OUT_RADIO]->hasoutput) + out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO); + if(out[RRES_OUT_INDEXOB]->hasoutput) + out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); + +} + static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out) { Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */ @@ -1191,33 +1201,8 @@ static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, if(out[RRES_OUT_ALPHA]->hasoutput) out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - if(out[RRES_OUT_Z]->hasoutput) - out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_Z); - if(out[RRES_OUT_VEC]->hasoutput) - out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_VECTOR); - if(out[RRES_OUT_NORMAL]->hasoutput) - out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_NORMAL); - if(out[RRES_OUT_UV]->hasoutput) - out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_UV); - - if(out[RRES_OUT_RGBA]->hasoutput) - out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_RGBA); - if(out[RRES_OUT_DIFF]->hasoutput) - out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_DIFFUSE); - if(out[RRES_OUT_SPEC]->hasoutput) - out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_SPEC); - if(out[RRES_OUT_SHADOW]->hasoutput) - out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_SHADOW); - if(out[RRES_OUT_AO]->hasoutput) - out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_AO); - if(out[RRES_OUT_REFLECT]->hasoutput) - out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_REFLECT); - if(out[RRES_OUT_REFRACT]->hasoutput) - out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_REFRACT); - if(out[RRES_OUT_RADIO]->hasoutput) - out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_RADIO); - if(out[RRES_OUT_INDEXOB]->hasoutput) - out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rr->rectx, rr->recty, SCE_PASS_INDEXOB); + + node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty); generate_preview(node, stackbuf); } @@ -3415,10 +3400,6 @@ static void node_composit_exec_dilateerode(void *data, bNode *node, bNodeStack * CompBuf *stackbuf= dupalloc_compbuf(cbuf); short i; - /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ - stackbuf->xof= cbuf->xof; - stackbuf->yof= cbuf->yof; - if (node->custom2 > 0) { // positive, dilate for (i = 0; i < node->custom2; i++) morpho_dilate(stackbuf); @@ -3427,6 +3408,9 @@ static void node_composit_exec_dilateerode(void *data, bNode *node, bNodeStack * morpho_erode(stackbuf); } + if(cbuf!=in[0]->data) + free_compbuf(cbuf); + out[0]->data= stackbuf; } } @@ -4673,6 +4657,43 @@ bNodeType *node_all_composit[]= { /* ******************* parse ************ */ +/* clumsy checking... should do dynamic outputs once */ +static void force_hidden_passes(bNode *node, int passflag) +{ + bNodeSocket *sock; + + for(sock= node->outputs.first; sock; sock= sock->next) + sock->flag &= ~SOCK_UNAVAIL; + + sock= BLI_findlink(&node->outputs, RRES_OUT_Z); + if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); + if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); + if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_UV); + if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); + if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); + if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); + if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); + if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_AO); + if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); + if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); + if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_RADIO); + if(!(passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; + sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); + if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; + +} + /* based on rules, force sockets hidden always */ void ntreeCompositForceHidden(bNodeTree *ntree) { @@ -4684,38 +4705,26 @@ void ntreeCompositForceHidden(bNodeTree *ntree) if( node->type==CMP_NODE_R_LAYERS) { Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */ SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); - if(srl) { - bNodeSocket *sock; - for(sock= node->outputs.first; sock; sock= sock->next) - sock->flag &= ~SOCK_UNAVAIL; - - sock= BLI_findlink(&node->outputs, RRES_OUT_Z); - if(!(srl->passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); - if(!(srl->passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); - if(!(srl->passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_UV); - if(!(srl->passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); - if(!(srl->passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); - if(!(srl->passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); - if(!(srl->passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); - if(!(srl->passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_AO); - if(!(srl->passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); - if(!(srl->passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); - if(!(srl->passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_RADIO); - if(!(srl->passflag & SCE_PASS_RADIO)) sock->flag |= SOCK_UNAVAIL; - sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); - if(!(srl->passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; + if(srl) + force_hidden_passes(node, srl->passflag); + } + else if( node->type==CMP_NODE_IMAGE) { + Image *ima= (Image *)node->id; + if(ima) { + if(ima->rr) { + ImageUser *iuser= node->storage; + RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); + if(rl) + force_hidden_passes(node, rl->passflag); + else + force_hidden_passes(node, 0); + } + else if(ima->type!=IMA_TYPE_MULTILAYER) { /* if ->rr not yet read we keep inputs */ + force_hidden_passes(node, 0); + } } + else + force_hidden_passes(node, 0); } } @@ -4743,8 +4752,8 @@ void ntreeCompositTagAnimated(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= node->next) { if(node->type==CMP_NODE_IMAGE) { - /* no actual test yet... */ - if(node->storage) + Image *ima= (Image *)node->id; + if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) NodeTagChanged(ntree, node); } else if(node->type==CMP_NODE_TIME) diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 49ad8d2ac67..0cdfda3be5d 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -402,7 +402,7 @@ there was an error or when the user desides to cancel the operation. */ -char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +char *unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) { char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; char line[FILE_MAXDIR + FILE_MAXFILE + 100]; @@ -413,7 +413,7 @@ char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) if (pf != NULL) { if (how == PF_ASK) { - strcpy(menu, "UnPack file%t"); + sprintf(menu, "UnPack file%%t|Remove Pack %%x%d", PF_REMOVE); if (strcmp(abs_name, local_name)) { switch (checkPackedFile(local_name, pf)) { @@ -460,6 +460,9 @@ char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) case -1: case PF_KEEP: break; + case PF_REMOVE: + temp= abs_name; + break; case PF_USE_LOCAL: // if file exists use it if (BLI_exists(local_name)) { @@ -596,10 +599,10 @@ int unpackImage(Image * ima, int how) if (newname != NULL) { ret_value = RET_OK; freePackedFile(ima->packedfile); - ima->packedfile = 0; + ima->packedfile = NULL; strcpy(ima->name, newname); MEM_freeN(newname); - free_image_buffers(ima); + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c656f5cdeb6..40488cf8644 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -68,6 +68,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_ipo.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 62ac911bea7..341397cba1b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -455,13 +455,17 @@ void default_tex(Tex *tex) pit = tex->plugin; if (pit) { - varstr= pit->varstr; - if(varstr) { - for(a=0; a<pit->vars; a++, varstr++) { - pit->data[a] = varstr->def; - } + varstr= pit->varstr; + if(varstr) { + for(a=0; a<pit->vars; a++, varstr++) { + pit->data[a] = varstr->def; } + } } + + tex->iuser.fie_ima= 2; + tex->iuser.ok= 1; + tex->iuser.frames= 100; } /* ------------------------------------------------------------------------- */ @@ -776,7 +780,7 @@ EnvMap *BKE_copy_envmap(EnvMap *env) envn= MEM_dupallocN(env); envn->ok= 0; - for(a=0; a<6; a++) envn->cube[a]= 0; + for(a=0; a<6; a++) envn->cube[a]= NULL; if(envn->ima) id_us_plus((ID *)envn->ima); return envn; @@ -786,20 +790,12 @@ EnvMap *BKE_copy_envmap(EnvMap *env) void BKE_free_envmapdata(EnvMap *env) { - Image *ima; - unsigned int a, part; + unsigned int part; for(part=0; part<6; part++) { - ima= env->cube[part]; - if(ima) { - if(ima->ibuf) IMB_freeImBuf(ima->ibuf); - - for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { - if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); - } - MEM_freeN(ima); - env->cube[part]= 0; - } + if(env->cube[part]) + IMB_freeImBuf(env->cube[part]); + env->cube[part]= NULL; } env->ok= 0; } |