Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2006-12-20 20:57:56 +0300
committerTon Roosendaal <ton@blender.org>2006-12-20 20:57:56 +0300
commit253432bfc7c2a1dae224a03fb3055de19743ec67 (patch)
tree2cea30606f9f29be51d5366ddf0d3747b9649b90 /source/blender/blenkernel
parent0a0753b409221b66f5003d8c257426043ada227e (diff)
The Big Image refactor!
Please read: http://www.blender3d.org/cms/Imaging.834.0.html Or in short: - adding MultiLayer Image support - recoded entire Image API - better integration of movie/sequence Images Was a whole load of work... went down for a week to do this. So, will need a lot of testing! Will be in irc all evening.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_blender.h2
-rw-r--r--source/blender/blenkernel/BKE_colortools.h4
-rw-r--r--source/blender/blenkernel/BKE_image.h116
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/BKE_utildefines.h4
-rw-r--r--source/blender/blenkernel/intern/colortools.c44
-rw-r--r--source/blender/blenkernel/intern/image.c1376
-rw-r--r--source/blender/blenkernel/intern/library.c33
-rw-r--r--source/blender/blenkernel/intern/node.c61
-rw-r--r--source/blender/blenkernel/intern/node_composite.c567
-rw-r--r--source/blender/blenkernel/intern/packedFile.c11
-rw-r--r--source/blender/blenkernel/intern/scene.c1
-rw-r--r--source/blender/blenkernel/intern/texture.c32
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;
}