diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2008-11-13 00:16:53 +0300 |
commit | bdfe7d89e2f1292644577972c716931b4ce3c6c3 (patch) | |
tree | d00eb50b749cb001e2b08272c91791e66740b05d /source/blender/blenkernel/intern/image.c | |
parent | 78a1c27c4a6abe0ed31ca93ad21910f3df04da56 (diff) | |
parent | 7e4db234cee71ead34ee81a12e27da4bd548eb4b (diff) |
Merge of trunk into blender 2.5:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r12987:17416
Issues:
* GHOST/X11 had conflicting changes. Some code was added in 2.5, which was
later added in trunk also, but reverted partially, specifically revision
16683. I have left out this reversion in the 2.5 branch since I think it is
needed there.
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16683
* Scons had various conflicting changes, I decided to go with trunk version
for everything except priorities and some library renaming.
* In creator.c, there were various fixes and fixes for fixes related to the -w
-W and -p options. In 2.5 -w and -W is not coded yet, and -p is done
differently. Since this is changed so much, and I don't think those fixes
would be needed in 2.5, I've left them out.
* Also in creator.c: there was code for a python bugfix where the screen was not
initialized when running with -P. The code that initializes the screen there
I had to disable, that can't work in 2.5 anymore but left it commented as a
reminder.
Further I had to disable some new function calls. using src/ and python/, as
was done already in this branch, disabled function calls:
* bpath.c: error reporting
* BME_conversions.c: editmesh conversion functions.
* SHD_dynamic: disabled almost completely, there is no python/.
* KX_PythonInit.cpp and Ketsji/ build files: Mathutils is not there, disabled.
* text.c: clipboard copy call.
* object.c: OB_SUPPORT_MATERIAL.
* DerivedMesh.c and subsurf_ccg, stipple_quarttone.
Still to be done:
* Go over files and functions that were moved to a different location but could
still use changes that were done in trunk.
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 588 |
1 files changed, 389 insertions, 199 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a79433fcfa1..de1747e514c 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -53,6 +53,7 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" +#include "DNA_sequence_types.h" #include "DNA_texture_types.h" #include "DNA_sequence_types.h" #include "DNA_userdef_types.h" @@ -81,6 +82,11 @@ /* for stamp drawing to an image */ #include "BMF_Api.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + +#include "BLO_sys_types.h" // for intptr_t support + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -93,32 +99,50 @@ /* used by sequencer and image premul option - IMA_DO_PREMUL */ void converttopremul(struct ImBuf *ibuf) { - int x, y, val; - char *cp; + int x, y; 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; + if (ibuf->rect) { + int val; + char *cp; + 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; + } + } + } else { + cp= (char *)(ibuf->rect); + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + val= cp[3]; + cp[0]= (cp[0]*val)>>8; + cp[1]= (cp[1]*val)>>8; + cp[2]= (cp[2]*val)>>8; + } } } - 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; + if (ibuf->rect_float) { + float val; + float *cp; + if(ibuf->depth==24) { /* put alpha at 1.0 */ + cp= ibuf->rect_float;; + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + cp[3]= 1.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; + } else { + cp= ibuf->rect_float; + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + val= cp[3]; + cp[0]= cp[0]*val; + cp[1]= cp[1]*val; + cp[2]= cp[2]*val; + } } } } @@ -215,7 +239,7 @@ static void image_free_buffers(Image *ima) ima->rr= NULL; } - //XXX free_realtime_image(ima); + GPU_free_image(ima); ima->ok= IMA_OK; } @@ -223,7 +247,6 @@ static void image_free_buffers(Image *ima) /* called by library too, do not free ima itself */ void free_image(Image *ima) { - image_free_buffers(ima); if (ima->packedfile) { freePackedFile(ima->packedfile); @@ -234,7 +257,6 @@ void free_image(Image *ima) if (ima->preview) { BKE_previewimg_free(&ima->preview); } - } /* only image block itself */ @@ -260,15 +282,19 @@ static Image *image_alloc(const char *name, short source, short type) /* get the ibuf from an image cache, local use here only */ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) { + /* this function is intended to be thread safe. with IMA_NO_INDEX this + * should be OK, but when iterating over the list this is more tricky + * */ 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; } } @@ -296,19 +322,16 @@ static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int frame) 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; - } - + + ibuf->index= index; + /* this function accepts link==NULL */ BLI_insertlinkbefore(&ima->ibufs, link, ibuf); - - ibuf->index= index; + + /* now we don't want copies? */ + if(link && ibuf->index==link->index) + image_remove_ibuf(ima, link); } - } /* checks if image was already loaded, then returns same image */ @@ -329,7 +352,8 @@ Image *BKE_add_image_file(const char *name) } BLI_strncpy(str, name, sizeof(str)); - BLI_convertstringcode(str, G.sce, G.scene->r.cfra); + BLI_convertstringcode(str, G.sce); + BLI_convertstringframe(str, G.scene->r.cfra); /* TODO - should this realy be here? */ /* exists? */ file= open(str, O_BINARY|O_RDONLY); @@ -340,7 +364,8 @@ Image *BKE_add_image_file(const char *name) for(ima= G.main->image.first; ima; ima= ima->id.next) { if(ima->source!=IMA_SRC_VIEWER && ima->source!=IMA_SRC_GENERATED) { BLI_strncpy(strtest, ima->name, sizeof(ima->name)); - BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); + BLI_convertstringcode(strtest, G.sce); + BLI_convertstringframe(strtest, G.scene->r.cfra); /* TODO - should this be here? */ if( strcmp(strtest, str)==0 ) { if(ima->anim==NULL || ima->id.us==0) { @@ -373,20 +398,27 @@ Image *BKE_add_image_file(const char *name) return ima; } -static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid, float color[4]) +static ImBuf *add_ibuf_size(int width, int height, char *name, int floatbuf, short uvtestgrid, float color[4]) { ImBuf *ibuf; float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b; - unsigned char *rect; + unsigned char *rect= NULL; + float *rect_float= NULL; int x, y; int checkerwidth=21, dark=1; - ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); + if (floatbuf) { + ibuf= IMB_allocImBuf(width, height, 24, IB_rectfloat, 0); + rect_float= (float*)ibuf->rect_float; + } + else { + ibuf= IMB_allocImBuf(width, height, 24, IB_rect, 0); + rect= (unsigned char*)ibuf->rect; + } + 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... */ @@ -395,26 +427,40 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid, for(y=0; y<ibuf->y; y++) { dark = pow(-1, floor(y / checkerwidth)); - for(x=0; x<ibuf->x; x++, rect+=4) { + for(x=0; x<ibuf->x; x++) { 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 (floatbuf) { + if (dark > 0) { + rect_float[0] = rect_float[1] = rect_float[2] = 0.25; + rect_float[3] = 1.0; + } else { + rect_float[0] = rect_float[1] = rect_float[2] = 0.58; + rect_float[3] = 1.0; + } + rect_float+=4; + } + else { + if (dark > 0) { + rect[0] = rect[1] = rect[2] = 64; + rect[3] = 255; + } else { + rect[0] = rect[1] = rect[2] = 150; + rect[3] = 255; + } + rect += 4; } } } /* 2nd pass, colored + */ - rect= (unsigned char*)ibuf->rect; + if (floatbuf) rect_float= (float*)ibuf->rect_float; + else rect= (unsigned char*)ibuf->rect; for(y=0; y<ibuf->y; y++) { hoffs = 0.125 * floor(y / checkerwidth); - for(x=0; x<ibuf->x; x++, rect+=4) { + for(x=0; x<ibuf->x; x++) { h = 0.125 * floor(x / checkerwidth); if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) && @@ -426,22 +472,44 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid, 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; + if (floatbuf) { + rect_float[0]= r; + rect_float[1]= g; + rect_float[2]= b; + rect_float[3]= 1.0; + } + else { + rect[0]= (char)(r * 255.0); + rect[1]= (char)(g * 255.0); + rect[2]= (char)(b * 255.0); + rect[3]= 255; + } } } - + + if (floatbuf) + rect_float+=4; + else + rect+=4; } } } else { /* blank image */ for(y=0; y<ibuf->y; y++) { - for(x=0; x<ibuf->x; x++, rect+=4) { - rect[0]= (char)(color[0] * 255.0); - rect[1]= (char)(color[1] * 255.0); - rect[2]= (char)(color[2] * 255.0); - rect[3]= (char)(color[3] * 255.0); + for(x=0; x<ibuf->x; x++) { + if (floatbuf) { + rect_float[0]= color[0]; + rect_float[1]= color[1]; + rect_float[2]= color[2]; + rect_float[3]= color[3]; + rect_float+=4; + } + else { + rect[0]= (char)(color[0] * 255.0); + rect[1]= (char)(color[1] * 255.0); + rect[2]= (char)(color[2] * 255.0); + rect[3]= (char)(color[3] * 255.0); + rect+=4; + } } } } @@ -449,7 +517,7 @@ static ImBuf *add_ibuf_size(int width, int height, char *name, short uvtestgrid, } /* adds new image block, creates ImBuf and initializes color */ -Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid, float color[4]) +Image *BKE_add_image_size(int width, int height, char *name, int floatbuf, short uvtestgrid, float color[4]) { Image *ima; @@ -464,7 +532,7 @@ Image *BKE_add_image_size(int width, int height, char *name, short uvtestgrid, f ima->gen_y= height; ima->gen_type= uvtestgrid; - ibuf= add_ibuf_size(width, height, name, uvtestgrid, color); + ibuf= add_ibuf_size(width, height, name, floatbuf, uvtestgrid, color); image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); ima->ok= IMA_OK_LOADED; @@ -515,7 +583,7 @@ void tag_image_time(Image *ima) ima->lastused = (int)PIL_check_seconds_timer(); } -void tag_all_images_time() +static void tag_all_images_time() { Image *ima; int ctime = (int)PIL_check_seconds_timer(); @@ -551,7 +619,7 @@ void free_old_images() This gives textures a "second chance" to be used before dying. */ if(ima->bindcode || ima->repbind) { - //XXX free_realtime_image(ima); + GPU_free_image(ima); ima->lastused = ctime; } /* Otherwise, just kill the buffers */ @@ -563,6 +631,47 @@ void free_old_images() } } +static uintptr_t image_mem_size(Image *ima) +{ + ImBuf *ibuf, *ibufm; + int level; + uintptr_t size = 0; + + size= 0; + for(ibuf= ima->ibufs.first; ibuf; ibuf= ibuf->next) { + if(ibuf->rect) size += MEM_allocN_len(ibuf->rect); + else if(ibuf->rect_float) size += MEM_allocN_len(ibuf->rect_float); + + for(level=0; level<IB_MIPMAP_LEVELS; level++) { + ibufm= ibuf->mipmap[level]; + if(ibufm) { + if(ibufm->rect) size += MEM_allocN_len(ibufm->rect); + else if(ibufm->rect_float) size += MEM_allocN_len(ibufm->rect_float); + } + } + } + + return size; +} + +void BKE_image_print_memlist(void) +{ + Image *ima; + uintptr_t size, totsize= 0; + + for(ima= G.main->image.first; ima; ima= ima->id.next) + totsize += image_mem_size(ima); + + printf("\ntotal image memory len: %.3lf MB\n", (double)totsize/(double)(1024*1024)); + + for(ima= G.main->image.first; ima; ima= ima->id.next) { + size= image_mem_size(ima); + + if(size) + printf("%s len: %.3f MB\n", ima->id.name+2, (double)size/(double)(1024*1024)); + } +} + void BKE_image_free_all_textures(void) { Tex *tex; @@ -740,17 +849,13 @@ void BKE_add_image_extension(char *string, int imtype) if(!BLI_testextensie(string, ".tga")) extension= ".tga"; } - else if(ELEM5(imtype, R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90)) { - if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg"))) - extension= ".jpg"; - } else if(imtype==R_BMP) { if(!BLI_testextensie(string, ".bmp")) extension= ".bmp"; } else if(G.have_libtiff && (imtype==R_TIFF)) { - if(!BLI_testextensie(string, ".tif")) - extension= ".tif"; + if(!BLI_testextensie(string, ".tif") && + !BLI_testextensie(string, ".tiff")) extension= ".tif"; } #ifdef WITH_OPENEXR else if( ELEM(imtype, R_OPENEXR, R_MULTILAYER)) { @@ -766,10 +871,14 @@ void BKE_add_image_extension(char *string, int imtype) if (!BLI_testextensie(string, ".dpx")) extension= ".dpx"; } - else { /* targa default */ + else if(imtype==R_TARGA) { if(!BLI_testextensie(string, ".tga")) extension= ".tga"; } + else { // R_MOVIE, R_AVICODEC, R_AVIRAW, R_AVIJPEG, R_JPEG90, R_QUICKTIME etc + if(!( BLI_testextensie(string, ".jpg") || BLI_testextensie(string, ".jpeg"))) + extension= ".jpg"; + } strcat(string, extension); } @@ -799,8 +908,13 @@ static void stampdata(StampData *stamp_data, int do_prefix) #endif /* WIN32 */ if (G.scene->r.stamp & R_STAMP_FILENAME) { - if (do_prefix) sprintf(stamp_data->file, "File %s", G.sce); - else sprintf(stamp_data->file, "%s", G.sce); + if (G.relbase_valid) { + if (do_prefix) sprintf(stamp_data->file, "File %s", G.sce); + else sprintf(stamp_data->file, "%s", G.sce); + } else { + if (do_prefix) strcpy(stamp_data->file, "File <untitled>"); + else strcpy(stamp_data->file, "<untitled>"); + } stamp_data->note[0] = '\0'; } else { stamp_data->file[0] = '\0'; @@ -877,8 +991,11 @@ static void stampdata(StampData *stamp_data, int do_prefix) } if (G.scene->r.stamp & R_STAMP_CAMERA) { - if (do_prefix) sprintf(stamp_data->camera, "Camera %s", ((Camera *) G.scene->camera)->id.name+2); - else sprintf(stamp_data->camera, "%s", ((Camera *) G.scene->camera)->id.name+2); + if (G.scene->camera) strcpy(text, ((Camera *) G.scene->camera)->id.name+2); + else strcpy(text, "<none>"); + + if (do_prefix) sprintf(stamp_data->camera, "Camera %s", text); + else sprintf(stamp_data->camera, "%s", text); } else { stamp_data->camera[0] = '\0'; } @@ -903,7 +1020,7 @@ static void stampdata(StampData *stamp_data, int do_prefix) } } -void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) +void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height, int channels) { struct StampData stamp_data; @@ -951,7 +1068,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) /* Top left corner */ text_width = BMF_GetStringWidth(font, stamp_data.file); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.file, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } @@ -959,7 +1076,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (stamp_data.note[0]) { text_width = BMF_GetStringWidth(font, stamp_data.note); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.note, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); y -= font_height+2; /* Top and bottom 1 pix padding each */ } @@ -967,7 +1084,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (stamp_data.date[0]) { text_width = BMF_GetStringWidth(font, stamp_data.date); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.date, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Bottom left corner, leaving space for timing */ @@ -976,7 +1093,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) y = font_height+2+1; /* 2 for padding in TIME|FRAME fields below and 1 for padding in this one */ text_width = BMF_GetStringWidth(font, stamp_data.marker); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.marker, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } /* Left bottom corner */ @@ -985,7 +1102,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) y = 1; text_width = BMF_GetStringWidth(font, stamp_data.time); buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.time, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); x += text_width+text_pad+2; /* Both sides have 1 pix additional padding each */ } @@ -995,7 +1112,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) if (!stamp_data.time[0]) x = 1; y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.frame, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.camera[0]) { @@ -1004,7 +1121,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = (width/2) - (BMF_GetStringWidth(font, stamp_data.camera)/2); y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.camera, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.scene[0]) { @@ -1013,7 +1130,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = width - (text_width+1+text_pad); y = 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.scene, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } if (stamp_data.strip[0]) { @@ -1022,7 +1139,7 @@ void BKE_stamp_buf(unsigned char *rect, float *rectf, int width, int height) x = width - (text_width+1+text_pad); y = height - font_height - 1; buf_rectfill_area(rect, rectf, width, height, G.scene->r.bg_stamp, x-1, y-1, x+text_width+text_pad+1, y+font_height+1); - BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height); + BMF_DrawStringBuf(font, stamp_data.strip, x+(text_pad/2), y, G.scene->r.fg_stamp, rect, rectf, width, height, channels); } } @@ -1070,6 +1187,9 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali } else if ((G.have_libtiff) && (imtype==R_TIFF)) { ibuf->ftype= TIF; + + if(subimtype & R_TIFF_16BIT) + ibuf->ftype |= TIF_16BIT; } #ifdef WITH_OPENEXR else if (imtype==R_OPENEXR || imtype==R_MULTILAYER) { @@ -1121,23 +1241,16 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali void BKE_makepicstring(char *string, char *base, int frame, int imtype) { - short i, len, digits= 4; /* digits in G.scene? */ - char num[10]; - if (string==NULL) return; BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ - BLI_convertstringcode(string, G.sce, frame); - - len= strlen(string); - - i= digits - sprintf(num, "%d", frame); - for(; i>0; i--){ - string[len]= '0'; - len++; - } - string[len]= 0; - strcat(string, num); + + /* if we dont have any #'s to insert numbers into, use 4 numbers by default */ + if (strchr(string, '#')==NULL) + strcat(string, "####"); /* 4 numbers */ + + BLI_convertstringcode(string, G.sce); + BLI_convertstringframe(string, frame); if(G.scene->r.scemode & R_EXTENSION) BKE_add_image_extension(string, imtype); @@ -1373,9 +1486,11 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) BLI_strncpy(name, ima->name, sizeof(name)); if(ima->id.lib) - BLI_convertstringcode(name, ima->id.lib->filename, frame); + BLI_convertstringcode(name, ima->id.lib->filename); else - BLI_convertstringcode(name, G.sce, frame); + BLI_convertstringcode(name, G.sce); + + BLI_convertstringframe(name, frame); /* TODO - should this be here? */ /* read ibuf */ ibuf = IMB_loadiffname(name, IB_rect|IB_multilayer); @@ -1391,13 +1506,17 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) ibuf= NULL; } else { - image_assign_ibuf(ima, ibuf, 0, frame); image_initialize_after_load(ima, ibuf); + image_assign_ibuf(ima, ibuf, 0, frame); } #else - image_assign_ibuf(ima, ibuf, 0, frame); image_initialize_after_load(ima, ibuf); + image_assign_ibuf(ima, ibuf, 0, frame); #endif + + if(ima->flag & IMA_DO_PREMUL) + converttopremul(ibuf); + } else ima->ok= 0; @@ -1432,8 +1551,9 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f // if(oldrr) printf("freed previous result %p\n", oldrr); if(oldrr) RE_FreeRenderResult(oldrr); } - else + else { ima->rr= oldrr; + } } if(ima->rr) { @@ -1448,8 +1568,8 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f ibuf->mall= IB_rectfloat; ibuf->channels= rpass->channels; - image_assign_ibuf(ima, ibuf, iuser->multi_index, frame); image_initialize_after_load(ima, ibuf); + image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:0, frame); } // else printf("pass not found\n"); @@ -1475,9 +1595,9 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) BLI_strncpy(str, ima->name, FILE_MAX); if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, 0); + BLI_convertstringcode(str, ima->id.lib->filename); else - BLI_convertstringcode(str, G.sce, 0); + BLI_convertstringcode(str, G.sce); ima->anim = openanim(str, IB_cmap | IB_rect); @@ -1495,8 +1615,8 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) ibuf = IMB_anim_absolute(ima->anim, fra); if(ibuf) { - image_assign_ibuf(ima, ibuf, 0, frame); image_initialize_after_load(ima, ibuf); + image_assign_ibuf(ima, ibuf, 0, frame); } else ima->ok= 0; @@ -1515,6 +1635,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) { struct ImBuf *ibuf; char str[FILE_MAX]; + int assign = 0; /* always ensure clean ima */ image_free_buffers(ima); @@ -1528,9 +1649,11 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* get the right string */ BLI_strncpy(str, ima->name, sizeof(str)); if(ima->id.lib) - BLI_convertstringcode(str, ima->id.lib->filename, cfra); + BLI_convertstringcode(str, ima->id.lib->filename); else - BLI_convertstringcode(str, G.sce, cfra); + BLI_convertstringcode(str, G.sce); + + BLI_convertstringframe(str, cfra); /* read ibuf */ ibuf = IMB_loadiffname(str, IB_rect|IB_multilayer|IB_imginfo); @@ -1545,8 +1668,8 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) ibuf= NULL; } else { - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); image_initialize_after_load(ima, ibuf); + assign= 1; /* check if the image is a font image... */ detectBitmapFont(ibuf); @@ -1562,6 +1685,9 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) else ima->ok= 0; + if(assign) + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + if(iuser) iuser->ok= ima->ok; @@ -1585,12 +1711,13 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *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; + + image_assign_ibuf(ima, ibuf, iuser?iuser->multi_index:IMA_NO_INDEX, 0); } } @@ -1609,31 +1736,38 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) { RenderResult *rr= RE_GetResult(RE_GetRender(G.scene->id.name)); - if(rr && iuser) { + if(rr) { RenderResult rres; float *rectf; unsigned int *rect; - int channels= 4, layer= iuser->layer; + float dither; + int channels, layer, pass; + + channels= 4; + layer= (iuser)? iuser->layer: 0; + pass= (iuser)? iuser->pass: 0; /* this gives active layer, composite or seqence result */ RE_GetResultImage(RE_GetRender(G.scene->id.name), &rres); rect= (unsigned int *)rres.rect32; rectf= rres.rectf; - + dither= G.scene->r.dither_intensity; + /* 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)); + RenderLayer *rl= BLI_findlink(&rr->layers, layer-(rr->rectf?1:0)); if(rl) { /* there's no combined pass, is in renderlayer itself */ - if(iuser->pass==0) { + if(pass==0) { rectf= rl->rectf; } else { - RenderPass *rpass= BLI_findlink(&rl->passes, iuser->pass-1); + RenderPass *rpass= BLI_findlink(&rl->passes, pass-1); if(rpass) { channels= rpass->channels; rectf= rpass->rect; + dither= 0.0f; /* don't dither passes */ } } } @@ -1658,6 +1792,9 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) ibuf->rect_float= rectf; ibuf->flags |= IB_rectfloat; ibuf->channels= channels; + ibuf->zbuf_float= rres.rectz; + ibuf->flags |= IB_zbuffloat; + ibuf->dither= dither; ima->ok= IMA_OK_LOADED; return ibuf; @@ -1667,118 +1804,171 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser) return NULL; } -/* Checks optional ImageUser and verifies/creates ImBuf. */ -/* returns ibuf */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) { - ImBuf *ibuf= NULL; - float color[] = {0, 0, 0, 1}; + ImBuf *ibuf = NULL; + int frame = 0, index = 0; - /* 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_IMAGE); - - /* handle image source and types */ + /* see if we already have an appropriate ibuf, with image source and type */ if(ima->source==IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ - int frame= iuser?iuser->framenr:ima->lastframe; - + frame= iuser?iuser->framenr:ima->lastframe; 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->type==IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ - int frame= iuser?iuser->framenr:ima->lastframe; - + frame= iuser?iuser->framenr:ima->lastframe; 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; - + else if(ima->type==IMA_TYPE_MULTILAYER) { + frame= iuser?iuser->framenr:ima->lastframe; + index= iuser?iuser->multi_index:IMA_NO_INDEX; 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) { + 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 */ + else if(ima->type==IMA_TYPE_MULTILAYER) 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(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, color); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok= IMA_OK_LOADED; - } - } } else if(ima->source == IMA_SRC_VIEWER) { if(ima->type==IMA_TYPE_R_RESULT) { - /* always verify entirely */ - ibuf= image_get_render_result(ima, iuser); + /* always verify entirely, not that this shouldn't happen + * during render anyway */ } else if(ima->type==IMA_TYPE_COMPOSITE) { - int frame= iuser?iuser->framenr:0; - - /* Composite Viewer, all handled in compositor */ + frame= iuser?iuser->framenr:0; ibuf= image_get_ibuf(ima, 0, frame); - if(ibuf==NULL) { - /* fake ibuf, will be filled in compositor */ - ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); - image_assign_ibuf(ima, ibuf, 0, frame); + } + } + + *frame_r = frame; + *index_r = index; + + return ibuf; +} + +/* Checks optional ImageUser and verifies/creates ImBuf. */ +/* returns ibuf */ +ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +{ + ImBuf *ibuf= NULL; + float color[] = {0, 0, 0, 1}; + int frame= 0, index= 0; + + /* This function is intended to be thread-safe. It postpones the mutex lock + * until it needs to load the image, if the image is already there it + * should just get the pointer and return. The reason is that a lot of mutex + * locks appears to be very slow on certain multicore macs, causing a render + * with image textures to actually slow down as more threads are used. + * + * Note that all the image loading functions should also make sure they do + * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. + * That means, the last two steps must be, 1) add the ibuf to the list and + * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ + + /* quick reject tests */ + if(ima==NULL) + return NULL; + if(iuser) { + if(iuser->ok==0) + return NULL; + } + else if(ima->ok==0) + return NULL; + + /* try to get the ibuf without locking */ + ibuf= image_get_ibuf_threadsafe(ima, iuser, &frame, &index); + + if(ibuf == NULL) { + /* couldn't get ibuf and image is not ok, so let's lock and try to + * load the image */ + BLI_lock_thread(LOCK_IMAGE); + + /* need to check ok flag and loading ibuf again, because the situation + * might have changed in the meantime */ + if(iuser) { + if(iuser->ok==0) { + BLI_unlock_thread(LOCK_IMAGE); + return NULL; } } + else if(ima->ok==0) { + BLI_unlock_thread(LOCK_IMAGE); + return NULL; + } + + ibuf= image_get_ibuf_threadsafe(ima, iuser, &frame, &index); + + if(ibuf == NULL) { + /* we are sure we have to load the ibuf, using source and type */ + if(ima->source==IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + ibuf= image_load_movie_file(ima, iuser, frame); + } + else if(ima->source==IMA_SRC_SEQUENCE) { + if(ima->type==IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + ibuf= image_load_sequence_file(ima, iuser, frame); + } + /* 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 */ + ibuf= image_load_sequence_multilayer(ima, iuser, frame); + } + + if(ibuf) + BLI_strncpy(ima->name, ibuf->name, sizeof(ima->name)); + } + else if(ima->source==IMA_SRC_FILE) { + + if(ima->type==IMA_TYPE_IMAGE) + 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_multilayer(ima, iuser); + + } + else if(ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + 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, 0, ima->gen_type, color); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok= IMA_OK_LOADED; + } + } + 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) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf= IMB_allocImBuf(256, 256, 32, IB_rect, 0); + image_assign_ibuf(ima, ibuf, 0, frame); + } + } + } + + BLI_unlock_thread(LOCK_IMAGE); } + /* we assuming that if it is not rendering, it's also not multithreaded + * (a somewhat weak assumption) */ if(G.rendering==0) tag_image_time(ima); - BLI_unlock_thread(LOCK_IMAGE); - return ibuf; } |