Compositor: finished work on node "File Output".

- It saves a file with indicated type on each change, with number
  appended denoting the current frame (like ANIM saving).
- Output filename button supports relative paths ("//")
- Shows optional preview image too
- For now, added a print on each file save as feedback

To make this option work nicely, changed the BKE_makepicstring() function
to have less globals inside, so it is more generic. Todo: allow amount of
digits in filenames to be set (to support files like tmp_123456.jpg)
This commit is contained in:
2006-08-10 10:38:50 +00:00
parent 86d72cb7d4
commit 7440aba482
10 changed files with 112 additions and 29 deletions

View File

@@ -51,7 +51,7 @@ void free_unused_animimages(void);
struct Image *new_image(int width, int height, char *name, short uvtestgrid);
int BKE_write_ibuf(struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality);
void BKE_makepicstring(char *string, int frame);
void BKE_makepicstring(char *string, char *base, int frame, int imtype);
void BKE_add_image_extension(char *string, int imtype);
int BKE_imtype_is_movie(int imtype);

View File

@@ -446,32 +446,28 @@ int BKE_write_ibuf(ImBuf *ibuf, char *name, int imtype, int subimtype, int quali
}
void BKE_makepicstring(char *string, int frame)
void BKE_makepicstring(char *string, char *base, int frame, int imtype)
{
short i,len;
char num[10], *extension;
short i, len, digits= 4; /* digits in G.scene? */
char num[10];
if (string==0) return;
if (string==NULL) return;
extension= "";
strcpy(string, G.scene->r.pic);
BLI_convertstringcode(string, G.sce, G.scene->r.cfra);
BLI_strncpy(string, base, FILE_MAXDIR + FILE_MAXFILE - 10); /* weak assumption */
BLI_convertstringcode(string, G.sce, frame);
len= strlen(string);
/* can also: sprintf(num, "%04d", frame); */
i=4-sprintf(num,"%d",frame);
for(;i>0;i--){
string[len]='0';
i= digits - sprintf(num, "%d", frame);
for(; i>0; i--){
string[len]= '0';
len++;
}
string[len]=0;
strcat(string,num);
string[len]= 0;
strcat(string, num);
if(G.scene->r.scemode & R_EXTENSION)
BKE_add_image_extension(string, G.scene->r.imtype);
BKE_add_image_extension(string, imtype);
}

View File

@@ -797,6 +797,14 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup)
nhs->sat= 1.0f;
nhs->val= 1.0f;
}
else if(type==CMP_NODE_OUTPUT_FILE) {
NodeImageFile *nif= MEM_callocN(sizeof(NodeImageFile), "node image file");
node->storage= nif;
BLI_strncpy(nif->name, G.scene->r.pic, sizeof(nif->name));
nif->imtype= G.scene->r.imtype;
nif->subimtype= G.scene->r.subimtype;
nif->quality= G.scene->r.quality;
}
}
return node;

View File

@@ -679,30 +679,48 @@ static bNodeType cmp_node_composite= {
/* **************** OUTPUT FILE ******************** */
static bNodeSocketType cmp_node_output_file_in[]= {
{ SOCK_RGBA, 1, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
{ SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
};
static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
/* image assigned to output */
/* stack order input sockets: col, alpha */
if(node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */
if(in[0]->data) {
RenderData *rd= data;
NodeImageFile *nif= node->storage;
CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
ImBuf *ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
char string[256];
ibuf->rect_float= cbuf->rect;
ibuf->dither= rd->dither_intensity;
BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype);
if(0 == BKE_write_ibuf(ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality))
printf("Cannot save Node File Output to %s\n", string);
else
printf("Saved: %s\n", string);
IMB_freeImBuf(ibuf);
generate_preview(node, cbuf);
if(in[0]->data != cbuf)
free_compbuf(cbuf);
}
else if(in[0]->data)
generate_preview(node, in[0]->data);
}
static bNodeType cmp_node_output_file= {
/* type code */ CMP_NODE_OUTPUT_FILE,
/* name */ "File Output",
/* width+range */ 80, 60, 200,
/* class+opts */ NODE_CLASS_FILE, NODE_PREVIEW,
/* width+range */ 140, 80, 300,
/* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS,
/* input sock */ cmp_node_output_file_in,
/* output sock */ NULL,
/* storage */ "",
/* storage */ "NodeImageFile",
/* execfunc */ node_composit_exec_output_file
};

View File

@@ -196,5 +196,10 @@ typedef struct NodeHueSat {
float hue, sat, val;
} NodeHueSat;
typedef struct NodeImageFile {
char name[256];
short imtype, subimtype, quality, codec;
} NodeImageFile;
#endif

View File

@@ -518,7 +518,7 @@ PyObject *RenderData_Play( BPy_RenderData * self )
pos[1], file );
system( str );
} else {
BKE_makepicstring( file, self->renderContext->sfra );
BKE_makepicstring( file, G.scene->r.pic, self->renderContext->sfra, G.scene->r.imtype);
if( BLI_exist( file ) ) {
calc_renderwin_rectangle(640, 480, G.winpos, pos, size);
sprintf( str, "%s -a -p %d %d \"%s\"", bprogname,

View File

@@ -1933,7 +1933,7 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh)
ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0);
int ok;
BKE_makepicstring(name, (scene->r.cfra));
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype);
/* if not exists, BKE_write_ibuf makes one */
ibuf->rect= rres.rect32;

