option to write images to a files on single frame renders, this isn't accessed by the UI at the moment, but could eventually be used for saving test-renders.

The main reason to have this is so renders can be scripted to write to a specific file without having to do annoying tricks like set a dummy start/end frame range, render an animation and work out the current frame image will be written to, then rename after rendering.

Also made some 'char *' args into 'const char *'
This commit is contained in:
Campbell Barton 2010-11-16 14:40:46 +00:00
parent 2153c663be
commit 1e245cc589
18 changed files with 87 additions and 51 deletions

@ -47,7 +47,7 @@ void free_image(struct Image *me);
void BKE_stamp_info(struct Scene *scene, struct ImBuf *ibuf); void BKE_stamp_info(struct Scene *scene, struct ImBuf *ibuf);
void BKE_stamp_buf(struct Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels); void BKE_stamp_buf(struct Scene *scene, unsigned char *rect, float *rectf, int width, int height, int channels);
int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality); int BKE_write_ibuf(struct Scene *scene, struct ImBuf *ibuf, char *name, int imtype, int subimtype, int quality);
void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext); void BKE_makepicstring(char *string, const char *base, int frame, int imtype, const short use_ext, const short use_frames);
int BKE_add_image_extension(char *string, int imtype); int BKE_add_image_extension(char *string, int imtype);
int BKE_ftype_to_imtype(int ftype); int BKE_ftype_to_imtype(int ftype);
int BKE_imtype_to_ftype(int imtype); int BKE_imtype_to_ftype(int imtype);

@ -1310,11 +1310,13 @@ int BKE_write_ibuf(Scene *scene, ImBuf *ibuf, char *name, int imtype, int subimt
} }
void BKE_makepicstring(char *string, char *base, int frame, int imtype, int use_ext) void BKE_makepicstring(char *string, const char *base, int frame, int imtype, const short use_ext, const short use_frames)
{ {
if (string==NULL) return; if (string==NULL) return;
BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */ BLI_strncpy(string, base, FILE_MAX - 10); /* weak assumption */
BLI_path_abs(string, G.main->name); BLI_path_abs(string, G.main->name);
if(use_frames)
BLI_path_frame(string, frame, 4); BLI_path_frame(string, frame, 4);
if(use_ext) if(use_ext)

@ -1828,7 +1828,7 @@ static ImBuf * seq_render_scene_strip_impl(
if(re==NULL) if(re==NULL)
re= RE_NewRender(sce->id.name); re= RE_NewRender(sce->id.name);
RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame); RE_BlenderFrame(re, bmain, sce, NULL, sce->lay, frame, FALSE);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */ /* restore previous state after it was toggled on & off by RE_BlenderFrame */
G.rendering = rendering; G.rendering = rendering;

@ -47,7 +47,7 @@ int BLI_is_writable(char *filename);
/** /**
* @attention Do not confuse with BLI_exist * @attention Do not confuse with BLI_exist
*/ */
int BLI_exists(char *file); int BLI_exists(const char *file);
int BLI_copy_fileops(char *file, char *to); int BLI_copy_fileops(char *file, char *to);
int BLI_rename(char *from, char *to); int BLI_rename(char *from, char *to);
int BLI_gzip(char *from, char *to); int BLI_gzip(char *from, char *to);

@ -42,9 +42,9 @@ struct direntry;
char *BLI_getDefaultDocumentFolder(void); char *BLI_getDefaultDocumentFolder(void);
char *BLI_get_folder(int folder_id, char *subfolder); char *BLI_get_folder(int folder_id, const char *subfolder);
char *BLI_get_folder_create(int folder_id, char *subfolder); char *BLI_get_folder_create(int folder_id, const char *subfolder);
char *BLI_get_user_folder_notest(int folder_id, char *subfolder); char *BLI_get_user_folder_notest(int folder_id, const char *subfolder);
/* folder_id */ /* folder_id */
@ -101,7 +101,7 @@ void BLI_setenv_if_new(const char *env, const char* val);
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
void BLI_make_exist(char *dir); void BLI_make_exist(char *dir);
void BLI_make_existing_file(char *name); void BLI_make_existing_file(const char *name);
void BLI_split_dirfile(const char *string, char *dir, char *file); void BLI_split_dirfile(const char *string, char *dir, char *file);
void BLI_join_dirfile(char *string, const char *dir, const char *file); void BLI_join_dirfile(char *string, const char *dir, const char *file);
char *BLI_path_basename(char *path); char *BLI_path_basename(char *path);

@ -143,7 +143,7 @@ int BLI_touch(const char *file)
return 0; return 0;
} }
int BLI_exists(char *file) { int BLI_exists(const char *file) {
return BLI_exist(file); return BLI_exist(file);
} }

