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.c588
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;
}