diff --git a/player/screenshot.c b/player/screenshot.c index f537fc4604..aa637e6e63 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -77,7 +77,8 @@ static char *stripext(void *talloc_ctx, const char *s) } static bool write_screenshot(struct mp_cmd_ctx *cmd, struct mp_image *img, - const char *filename, struct image_writer_opts *opts) + const char *filename, struct image_writer_opts *opts, + bool overwrite) { struct MPContext *mpctx = cmd->mpctx; struct image_writer_opts *gopts = mpctx->opts->screenshot_image_opts; @@ -88,7 +89,7 @@ static bool write_screenshot(struct mp_cmd_ctx *cmd, struct mp_image *img, mp_core_unlock(mpctx); bool ok = img && write_image(img, &opts_copy, filename, mpctx->global, - mpctx->screenshot_ctx->log); + mpctx->screenshot_ctx->log, overwrite); mp_core_lock(mpctx); @@ -496,7 +497,7 @@ void cmd_screenshot_to_file(void *p) cmd->success = false; return; } - cmd->success = write_screenshot(cmd, image, filename, &opts); + cmd->success = write_screenshot(cmd, image, filename, &opts, true); talloc_free(image); } @@ -537,7 +538,7 @@ void cmd_screenshot(void *p) if (image) { char *filename = gen_fname(cmd, image_writer_file_ext(opts)); if (filename) { - cmd->success = write_screenshot(cmd, image, filename, NULL); + cmd->success = write_screenshot(cmd, image, filename, NULL, false); if (cmd->success) { node_init(res, MPV_FORMAT_NODE_MAP, NULL); node_map_add_string(res, "filename", filename); diff --git a/test/scale_test.c b/test/scale_test.c index fa7886de48..8d8f63f0ee 100644 --- a/test/scale_test.c +++ b/test/scale_test.c @@ -60,7 +60,7 @@ static void dump_image(struct scale_test *stest, const char *name, struct image_writer_opts opts = image_writer_opts_defaults; opts.format = AV_CODEC_ID_PNG; - if (!write_image(img, &opts, path, NULL, NULL)) { + if (!write_image(img, &opts, path, NULL, NULL, true)) { printf("Failed to write '%s'.\n", path); abort(); } diff --git a/video/image_writer.c b/video/image_writer.c index 62dd34f288..c3cf930401 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -37,6 +37,7 @@ #endif #include "osdep/io.h" +#include "misc/path_utils.h" #include "common/av_common.h" #include "common/msg.h" @@ -162,9 +163,14 @@ static void prepare_avframe(AVFrame *pic, AVCodecContext *avctx, ); } -static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, const char *filename) +static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, + const char *filename, bool overwrite) { - FILE *fp = fopen(filename, "wb"); + FILE *fp = fopen(filename, overwrite ? "wb" : "wbx"); + if (!fp && errno == EEXIST) { + MP_ERR(ctx, "File '%s' already exists!\n", filename); + return false; + } if (!fp) { MP_ERR(ctx, "Error opening '%s' for writing!\n", filename); return false; @@ -277,9 +283,13 @@ static void write_jpeg_error_exit(j_common_ptr cinfo) } static bool write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, - const char *filename) + const char *filename, bool overwrite) { - FILE *fp = fopen(filename, "wb"); + FILE *fp = fopen(filename, overwrite ? "wb" : "wbx"); + if (!fp && errno == EEXIST) { + MP_ERR(ctx, "File '%s' already exists!\n", filename); + return false; + } if (!fp) { MP_ERR(ctx, "Error opening '%s' for writing!\n", filename); return false; @@ -361,7 +371,7 @@ static void log_side_data(struct image_writer_ctx *ctx, AVPacketSideData *data, } static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, - const char *filename) + const char *filename, bool overwrite) { const AVCodec *codec = NULL; const AVOutputFormat *ofmt = NULL; @@ -429,6 +439,11 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, goto free_data; } + if (!overwrite && mp_path_exists(filename)) { + MP_ERR(ctx, "File '%s' already exists\n", filename); + goto free_data; + } + ret = avio_open(&avioctx, filename, AVIO_FLAG_WRITE); if (ret < 0) { MP_ERR(ctx, "Could not open file '%s' for saving images\n", filename); @@ -705,7 +720,7 @@ static struct mp_image *convert_image(struct mp_image *image, int destfmt, bool write_image(struct mp_image *image, const struct image_writer_opts *opts, const char *filename, struct mpv_global *global, - struct mp_log *log) + struct mp_log *log, bool overwrite) { struct image_writer_opts defs = image_writer_opts_defaults; if (!opts) @@ -714,7 +729,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, mp_verbose(log, "input: %s\n", mp_image_params_to_str(&image->params)); struct image_writer_ctx ctx = { log, opts, image->fmt }; - bool (*write)(struct image_writer_ctx *, mp_image_t *, const char *) = write_lavc; + bool (*write)(struct image_writer_ctx *, mp_image_t *, const char *, bool) = write_lavc; int destfmt = 0; #if HAVE_JPEG @@ -751,7 +766,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, if (!dst) return false; - bool success = write(&ctx, dst, filename); + bool success = write(&ctx, dst, filename, overwrite); if (!success) mp_err(log, "Error writing file '%s'!\n", filename); @@ -763,5 +778,5 @@ void dump_png(struct mp_image *image, const char *filename, struct mp_log *log) { struct image_writer_opts opts = image_writer_opts_defaults; opts.format = AV_CODEC_ID_PNG; - write_image(image, &opts, filename, NULL, log); + write_image(image, &opts, filename, NULL, log, true); } diff --git a/video/image_writer.h b/video/image_writer.h index 72d160269b..c22606ed65 100644 --- a/video/image_writer.h +++ b/video/image_writer.h @@ -68,7 +68,7 @@ int image_writer_format_from_ext(const char *ext); */ bool write_image(struct mp_image *image, const struct image_writer_opts *opts, const char *filename, struct mpv_global *global, - struct mp_log *log); + struct mp_log *log, bool overwrite); // Debugging helper. void dump_png(struct mp_image *image, const char *filename, struct mp_log *log); diff --git a/video/out/vo_image.c b/video/out/vo_image.c index cc48ab3404..84e164f6e5 100644 --- a/video/out/vo_image.c +++ b/video/out/vo_image.c @@ -118,7 +118,7 @@ static void flip_page(struct vo *vo) filename = mp_path_join(t, p->opts->outdir, filename); MP_INFO(vo, "Saving %s\n", filename); - write_image(p->current, p->opts->opts, filename, vo->global, vo->log); + write_image(p->current, p->opts->opts, filename, vo->global, vo->log, true); talloc_free(t); }