@ -854,7 +854,7 @@ static char *blender_version_decimal(void)
return version_str; return version_str;
} }
static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name) static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
{ {
char tmppath[FILE_MAX]; char tmppath[FILE_MAX];
@ -878,7 +878,7 @@ static int test_path(char *targetpath, char *path_base, char *path_sep, char *fo
} }
} }
static int test_env_path(char *path, char *envvar) static int test_env_path(char *path, const char *envvar)
{ {
char *env = envvar?getenv(envvar):NULL; char *env = envvar?getenv(envvar):NULL;
if (!env) return 0; if (!env) return 0;
@ -892,7 +892,7 @@ static int test_env_path(char *path, char *envvar)
} }
} }
static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name) static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name)
{ {
extern char bprogname[]; /* argv[0] from creator.c */ extern char bprogname[]; /* argv[0] from creator.c */
char bprogdir[FILE_MAX]; char bprogdir[FILE_MAX];
@ -918,7 +918,7 @@ static int get_path_local(char *targetpath, char *folder_name, char *subfolder_n
return 0; return 0;
} }
static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar) static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
{ {
char user_path[FILE_MAX]; char user_path[FILE_MAX];
const char *user_base_path; const char *user_base_path;
@ -955,7 +955,7 @@ static int get_path_user(char *targetpath, char *folder_name, char *subfolder_na
} }
} }
static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar) static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar)
{ {
char system_path[FILE_MAX]; char system_path[FILE_MAX];
const char *system_base_path; const char *system_base_path;
@ -1022,7 +1022,7 @@ static int get_path_system(char *targetpath, char *folder_name, char *subfolder_
/* get a folder out of the 'folder_id' presets for paths */ /* get a folder out of the 'folder_id' presets for paths */
/* returns the path if found, NULL string if not */ /* returns the path if found, NULL string if not */
char *BLI_get_folder(int folder_id, char *subfolder) char *BLI_get_folder(int folder_id, const char *subfolder)
{ {
static char path[FILE_MAX] = ""; static char path[FILE_MAX] = "";
@ -1094,7 +1094,7 @@ char *BLI_get_folder(int folder_id, char *subfolder)
return path; return path;
} }
char *BLI_get_user_folder_notest(int folder_id, char *subfolder) char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
{ {
static char path[FILE_MAX] = ""; static char path[FILE_MAX] = "";
@ -1118,7 +1118,7 @@ char *BLI_get_user_folder_notest(int folder_id, char *subfolder)
return path; return path;
} }
char *BLI_get_folder_create(int folder_id, char *subfolder) char *BLI_get_folder_create(int folder_id, const char *subfolder)
{ {
char *path; char *path;
@ -1226,7 +1226,7 @@ void BLI_make_exist(char *dir) {
} }
} }
void BLI_make_existing_file(char *name) void BLI_make_existing_file(const char *name)
{ {
char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE]; char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];

@ -474,7 +474,7 @@ int BLI_exist(const char *name)
} }
/* would be better in fileops.c except that it needs stat.h so add here */ /* would be better in fileops.c except that it needs stat.h so add here */
int BLI_is_dir(char *file) { int BLI_is_dir(const char *file) {
return S_ISDIR(BLI_exist(file)); return S_ISDIR(BLI_exist(file));
} }

