Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/image.c')
-rw-r--r--source/blender/blenkernel/intern/image.c169
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;