View File

@@ -513,7 +513,7 @@ void playback_anim(void)
else error("Can't find movie: %s", file);
}
else {
BKE_makepicstring(file, G.scene->r.sfra);
BKE_makepicstring(file, G.scene->r.pic, G.scene->r.sfra, G.scene->r.imtype);
if(BLI_exist(file)) {
run_playanim(file);
}

View File

@@ -1027,6 +1027,59 @@ static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNod
return 20;
}
/* allocate sufficient! */
static void node_imagetype_string(char *str)
{
str += sprintf(str, "Save Image as: %%t|");
str += sprintf(str, "Targa %%x%d|", R_TARGA);
str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
str += sprintf(str, "PNG %%x%d|", R_PNG);
str += sprintf(str, "BMP %%x%d|", R_BMP);
str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
str += sprintf(str, "Iris %%x%d|", R_IRIS);
str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
str += sprintf(str, "Cineon %%x%d|", R_CINEON);
str += sprintf(str, "DPX %%x%d|", R_DPX);
str += sprintf(str, "OpenEXR %%x%d", R_OPENEXR);
}
static int node_composit_buts_file_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
{
if(block) {
NodeImageFile *nif= node->storage;
char str[320];
node_imagetype_string(str);
uiBlockBeginAlign(block);
uiDefBut(block, TEX, B_NOP, "",
butr->xmin, butr->ymin+40.0f, butr->xmax-butr->xmin, 20,
nif->name, 0.0f, 240.0f, 0, 0, "");
uiDefButS(block, MENU, B_NOP, str,
butr->xmin, butr->ymin+20.0f, butr->xmax-butr->xmin, 20,
&nif->imtype, 0.0f, 1.0f, 0, 0, "");
if(nif->imtype==R_OPENEXR) {
uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_NOP, "Half",
butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
&nif->subimtype, 0, 0, 0, 0, "");
uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4",
butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 20,
&nif->codec, 0, 0, 0, 0, "");
}
else {
uiDefButS(block, NUM, B_NOP, "Quality: ",
butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
&nif->quality, 10.0f, 100.0f, 10, 0, "");
}
}
return 60;
}
/* only once called */
static void node_composit_set_butfunc(bNodeType *ntype)
{
@@ -1088,6 +1141,9 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_DILATEERODE:
ntype->butfunc= node_composit_buts_dilateerode;
break;
case CMP_NODE_OUTPUT_FILE:
ntype->butfunc= node_composit_buts_file_output;
break;
default:
ntype->butfunc= NULL;
}

View File

@@ -1251,7 +1251,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim)
char name[FILE_MAXDIR+FILE_MAXFILE];
int ok;
BKE_makepicstring(name, (G.scene->r.cfra));
BKE_makepicstring(name, G.scene->r.pic, G.scene->r.cfra, G.scene->r.imtype);
ibuf->rect= rr->rect32;
ok= BKE_write_ibuf(ibuf, name, G.scene->r.imtype, G.scene->r.subimtype, G.scene->r.quality);