@ -402,6 +402,13 @@ static int screen_render_exec(bContext *C, wmOperator *op)
View3D *v3d= CTX_wm_view3d(C); View3D *v3d= CTX_wm_view3d(C);
Main *mainp= CTX_data_main(C); Main *mainp= CTX_data_main(C);
unsigned int lay= (v3d)? v3d->lay: scene->lay; unsigned int lay= (v3d)? v3d->lay: scene->lay;
const short is_animation= RNA_boolean_get(op->ptr, "animation");
const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
return OPERATOR_CANCELLED;
}
if(re==NULL) { if(re==NULL) {
re= RE_NewRender(scene->id.name); re= RE_NewRender(scene->id.name);
@ -421,10 +428,10 @@ static int screen_render_exec(bContext *C, wmOperator *op)
since sequence rendering can call that recursively... (peter) */ since sequence rendering can call that recursively... (peter) */
seq_stripelem_cache_cleanup(); seq_stripelem_cache_cleanup();
if(RNA_boolean_get(op->ptr, "animation")) if(is_animation)
RE_BlenderAnim(re, mainp, scene, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports); RE_BlenderAnim(re, mainp, scene, lay, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports);
else else
RE_BlenderFrame(re, mainp, scene, NULL, lay, scene->r.cfra); RE_BlenderFrame(re, mainp, scene, NULL, lay, scene->r.cfra, is_write_still);
// no redraw needed, we leave state as we entered it // no redraw needed, we leave state as we entered it
ED_update_for_newframe(mainp, scene, CTX_wm_screen(C), 1); ED_update_for_newframe(mainp, scene, CTX_wm_screen(C), 1);
@ -441,7 +448,7 @@ typedef struct RenderJob {
wmWindow *win; wmWindow *win;
SceneRenderLayer *srl; SceneRenderLayer *srl;
int lay; int lay;
int anim; short anim, write_still;
Image *image; Image *image;
ImageUser iuser; ImageUser iuser;
short *stop; short *stop;
@ -568,7 +575,7 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
if(rj->anim) if(rj->anim)
RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->lay, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports); RE_BlenderAnim(rj->re, rj->main, rj->scene, rj->lay, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports);
else else
RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->lay, rj->scene->r.cfra); RE_BlenderFrame(rj->re, rj->main, rj->scene, rj->srl, rj->lay, rj->scene->r.cfra, rj->write_still);
} }
static void render_endjob(void *rjv) static void render_endjob(void *rjv)
@ -632,6 +639,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
wmJob *steve; wmJob *steve;
RenderJob *rj; RenderJob *rj;
Image *ima; Image *ima;
const short is_animation= RNA_boolean_get(op->ptr, "animation");
const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
/* only one render job at a time */ /* only one render job at a time */
if(WM_jobs_test(CTX_wm_manager(C), scene)) if(WM_jobs_test(CTX_wm_manager(C), scene))
@ -641,6 +650,11 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_CANCELLED; return OPERATOR_CANCELLED;
} }
if(!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.imtype)) {
BKE_report(op->reports, RPT_ERROR, "Can't write a single file with an animation format selected.");
return OPERATOR_CANCELLED;
}
/* stop all running jobs, currently previews frustrate Render */ /* stop all running jobs, currently previews frustrate Render */
WM_jobs_stop_all(CTX_wm_manager(C)); WM_jobs_stop_all(CTX_wm_manager(C));
@ -703,7 +717,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
rj->win= CTX_wm_window(C); rj->win= CTX_wm_window(C);
rj->srl = srl; rj->srl = srl;
rj->lay = (v3d)? v3d->lay: scene->lay; rj->lay = (v3d)? v3d->lay: scene->lay;
rj->anim= RNA_boolean_get(op->ptr, "animation"); rj->anim= is_animation;
rj->write_still= is_write_still;
rj->iuser.scene= scene; rj->iuser.scene= scene;
rj->iuser.ok= 1; rj->iuser.ok= 1;
rj->reports= op->reports; rj->reports= op->reports;
@ -764,7 +779,8 @@ void RENDER_OT_render(wmOperatorType *ot)
ot->poll= ED_operator_screenactive; ot->poll= ED_operator_screenactive;
RNA_def_boolean(ot->srna, "animation", 0, "Animation", ""); RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");
RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render"); RNA_def_string(ot->srna, "layer", "", RE_MAXNAME, "Render Layer", "Single render layer to re-render");
RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene"); RNA_def_string(ot->srna, "scene", "", 19, "Scene", "Re-render single layer in this scene");
} }

@ -389,7 +389,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op)
} }
} }
else { else {
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE);
ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality); ok= BKE_write_ibuf(scene, ibuf, name, scene->r.imtype, scene->r.subimtype, scene->r.quality);
if(ok==0) { if(ok==0) {

@ -256,7 +256,7 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float
char name[FILE_MAXDIR+FILE_MAXFILE]; char name[FILE_MAXDIR+FILE_MAXFILE];
int ok; int ok;
BKE_makepicstring(name, rd.pic, cfra, rd.imtype, rd.scemode & R_EXTENSION); BKE_makepicstring(name, rd.pic, cfra, rd.imtype, rd.scemode & R_EXTENSION, TRUE);
ibuf->rect= sj->dumprect; ibuf->rect= sj->dumprect;
ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality); ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality);

@ -283,7 +283,7 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned
* *
* @attention Defined in writeimage.c * @attention Defined in writeimage.c
*/ */
short IMB_saveiff(struct ImBuf *ibuf,char *naam,int flags); short IMB_saveiff(struct ImBuf *ibuf, char *filepath, int flags);
/** /**
* Encodes a png image from an ImBuf * Encodes a png image from an ImBuf

@ -482,7 +482,7 @@ void IMB_exr_add_channel(void *handle, const char *layname, const char *passname
} }
/* only used for writing temp. render results (not image files) */ /* only used for writing temp. render results (not image files) */
void IMB_exr_begin_write(void *handle, char *filename, int width, int height, int compress) void IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress)
{ {
ExrHandle *data= (ExrHandle *)handle; ExrHandle *data= (ExrHandle *)handle;
Header header (width, height); Header header (width, height);
@ -503,7 +503,7 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height, in
data->ofile = new OutputFile(filename, header); data->ofile = new OutputFile(filename, header);
} }
void IMB_exrtile_begin_write(void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley) void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley)
{ {
ExrHandle *data= (ExrHandle *)handle; ExrHandle *data= (ExrHandle *)handle;
Header header (width, height); Header header (width, height);
@ -528,7 +528,7 @@ void IMB_exrtile_begin_write(void *handle, char *filename, int mipmap, int width
} }
/* read from file */ /* read from file */
int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height) int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height)
{ {
ExrHandle *data= (ExrHandle *)handle; ExrHandle *data= (ExrHandle *)handle;

@ -44,9 +44,9 @@
void * IMB_exr_get_handle (void); void * IMB_exr_get_handle (void);
void IMB_exr_add_channel (void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect); void IMB_exr_add_channel (void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect);
int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height); int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height);
void IMB_exr_begin_write (void *handle, char *filename, int width, int height, int compress); void IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress);
void IMB_exrtile_begin_write (void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley); void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley);
void IMB_exr_set_channel (void *handle, char *layname, char *passname, int xstride, int ystride, float *rect); void IMB_exr_set_channel (void *handle, char *layname, char *passname, int xstride, int ystride, float *rect);
@ -69,9 +69,9 @@ void IMB_exr_close (void *handle);
void * IMB_exr_get_handle (void) {return NULL;} void * IMB_exr_get_handle (void) {return NULL;}
void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }
int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;}
void IMB_exr_begin_write (void *handle, char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; } void IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; }
void IMB_exrtile_begin_write (void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; }
void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; }

@ -68,7 +68,7 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name
if(BKE_imtype_is_movie(rd->imtype)) if(BKE_imtype_is_movie(rd->imtype))
BKE_makeanimstring(name, rd); BKE_makeanimstring(name, rd);
else else
BKE_makepicstring(name, rd->pic, (frame==INT_MIN) ? rd->cfra : frame, rd->imtype, rd->scemode & R_EXTENSION); BKE_makepicstring(name, rd->pic, (frame==INT_MIN) ? rd->cfra : frame, rd->imtype, rd->scemode & R_EXTENSION, TRUE);
} }
#ifdef WITH_COLLADA #ifdef WITH_COLLADA

@ -71,7 +71,7 @@ static void node_composit_exec_output_file(void *data, bNode *node, bNodeStack *
} }
} }
BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype, (rd->scemode & R_EXTENSION)); BKE_makepicstring(string, nif->name, rd->cfra, nif->imtype, (rd->scemode & R_EXTENSION), TRUE);
if(0 == BKE_write_ibuf((Scene *)node->id, ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality)) if(0 == BKE_write_ibuf((Scene *)node->id, ibuf, string, nif->imtype, nif->subimtype, nif->imtype==R_OPENEXR?nif->codec:nif->quality))
printf("Cannot save Node File Output to %s\n", string); printf("Cannot save Node File Output to %s\n", string);

