diff options
Diffstat (limited to 'source/blender/editors/space_image/image_ops.c')
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 369 |
1 files changed, 114 insertions, 255 deletions
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index aa77aab2283..336331e44e7 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1680,184 +1680,28 @@ void IMAGE_OT_replace(wmOperatorType *ot) typedef struct ImageSaveData { ImageUser *iuser; Image *image; - ImageFormatData im_format; + ImageSaveOptions opts; } ImageSaveData; -static char imtype_best_depth(ImBuf *ibuf, const char imtype) +static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOperator *op) { - const char depth_ok = BKE_imtype_valid_depths(imtype); - - if (ibuf->rect_float) { - if (depth_ok & R_IMF_CHAN_DEPTH_32) { - return R_IMF_CHAN_DEPTH_32; - } - if (depth_ok & R_IMF_CHAN_DEPTH_24) { - return R_IMF_CHAN_DEPTH_24; - } - if (depth_ok & R_IMF_CHAN_DEPTH_16) { - return R_IMF_CHAN_DEPTH_16; - } - if (depth_ok & R_IMF_CHAN_DEPTH_12) { - return R_IMF_CHAN_DEPTH_12; - } - return R_IMF_CHAN_DEPTH_8; - } - - if (depth_ok & R_IMF_CHAN_DEPTH_8) { - return R_IMF_CHAN_DEPTH_8; - } - if (depth_ok & R_IMF_CHAN_DEPTH_12) { - return R_IMF_CHAN_DEPTH_12; - } - if (depth_ok & R_IMF_CHAN_DEPTH_16) { - return R_IMF_CHAN_DEPTH_16; - } - if (depth_ok & R_IMF_CHAN_DEPTH_24) { - return R_IMF_CHAN_DEPTH_24; - } - if (depth_ok & R_IMF_CHAN_DEPTH_32) { - return R_IMF_CHAN_DEPTH_32; - } - return R_IMF_CHAN_DEPTH_8; /* fallback, should not get here */ -} - -static int image_save_options_init(Main *bmain, - ImageSaveOptions *opts, - Image *ima, - ImageUser *iuser, - const bool guess_path, - const bool save_as_render) -{ - void *lock; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - - if (ibuf) { - Scene *scene = opts->scene; - bool is_depth_set = false; - - if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) { - /* imtype */ - BKE_image_format_init_for_write(&opts->im_format, scene, NULL); - is_depth_set = true; - if (!BKE_image_is_multiview(ima)) { - /* In case multiview is disabled, - * render settings would be invalid for render result in this area. */ - opts->im_format.stereo3d_format = *ima->stereo3d_format; - opts->im_format.views_format = ima->views_format; - } - } - else { - if (ima->source == IMA_SRC_GENERATED) { - opts->im_format.imtype = R_IMF_IMTYPE_PNG; - opts->im_format.compress = ibuf->foptions.quality; - opts->im_format.planes = ibuf->planes; - } - else { - BKE_image_format_from_imbuf(&opts->im_format, ibuf); - } - - /* use the multiview image settings as the default */ - opts->im_format.stereo3d_format = *ima->stereo3d_format; - opts->im_format.views_format = ima->views_format; - - BKE_image_format_color_management_copy_from_scene(&opts->im_format, scene); - } - - opts->im_format.color_management = R_IMF_COLOR_MANAGEMENT_FOLLOW_SCENE; - - if (ima->source == IMA_SRC_TILED) { - BLI_strncpy(opts->filepath, ima->filepath, sizeof(opts->filepath)); - BLI_path_abs(opts->filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id)); - } - else { - BLI_strncpy(opts->filepath, ibuf->name, sizeof(opts->filepath)); - } - - /* sanitize all settings */ - - /* unlikely but just in case */ - if (ELEM(opts->im_format.planes, R_IMF_PLANES_BW, R_IMF_PLANES_RGB, R_IMF_PLANES_RGBA) == 0) { - opts->im_format.planes = R_IMF_PLANES_RGBA; - } - - /* depth, account for float buffer and format support */ - if (is_depth_set == false) { - opts->im_format.depth = imtype_best_depth(ibuf, opts->im_format.imtype); - } - - /* some formats don't use quality so fallback to scenes quality */ - if (opts->im_format.quality == 0) { - opts->im_format.quality = scene->r.im_format.quality; - } - - /* check for empty path */ - if (guess_path && opts->filepath[0] == 0) { - const bool is_prev_save = !STREQ(G.ima, "//"); - if (save_as_render) { - if (is_prev_save) { - BLI_strncpy(opts->filepath, G.ima, sizeof(opts->filepath)); - } - else { - BLI_strncpy(opts->filepath, "//untitled", sizeof(opts->filepath)); - BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain)); - } - } - else { - BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", ima->id.name + 2); - BLI_path_make_safe(opts->filepath); - BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain)); - } - - /* append UDIM marker if not present */ - if (ima->source == IMA_SRC_TILED && strstr(opts->filepath, "<UDIM>") == NULL) { - int len = strlen(opts->filepath); - STR_CONCAT(opts->filepath, len, ".<UDIM>"); - } - } - } - - BKE_image_release_ibuf(ima, ibuf, lock); - - return (ibuf != NULL); -} - -static void image_save_options_from_op(Main *bmain, - ImageSaveOptions *opts, - wmOperator *op, - ImageFormatData *imf) -{ - if (imf) { - BKE_image_format_free(&opts->im_format); - BKE_image_format_copy(&opts->im_format, imf); - } - if (RNA_struct_property_is_set(op->ptr, "filepath")) { RNA_string_get(op->ptr, "filepath", opts->filepath); BLI_path_abs(opts->filepath, BKE_main_blendfile_path(bmain)); } -} - -static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op) -{ - if (op->customdata) { - ImageSaveData *isd = op->customdata; - BKE_image_format_free(&isd->im_format); - BKE_image_format_copy(&isd->im_format, &opts->im_format); - } - - RNA_string_set(op->ptr, "filepath", opts->filepath); -} -static bool save_image_op( - Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts) -{ opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); opts->save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); opts->save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); + opts->do_newpath = true; +} +static bool save_image_op( + Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts) +{ WM_cursor_wait(true); bool ok = BKE_image_save(op->reports, bmain, ima, iuser, opts); @@ -1872,11 +1716,54 @@ static bool save_image_op( return ok; } +static ImageSaveData *image_save_as_init(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Image *image = image_from_context(C); + ImageUser *iuser = image_user_from_context(C); + Scene *scene = CTX_data_scene(C); + + ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__); + isd->image = image; + isd->iuser = iuser; + + if (!BKE_image_save_options_init(&isd->opts, bmain, scene, image, iuser, true)) { + BKE_image_save_options_free(&isd->opts); + MEM_freeN(isd); + return NULL; + } + + if (!RNA_struct_property_is_set(op->ptr, "filepath")) { + RNA_string_set(op->ptr, "filepath", isd->opts.filepath); + } + + /* Enable save_copy by default for render results. */ + if (ELEM(image->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) && + !RNA_struct_property_is_set(op->ptr, "copy")) { + RNA_boolean_set(op->ptr, "copy", true); + } + + if (!RNA_struct_property_is_set(op->ptr, "save_as_render")) { + RNA_boolean_set(op->ptr, "save_as_render", isd->opts.save_as_render); + } + + /* Show multiview save options only if image has multiviews. */ + PropertyRNA *prop; + prop = RNA_struct_find_property(op->ptr, "show_multiview"); + RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(image)); + prop = RNA_struct_find_property(op->ptr, "use_multiview"); + RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(image)); + + op->customdata = isd; + + return isd; +} + static void image_save_as_free(wmOperator *op) { if (op->customdata) { ImageSaveData *isd = op->customdata; - BKE_image_format_free(&isd->im_format); + BKE_image_save_options_free(&isd->opts); MEM_freeN(op->customdata); op->customdata = NULL; @@ -1886,96 +1773,55 @@ static void image_save_as_free(wmOperator *op) static int image_save_as_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ImageSaveOptions opts; + ImageSaveData *isd; - Image *image = NULL; - ImageUser *iuser = NULL; - ImageFormatData *imf = NULL; if (op->customdata) { - ImageSaveData *isd = op->customdata; - image = isd->image; - iuser = isd->iuser; - imf = &isd->im_format; + isd = op->customdata; } else { - image = image_from_context(C); - iuser = image_user_from_context(C); + isd = image_save_as_init(C, op); + if (isd == NULL) { + return OPERATOR_CANCELLED; + } } - BKE_image_save_options_init(&opts, bmain, scene); - - /* just in case to initialize values, - * these should be set on invoke or by the caller. */ - image_save_options_init(bmain, &opts, image, iuser, false, false); + image_save_options_from_op(bmain, &isd->opts, op); + BKE_image_save_options_update(&isd->opts, isd->image); - image_save_options_from_op(bmain, &opts, op, imf); - opts.do_newpath = true; + save_image_op(bmain, isd->image, isd->iuser, op, &isd->opts); - save_image_op(bmain, image, iuser, op, &opts); - - if (opts.save_copy == false) { - BKE_image_free_packedfiles(image); + if (isd->opts.save_copy == false) { + BKE_image_free_packedfiles(isd->image); } - BKE_image_save_options_free(&opts); - image_save_as_free(op); return OPERATOR_FINISHED; } -static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op) +static bool image_save_as_check(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); ImageSaveData *isd = op->customdata; - return WM_operator_filesel_ensure_ext_imtype(op, &isd->im_format); + + image_save_options_from_op(bmain, &isd->opts, op); + BKE_image_save_options_update(&isd->opts, isd->image); + + return WM_operator_filesel_ensure_ext_imtype(op, &isd->opts.im_format); } static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Main *bmain = CTX_data_main(C); - Image *ima = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); - Scene *scene = CTX_data_scene(C); - ImageSaveOptions opts; - PropertyRNA *prop; - const bool save_as_render = (ima->source == IMA_SRC_VIEWER); - if (RNA_struct_property_is_set(op->ptr, "filepath")) { return image_save_as_exec(C, op); } - BKE_image_save_options_init(&opts, bmain, scene); - - if (image_save_options_init(bmain, &opts, ima, iuser, true, save_as_render) == 0) { - BKE_image_save_options_free(&opts); + ImageSaveData *isd = image_save_as_init(C, op); + if (isd == NULL) { return OPERATOR_CANCELLED; } - image_save_options_to_op(&opts, op); - /* enable save_copy by default for render results */ - if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE) && - !RNA_struct_property_is_set(op->ptr, "copy")) { - RNA_boolean_set(op->ptr, "copy", true); - } - - RNA_boolean_set(op->ptr, "save_as_render", save_as_render); - - ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__); - isd->image = ima; - isd->iuser = iuser; - - BKE_image_format_copy(&isd->im_format, &opts.im_format); - op->customdata = isd; - - /* show multiview save options only if image has multiviews */ - prop = RNA_struct_find_property(op->ptr, "show_multiview"); - RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima)); - prop = RNA_struct_find_property(op->ptr, "use_multiview"); - RNA_property_boolean_set(op->ptr, prop, BKE_image_is_multiview(ima)); - - image_filesel(C, op, opts.filepath); - BKE_image_save_options_free(&opts); + image_filesel(C, op, isd->opts.filepath); return OPERATOR_RUNNING_MODAL; } @@ -2003,7 +1849,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) ImageSaveData *isd = op->customdata; PointerRNA imf_ptr; const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview"); - const bool use_color_management = RNA_boolean_get(op->ptr, "save_as_render"); + const bool save_as_render = RNA_boolean_get(op->ptr, "save_as_render"); uiLayoutSetPropSep(layout, true); uiLayoutSetPropDecorate(layout, false); @@ -2015,8 +1861,15 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) uiItemS(layout); /* image template */ - RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr); - uiTemplateImageSettings(layout, &imf_ptr, use_color_management); + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->opts.im_format, &imf_ptr); + uiTemplateImageSettings(layout, &imf_ptr, save_as_render); + + if (!save_as_render) { + PointerRNA linear_settings_ptr = RNA_pointer_get(&imf_ptr, "linear_colorspace_settings"); + uiLayout *col = uiLayoutColumn(layout, true); + uiItemS(col); + uiItemR(col, &linear_settings_ptr, "name", 0, IFACE_("Color Space"), ICON_NONE); + } /* multiview template */ if (is_multiview) { @@ -2062,16 +1915,19 @@ void IMAGE_OT_save_as(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, - "save_as_render", - 0, - "Save As Render", - "Apply render part of display transform when saving byte image"); - RNA_def_boolean(ot->srna, - "copy", - 0, - "Copy", - "Create a new image file without modifying the current image in blender"); + PropertyRNA *prop; + prop = RNA_def_boolean(ot->srna, + "save_as_render", + 0, + "Save As Render", + "Apply render part of display transform when saving byte image"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, + "copy", + 0, + "Copy", + "Create a new image file without modifying the current image in blender"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); image_operator_prop_allow_tokens(ot); WM_operator_properties_filesel(ot, @@ -2138,12 +1994,11 @@ static int image_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } - BKE_image_save_options_init(&opts, bmain, scene); - if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) { + if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false)) { BKE_image_save_options_free(&opts); return OPERATOR_CANCELLED; } - image_save_options_from_op(bmain, &opts, op, NULL); + image_save_options_from_op(bmain, &opts, op); /* Check if file write permission is ok. */ if (BLI_exists(opts.filepath) && !BLI_file_is_writable(opts.filepath)) { @@ -2316,6 +2171,14 @@ static bool image_has_valid_path(Image *ima) return strchr(ima->filepath, '\\') || strchr(ima->filepath, '/'); } +static bool image_should_pack_during_save_all(const Image *ima) +{ + /* Images without a filepath (implied with IMA_SRC_GENERATED) should + * be packed during a save_all operation. */ + return (ima->source == IMA_SRC_GENERATED) || + (ima->source == IMA_SRC_TILED && !BKE_image_has_filepath(ima)); +} + bool ED_image_should_save_modified(const Main *bmain) { ReportList reports; @@ -2339,7 +2202,7 @@ int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports) bool is_format_writable; if (image_should_be_saved(ima, &is_format_writable)) { - if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) { + if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) { if (!ID_IS_LINKED(ima)) { num_saveable_images++; } @@ -2396,15 +2259,14 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports) bool is_format_writable; if (image_should_be_saved(ima, &is_format_writable)) { - if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) { + if (BKE_image_has_packedfile(ima) || image_should_pack_during_save_all(ima)) { BKE_image_memorypack(ima); } else if (is_format_writable) { if (image_has_valid_path(ima)) { ImageSaveOptions opts; Scene *scene = CTX_data_scene(C); - BKE_image_save_options_init(&opts, bmain, scene); - if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) { + if (!BKE_image_save_options_init(&opts, bmain, scene, ima, NULL, false)) { bool saved_successfully = BKE_image_save(reports, bmain, ima, NULL, &opts); ok = ok && saved_successfully; } @@ -3040,9 +2902,8 @@ static bool image_pack_test(bContext *C, wmOperator *op) return false; } - if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) { - BKE_report( - op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported"); + if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported"); return false; } @@ -3110,9 +2971,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) { - BKE_report( - op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported"); + if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported"); return OPERATOR_CANCELLED; } @@ -3144,9 +3004,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return OPERATOR_CANCELLED; } - if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) { - BKE_report( - op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported"); + if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported"); return OPERATOR_CANCELLED; } |