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:
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r--source/blender/blenkernel/intern/image.c1376
1 files changed, 1062 insertions, 314 deletions
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;
+ }
+}