@ -212,14 +212,14 @@ void RE_init_threadcount(Render *re);
void RE_TileProcessor(struct Render *re); void RE_TileProcessor(struct Render *re);
/* only RE_NewRender() needed, main Blender render calls */ /* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, unsigned int lay, int frame); void RE_BlenderFrame(struct Render *re, struct Main *bmain, struct Scene *scene, struct SceneRenderLayer *srl, unsigned int lay, int frame, const short write_still);
void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int sfra, int efra, int tfra, struct ReportList *reports); void RE_BlenderAnim(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int sfra, int efra, int tfra, struct ReportList *reports);
/* main preview render call */ /* main preview render call */
void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene); void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene);
void RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); void RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode);
void RE_WriteRenderResult(RenderResult *rr, char *filename, int compress); void RE_WriteRenderResult(RenderResult *rr, const char *filename, int compress);
struct RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty); struct RenderResult *RE_MultilayerConvert(void *exrhandle, int rectx, int recty);
/* do a full sample buffer compo */ /* do a full sample buffer compo */

@ -120,6 +120,7 @@ Render R;
/* ********* alloc and free ******** */ /* ********* alloc and free ******** */
static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports, const char *name_override);
static volatile int g_break= 0; static volatile int g_break= 0;
static int thread_break(void *UNUSED(arg)) static int thread_break(void *UNUSED(arg))
@ -807,7 +808,7 @@ static char *make_pass_name(RenderPass *rpass, int chan)
/* filename already made absolute */ /* filename already made absolute */
/* called from within UI, saves both rendered result as a file-read result */ /* called from within UI, saves both rendered result as a file-read result */
void RE_WriteRenderResult(RenderResult *rr, char *filename, int compress) void RE_WriteRenderResult(RenderResult *rr, const char *filename, int compress)
{ {
RenderLayer *rl; RenderLayer *rl;
RenderPass *rpass; RenderPass *rpass;
@ -2844,7 +2845,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc
} }
/* general Blender frame render call */ /* general Blender frame render call */
void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, unsigned int lay, int frame) void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *srl, unsigned int lay, int frame, const short write_still)
{ {
/* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */ /* ugly global still... is to prevent preview events and signal subsurfs etc to make full resol */
G.rendering= 1; G.rendering= 1;
@ -2856,11 +2857,25 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr
do_render_all_options(re); do_render_all_options(re);
} }
if(write_still) {
if(BKE_imtype_is_movie(scene->r.imtype)) {
/* operator checks this but incase its called from elsewhere */
printf("Error: cant write single images with a movie format!\n");
}
else {
char name[FILE_MAX];
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, FALSE);
/* reports only used for Movie */
do_write_image_or_movie(re, scene, NULL, NULL, name);
}
}
/* UGLY WARNING */ /* UGLY WARNING */
G.rendering= 0; G.rendering= 0;
} }
static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports) static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports, const char *name_override)
{ {
char name[FILE_MAX]; char name[FILE_MAX];
RenderResult rres; RenderResult rres;
@ -2884,7 +2899,10 @@ static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, R
printf("Append frame %d", scene->r.cfra); printf("Append frame %d", scene->r.cfra);
} }
else { else {
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); if(name_override)
BLI_strncpy(name, name_override, sizeof(name));
else
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE);
if(re->r.imtype==R_MULTILAYER) { if(re->r.imtype==R_MULTILAYER) {
if(re->result) { if(re->result) {
@ -2974,7 +2992,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int
do_render_all_options(re); do_render_all_options(re);
if(re->test_break(re->tbh) == 0) { if(re->test_break(re->tbh) == 0) {
if(!do_write_image_or_movie(re, scene, mh, reports)) if(!do_write_image_or_movie(re, scene, mh, reports, NULL))
G.afbreek= 1; G.afbreek= 1;
} }
} else { } else {
@ -3011,7 +3029,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int
/* Touch/NoOverwrite options are only valid for image's */ /* Touch/NoOverwrite options are only valid for image's */
if(BKE_imtype_is_movie(scene->r.imtype) == 0) { if(BKE_imtype_is_movie(scene->r.imtype) == 0) {
if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) if(scene->r.mode & (R_NO_OVERWRITE | R_TOUCH))
BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION); BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype, scene->r.scemode & R_EXTENSION, TRUE);
if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) { if(scene->r.mode & R_NO_OVERWRITE && BLI_exist(name)) {
printf("skipping existing frame \"%s\"\n", name); printf("skipping existing frame \"%s\"\n", name);
@ -3029,7 +3047,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, unsigned int lay, int
if(re->test_break(re->tbh) == 0) { if(re->test_break(re->tbh) == 0) {
if(!G.afbreek) if(!G.afbreek)
if(!do_write_image_or_movie(re, scene, mh, reports)) if(!do_write_image_or_movie(re, scene, mh, reports, NULL))
G.afbreek= 1; G.afbreek= 1;
} }
else else