diff options
author | Siddhartha Jejurkar <f20180617@goa.bits-pilani.ac.in> | 2021-12-17 16:01:32 +0300 |
---|---|---|
committer | Siddhartha Jejurkar <f20180617@goa.bits-pilani.ac.in> | 2021-12-17 16:01:32 +0300 |
commit | dbc41b30f88b96f7d8c6e995b17f5930eb55cc77 (patch) | |
tree | c6c495328443ea3621e5df2ef483b0e0dd504496 /source/blender/blenkernel/intern/image.c | |
parent | 99a2af76d10e05a18987be5d554ada197b1ca086 (diff) | |
parent | 7c9e4099854a4fc8eab4db97173c1aacd25f9e08 (diff) |
Merge branch 'master' into soc-2021-uv-edge-select-supportsoc-2021-uv-edge-select-support
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r-- | source/blender/blenkernel/intern/image.c | 169 |
1 files changed, 93 insertions, 76 deletions
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index c0efc246567..f43cf00a310 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -75,6 +75,7 @@ #include "BLT_translation.h" +#include "BKE_bpath.h" #include "BKE_colortools.h" #include "BKE_global.h" #include "BKE_icons.h" @@ -252,6 +253,34 @@ static void image_foreach_cache(ID *id, } } +static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data) +{ + Image *ima = (Image *)id; + const eBPathForeachFlag flag = bpath_data->flag; + + if (BKE_image_has_packedfile(ima) && (flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) { + return; + } + /* Skip empty file paths, these are typically from generated images and + * don't make sense to add directories to until the image has been saved + * once to give it a meaningful value. */ + /* TODO re-assess whether this behavior is desired in the new generic code context. */ + if (!ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED) || + ima->filepath[0] == '\0') { + return; + } + + if (BKE_bpath_foreach_path_fixed_process(bpath_data, ima->filepath)) { + if (flag & BKE_BPATH_FOREACH_PATH_RELOAD_EDITED) { + if (!BKE_image_has_packedfile(ima) && + /* Image may have been painted onto (and not saved, T44543). */ + !BKE_image_is_dirty(ima)) { + BKE_image_signal(bpath_data->bmain, ima, NULL, IMA_SIGNAL_RELOAD); + } + } + } +} + static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address) { Image *ima = (Image *)id; @@ -369,6 +398,7 @@ IDTypeInfo IDType_ID_IM = { .name_plural = "images", .translation_context = BLT_I18NCONTEXT_ID_IMAGE, .flags = IDTYPE_FLAGS_NO_ANIMDATA | IDTYPE_FLAGS_APPEND_IS_REUSABLE, + .asset_type_info = NULL, .init_data = image_init_data, .copy_data = image_copy_data, @@ -376,6 +406,7 @@ IDTypeInfo IDType_ID_IM = { .make_local = NULL, .foreach_id = NULL, .foreach_cache = image_foreach_cache, + .foreach_path = image_foreach_path, .owner_get = NULL, .blend_write = image_blend_write, @@ -518,10 +549,6 @@ static void image_free_anims(Image *ima) } } -/** - * Simply free the image data from memory, - * on display the image can load again (except for render buffers). - */ void BKE_image_free_buffers_ex(Image *ima, bool do_lock) { if (do_lock) { @@ -548,7 +575,6 @@ void BKE_image_free_buffers(Image *ima) BKE_image_free_buffers_ex(ima, false); } -/** Free (or release) any data used by this image (does not free the image itself). */ void BKE_image_free_data(Image *ima) { image_free_data(&ima->id); @@ -675,9 +701,11 @@ void BKE_image_merge(Main *bmain, Image *dest, Image *source) } } -/* NOTE: We could be clever and scale all imbuf's but since some are mipmaps its not so simple. */ bool BKE_image_scale(Image *image, int width, int height) { + /* NOTE: We could be clever and scale all imbuf's + * but since some are mipmaps its not so simple. */ + ImBuf *ibuf; void *lock; @@ -776,9 +804,6 @@ int BKE_image_get_tile_from_pos(struct Image *ima, return tile_number; } -/** - * Return the tile_number for the closest UDIM tile. - */ int BKE_image_find_nearest_tile(const Image *image, const float co[2]) { const float co_floor[2] = {floorf(co[0]), floorf(co[1])}; @@ -877,17 +902,13 @@ Image *BKE_image_load(Main *bmain, const char *filepath) return ima; } -/* checks if image was already loaded, then returns same image */ -/* otherwise creates new. */ -/* does not load ibuf itself */ -/* pass on optional frame for #name images */ Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists) { Image *ima; char str[FILE_MAX], strtest[FILE_MAX]; STRNCPY(str, filepath); - BLI_path_abs(str, bmain->name); + BLI_path_abs(str, bmain->filepath); /* first search an identical filepath */ for (ima = bmain->images.first; ima; ima = ima->id.next) { @@ -1027,7 +1048,6 @@ static ImBuf *add_ibuf_size(unsigned int width, return ibuf; } -/* adds new image block, creates ImBuf and initializes color */ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, @@ -1088,11 +1108,6 @@ Image *BKE_image_add_generated(Main *bmain, return ima; } -/** - * Create an image from ibuf. The refcount of ibuf is increased, - * caller should take care to drop its reference by calling - * #IMB_freeImBuf if needed. - */ Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name) { /* on save, type is changed to FILE in editsima.c */ @@ -1144,7 +1159,6 @@ static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, const char *filepath return true; } -/* Pack image to memory. */ bool BKE_image_memorypack(Image *ima) { bool ok = true; @@ -1377,7 +1391,6 @@ static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void (except_frame != IMA_INDEX_ENTRY(ibuf->index)); } -/* except_frame is weak, only works for seqs without offset... */ void BKE_image_free_anim_ibufs(Image *ima, int except_frame) { BLI_mutex_lock(ima->runtime.cache_mutex); @@ -1639,8 +1652,6 @@ char BKE_imtype_valid_depths(const char imtype) } } -/* string is from command line --render-format arg, keep in sync with - * creator_args.c help info */ char BKE_imtype_from_arg(const char *imtype_arg) { if (STREQ(imtype_arg, "TGA")) { @@ -2051,9 +2062,10 @@ static void stampdata( time_t t; if (scene->r.stamp & R_STAMP_FILENAME) { + const char *blendfile_path = BKE_main_blendfile_path_from_global(); SNPRINTF(stamp_data->file, do_prefix ? "File %s" : "%s", - G.relbase_valid ? BKE_main_blendfile_path_from_global() : "<untitled>"); + (blendfile_path[0] != '\0') ? blendfile_path : "<untitled>"); } else { stamp_data->file[0] = '\0'; @@ -2744,8 +2756,6 @@ static const char *stamp_metadata_fields[] = { NULL, }; -/* Check whether the given metadata field name translates to a known field of - * a stamp. */ bool BKE_stamp_is_known_field(const char *field_name) { int i = 0; @@ -2907,8 +2917,6 @@ bool BKE_imbuf_alpha_test(ImBuf *ibuf) return false; } -/* NOTE: imf->planes is ignored here, its assumed the image channels - * are already set */ void BKE_imbuf_write_prepare(ImBuf *ibuf, const ImageFormatData *imf) { char imtype = imf->imtype; @@ -3085,8 +3093,6 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, const ImageFormatData *imf) return ok; } -/* same as BKE_imbuf_write() but crappy workaround not to permanently modify - * _some_, values in the imbuf */ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, const bool save_copy) { ImBuf ibuf_back = *ibuf; @@ -3185,7 +3191,6 @@ struct anim *openanim_noload(const char *name, return anim; } -/* used by sequencer too */ struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE]) { struct anim *anim; @@ -3231,8 +3236,6 @@ struct anim *openanim(const char *name, int flags, int streamindex, char colorsp * -> comes from packedfile or filename or generated */ -/* forces existence of 1 Image for renderout or nodes, returns Image */ -/* name is only for default, when making new one */ Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name) { Image *ima; @@ -3273,7 +3276,6 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima) } } -/* Reset the image cache and views when the Viewer Nodes views don't match the scene views */ void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser) { bool do_reset; @@ -3928,7 +3930,6 @@ bool BKE_image_fill_tile(struct Image *ima, /* if layer or pass changes, we need an index for the imbufs list */ /* note it is called for rendered results, but it doesn't use the index! */ -/* and because rendered results use fake layer/passes, don't correct for wrong indices here */ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser) { RenderLayer *rl; @@ -3983,7 +3984,6 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser) /* if layer or pass changes, we need an index for the imbufs list */ /* note it is called for rendered results, but it doesn't use the index! */ -/* and because rendered results use fake layer/passes, don't correct for wrong indices here */ bool BKE_image_is_multilayer(Image *ima) { if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) { @@ -4233,13 +4233,16 @@ static int image_num_files(Image *ima) return BLI_listbase_count(&ima->views); } -static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, const int view_id) +static ImBuf *load_sequence_single( + Image *ima, ImageUser *iuser, int frame, const int view_id, bool *r_cache_ibuf) { struct ImBuf *ibuf; char name[FILE_MAX]; int flag; ImageUser iuser_t = {0}; + *r_cache_ibuf = true; + ima->lastframe = frame; if (iuser) { @@ -4279,6 +4282,9 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); ibuf = NULL; + /* NULL ibuf in the cache means the image failed to load. However for multilayer we load + * pixels into RenderResult instead and intentionally leave ibuf NULL. */ + *r_cache_ibuf = false; } } else { @@ -4299,17 +4305,21 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, const int totfiles = image_num_files(ima); if (!is_multiview) { - ibuf = load_sequence_single(ima, iuser, frame, 0); - image_assign_ibuf(ima, ibuf, 0, entry); + bool put_in_cache; + ibuf = load_sequence_single(ima, iuser, frame, 0, &put_in_cache); + if (put_in_cache) { + image_assign_ibuf(ima, ibuf, 0, entry); + } } else { const int totviews = BLI_listbase_count(&ima->views); struct ImBuf **ibuf_arr; ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); + bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image View Put In Cache"); for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i); + ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, cache_ibuf_arr + i); } if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) { @@ -4320,7 +4330,9 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)]; for (int i = 0; i < totviews; i++) { - image_assign_ibuf(ima, ibuf_arr[i], i, entry); + if (cache_ibuf_arr[i]) { + image_assign_ibuf(ima, ibuf_arr[i], i, entry); + } } /* "remove" the others (decrease their refcount) */ @@ -4332,6 +4344,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, /* cleanup */ MEM_freeN(ibuf_arr); + MEM_freeN(cache_ibuf_arr); } return ibuf; @@ -4493,13 +4506,19 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) return ibuf; } -static ImBuf *load_image_single( - Image *ima, ImageUser *iuser, int cfra, const int view_id, const bool has_packed) +static ImBuf *load_image_single(Image *ima, + ImageUser *iuser, + int cfra, + const int view_id, + const bool has_packed, + bool *r_cache_ibuf) { char filepath[FILE_MAX]; struct ImBuf *ibuf = NULL; int flag; + *r_cache_ibuf = true; + /* is there a PackedFile with this image ? */ if (has_packed) { ImagePackedFile *imapf; @@ -4550,6 +4569,9 @@ static ImBuf *load_image_single( ima->type = IMA_TYPE_MULTILAYER; IMB_freeImBuf(ibuf); ibuf = NULL; + /* NULL ibuf in the cache means the image failed to load. However for multilayer we load + * pixels into RenderResult instead and intentionally leave ibuf NULL. */ + *r_cache_ibuf = false; } } else @@ -4594,8 +4616,11 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } if (!is_multiview) { - ibuf = load_image_single(ima, iuser, cfra, 0, has_packed); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + bool put_in_cache; + ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &put_in_cache); + if (put_in_cache) { + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + } } else { struct ImBuf **ibuf_arr; @@ -4603,9 +4628,10 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) BLI_assert(totviews > 0); ibuf_arr = MEM_callocN(sizeof(ImBuf *) * totviews, "Image Views Imbufs"); + bool *cache_ibuf_arr = MEM_mallocN(sizeof(bool) * totviews, "Image Views Put In Cache"); for (int i = 0; i < totfiles; i++) { - ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed); + ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, cache_ibuf_arr + i); } /* multi-views/multi-layers OpenEXR files directly populate ima, and return NULL ibuf... */ @@ -4619,7 +4645,9 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) ibuf = ibuf_arr[i]; for (i = 0; i < totviews; i++) { - image_assign_ibuf(ima, ibuf_arr[i], i, 0); + if (cache_ibuf_arr[i]) { + image_assign_ibuf(ima, ibuf_arr[i], i, 0); + } } /* "remove" the others (decrease their refcount) */ @@ -4631,6 +4659,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) /* cleanup */ MEM_freeN(ibuf_arr); + MEM_freeN(cache_ibuf_arr); } return ibuf; @@ -4986,9 +5015,10 @@ BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser) return true; } -/* Checks optional ImageUser and verifies/creates ImBuf. +/** + * Checks optional #ImageUser and verifies/creates #ImBuf. * - * not thread-safe, so callee should worry about thread locks + * \warning Not thread-safe, so callee should worry about thread locks. */ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { @@ -5109,15 +5139,15 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) return ibuf; } -/* return image buffer for given image and user - * - * - will lock render result if image type is render result and lock is not NULL - * - will return NULL if image type if render or composite result and lock is NULL - * - * references the result, BKE_image_release_ibuf should be used to de-reference - */ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock) { + /* NOTE: same as #image_acquire_ibuf, but can be used to retrieve images being rendered in + * a thread safe way, always call both acquire and release. */ + + if (ima == NULL) { + return NULL; + } + ImBuf *ibuf; BLI_mutex_lock(ima->runtime.cache_mutex); @@ -5149,7 +5179,6 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) } } -/* checks whether there's an image buffer for given image and user */ bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser) { ImBuf *ibuf; @@ -5657,19 +5686,16 @@ bool BKE_image_has_filepath(Image *ima) return ima->filepath[0] != '\0'; } -/* Checks the image buffer changes with time (not keyframed values). */ bool BKE_image_is_animated(Image *image) { return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE); } -/* Checks whether the image consists of multiple buffers. */ bool BKE_image_has_multiple_ibufs(Image *image) { return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED); } -/* Image modifications */ bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable) { bool is_dirty = false; @@ -5745,8 +5771,12 @@ bool BKE_image_has_loaded_ibuf(Image *image) struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache); while (!IMB_moviecacheIter_done(iter)) { - has_loaded_ibuf = true; - break; + ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter); + if (ibuf != NULL) { + has_loaded_ibuf = true; + break; + } + IMB_moviecacheIter_step(iter); } IMB_moviecacheIter_free(iter); } @@ -5755,10 +5785,6 @@ bool BKE_image_has_loaded_ibuf(Image *image) return has_loaded_ibuf; } -/** - * References the result, #BKE_image_release_ibuf is to be called to de-reference. - * Use lock=NULL when calling #BKE_image_release_ibuf(). - */ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) { ImBuf *ibuf = NULL; @@ -5783,15 +5809,6 @@ ImBuf *BKE_image_get_ibuf_with_name(Image *image, const char *name) return ibuf; } -/** - * References the result, #BKE_image_release_ibuf is to be called to de-reference. - * Use lock=NULL when calling #BKE_image_release_ibuf(). - * - * TODO(sergey): This is actually "get first item from the cache", which is - * not so much predictable. But using first loaded image buffer - * was also malicious logic and all the areas which uses this - * function are to be re-considered. - */ ImBuf *BKE_image_get_first_ibuf(Image *image) { ImBuf *ibuf = NULL; |