Python API: make Image.save and Image.save_render more consistent with operator
Previously these only supported a subset of what the save operator could do, for example no multilayer or stereo saving, no proper color management. Now share code with the image save operator so it's more consistent.
This commit is contained in:
parent
adf183eeae
commit
29a3f43da5
Notes:
blender-bot
2023-02-13 22:37:44 +01:00
Referenced by issue #102421, Image.save() more heavy than original when using bpy Referenced by issue #100281, Regression: Fail to save to right image via bpy when copying image Referenced by issue #98305, Regression: Calling save on image fails due to file path options not being correctly applied
|
@ -46,8 +46,7 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
|||
struct Scene *scene,
|
||||
struct Image *ima,
|
||||
struct ImageUser *iuser,
|
||||
const bool guess_path,
|
||||
const bool save_as_render);
|
||||
const bool guess_path);
|
||||
void BKE_image_save_options_update(struct ImageSaveOptions *opts, struct Image *ima);
|
||||
void BKE_image_save_options_free(struct ImageSaveOptions *opts);
|
||||
|
||||
|
|
|
@ -78,14 +78,21 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
|||
Scene *scene,
|
||||
Image *ima,
|
||||
ImageUser *iuser,
|
||||
const bool guess_path,
|
||||
const bool save_as_render)
|
||||
const bool guess_path)
|
||||
{
|
||||
/* For saving a tiled image we need an iuser, so use a local one if there isn't already one. */
|
||||
ImageUser save_iuser;
|
||||
if (iuser == nullptr) {
|
||||
BKE_imageuser_default(&save_iuser);
|
||||
iuser = &save_iuser;
|
||||
iuser->scene = scene;
|
||||
}
|
||||
|
||||
memset(opts, 0, sizeof(*opts));
|
||||
|
||||
opts->bmain = bmain;
|
||||
opts->scene = scene;
|
||||
opts->save_as_render = save_as_render;
|
||||
opts->save_as_render = ima->source == IMA_SRC_VIEWER;
|
||||
|
||||
BKE_image_format_init(&opts->im_format, false);
|
||||
|
||||
|
@ -126,7 +133,7 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
|||
}
|
||||
|
||||
/* Default to saving in the same colorspace as the image setting. */
|
||||
if (!save_as_render) {
|
||||
if (!opts->save_as_render) {
|
||||
BKE_color_managed_colorspace_settings_copy(&opts->im_format.linear_colorspace_settings,
|
||||
&ima->colorspace_settings);
|
||||
}
|
||||
|
@ -161,7 +168,7 @@ bool BKE_image_save_options_init(ImageSaveOptions *opts,
|
|||
/* check for empty path */
|
||||
if (guess_path && opts->filepath[0] == 0) {
|
||||
const bool is_prev_save = !STREQ(G.ima, "//");
|
||||
if (save_as_render) {
|
||||
if (opts->save_as_render) {
|
||||
if (is_prev_save) {
|
||||
BLI_strncpy(opts->filepath, G.ima, sizeof(opts->filepath));
|
||||
}
|
||||
|
@ -596,8 +603,13 @@ static bool image_save_single(ReportList *reports,
|
|||
bool BKE_image_save(
|
||||
ReportList *reports, Main *bmain, Image *ima, ImageUser *iuser, ImageSaveOptions *opts)
|
||||
{
|
||||
/* For saving a tiled image we need an iuser, so use a local one if there isn't already one. */
|
||||
ImageUser save_iuser;
|
||||
BKE_imageuser_default(&save_iuser);
|
||||
if (iuser == nullptr) {
|
||||
BKE_imageuser_default(&save_iuser);
|
||||
iuser = &save_iuser;
|
||||
iuser->scene = opts->scene;
|
||||
}
|
||||
|
||||
bool colorspace_changed = false;
|
||||
|
||||
|
@ -614,12 +626,6 @@ bool BKE_image_save(
|
|||
opts->filepath);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For saving a tiled image we need an iuser, so use a local one if there isn't already one.
|
||||
*/
|
||||
if (iuser == nullptr) {
|
||||
iuser = &save_iuser;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save images */
|
||||
|
|
|
@ -1722,13 +1722,12 @@ static ImageSaveData *image_save_as_init(bContext *C, wmOperator *op)
|
|||
Image *image = image_from_context(C);
|
||||
ImageUser *iuser = image_user_from_context(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const bool save_as_render = (image->source == IMA_SRC_VIEWER);
|
||||
|
||||
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, save_as_render)) {
|
||||
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;
|
||||
|
@ -1995,7 +1994,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false, false)) {
|
||||
if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false)) {
|
||||
BKE_image_save_options_free(&opts);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
@ -2267,7 +2266,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
|
|||
if (image_has_valid_path(ima)) {
|
||||
ImageSaveOptions opts;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
if (!BKE_image_save_options_init(&opts, bmain, scene, 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;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
# include "BKE_image.h"
|
||||
# include "BKE_image_format.h"
|
||||
# include "BKE_image_save.h"
|
||||
# include "BKE_main.h"
|
||||
# include "BKE_scene.h"
|
||||
# include <errno.h>
|
||||
|
@ -50,77 +51,40 @@ static void rna_ImagePackedFile_save(ImagePackedFile *imapf, Main *bmain, Report
|
|||
static void rna_Image_save_render(
|
||||
Image *image, bContext *C, ReportList *reports, const char *path, Scene *scene)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
if (scene == NULL) {
|
||||
scene = CTX_data_scene(C);
|
||||
}
|
||||
|
||||
if (scene) {
|
||||
ImageUser iuser = {NULL};
|
||||
void *lock;
|
||||
ImageSaveOptions opts;
|
||||
|
||||
iuser.scene = scene;
|
||||
if (BKE_image_save_options_init(&opts, bmain, scene, image, NULL, false)) {
|
||||
opts.save_copy = true;
|
||||
opts.save_as_render = true;
|
||||
STRNCPY(opts.filepath, path);
|
||||
|
||||
ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
|
||||
|
||||
if (ibuf == NULL) {
|
||||
BKE_report(reports, RPT_ERROR, "Could not acquire buffer from image");
|
||||
if (!BKE_image_save(reports, bmain, image, NULL, &opts)) {
|
||||
BKE_reportf(
|
||||
reports, RPT_ERROR, "Image '%s' could not be saved to '%s'", image->id.name + 2, path);
|
||||
}
|
||||
else {
|
||||
ImBuf *write_ibuf;
|
||||
|
||||
ImageFormatData image_format;
|
||||
BKE_image_format_init_for_write(&image_format, scene, NULL);
|
||||
|
||||
write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &image_format);
|
||||
|
||||
write_ibuf->planes = image_format.planes;
|
||||
write_ibuf->dither = scene->r.dither_intensity;
|
||||
|
||||
if (!BKE_imbuf_write(write_ibuf, path, &image_format)) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Could not write image: %s, '%s'", strerror(errno), path);
|
||||
}
|
||||
|
||||
if (write_ibuf != ibuf) {
|
||||
IMB_freeImBuf(write_ibuf);
|
||||
}
|
||||
|
||||
BKE_image_format_free(&image_format);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(image, ibuf, lock);
|
||||
}
|
||||
else {
|
||||
BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters");
|
||||
BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
|
||||
}
|
||||
|
||||
BKE_image_save_options_free(&opts);
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, image);
|
||||
}
|
||||
|
||||
static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *reports)
|
||||
{
|
||||
void *lock;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ImageSaveOptions opts;
|
||||
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
|
||||
if (ibuf) {
|
||||
char filepath[FILE_MAX];
|
||||
BLI_strncpy(filepath, image->filepath, sizeof(filepath));
|
||||
BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &image->id));
|
||||
|
||||
/* NOTE: we purposefully ignore packed files here,
|
||||
* developers need to explicitly write them via 'packed_files' */
|
||||
|
||||
if (IMB_saveiff(ibuf, filepath, ibuf->flags)) {
|
||||
image->type = IMA_TYPE_IMAGE;
|
||||
|
||||
if (image->source == IMA_SRC_GENERATED) {
|
||||
image->source = IMA_SRC_FILE;
|
||||
}
|
||||
|
||||
IMB_colormanagement_colorspace_from_ibuf_ftype(&image->colorspace_settings, ibuf);
|
||||
|
||||
ibuf->userflags &= ~IB_BITMAPDIRTY;
|
||||
}
|
||||
else {
|
||||
if (BKE_image_save_options_init(&opts, bmain, scene, image, NULL, false)) {
|
||||
if (!BKE_image_save(reports, bmain, image, NULL, &opts)) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Image '%s' could not be saved to '%s'",
|
||||
|
@ -132,7 +96,8 @@ static void rna_Image_save(Image *image, Main *bmain, bContext *C, ReportList *r
|
|||
BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(image, ibuf, lock);
|
||||
BKE_image_save_options_free(&opts);
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, image);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue