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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user