Blender  V3.3
source/blender/blenkernel/intern/image.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <cctype>
9 #include <cmath>
10 #include <cstdio>
11 #include <cstring>
12 #include <ctime>
13 #include <fcntl.h>
14 #ifndef WIN32
15 # include <unistd.h>
16 #else
17 # include <io.h>
18 #endif
19 
20 #include <regex>
21 #include <string>
22 
23 #include "BLI_array.hh"
24 
25 #include "CLG_log.h"
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "IMB_colormanagement.h"
30 #include "IMB_imbuf.h"
31 #include "IMB_imbuf_types.h"
32 #include "IMB_metadata.h"
33 #include "IMB_moviecache.h"
34 #include "IMB_openexr.h"
35 
36 /* Allow using deprecated functionality for .blend file I/O. */
37 #define DNA_DEPRECATED_ALLOW
38 
39 #include "DNA_brush_types.h"
40 #include "DNA_camera_types.h"
41 #include "DNA_defaults.h"
42 #include "DNA_light_types.h"
43 #include "DNA_material_types.h"
44 #include "DNA_mesh_types.h"
45 #include "DNA_meshdata_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_packedFile_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_sequence_types.h"
50 #include "DNA_simulation_types.h"
51 #include "DNA_world_types.h"
52 
53 #include "BLI_blenlib.h"
54 #include "BLI_math_vector.h"
55 #include "BLI_mempool.h"
56 #include "BLI_system.h"
57 #include "BLI_task.h"
58 #include "BLI_threads.h"
59 #include "BLI_timecode.h" /* For stamp time-code format. */
60 #include "BLI_utildefines.h"
61 
62 #include "BLT_translation.h"
63 
64 #include "BKE_bpath.h"
65 #include "BKE_colortools.h"
66 #include "BKE_global.h"
67 #include "BKE_icons.h"
68 #include "BKE_idtype.h"
69 #include "BKE_image.h"
70 #include "BKE_image_format.h"
71 #include "BKE_lib_id.h"
72 #include "BKE_main.h"
73 #include "BKE_node.h"
74 #include "BKE_node_tree_update.h"
75 #include "BKE_packedFile.h"
76 #include "BKE_report.h"
77 #include "BKE_scene.h"
78 #include "BKE_workspace.h"
79 
80 #include "BLF_api.h"
81 
82 #include "PIL_time.h"
83 
84 #include "RE_pipeline.h"
85 
86 #include "SEQ_utils.h" /* SEQ_get_topmost_sequence() */
87 
88 #include "GPU_material.h"
89 #include "GPU_texture.h"
90 
91 #include "BLI_sys_types.h" /* for intptr_t support */
92 
93 #include "DEG_depsgraph.h"
94 #include "DEG_depsgraph_query.h"
95 
96 #include "BLO_read_write.h"
97 
98 /* for image user iteration */
99 #include "DNA_node_types.h"
100 #include "DNA_screen_types.h"
101 #include "DNA_space_types.h"
102 #include "DNA_view3d_types.h"
103 
104 using blender::Array;
105 
106 static CLG_LogRef LOG = {"bke.image"};
107 
108 static void image_init(Image *ima, short source, short type);
109 static void image_free_packedfiles(Image *ima);
110 static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src);
111 
112 /* -------------------------------------------------------------------- */
117 static void image_runtime_reset(struct Image *image)
118 {
119  memset(&image->runtime, 0, sizeof(image->runtime));
120  image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
121  BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
122 }
123 
126 {
127  image->runtime.cache_mutex = MEM_mallocN(sizeof(ThreadMutex), "image runtime cache_mutex");
128  BLI_mutex_init(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
129 
130  image->runtime.partial_update_register = nullptr;
131  image->runtime.partial_update_user = nullptr;
132 }
133 
134 static void image_runtime_free_data(struct Image *image)
135 {
136  BLI_mutex_end(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
137  MEM_freeN(image->runtime.cache_mutex);
138  image->runtime.cache_mutex = nullptr;
139 
140  if (image->runtime.partial_update_user != nullptr) {
141  BKE_image_partial_update_free(image->runtime.partial_update_user);
142  image->runtime.partial_update_user = nullptr;
143  }
145 }
146 
147 static void image_init_data(ID *id)
148 {
149  Image *image = (Image *)id;
150 
151  if (image != nullptr) {
153  }
154 }
155 
156 static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
157 {
158  Image *image_dst = (Image *)id_dst;
159  const Image *image_src = (const Image *)id_src;
160 
162  &image_src->colorspace_settings);
163 
164  copy_image_packedfiles(&image_dst->packedfiles, &image_src->packedfiles);
165 
166  image_dst->stereo3d_format = static_cast<Stereo3dFormat *>(
167  MEM_dupallocN(image_src->stereo3d_format));
168  BLI_duplicatelist(&image_dst->views, &image_src->views);
169 
170  /* Cleanup stuff that cannot be copied. */
171  image_dst->cache = nullptr;
172  image_dst->rr = nullptr;
173 
174  BLI_duplicatelist(&image_dst->renderslots, &image_src->renderslots);
175  LISTBASE_FOREACH (RenderSlot *, slot, &image_dst->renderslots) {
176  slot->render = nullptr;
177  }
178 
179  BLI_listbase_clear(&image_dst->anims);
180 
181  BLI_duplicatelist(&image_dst->tiles, &image_src->tiles);
182 
183  for (int eye = 0; eye < 2; eye++) {
184  for (int i = 0; i < TEXTARGET_COUNT; i++) {
185  image_dst->gputexture[i][eye] = nullptr;
186  }
187  }
188 
189  if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
190  BKE_previewimg_id_copy(&image_dst->id, &image_src->id);
191  }
192  else {
193  image_dst->preview = nullptr;
194  }
195 
196  image_runtime_reset_on_copy(image_dst);
197 }
198 
199 static void image_free_data(ID *id)
200 {
201  Image *image = (Image *)id;
202 
203  /* Also frees animations (#Image.anims list). */
205 
207 
208  LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) {
209  if (slot->render) {
210  RE_FreeRenderResult(slot->render);
211  slot->render = nullptr;
212  }
213  }
214  BLI_freelistN(&image->renderslots);
215 
217  MEM_SAFE_FREE(image->stereo3d_format);
218 
220  BKE_previewimg_free(&image->preview);
221 
222  BLI_freelistN(&image->tiles);
223 
225 }
226 
227 static void image_foreach_cache(ID *id,
228  IDTypeForeachCacheFunctionCallback function_callback,
229  void *user_data)
230 {
231  Image *image = (Image *)id;
232  IDCacheKey key;
233  key.id_session_uuid = id->session_uuid;
234  key.offset_in_ID = offsetof(Image, cache);
235  function_callback(id, &key, (void **)&image->cache, 0, user_data);
236 
237  auto gputexture_offset = [image](int target, int eye) {
238  constexpr size_t base_offset = offsetof(Image, gputexture);
239  struct GPUTexture **first = &image->gputexture[0][0];
240  const size_t array_offset = sizeof(*first) * (&image->gputexture[target][eye] - first);
241  return base_offset + array_offset;
242  };
243 
244  for (int eye = 0; eye < 2; eye++) {
245  for (int a = 0; a < TEXTARGET_COUNT; a++) {
246  GPUTexture *texture = image->gputexture[a][eye];
247  if (texture == nullptr) {
248  continue;
249  }
250  key.offset_in_ID = gputexture_offset(a, eye);
251  function_callback(id, &key, (void **)&image->gputexture[a][eye], 0, user_data);
252  }
253  }
254 
255  key.offset_in_ID = offsetof(Image, rr);
256  function_callback(id, &key, (void **)&image->rr, 0, user_data);
257 
258  LISTBASE_FOREACH (RenderSlot *, slot, &image->renderslots) {
259  key.offset_in_ID = (size_t)BLI_ghashutil_strhash_p(slot->name);
260  function_callback(id, &key, (void **)&slot->render, 0, user_data);
261  }
262 }
263 
264 static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data)
265 {
266  Image *ima = (Image *)id;
267  const eBPathForeachFlag flag = bpath_data->flag;
268 
270  return;
271  }
272  /* Skip empty file paths, these are typically from generated images and
273  * don't make sense to add directories to until the image has been saved
274  * once to give it a meaningful value. */
275  /* TODO re-assess whether this behavior is desired in the new generic code context. */
277  ima->filepath[0] == '\0') {
278  return;
279  }
280 
281  /* If this is a tiled image, and we're asked to resolve the tokens in the virtual
282  * filepath, use the first tile to generate a concrete path for use during processing. */
283  bool result = false;
284  if (ima->source == IMA_SRC_TILED && (flag & BKE_BPATH_FOREACH_PATH_RESOLVE_TOKEN) != 0) {
285  char temp_path[FILE_MAX], orig_file[FILE_MAXFILE];
286  BLI_strncpy(temp_path, ima->filepath, sizeof(temp_path));
287  BLI_split_file_part(temp_path, orig_file, sizeof(orig_file));
288 
289  eUDIM_TILE_FORMAT tile_format;
290  char *udim_pattern = BKE_image_get_tile_strformat(temp_path, &tile_format);
292  temp_path, udim_pattern, tile_format, ((ImageTile *)ima->tiles.first)->tile_number);
293  MEM_SAFE_FREE(udim_pattern);
294 
295  result = BKE_bpath_foreach_path_fixed_process(bpath_data, temp_path);
296  if (result) {
297  /* Put the filepath back together using the new directory and the original file name. */
298  char new_dir[FILE_MAXDIR];
299  BLI_split_dir_part(temp_path, new_dir, sizeof(new_dir));
300  BLI_join_dirfile(ima->filepath, sizeof(ima->filepath), new_dir, orig_file);
301  }
302  }
303  else {
305  }
306 
307  if (result) {
309  if (!BKE_image_has_packedfile(ima) &&
310  /* Image may have been painted onto (and not saved, T44543). */
311  !BKE_image_is_dirty(ima)) {
312  BKE_image_signal(bpath_data->bmain, ima, nullptr, IMA_SIGNAL_RELOAD);
313  }
314  }
315  }
316 }
317 
318 static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address)
319 {
320  Image *ima = (Image *)id;
321  const bool is_undo = BLO_write_is_undo(writer);
322 
323  /* Clear all data that isn't read to reduce false detection of changed image during memfile undo.
324  */
325  ima->lastused = 0;
326  ima->cache = nullptr;
327  ima->gpuflag = 0;
328  BLI_listbase_clear(&ima->anims);
329  ima->runtime.partial_update_register = nullptr;
330  ima->runtime.partial_update_user = nullptr;
331  for (int i = 0; i < 3; i++) {
332  for (int j = 0; j < 2; j++) {
333  ima->gputexture[i][j] = nullptr;
334  }
335  }
336 
337  ImagePackedFile *imapf;
338 
339  BLI_assert(ima->packedfile == nullptr);
340  if (!is_undo) {
341  /* Do not store packed files in case this is a library override ID. */
342  if (ID_IS_OVERRIDE_LIBRARY(ima)) {
344  }
345  else {
346  /* Some trickery to keep forward compatibility of packed images. */
347  if (ima->packedfiles.first != nullptr) {
348  imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first);
349  ima->packedfile = imapf->packedfile;
350  }
351  }
352  }
353 
354  /* write LibData */
355  BLO_write_id_struct(writer, Image, id_address, &ima->id);
356  BKE_id_blend_write(writer, &ima->id);
357 
358  for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf;
359  imapf = imapf->next) {
360  BLO_write_struct(writer, ImagePackedFile, imapf);
361  BKE_packedfile_blend_write(writer, imapf->packedfile);
362  }
363 
364  BKE_previewimg_blend_write(writer, ima->preview);
365 
366  LISTBASE_FOREACH (ImageView *, iv, &ima->views) {
367  BLO_write_struct(writer, ImageView, iv);
368  }
370 
371  BLO_write_struct_list(writer, ImageTile, &ima->tiles);
372 
373  ima->packedfile = nullptr;
374 
376 }
377 
378 static void image_blend_read_data(BlendDataReader *reader, ID *id)
379 {
380  Image *ima = (Image *)id;
381  BLO_read_list(reader, &ima->tiles);
382 
383  BLO_read_list(reader, &(ima->renderslots));
384  if (!BLO_read_data_is_undo(reader)) {
385  /* We reset this last render slot index only when actually reading a file, not for undo. */
386  ima->last_render_slot = ima->render_slot;
387  }
388 
389  BLO_read_list(reader, &(ima->views));
390  BLO_read_list(reader, &(ima->packedfiles));
391 
392  if (ima->packedfiles.first) {
393  LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
394  BKE_packedfile_blend_read(reader, &imapf->packedfile);
395  }
396  ima->packedfile = nullptr;
397  }
398  else {
399  BKE_packedfile_blend_read(reader, &ima->packedfile);
400  }
401 
402  BLI_listbase_clear(&ima->anims);
403  BLO_read_data_address(reader, &ima->preview);
404  BKE_previewimg_blend_read(reader, ima->preview);
405  BLO_read_data_address(reader, &ima->stereo3d_format);
406 
407  ima->lastused = 0;
408  ima->gpuflag = 0;
409 
410  image_runtime_reset(ima);
411 }
412 
413 static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id)
414 {
415  Image *ima = (Image *)id;
416  /* Images have some kind of 'main' cache, when null we should also clear all others. */
417  /* Needs to be done *after* cache pointers are restored (call to
418  * `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in
419  * lib_link... */
420  if (ima->cache == nullptr) {
422  }
423 }
424 
426 {
427  IDTypeInfo info{};
428  info.id_code = ID_IM;
429  info.id_filter = FILTER_ID_IM;
430  info.main_listbase_index = INDEX_ID_IM;
431  info.struct_size = sizeof(Image);
432  info.name = "Image";
433  info.name_plural = "images";
434  info.translation_context = BLT_I18NCONTEXT_ID_IMAGE;
436  info.asset_type_info = nullptr;
437 
438  info.init_data = image_init_data;
439  info.copy_data = image_copy_data;
440  info.free_data = image_free_data;
441  info.make_local = nullptr;
442  info.foreach_id = nullptr;
443  info.foreach_cache = image_foreach_cache;
444  info.foreach_path = image_foreach_path;
445  info.owner_get = nullptr;
446 
447  info.blend_write = image_blend_write;
448  info.blend_read_data = image_blend_read_data;
449  info.blend_read_lib = image_blend_read_lib;
450  info.blend_read_expand = nullptr;
451 
452  info.blend_read_undo_preserve = nullptr;
453 
454  info.lib_override_apply_post = nullptr;
455  return info;
456 }
458 
459 /* prototypes */
460 static int image_num_viewfiles(Image *ima);
462  Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence);
463 static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock);
464 static void image_update_views_format(Image *ima, ImageUser *iuser);
465 static void image_add_view(Image *ima, const char *viewname, const char *filepath);
466 
467 /* max int, to indicate we don't store sequences in ibuf */
468 #define IMA_NO_INDEX 0x7FEFEFEF
469 
470 /* quick lookup: supports 1 million entries, thousand passes */
471 #define IMA_MAKE_INDEX(entry, index) (((entry) << 10) + (index))
472 #define IMA_INDEX_ENTRY(index) ((index) >> 10)
473 #if 0
474 # define IMA_INDEX_PASS(index) (index & ~1023)
475 #endif
476 
479 /* -------------------------------------------------------------------- */
484  int index;
485 };
486 
487 static unsigned int imagecache_hashhash(const void *key_v)
488 {
489  const ImageCacheKey *key = static_cast<const ImageCacheKey *>(key_v);
490  return key->index;
491 }
492 
493 static bool imagecache_hashcmp(const void *a_v, const void *b_v)
494 {
495  const ImageCacheKey *a = static_cast<const ImageCacheKey *>(a_v);
496  const ImageCacheKey *b = static_cast<const ImageCacheKey *>(b_v);
497 
498  return (a->index != b->index);
499 }
500 
501 static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
502 {
503  ImageCacheKey *key = static_cast<ImageCacheKey *>(userkey);
504 
505  *framenr = IMA_INDEX_ENTRY(key->index);
506  *proxy = IMB_PROXY_NONE;
507  *render_flags = 0;
508 }
509 
510 static void imagecache_put(Image *image, int index, ImBuf *ibuf)
511 {
512  ImageCacheKey key;
513 
514  if (image->cache == nullptr) {
515  // char cache_name[64];
516  // SNPRINTF(cache_name, "Image Datablock %s", image->id.name);
517 
518  image->cache = IMB_moviecache_create(
519  "Image Datablock Cache", sizeof(ImageCacheKey), imagecache_hashhash, imagecache_hashcmp);
521  }
522 
523  key.index = index;
524 
525  IMB_moviecache_put(image->cache, &key, ibuf);
526 }
527 
528 static void imagecache_remove(Image *image, int index)
529 {
530  if (image->cache == nullptr) {
531  return;
532  }
533 
534  ImageCacheKey key;
535  key.index = index;
536  IMB_moviecache_remove(image->cache, &key);
537 }
538 
539 static struct ImBuf *imagecache_get(Image *image, int index, bool *r_is_cached_empty)
540 {
541  if (image->cache) {
542  ImageCacheKey key;
543  key.index = index;
544  return IMB_moviecache_get(image->cache, &key, r_is_cached_empty);
545  }
546 
547  return nullptr;
548 }
549 
552 /* -------------------------------------------------------------------- */
557 {
558  if (image->cache) {
559  IMB_moviecache_free(image->cache);
560  image->cache = nullptr;
561  }
562 }
563 
564 static void image_free_packedfiles(Image *ima)
565 {
566  while (ima->packedfiles.last) {
567  ImagePackedFile *imapf = static_cast<ImagePackedFile *>(ima->packedfiles.last);
568  if (imapf->packedfile) {
570  }
571  BLI_remlink(&ima->packedfiles, imapf);
572  MEM_freeN(imapf);
573  }
574 }
575 
577 {
579 }
580 
582 {
583  BLI_freelistN(&image->views);
584 }
585 
586 static void image_free_anims(Image *ima)
587 {
588  while (ima->anims.last) {
589  ImageAnim *ia = static_cast<ImageAnim *>(ima->anims.last);
590  if (ia->anim) {
591  IMB_free_anim(ia->anim);
592  ia->anim = nullptr;
593  }
594  BLI_remlink(&ima->anims, ia);
595  MEM_freeN(ia);
596  }
597 }
598 
599 void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
600 {
601  if (do_lock) {
602  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
603  }
605 
606  image_free_anims(ima);
607 
608  if (ima->rr) {
609  RE_FreeRenderResult(ima->rr);
610  ima->rr = nullptr;
611  }
612 
614 
615  if (do_lock) {
616  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
617  }
618 }
619 
621 {
622  BKE_image_free_buffers_ex(ima, false);
623 }
624 
626 {
627  image_free_data(&ima->id);
628 }
629 
630 /* only image block itself */
631 static void image_init(Image *ima, short source, short type)
632 {
634 
636 
637  ima->source = source;
638  ima->type = type;
639 
640  if (source == IMA_SRC_VIEWER) {
641  ima->flag |= IMA_VIEW_AS_RENDER;
642  }
643 
644  ImageTile *tile = MEM_cnew<ImageTile>("Image Tiles");
645  tile->tile_number = 1001;
646  BLI_addtail(&ima->tiles, tile);
647 
648  if (type == IMA_TYPE_R_RESULT) {
649  for (int i = 0; i < 8; i++) {
650  BKE_image_add_renderslot(ima, nullptr);
651  }
652  }
653 
654  image_runtime_reset(ima);
655 
657  ima->stereo3d_format = MEM_cnew<Stereo3dFormat>("Image Stereo Format");
658 }
659 
660 static Image *image_alloc(Main *bmain, const char *name, short source, short type)
661 {
662  Image *ima;
663 
664  ima = static_cast<Image *>(BKE_libblock_alloc(bmain, ID_IM, name, 0));
665  if (ima) {
666  image_init(ima, source, type);
667  }
668 
669  return ima;
670 }
671 
680  int index,
681  int entry,
682  bool *r_is_cached_empty)
683 {
684  if (index != IMA_NO_INDEX) {
685  index = IMA_MAKE_INDEX(entry, index);
686  }
687 
688  return imagecache_get(ima, index, r_is_cached_empty);
689 }
690 
691 static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int entry)
692 {
693  if (index != IMA_NO_INDEX) {
694  index = IMA_MAKE_INDEX(entry, index);
695  }
696 
697  imagecache_put(ima, index, ibuf);
698 }
699 
700 static void image_remove_ibuf(Image *ima, int index, int entry)
701 {
702  if (index != IMA_NO_INDEX) {
703  index = IMA_MAKE_INDEX(entry, index);
704  }
705  imagecache_remove(ima, index);
706 }
707 
708 static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
709 {
710  const ImagePackedFile *imapf_src;
711 
712  BLI_listbase_clear(lb_dst);
713  for (imapf_src = static_cast<const ImagePackedFile *>(lb_src->first); imapf_src;
714  imapf_src = imapf_src->next) {
715  ImagePackedFile *imapf_dst = static_cast<ImagePackedFile *>(
716  MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)"));
717 
718  imapf_dst->view = imapf_src->view;
719  imapf_dst->tile_number = imapf_src->tile_number;
720  STRNCPY(imapf_dst->filepath, imapf_src->filepath);
721 
722  if (imapf_src->packedfile) {
723  imapf_dst->packedfile = BKE_packedfile_duplicate(imapf_src->packedfile);
724  }
725 
726  BLI_addtail(lb_dst, imapf_dst);
727  }
728 }
729 
730 void BKE_image_merge(Main *bmain, Image *dest, Image *source)
731 {
732  /* sanity check */
733  if (dest && source && dest != source) {
734  BLI_mutex_lock(static_cast<ThreadMutex *>(source->runtime.cache_mutex));
735  BLI_mutex_lock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex));
736 
737  if (source->cache != nullptr) {
738  struct MovieCacheIter *iter;
739  iter = IMB_moviecacheIter_new(source->cache);
740  while (!IMB_moviecacheIter_done(iter)) {
741  ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
742  ImageCacheKey *key = static_cast<ImageCacheKey *>(IMB_moviecacheIter_getUserKey(iter));
743  imagecache_put(dest, key->index, ibuf);
745  }
747  }
748 
749  BLI_mutex_unlock(static_cast<ThreadMutex *>(dest->runtime.cache_mutex));
750  BLI_mutex_unlock(static_cast<ThreadMutex *>(source->runtime.cache_mutex));
751 
752  BKE_id_free(bmain, source);
753  }
754 }
755 
757 {
758  /* NOTE: We could be clever and scale all imbuf's
759  * but since some are mipmaps its not so simple. */
760 
761  ImBuf *ibuf;
762  void *lock;
763 
764  ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock);
765 
766  if (ibuf) {
767  IMB_scaleImBuf(ibuf, width, height);
769  }
770 
772 
773  return (ibuf != nullptr);
774 }
775 
777 {
778  for (int eye = 0; eye < 2; eye++) {
779  for (int i = 0; i < TEXTARGET_COUNT; i++) {
780  if (ima->gputexture[i][eye] != nullptr) {
781  return true;
782  }
783  }
784  }
785  return false;
786 }
787 
788 static int image_get_tile_number_from_iuser(const Image *ima, const ImageUser *iuser)
789 {
790  BLI_assert(ima != nullptr && ima->tiles.first);
791  ImageTile *tile = static_cast<ImageTile *>(ima->tiles.first);
792  return (iuser && iuser->tile) ? iuser->tile : tile->tile_number;
793 }
794 
795 ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
796 {
797  if (ima == nullptr) {
798  return nullptr;
799  }
800 
801  /* Tiles 0 and 1001 are a special case and refer to the first tile, typically
802  * coming from non-UDIM-aware code. */
803  if (ELEM(tile_number, 0, 1001)) {
804  return static_cast<ImageTile *>(ima->tiles.first);
805  }
806 
807  /* Must have a tiled image and a valid tile number at this point. */
808  if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
809  return nullptr;
810  }
811 
812  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
813  if (tile->tile_number == tile_number) {
814  return tile;
815  }
816  }
817 
818  return nullptr;
819 }
820 
822 {
823  return BKE_image_get_tile(ima, image_get_tile_number_from_iuser(ima, iuser));
824 }
825 
826 int BKE_image_get_tile_from_pos(Image *ima, const float uv[2], float r_uv[2], float r_ofs[2])
827 {
828  float local_ofs[2];
829  if (r_ofs == nullptr) {
830  r_ofs = local_ofs;
831  }
832 
833  copy_v2_v2(r_uv, uv);
834  zero_v2(r_ofs);
835 
836  if ((ima->source != IMA_SRC_TILED) || uv[0] < 0.0f || uv[1] < 0.0f || uv[0] >= 10.0f) {
837  return 0;
838  }
839 
840  int ix = (int)uv[0];
841  int iy = (int)uv[1];
842  int tile_number = 1001 + 10 * iy + ix;
843 
844  if (BKE_image_get_tile(ima, tile_number) == nullptr) {
845  return 0;
846  }
847  r_ofs[0] = ix;
848  r_ofs[1] = iy;
849  sub_v2_v2(r_uv, r_ofs);
850 
851  return tile_number;
852 }
853 
854 void BKE_image_get_tile_uv(const Image *ima, const int tile_number, float r_uv[2])
855 {
856  if (ima->source != IMA_SRC_TILED) {
857  zero_v2(r_uv);
858  }
859  else {
860  const int tile_index = tile_number - 1001;
861  r_uv[0] = static_cast<float>(tile_index % 10);
862  r_uv[1] = static_cast<float>(tile_index / 10);
863  }
864 }
865 
867  const float co[2],
868  float r_uv_offset[2])
869 {
870  /* Distance squared to the closest UDIM tile. */
871  float dist_best_sq = FLT_MAX;
872  float uv_offset_best[2] = {0, 0};
873  int tile_number_best = -1;
874 
875  const float co_offset[2] = {co[0] - 0.5f, co[1] - 0.5f};
876 
877  LISTBASE_FOREACH (const ImageTile *, tile, &image->tiles) {
878  float uv_offset[2];
879  BKE_image_get_tile_uv(image, tile->tile_number, uv_offset);
880 
881  /* Distance squared between co[2] and center of UDIM tile. */
882  const float dist_sq = len_squared_v2v2(uv_offset, co_offset);
883 
884  if (dist_sq < dist_best_sq) {
885  dist_best_sq = dist_sq;
886  tile_number_best = tile->tile_number;
887  copy_v2_v2(uv_offset_best, uv_offset);
888 
889  if (dist_best_sq < 0.5f * 0.5f) {
890  break; /* No other tile can be closer. */
891  }
892  }
893  }
894  if (tile_number_best != -1) {
895  copy_v2_v2(r_uv_offset, uv_offset_best);
896  }
897  return tile_number_best;
898 }
899 
900 int BKE_image_find_nearest_tile(const struct Image *image, const float co[2])
901 {
902  float uv_offset_dummy[2];
903  return BKE_image_find_nearest_tile_with_offset(image, co, uv_offset_dummy);
904 }
905 
907 {
908  ImBuf *ibuf;
909  char name[FILE_MAX];
910 
911  BKE_image_user_file_path(nullptr, ima, name);
912 
913  /* will set input color space to image format default's */
915 
916  if (ibuf) {
917  if (ibuf->flags & IB_alphamode_premul) {
919  }
920  else if (ibuf->flags & IB_alphamode_channel_packed) {
922  }
923  else if (ibuf->flags & IB_alphamode_ignore) {
925  }
926  else {
928  }
929 
930  IMB_freeImBuf(ibuf);
931  }
932 }
933 
934 char BKE_image_alpha_mode_from_extension_ex(const char *filepath)
935 {
936  if (BLI_path_extension_check_n(filepath, ".exr", ".cin", ".dpx", ".hdr", nullptr)) {
937  return IMA_ALPHA_PREMUL;
938  }
939 
940  return IMA_ALPHA_STRAIGHT;
941 }
942 
944 {
945  image->alpha_mode = BKE_image_alpha_mode_from_extension_ex(image->filepath);
946 }
947 
948 Image *BKE_image_load(Main *bmain, const char *filepath)
949 {
950  Image *ima;
951  int file;
952  char str[FILE_MAX];
953 
954  STRNCPY(str, filepath);
956 
957  /* exists? */
958  file = BLI_open(str, O_BINARY | O_RDONLY, 0);
959  if (file == -1) {
961  return nullptr;
962  }
963  }
964  else {
965  close(file);
966  }
967 
968  ima = image_alloc(bmain, BLI_path_basename(filepath), IMA_SRC_FILE, IMA_TYPE_IMAGE);
969  STRNCPY(ima->filepath, filepath);
970 
972  ima->source = IMA_SRC_MOVIE;
973  }
974 
976 
977  return ima;
978 }
979 
980 Image *BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
981 {
982  Image *ima;
983  char str[FILE_MAX], strtest[FILE_MAX];
984 
985  STRNCPY(str, filepath);
986  BLI_path_abs(str, bmain->filepath);
987 
988  /* first search an identical filepath */
989  for (ima = static_cast<Image *>(bmain->images.first); ima;
990  ima = static_cast<Image *>(ima->id.next)) {
992  STRNCPY(strtest, ima->filepath);
993  BLI_path_abs(strtest, ID_BLEND_PATH(bmain, &ima->id));
994 
995  if (BLI_path_cmp(strtest, str) == 0) {
996  if ((BKE_image_has_anim(ima) == false) || (ima->id.us == 0)) {
997  id_us_plus(&ima->id); /* officially should not, it doesn't link here! */
998  if (r_exists) {
999  *r_exists = true;
1000  }
1001  return ima;
1002  }
1003  }
1004  }
1005  }
1006 
1007  if (r_exists) {
1008  *r_exists = false;
1009  }
1010  return BKE_image_load(bmain, filepath);
1011 }
1012 
1013 Image *BKE_image_load_exists(Main *bmain, const char *filepath)
1014 {
1015  return BKE_image_load_exists_ex(bmain, filepath, nullptr);
1016 }
1017 
1019  short gen_type;
1022  unsigned char *rect;
1023  float *rect_float;
1024  float fill_color[4];
1025 };
1026 
1027 static void image_buf_fill_isolated(void *usersata_v)
1028 {
1029  ImageFillData *usersata = static_cast<ImageFillData *>(usersata_v);
1030 
1031  const short gen_type = usersata->gen_type;
1032  const uint width = usersata->width;
1033  const uint height = usersata->height;
1034 
1035  unsigned char *rect = usersata->rect;
1036  float *rect_float = usersata->rect_float;
1037 
1038  switch (gen_type) {
1039  case IMA_GENTYPE_GRID:
1040  BKE_image_buf_fill_checker(rect, rect_float, width, height);
1041  break;
1043  BKE_image_buf_fill_checker_color(rect, rect_float, width, height);
1044  break;
1045  default:
1046  BKE_image_buf_fill_color(rect, rect_float, width, height, usersata->fill_color);
1047  break;
1048  }
1049 }
1050 
1051 static ImBuf *add_ibuf_size(unsigned int width,
1052  unsigned int height,
1053  const char *name,
1054  int depth,
1055  int floatbuf,
1056  short gen_type,
1057  const float color[4],
1058  ColorManagedColorspaceSettings *colorspace_settings)
1059 {
1060  ImBuf *ibuf;
1061  unsigned char *rect = nullptr;
1062  float *rect_float = nullptr;
1063  float fill_color[4];
1064 
1065  if (floatbuf) {
1066  ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat);
1067 
1068  if (colorspace_settings->name[0] == '\0') {
1069  const char *colorspace = IMB_colormanagement_role_colorspace_name_get(
1071 
1072  STRNCPY(colorspace_settings->name, colorspace);
1073  }
1074 
1075  if (ibuf != nullptr) {
1076  rect_float = ibuf->rect_float;
1077  IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name);
1078  }
1079 
1080  if (IMB_colormanagement_space_name_is_data(colorspace_settings->name)) {
1081  copy_v4_v4(fill_color, color);
1082  }
1083  else {
1084  /* The input color here should ideally be linear already, but for now
1085  * we just convert and postpone breaking the API for later. */
1086  srgb_to_linearrgb_v4(fill_color, color);
1087  }
1088  }
1089  else {
1090  ibuf = IMB_allocImBuf(width, height, depth, IB_rect);
1091 
1092  if (colorspace_settings->name[0] == '\0') {
1093  const char *colorspace = IMB_colormanagement_role_colorspace_name_get(
1095 
1096  STRNCPY(colorspace_settings->name, colorspace);
1097  }
1098 
1099  if (ibuf != nullptr) {
1100  rect = (unsigned char *)ibuf->rect;
1101  IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name);
1102  }
1103 
1104  copy_v4_v4(fill_color, color);
1105  }
1106 
1107  if (!ibuf) {
1108  return nullptr;
1109  }
1110 
1111  STRNCPY(ibuf->name, name);
1112 
1114 
1115  data.gen_type = gen_type;
1116  data.width = width;
1117  data.height = height;
1118  data.rect = rect;
1119  data.rect_float = rect_float;
1120  copy_v4_v4(data.fill_color, fill_color);
1121 
1123 
1124  return ibuf;
1125 }
1126 
1128  unsigned int width,
1129  unsigned int height,
1130  const char *name,
1131  int depth,
1132  int floatbuf,
1133  short gen_type,
1134  const float color[4],
1135  const bool stereo3d,
1136  const bool is_data,
1137  const bool tiled)
1138 {
1139  /* Saving the image changes it's #Image.source to #IMA_SRC_FILE (leave as generated here). */
1140  Image *ima;
1141  if (tiled) {
1142  ima = image_alloc(bmain, name, IMA_SRC_TILED, IMA_TYPE_IMAGE);
1143  }
1144  else {
1145  ima = image_alloc(bmain, name, IMA_SRC_GENERATED, IMA_TYPE_UV_TEST);
1146  }
1147  if (ima == nullptr) {
1148  return nullptr;
1149  }
1150 
1151  int view_id;
1152  const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
1153 
1154  /* NOTE: leave `ima->filepath` unset,
1155  * setting it to a dummy value may write to an invalid file-path. */
1156  ima->gen_x = width;
1157  ima->gen_y = height;
1158  ima->gen_type = gen_type;
1159  ima->gen_flag |= (floatbuf ? IMA_GEN_FLOAT : 0);
1160  ima->gen_depth = depth;
1161  copy_v4_v4(ima->gen_color, color);
1162 
1163  if (is_data) {
1166  }
1167 
1168  for (view_id = 0; view_id < 2; view_id++) {
1169  ImBuf *ibuf;
1170  ibuf = add_ibuf_size(
1171  width, height, ima->filepath, depth, floatbuf, gen_type, color, &ima->colorspace_settings);
1172  int index = tiled ? 0 : IMA_NO_INDEX;
1173  int entry = tiled ? 1001 : 0;
1174  image_assign_ibuf(ima, ibuf, stereo3d ? view_id : index, entry);
1175 
1176  /* #image_assign_ibuf puts buffer to the cache, which increments user counter. */
1177  IMB_freeImBuf(ibuf);
1178  if (!stereo3d) {
1179  break;
1180  }
1181 
1182  image_add_view(ima, names[view_id], "");
1183  }
1184 
1185  return ima;
1186 }
1187 
1188 static void image_colorspace_from_imbuf(Image *image, const ImBuf *ibuf)
1189 {
1190  const char *colorspace_name = NULL;
1191 
1192  if (ibuf->rect_float) {
1193  if (ibuf->float_colorspace) {
1195  }
1196  else {
1198  }
1199  }
1200 
1201  if (ibuf->rect && !colorspace_name) {
1202  if (ibuf->rect_colorspace) {
1204  }
1205  else {
1207  }
1208  }
1209 
1210  if (colorspace_name) {
1211  STRNCPY(image->colorspace_settings.name, colorspace_name);
1212  }
1213 }
1214 
1215 Image *BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
1216 {
1217  if (name == nullptr) {
1218  name = BLI_path_basename(ibuf->name);
1219  }
1220 
1221  /* When the image buffer has valid path create a new image with "file" source and copy the path
1222  * from the image buffer.
1223  * Otherwise create "generated" image, avoiding invalid configuration with an empty file path. */
1224  const eImageSource source = ibuf->name[0] != '\0' ? IMA_SRC_FILE : IMA_SRC_GENERATED;
1225 
1226  Image *ima = image_alloc(bmain, name, source, IMA_TYPE_IMAGE);
1227 
1228  if (!ima) {
1229  return nullptr;
1230  }
1231 
1232  BKE_image_replace_imbuf(ima, ibuf);
1233 
1234  return ima;
1235 }
1236 
1238 {
1239  BLI_assert(image->type == IMA_TYPE_IMAGE &&
1241 
1243 
1246 
1247  /* Keep generated image type flags consistent with the image buffer. */
1248  if (image->source == IMA_SRC_GENERATED) {
1249  if (ibuf->rect_float) {
1250  image->gen_flag |= IMA_GEN_FLOAT;
1251  }
1252  else {
1253  image->gen_flag &= ~IMA_GEN_FLOAT;
1254  }
1255 
1256  image->gen_x = ibuf->x;
1257  image->gen_y = ibuf->y;
1258  }
1259 
1260  /* Consider image dirty since its content can not be re-created unless the image is explicitly
1261  * saved. */
1262  BKE_image_mark_dirty(image, ibuf);
1263 }
1264 
1267  Image *ima, ImBuf *ibuf, int view, int tile_number, const char *filepath)
1268 {
1269  ibuf->ftype = (ibuf->rect_float) ? IMB_FTYPE_OPENEXR : IMB_FTYPE_PNG;
1270 
1271  IMB_saveiff(ibuf, filepath, IB_rect | IB_mem);
1272 
1273  if (ibuf->encodedbuffer == nullptr) {
1274  CLOG_STR_ERROR(&LOG, "memory save for pack error");
1275  IMB_freeImBuf(ibuf);
1277  return false;
1278  }
1279 
1280  ImagePackedFile *imapf;
1281  PackedFile *pf = MEM_cnew<PackedFile>("PackedFile");
1282 
1283  pf->data = ibuf->encodedbuffer;
1284  pf->size = ibuf->encodedsize;
1285 
1286  imapf = static_cast<ImagePackedFile *>(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile"));
1287  STRNCPY(imapf->filepath, filepath);
1288  imapf->packedfile = pf;
1289  imapf->view = view;
1290  imapf->tile_number = tile_number;
1291  BLI_addtail(&ima->packedfiles, imapf);
1292 
1293  ibuf->encodedbuffer = nullptr;
1294  ibuf->encodedsize = 0;
1295  ibuf->userflags &= ~IB_BITMAPDIRTY;
1296 
1297  return true;
1298 }
1299 
1301 {
1302  bool ok = true;
1303 
1305 
1306  const int tot_viewfiles = image_num_viewfiles(ima);
1307  const bool is_tiled = (ima->source == IMA_SRC_TILED);
1308  const bool is_multiview = BKE_image_is_multiview(ima);
1309 
1310  ImageUser iuser{};
1311  BKE_imageuser_default(&iuser);
1312  char tiled_filepath[FILE_MAX];
1313 
1314  for (int view = 0; view < tot_viewfiles; view++) {
1315  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
1316  int index = (is_multiview || is_tiled) ? view : IMA_NO_INDEX;
1317  int entry = is_tiled ? tile->tile_number : 0;
1318  ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr);
1319  if (!ibuf) {
1320  ok = false;
1321  break;
1322  }
1323 
1324  const char *filepath = ibuf->name;
1325  if (is_tiled) {
1326  iuser.tile = tile->tile_number;
1327  BKE_image_user_file_path(&iuser, ima, tiled_filepath);
1328  filepath = tiled_filepath;
1329  }
1330  else if (is_multiview) {
1331  ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, view));
1332  /* if the image was a R_IMF_VIEWS_STEREO_3D we force _L, _R suffices */
1333  if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
1334  const char *suffix[2] = {STEREO_LEFT_SUFFIX, STEREO_RIGHT_SUFFIX};
1335  BLI_path_suffix(iv->filepath, FILE_MAX, suffix[view], "");
1336  }
1337  filepath = iv->filepath;
1338  }
1339 
1340  ok = ok && image_memorypack_imbuf(ima, ibuf, view, tile->tile_number, filepath);
1341  IMB_freeImBuf(ibuf);
1342  }
1343  }
1344 
1345  if (is_multiview) {
1347  }
1348 
1349  if (ok && ima->source == IMA_SRC_GENERATED) {
1350  ima->source = IMA_SRC_FILE;
1351  ima->type = IMA_TYPE_IMAGE;
1352  }
1353 
1354  return ok;
1355 }
1356 
1357 void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
1358 {
1359  const int tot_viewfiles = image_num_viewfiles(ima);
1360 
1361  ImageUser iuser{};
1362  BKE_imageuser_default(&iuser);
1363  for (int view = 0; view < tot_viewfiles; view++) {
1364  iuser.view = view;
1365  LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
1366  iuser.tile = tile->tile_number;
1367  char filepath[FILE_MAX];
1368  BKE_image_user_file_path(&iuser, ima, filepath);
1369 
1370  ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
1371  MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
1372  BLI_addtail(&ima->packedfiles, imapf);
1373 
1374  imapf->packedfile = BKE_packedfile_new(reports, filepath, basepath);
1375  imapf->view = view;
1376  imapf->tile_number = tile->tile_number;
1377  if (imapf->packedfile) {
1378  STRNCPY(imapf->filepath, filepath);
1379  }
1380  else {
1381  BLI_freelinkN(&ima->packedfiles, imapf);
1382  }
1383  }
1384  }
1385 }
1386 
1388  Image *ima,
1389  char *data,
1390  const size_t data_len)
1391 {
1392  const int tot_viewfiles = image_num_viewfiles(ima);
1393 
1394  if (tot_viewfiles != 1) {
1395  BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
1396  }
1397  else if (ima->source == IMA_SRC_TILED) {
1398  BKE_report(reports, RPT_ERROR, "Cannot pack tiled images from raw data currently...");
1399  }
1400  else {
1401  ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
1402  MEM_mallocN(sizeof(ImagePackedFile), __func__));
1403  BLI_addtail(&ima->packedfiles, imapf);
1404  imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len);
1405  imapf->view = 0;
1406  imapf->tile_number = 1001;
1407  STRNCPY(imapf->filepath, ima->filepath);
1408  }
1409 }
1410 
1412 {
1414 }
1415 
1417 {
1418  uintptr_t size = 0;
1419 
1420  /* viewers have memory depending on other rules, has no valid rect pointer */
1421  if (image->source == IMA_SRC_VIEWER) {
1422  return 0;
1423  }
1424 
1425  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
1426 
1427  if (image->cache != nullptr) {
1428  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
1429 
1430  while (!IMB_moviecacheIter_done(iter)) {
1431  ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
1433  if (ibuf == nullptr) {
1434  continue;
1435  }
1436  ImBuf *ibufm;
1437  int level;
1438 
1439  if (ibuf->rect) {
1440  size += MEM_allocN_len(ibuf->rect);
1441  }
1442  if (ibuf->rect_float) {
1443  size += MEM_allocN_len(ibuf->rect_float);
1444  }
1445 
1446  for (level = 0; level < IMB_MIPMAP_LEVELS; level++) {
1447  ibufm = ibuf->mipmap[level];
1448  if (ibufm) {
1449  if (ibufm->rect) {
1450  size += MEM_allocN_len(ibufm->rect);
1451  }
1452  if (ibufm->rect_float) {
1453  size += MEM_allocN_len(ibufm->rect_float);
1454  }
1455  }
1456  }
1457  }
1459  }
1460 
1461  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
1462 
1463  return size;
1464 }
1465 
1467 {
1468  Image *ima;
1469  uintptr_t size, totsize = 0;
1470 
1471  for (ima = static_cast<Image *>(bmain->images.first); ima;
1472  ima = static_cast<Image *>(ima->id.next)) {
1473  totsize += image_mem_size(ima);
1474  }
1475 
1476  printf("\ntotal image memory len: %.3f MB\n", (double)totsize / (double)(1024 * 1024));
1477 
1478  for (ima = static_cast<Image *>(bmain->images.first); ima;
1479  ima = static_cast<Image *>(ima->id.next)) {
1480  size = image_mem_size(ima);
1481 
1482  if (size) {
1483  printf("%s len: %.3f MB\n", ima->id.name + 2, (double)size / (double)(1024 * 1024));
1484  }
1485  }
1486 }
1487 
1488 static bool imagecache_check_dirty(ImBuf *ibuf, void *UNUSED(userkey), void *UNUSED(userdata))
1489 {
1490  if (ibuf == nullptr) {
1491  return false;
1492  }
1493  return (ibuf->userflags & IB_BITMAPDIRTY) == 0;
1494 }
1495 
1497 {
1498 #undef CHECK_FREED_SIZE
1499 
1500  Tex *tex;
1501  Image *ima;
1502 #ifdef CHECK_FREED_SIZE
1503  uintptr_t tot_freed_size = 0;
1504 #endif
1505 
1506  for (ima = static_cast<Image *>(bmain->images.first); ima;
1507  ima = static_cast<Image *>(ima->id.next)) {
1508  ima->id.tag &= ~LIB_TAG_DOIT;
1509  }
1510 
1511  for (tex = static_cast<Tex *>(bmain->textures.first); tex;
1512  tex = static_cast<Tex *>(tex->id.next)) {
1513  if (tex->ima) {
1514  tex->ima->id.tag |= LIB_TAG_DOIT;
1515  }
1516  }
1517 
1518  for (ima = static_cast<Image *>(bmain->images.first); ima;
1519  ima = static_cast<Image *>(ima->id.next)) {
1520  if (ima->cache && (ima->id.tag & LIB_TAG_DOIT)) {
1521 #ifdef CHECK_FREED_SIZE
1522  uintptr_t old_size = image_mem_size(ima);
1523 #endif
1524 
1526 
1527 #ifdef CHECK_FREED_SIZE
1528  tot_freed_size += old_size - image_mem_size(ima);
1529 #endif
1530  }
1531  }
1532 #ifdef CHECK_FREED_SIZE
1533  printf("%s: freed total %lu MB\n", __func__, tot_freed_size / (1024 * 1024));
1534 #endif
1535 }
1536 
1537 static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void *userdata)
1538 {
1539  if (ibuf == nullptr) {
1540  return true;
1541  }
1542  int except_frame = *(int *)userdata;
1543  return (ibuf->userflags & IB_BITMAPDIRTY) == 0 && (ibuf->index != IMA_NO_INDEX) &&
1544  (except_frame != IMA_INDEX_ENTRY(ibuf->index));
1545 }
1546 
1547 void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
1548 {
1549  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
1550  if (ima->cache != nullptr) {
1552  }
1553  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
1554 }
1555 
1556 void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
1557 {
1558  Image *ima;
1559 
1560  for (ima = static_cast<Image *>(bmain->images.first); ima;
1561  ima = static_cast<Image *>(ima->id.next)) {
1562  if (BKE_image_is_animated(ima)) {
1563  BKE_image_free_anim_ibufs(ima, cfra);
1564  }
1565  }
1566 }
1567 
1570 /* -------------------------------------------------------------------- */
1574 #define STAMP_NAME_SIZE ((MAX_ID_NAME - 2) + 16)
1575 /* could allow access externally - 512 is for long names,
1576  * STAMP_NAME_SIZE is for id names, allowing them some room for description */
1579  /* TODO(sergey): Think of better size here, maybe dynamically allocated even. */
1580  char key[512];
1581  char *value;
1582  /* TODO(sergey): Support non-string values. */
1583 };
1584 
1585 struct StampData {
1586  char file[512];
1587  char note[512];
1588  char date[512];
1589  char marker[512];
1590  char time[512];
1591  char frame[512];
1592  char frame_range[512];
1599  char hostname[512];
1600 
1601  /* Custom fields are used to put extra meta information header from render
1602  * engine to the result image.
1603  *
1604  * NOTE: This fields are not stamped onto the image. At least for now.
1605  */
1607 };
1608 #undef STAMP_NAME_SIZE
1609 
1614 static void stampdata(
1615  const Scene *scene, Object *camera, StampData *stamp_data, int do_prefix, bool use_dynamic)
1616 {
1617  char text[256];
1618  struct tm *tl;
1619  time_t t;
1620 
1621  if (scene->r.stamp & R_STAMP_FILENAME) {
1622  const char *blendfile_path = BKE_main_blendfile_path_from_global();
1623  SNPRINTF(stamp_data->file,
1624  do_prefix ? "File %s" : "%s",
1625  (blendfile_path[0] != '\0') ? blendfile_path : "<untitled>");
1626  }
1627  else {
1628  stamp_data->file[0] = '\0';
1629  }
1630 
1631  if (scene->r.stamp & R_STAMP_NOTE) {
1632  /* Never do prefix for Note */
1633  SNPRINTF(stamp_data->note, "%s", scene->r.stamp_udata);
1634  }
1635  else {
1636  stamp_data->note[0] = '\0';
1637  }
1638 
1639  if (scene->r.stamp & R_STAMP_DATE) {
1640  t = time(nullptr);
1641  tl = localtime(&t);
1642  SNPRINTF(text,
1643  "%04d/%02d/%02d %02d:%02d:%02d",
1644  tl->tm_year + 1900,
1645  tl->tm_mon + 1,
1646  tl->tm_mday,
1647  tl->tm_hour,
1648  tl->tm_min,
1649  tl->tm_sec);
1650  SNPRINTF(stamp_data->date, do_prefix ? "Date %s" : "%s", text);
1651  }
1652  else {
1653  stamp_data->date[0] = '\0';
1654  }
1655 
1656  if (use_dynamic && scene->r.stamp & R_STAMP_MARKER) {
1657  const char *name = BKE_scene_find_last_marker_name(scene, scene->r.cfra);
1658 
1659  if (name) {
1660  STRNCPY(text, name);
1661  }
1662  else {
1663  STRNCPY(text, "<none>");
1664  }
1665 
1666  SNPRINTF(stamp_data->marker, do_prefix ? "Marker %s" : "%s", text);
1667  }
1668  else {
1669  stamp_data->marker[0] = '\0';
1670  }
1671 
1672  if (use_dynamic && scene->r.stamp & R_STAMP_TIME) {
1673  const short timecode_style = USER_TIMECODE_SMPTE_FULL;
1675  text, sizeof(text), 0, FRA2TIME(scene->r.cfra), FPS, timecode_style);
1676  SNPRINTF(stamp_data->time, do_prefix ? "Timecode %s" : "%s", text);
1677  }
1678  else {
1679  stamp_data->time[0] = '\0';
1680  }
1681 
1682  if (use_dynamic && scene->r.stamp & R_STAMP_FRAME) {
1683  char fmtstr[32];
1684  int digits = 1;
1685 
1686  if (scene->r.efra > 9) {
1687  digits = integer_digits_i(scene->r.efra);
1688  }
1689 
1690  SNPRINTF(fmtstr, do_prefix ? "Frame %%0%di" : "%%0%di", digits);
1691  SNPRINTF(stamp_data->frame, fmtstr, scene->r.cfra);
1692  }
1693  else {
1694  stamp_data->frame[0] = '\0';
1695  }
1696 
1697  if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
1698  SNPRINTF(stamp_data->frame_range,
1699  do_prefix ? "Frame Range %d:%d" : "%d:%d",
1700  scene->r.sfra,
1701  scene->r.efra);
1702  }
1703  else {
1704  stamp_data->frame_range[0] = '\0';
1705  }
1706 
1707  if (use_dynamic && scene->r.stamp & R_STAMP_CAMERA) {
1708  SNPRINTF(stamp_data->camera,
1709  do_prefix ? "Camera %s" : "%s",
1710  camera ? camera->id.name + 2 : "<none>");
1711  }
1712  else {
1713  stamp_data->camera[0] = '\0';
1714  }
1715 
1716  if (use_dynamic && scene->r.stamp & R_STAMP_CAMERALENS) {
1717  if (camera && camera->type == OB_CAMERA) {
1718  SNPRINTF(text, "%.2f", ((Camera *)camera->data)->lens);
1719  }
1720  else {
1721  STRNCPY(text, "<none>");
1722  }
1723 
1724  SNPRINTF(stamp_data->cameralens, do_prefix ? "Lens %s" : "%s", text);
1725  }
1726  else {
1727  stamp_data->cameralens[0] = '\0';
1728  }
1729 
1730  if (scene->r.stamp & R_STAMP_SCENE) {
1731  SNPRINTF(stamp_data->scene, do_prefix ? "Scene %s" : "%s", scene->id.name + 2);
1732  }
1733  else {
1734  stamp_data->scene[0] = '\0';
1735  }
1736 
1737  if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) {
1739 
1740  if (seq) {
1741  STRNCPY(text, seq->name + 2);
1742  }
1743  else {
1744  STRNCPY(text, "<none>");
1745  }
1746 
1747  SNPRINTF(stamp_data->strip, do_prefix ? "Strip %s" : "%s", text);
1748  }
1749  else {
1750  stamp_data->strip[0] = '\0';
1751  }
1752 
1753  {
1755  RenderStats *stats = re ? RE_GetStats(re) : nullptr;
1756 
1757  if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
1758  BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime);
1759 
1760  SNPRINTF(stamp_data->rendertime, do_prefix ? "RenderTime %s" : "%s", text);
1761  }
1762  else {
1763  stamp_data->rendertime[0] = '\0';
1764  }
1765 
1766  if (use_dynamic && stats && (scene->r.stamp & R_STAMP_MEMORY)) {
1767  SNPRINTF(stamp_data->memory, do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak);
1768  }
1769  else {
1770  stamp_data->memory[0] = '\0';
1771  }
1772  }
1773  if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
1774  SNPRINTF(stamp_data->frame_range,
1775  do_prefix ? "Frame Range %d:%d" : "%d:%d",
1776  scene->r.sfra,
1777  scene->r.efra);
1778  }
1779  else {
1780  stamp_data->frame_range[0] = '\0';
1781  }
1782 
1783  if (scene->r.stamp & R_STAMP_HOSTNAME) {
1784  char hostname[500]; /* sizeof(stamp_data->hostname) minus some bytes for a label. */
1785  BLI_hostname_get(hostname, sizeof(hostname));
1786  SNPRINTF(stamp_data->hostname, do_prefix ? "Hostname %s" : "%s", hostname);
1787  }
1788  else {
1789  stamp_data->hostname[0] = '\0';
1790  }
1791 }
1792 
1793 static void stampdata_from_template(StampData *stamp_data,
1794  const Scene *scene,
1795  const StampData *stamp_data_template,
1796  bool do_prefix)
1797 {
1798  if (scene->r.stamp & R_STAMP_FILENAME) {
1799  SNPRINTF(stamp_data->file, do_prefix ? "File %s" : "%s", stamp_data_template->file);
1800  }
1801  else {
1802  stamp_data->file[0] = '\0';
1803  }
1804  if (scene->r.stamp & R_STAMP_NOTE) {
1805  STRNCPY(stamp_data->note, stamp_data_template->note);
1806  }
1807  else {
1808  stamp_data->note[0] = '\0';
1809  }
1810  if (scene->r.stamp & R_STAMP_DATE) {
1811  SNPRINTF(stamp_data->date, do_prefix ? "Date %s" : "%s", stamp_data_template->date);
1812  }
1813  else {
1814  stamp_data->date[0] = '\0';
1815  }
1816  if (scene->r.stamp & R_STAMP_MARKER) {
1817  SNPRINTF(stamp_data->marker, do_prefix ? "Marker %s" : "%s", stamp_data_template->marker);
1818  }
1819  else {
1820  stamp_data->marker[0] = '\0';
1821  }
1822  if (scene->r.stamp & R_STAMP_TIME) {
1823  SNPRINTF(stamp_data->time, do_prefix ? "Timecode %s" : "%s", stamp_data_template->time);
1824  }
1825  else {
1826  stamp_data->time[0] = '\0';
1827  }
1828  if (scene->r.stamp & R_STAMP_FRAME) {
1829  SNPRINTF(stamp_data->frame, do_prefix ? "Frame %s" : "%s", stamp_data_template->frame);
1830  }
1831  else {
1832  stamp_data->frame[0] = '\0';
1833  }
1834  if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
1835  SNPRINTF(stamp_data->frame_range,
1836  do_prefix ? "Frame Range %s" : "%s",
1837  stamp_data_template->frame_range);
1838  }
1839  else {
1840  stamp_data->frame_range[0] = '\0';
1841  }
1842  if (scene->r.stamp & R_STAMP_CAMERA) {
1843  SNPRINTF(stamp_data->camera, do_prefix ? "Camera %s" : "%s", stamp_data_template->camera);
1844  }
1845  else {
1846  stamp_data->camera[0] = '\0';
1847  }
1848  if (scene->r.stamp & R_STAMP_CAMERALENS) {
1849  SNPRINTF(
1850  stamp_data->cameralens, do_prefix ? "Lens %s" : "%s", stamp_data_template->cameralens);
1851  }
1852  else {
1853  stamp_data->cameralens[0] = '\0';
1854  }
1855  if (scene->r.stamp & R_STAMP_SCENE) {
1856  SNPRINTF(stamp_data->scene, do_prefix ? "Scene %s" : "%s", stamp_data_template->scene);
1857  }
1858  else {
1859  stamp_data->scene[0] = '\0';
1860  }
1861  if (scene->r.stamp & R_STAMP_SEQSTRIP) {
1862  SNPRINTF(stamp_data->strip, do_prefix ? "Strip %s" : "%s", stamp_data_template->strip);
1863  }
1864  else {
1865  stamp_data->strip[0] = '\0';
1866  }
1867  if (scene->r.stamp & R_STAMP_RENDERTIME) {
1868  SNPRINTF(stamp_data->rendertime,
1869  do_prefix ? "RenderTime %s" : "%s",
1870  stamp_data_template->rendertime);
1871  }
1872  else {
1873  stamp_data->rendertime[0] = '\0';
1874  }
1875  if (scene->r.stamp & R_STAMP_MEMORY) {
1876  SNPRINTF(stamp_data->memory, do_prefix ? "Peak Memory %s" : "%s", stamp_data_template->memory);
1877  }
1878  else {
1879  stamp_data->memory[0] = '\0';
1880  }
1881  if (scene->r.stamp & R_STAMP_HOSTNAME) {
1882  SNPRINTF(
1883  stamp_data->hostname, do_prefix ? "Hostname %s" : "%s", stamp_data_template->hostname);
1884  }
1885  else {
1886  stamp_data->hostname[0] = '\0';
1887  }
1888 }
1889 
1891  Object *camera,
1892  const StampData *stamp_data_template,
1893  unsigned char *rect,
1894  float *rectf,
1895  int width,
1896  int height,
1897  int channels)
1898 {
1899  struct StampData stamp_data;
1900  int w, h, pad;
1901  int x, y, y_ofs;
1902  int h_fixed;
1903  const int mono = blf_mono_font_render; /* XXX */
1904  struct ColorManagedDisplay *display;
1905  const char *display_device;
1906 
1907  /* vars for calculating wordwrap */
1908  struct {
1909  struct ResultBLF info;
1910  rcti rect;
1911  } wrap;
1912 
1913  /* this could be an argument if we want to operate on non linear float imbuf's
1914  * for now though this is only used for renders which use scene settings */
1915 
1916 #define TEXT_SIZE_CHECK(str, w, h) \
1917  ((str[0]) && ((void)(h = h_fixed), (w = (int)BLF_width(mono, str, sizeof(str)))))
1918 
1919  /* must enable BLF_WORD_WRAP before using */
1920 #define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h) \
1921  ((str[0]) && (BLF_boundbox_ex(mono, str, sizeof(str), &wrap.rect, &wrap.info), \
1922  (void)(h = h_fixed * wrap.info.lines), \
1923  (w = BLI_rcti_size_x(&wrap.rect))))
1924 
1925 #define BUFF_MARGIN_X 2
1926 #define BUFF_MARGIN_Y 1
1927 
1928  if (!rect && !rectf) {
1929  return;
1930  }
1931 
1932  display_device = scene->display_settings.display_device;
1933  display = IMB_colormanagement_display_get_named(display_device);
1934 
1935  bool do_prefix = (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0;
1936  if (stamp_data_template == nullptr) {
1937  stampdata(scene, camera, &stamp_data, do_prefix, true);
1938  }
1939  else {
1940  stampdata_from_template(&stamp_data, scene, stamp_data_template, do_prefix);
1941  }
1942 
1943  /* TODO: do_versions. */
1944  if (scene->r.stamp_font_id < 8) {
1945  scene->r.stamp_font_id = 12;
1946  }
1947 
1948  /* set before return */
1949  BLF_size(mono, scene->r.stamp_font_id, 72);
1950  BLF_wordwrap(mono, width - (BUFF_MARGIN_X * 2));
1951 
1952  BLF_buffer(mono, rectf, rect, width, height, channels, display);
1953  BLF_buffer_col(mono, scene->r.fg_stamp);
1954  pad = BLF_width_max(mono);
1955 
1956  /* use 'h_fixed' rather than 'h', aligns better */
1957  h_fixed = BLF_height_max(mono);
1958  y_ofs = -BLF_descender(mono);
1959 
1960  x = 0;
1961  y = height;
1962 
1963  if (TEXT_SIZE_CHECK(stamp_data.file, w, h)) {
1964  /* Top left corner */
1965  y -= h;
1966 
1967  /* also a little of space to the background. */
1968  buf_rectfill_area(rect,
1969  rectf,
1970  width,
1971  height,
1972  scene->r.bg_stamp,
1973  display,
1974  x - BUFF_MARGIN_X,
1975  y - BUFF_MARGIN_Y,
1976  w + BUFF_MARGIN_X,
1977  y + h + BUFF_MARGIN_Y);
1978 
1979  /* and draw the text. */
1980  BLF_position(mono, x, y + y_ofs, 0.0);
1981  BLF_draw_buffer(mono, stamp_data.file, sizeof(stamp_data.file));
1982 
1983  /* the extra pixel for background. */
1984  y -= BUFF_MARGIN_Y * 2;
1985  }
1986 
1987  /* Top left corner, below File */
1988  if (TEXT_SIZE_CHECK(stamp_data.date, w, h)) {
1989  y -= h;
1990 
1991  /* and space for background. */
1992  buf_rectfill_area(rect,
1993  rectf,
1994  width,
1995  height,
1996  scene->r.bg_stamp,
1997  display,
1998  0,
1999  y - BUFF_MARGIN_Y,
2000  w + BUFF_MARGIN_X,
2001  y + h + BUFF_MARGIN_Y);
2002 
2003  BLF_position(mono, x, y + y_ofs, 0.0);
2004  BLF_draw_buffer(mono, stamp_data.date, sizeof(stamp_data.date));
2005 
2006  /* the extra pixel for background. */
2007  y -= BUFF_MARGIN_Y * 2;
2008  }
2009 
2010  /* Top left corner, below File, Date */
2011  if (TEXT_SIZE_CHECK(stamp_data.rendertime, w, h)) {
2012  y -= h;
2013 
2014  /* and space for background. */
2015  buf_rectfill_area(rect,
2016  rectf,
2017  width,
2018  height,
2019  scene->r.bg_stamp,
2020  display,
2021  0,
2022  y - BUFF_MARGIN_Y,
2023  w + BUFF_MARGIN_X,
2024  y + h + BUFF_MARGIN_Y);
2025 
2026  BLF_position(mono, x, y + y_ofs, 0.0);
2027  BLF_draw_buffer(mono, stamp_data.rendertime, sizeof(stamp_data.rendertime));
2028 
2029  /* the extra pixel for background. */
2030  y -= BUFF_MARGIN_Y * 2;
2031  }
2032 
2033  /* Top left corner, below File, Date, Render-time */
2034  if (TEXT_SIZE_CHECK(stamp_data.memory, w, h)) {
2035  y -= h;
2036 
2037  /* and space for background. */
2038  buf_rectfill_area(rect,
2039  rectf,
2040  width,
2041  height,
2042  scene->r.bg_stamp,
2043  display,
2044  0,
2045  y - BUFF_MARGIN_Y,
2046  w + BUFF_MARGIN_X,
2047  y + h + BUFF_MARGIN_Y);
2048 
2049  BLF_position(mono, x, y + y_ofs, 0.0);
2050  BLF_draw_buffer(mono, stamp_data.memory, sizeof(stamp_data.memory));
2051 
2052  /* the extra pixel for background. */
2053  y -= BUFF_MARGIN_Y * 2;
2054  }
2055 
2056  /* Top left corner, below: File, Date, Render-time, Memory. */
2057  if (TEXT_SIZE_CHECK(stamp_data.hostname, w, h)) {
2058  y -= h;
2059 
2060  /* and space for background. */
2061  buf_rectfill_area(rect,
2062  rectf,
2063  width,
2064  height,
2065  scene->r.bg_stamp,
2066  display,
2067  0,
2068  y - BUFF_MARGIN_Y,
2069  w + BUFF_MARGIN_X,
2070  y + h + BUFF_MARGIN_Y);
2071 
2072  BLF_position(mono, x, y + y_ofs, 0.0);
2073  BLF_draw_buffer(mono, stamp_data.hostname, sizeof(stamp_data.hostname));
2074 
2075  /* the extra pixel for background. */
2076  y -= BUFF_MARGIN_Y * 2;
2077  }
2078 
2079  /* Top left corner, below: File, Date, Memory, Render-time, Host-name. */
2080  BLF_enable(mono, BLF_WORD_WRAP);
2081  if (TEXT_SIZE_CHECK_WORD_WRAP(stamp_data.note, w, h)) {
2082  y -= h;
2083 
2084  /* and space for background. */
2085  buf_rectfill_area(rect,
2086  rectf,
2087  width,
2088  height,
2089  scene->r.bg_stamp,
2090  display,
2091  0,
2092  y - BUFF_MARGIN_Y,
2093  w + BUFF_MARGIN_X,
2094  y + h + BUFF_MARGIN_Y);
2095 
2096  BLF_position(mono, x, y + y_ofs + (h - h_fixed), 0.0);
2097  BLF_draw_buffer(mono, stamp_data.note, sizeof(stamp_data.note));
2098  }
2099  BLF_disable(mono, BLF_WORD_WRAP);
2100 
2101  x = 0;
2102  y = 0;
2103 
2104  /* Bottom left corner, leaving space for timing */
2105  if (TEXT_SIZE_CHECK(stamp_data.marker, w, h)) {
2106 
2107  /* extra space for background. */
2108  buf_rectfill_area(rect,
2109  rectf,
2110  width,
2111  height,
2112  scene->r.bg_stamp,
2113  display,
2114  x - BUFF_MARGIN_X,
2115  y - BUFF_MARGIN_Y,
2116  w + BUFF_MARGIN_X,
2117  y + h + BUFF_MARGIN_Y);
2118 
2119  /* and pad the text. */
2120  BLF_position(mono, x, y + y_ofs, 0.0);
2121  BLF_draw_buffer(mono, stamp_data.marker, sizeof(stamp_data.marker));
2122 
2123  /* space width. */
2124  x += w + pad;
2125  }
2126 
2127  /* Left bottom corner */
2128  if (TEXT_SIZE_CHECK(stamp_data.time, w, h)) {
2129 
2130  /* extra space for background */
2131  buf_rectfill_area(rect,
2132  rectf,
2133  width,
2134  height,
2135  scene->r.bg_stamp,
2136  display,
2137  x - BUFF_MARGIN_X,
2138  y,
2139  x + w + BUFF_MARGIN_X,
2140  y + h + BUFF_MARGIN_Y);
2141 
2142  /* and pad the text. */
2143  BLF_position(mono, x, y + y_ofs, 0.0);
2144  BLF_draw_buffer(mono, stamp_data.time, sizeof(stamp_data.time));
2145 
2146  /* space width. */
2147  x += w + pad;
2148  }
2149 
2150  if (TEXT_SIZE_CHECK(stamp_data.frame, w, h)) {
2151 
2152  /* extra space for background. */
2153  buf_rectfill_area(rect,
2154  rectf,
2155  width,
2156  height,
2157  scene->r.bg_stamp,
2158  display,
2159  x - BUFF_MARGIN_X,
2160  y - BUFF_MARGIN_Y,
2161  x + w + BUFF_MARGIN_X,
2162  y + h + BUFF_MARGIN_Y);
2163 
2164  /* and pad the text. */
2165  BLF_position(mono, x, y + y_ofs, 0.0);
2166  BLF_draw_buffer(mono, stamp_data.frame, sizeof(stamp_data.frame));
2167 
2168  /* space width. */
2169  x += w + pad;
2170  }
2171 
2172  if (TEXT_SIZE_CHECK(stamp_data.frame_range, w, h)) {
2173 
2174  /* extra space for background. */
2175  buf_rectfill_area(rect,
2176  rectf,
2177  width,
2178  height,
2179  scene->r.bg_stamp,
2180  display,
2181  x - BUFF_MARGIN_X,
2182  y - BUFF_MARGIN_Y,
2183  x + w + BUFF_MARGIN_X,
2184  y + h + BUFF_MARGIN_Y);
2185 
2186  /* and pad the text. */
2187  BLF_position(mono, x, y + y_ofs, 0.0);
2188  BLF_draw_buffer(mono, stamp_data.frame_range, sizeof(stamp_data.frame_range));
2189 
2190  /* space width. */
2191  x += w + pad;
2192  }
2193 
2194  if (TEXT_SIZE_CHECK(stamp_data.camera, w, h)) {
2195 
2196  /* extra space for background. */
2197  buf_rectfill_area(rect,
2198  rectf,
2199  width,
2200  height,
2201  scene->r.bg_stamp,
2202  display,
2203  x - BUFF_MARGIN_X,
2204  y - BUFF_MARGIN_Y,
2205  x + w + BUFF_MARGIN_X,
2206  y + h + BUFF_MARGIN_Y);
2207  BLF_position(mono, x, y + y_ofs, 0.0);
2208  BLF_draw_buffer(mono, stamp_data.camera, sizeof(stamp_data.camera));
2209 
2210  /* space width. */
2211  x += w + pad;
2212  }
2213 
2214  if (TEXT_SIZE_CHECK(stamp_data.cameralens, w, h)) {
2215 
2216  /* extra space for background. */
2217  buf_rectfill_area(rect,
2218  rectf,
2219  width,
2220  height,
2221  scene->r.bg_stamp,
2222  display,
2223  x - BUFF_MARGIN_X,
2224  y - BUFF_MARGIN_Y,
2225  x + w + BUFF_MARGIN_X,
2226  y + h + BUFF_MARGIN_Y);
2227  BLF_position(mono, x, y + y_ofs, 0.0);
2228  BLF_draw_buffer(mono, stamp_data.cameralens, sizeof(stamp_data.cameralens));
2229  }
2230 
2231  if (TEXT_SIZE_CHECK(stamp_data.scene, w, h)) {
2232 
2233  /* Bottom right corner, with an extra space because the BLF API is too strict! */
2234  x = width - w - 2;
2235 
2236  /* extra space for background. */
2237  buf_rectfill_area(rect,
2238  rectf,
2239  width,
2240  height,
2241  scene->r.bg_stamp,
2242  display,
2243  x - BUFF_MARGIN_X,
2244  y - BUFF_MARGIN_Y,
2245  x + w + BUFF_MARGIN_X,
2246  y + h + BUFF_MARGIN_Y);
2247 
2248  /* and pad the text. */
2249  BLF_position(mono, x, y + y_ofs, 0.0);
2250  BLF_draw_buffer(mono, stamp_data.scene, sizeof(stamp_data.scene));
2251  }
2252 
2253  if (TEXT_SIZE_CHECK(stamp_data.strip, w, h)) {
2254 
2255  /* Top right corner, with an extra space because the BLF API is too strict! */
2256  x = width - w - pad;
2257  y = height - h;
2258 
2259  /* extra space for background. */
2260  buf_rectfill_area(rect,
2261  rectf,
2262  width,
2263  height,
2264  scene->r.bg_stamp,
2265  display,
2266  x - BUFF_MARGIN_X,
2267  y - BUFF_MARGIN_Y,
2268  x + w + BUFF_MARGIN_X,
2269  y + h + BUFF_MARGIN_Y);
2270 
2271  BLF_position(mono, x, y + y_ofs, 0.0);
2272  BLF_draw_buffer(mono, stamp_data.strip, sizeof(stamp_data.strip));
2273  }
2274 
2275  /* cleanup the buffer. */
2276  BLF_buffer(mono, nullptr, nullptr, 0, 0, 0, nullptr);
2277  BLF_wordwrap(mono, 0);
2278 
2279 #undef TEXT_SIZE_CHECK
2280 #undef TEXT_SIZE_CHECK_WORD_WRAP
2281 #undef BUFF_MARGIN_X
2282 #undef BUFF_MARGIN_Y
2283 }
2284 
2286  Object *camera,
2287  struct RenderResult *rr,
2288  bool allocate_only)
2289 {
2290  struct StampData *stamp_data;
2291 
2292  if (!(scene && (scene->r.stamp & R_STAMP_ALL)) && !allocate_only) {
2293  return;
2294  }
2295 
2296  if (!rr->stamp_data) {
2297  stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
2298  }
2299  else {
2300  stamp_data = rr->stamp_data;
2301  }
2302 
2303  if (!allocate_only) {
2304  stampdata(scene, camera, stamp_data, 0, true);
2305  }
2306 
2307  if (!rr->stamp_data) {
2308  rr->stamp_data = stamp_data;
2309  }
2310 }
2311 
2313 {
2314  struct StampData *stamp_data;
2315 
2316  if (!(scene && (scene->r.stamp & R_STAMP_ALL))) {
2317  return nullptr;
2318  }
2319 
2320  /* Memory is allocated here (instead of by the caller) so that the caller
2321  * doesn't have to know the size of the StampData struct. */
2322  stamp_data = MEM_cnew<StampData>(__func__);
2323  stampdata(scene, nullptr, stamp_data, 0, false);
2324 
2325  return stamp_data;
2326 }
2327 
2328 static const char *stamp_metadata_fields[] = {
2329  "File",
2330  "Note",
2331  "Date",
2332  "Marker",
2333  "Time",
2334  "Frame",
2335  "FrameRange",
2336  "Camera",
2337  "Lens",
2338  "Scene",
2339  "Strip",
2340  "RenderTime",
2341  "Memory",
2342  "Hostname",
2343  nullptr,
2344 };
2345 
2346 bool BKE_stamp_is_known_field(const char *field_name)
2347 {
2348  int i = 0;
2349  while (stamp_metadata_fields[i] != nullptr) {
2350  if (STREQ(field_name, stamp_metadata_fields[i])) {
2351  return true;
2352  }
2353  i++;
2354  }
2355  return false;
2356 }
2357 
2359  struct StampData *stamp_data,
2361  bool noskip)
2362 {
2363  if ((callback == nullptr) || (stamp_data == nullptr)) {
2364  return;
2365  }
2366 
2367 #define CALL(member, value_str) \
2368  if (noskip || stamp_data->member[0]) { \
2369  callback(data, value_str, stamp_data->member, sizeof(stamp_data->member)); \
2370  } \
2371  ((void)0)
2372 
2373  /* TODO(sergey): Use stamp_metadata_fields somehow, or make it more generic
2374  * meta information to avoid duplication. */
2375  CALL(file, "File");
2376  CALL(note, "Note");
2377  CALL(date, "Date");
2378  CALL(marker, "Marker");
2379  CALL(time, "Time");
2380  CALL(frame, "Frame");
2381  CALL(frame_range, "FrameRange");
2382  CALL(camera, "Camera");
2383  CALL(cameralens, "Lens");
2384  CALL(scene, "Scene");
2385  CALL(strip, "Strip");
2386  CALL(rendertime, "RenderTime");
2387  CALL(memory, "Memory");
2388  CALL(hostname, "Hostname");
2389 
2390  LISTBASE_FOREACH (StampDataCustomField *, custom_field, &stamp_data->custom_fields) {
2391  if (noskip || custom_field->value[0]) {
2392  callback(data, custom_field->key, custom_field->value, strlen(custom_field->value) + 1);
2393  }
2394  }
2395 
2396 #undef CALL
2397 }
2398 
2399 void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char *value)
2400 {
2401  StampData *stamp_data;
2402  if (rr->stamp_data == nullptr) {
2403  rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
2404  }
2405  stamp_data = rr->stamp_data;
2406  StampDataCustomField *field = static_cast<StampDataCustomField *>(
2407  MEM_mallocN(sizeof(StampDataCustomField), "StampData Custom Field"));
2408  STRNCPY(field->key, key);
2409  field->value = BLI_strdup(value);
2410  BLI_addtail(&stamp_data->custom_fields, field);
2411 }
2412 
2414 {
2415  if (stamp_data == nullptr) {
2416  return nullptr;
2417  }
2418 
2419  StampData *stamp_datan = static_cast<StampData *>(MEM_dupallocN(stamp_data));
2420  BLI_duplicatelist(&stamp_datan->custom_fields, &stamp_data->custom_fields);
2421 
2422  LISTBASE_FOREACH (StampDataCustomField *, custom_fieldn, &stamp_datan->custom_fields) {
2423  custom_fieldn->value = static_cast<char *>(MEM_dupallocN(custom_fieldn->value));
2424  }
2425 
2426  return stamp_datan;
2427 }
2428 
2430 {
2431  if (stamp_data == nullptr) {
2432  return;
2433  }
2434  LISTBASE_FOREACH (StampDataCustomField *, custom_field, &stamp_data->custom_fields) {
2435  MEM_freeN(custom_field->value);
2436  }
2437  BLI_freelistN(&stamp_data->custom_fields);
2438  MEM_freeN(stamp_data);
2439 }
2440 
2441 /* wrap for callback only */
2442 static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
2443 {
2444  /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
2445  ImBuf *imbuf = static_cast<ImBuf *>(data);
2446  IMB_metadata_set_field(imbuf->metadata, propname, propvalue);
2447 }
2448 
2449 static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
2450 {
2451  /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
2452  ImBuf *imbuf = static_cast<ImBuf *>(data);
2453  IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
2454 }
2455 
2457 {
2458  StampData *stamp_data = const_cast<StampData *>(rr->stamp_data);
2459  IMB_metadata_ensure(&ibuf->metadata);
2460  BKE_stamp_info_callback(ibuf, stamp_data, metadata_set_field, false);
2461 }
2462 
2463 static void metadata_copy_custom_fields(const char *field, const char *value, void *rr_v)
2464 {
2465  if (BKE_stamp_is_known_field(field)) {
2466  return;
2467  }
2468  RenderResult *rr = (RenderResult *)rr_v;
2469  BKE_render_result_stamp_data(rr, field, value);
2470 }
2471 
2473 {
2474  if (rr->stamp_data == nullptr) {
2475  rr->stamp_data = MEM_cnew<StampData>("RenderResult.stamp_data");
2476  }
2477  StampData *stamp_data = rr->stamp_data;
2478  IMB_metadata_ensure(&ibuf->metadata);
2479  BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true);
2480  /* Copy render engine specific settings. */
2482 }
2483 
2485 {
2486  int tot;
2487  if (ibuf->rect_float) {
2488  const float *buf = ibuf->rect_float;
2489  for (tot = ibuf->x * ibuf->y; tot--; buf += 4) {
2490  if (buf[3] < 1.0f) {
2491  return true;
2492  }
2493  }
2494  }
2495  else if (ibuf->rect) {
2496  unsigned char *buf = (unsigned char *)ibuf->rect;
2497  for (tot = ibuf->x * ibuf->y; tot--; buf += 4) {
2498  if (buf[3] != 255) {
2499  return true;
2500  }
2501  }
2502  }
2503 
2504  return false;
2505 }
2506 
2507 int BKE_imbuf_write(ImBuf *ibuf, const char *name, const ImageFormatData *imf)
2508 {
2509  BKE_image_format_to_imbuf(ibuf, imf);
2510 
2511  BLI_make_existing_file(name);
2512 
2513  const bool ok = IMB_saveiff(ibuf, name, IB_rect | IB_zbuf | IB_zbuffloat);
2514  if (ok == 0) {
2515  perror(name);
2516  }
2517 
2518  return ok;
2519 }
2520 
2522  const char *name,
2523  const ImageFormatData *imf,
2524  const bool save_copy)
2525 {
2526  ImBuf ibuf_back = *ibuf;
2527  int ok;
2528 
2529  /* All data is RGBA anyway, this just controls how to save for some formats. */
2530  ibuf->planes = imf->planes;
2531 
2532  ok = BKE_imbuf_write(ibuf, name, imf);
2533 
2534  if (save_copy) {
2535  /* note that we are not restoring _all_ settings */
2536  ibuf->planes = ibuf_back.planes;
2537  ibuf->ftype = ibuf_back.ftype;
2538  ibuf->foptions = ibuf_back.foptions;
2539  }
2540 
2541  return ok;
2542 }
2543 
2545  const struct RenderResult *rr,
2546  ImBuf *ibuf,
2547  const char *name,
2548  const struct ImageFormatData *imf)
2549 {
2550  if (scene && scene->r.stamp & R_STAMP_ALL) {
2551  BKE_imbuf_stamp_info(rr, ibuf);
2552  }
2553 
2554  return BKE_imbuf_write(ibuf, name, imf);
2555 }
2556 
2557 struct anim *openanim_noload(const char *name,
2558  int flags,
2559  int streamindex,
2560  char colorspace[IMA_MAX_SPACE])
2561 {
2562  struct anim *anim;
2563 
2565  return anim;
2566 }
2567 
2568 struct anim *openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
2569 {
2570  struct anim *anim;
2571  struct ImBuf *ibuf;
2572 
2573  anim = IMB_open_anim(name, flags, streamindex, colorspace);
2574  if (anim == nullptr) {
2575  return nullptr;
2576  }
2577 
2579  if (ibuf == nullptr) {
2580  if (BLI_exists(name)) {
2581  printf("not an anim: %s\n", name);
2582  }
2583  else {
2584  printf("anim file doesn't exist: %s\n", name);
2585  }
2587  return nullptr;
2588  }
2589  IMB_freeImBuf(ibuf);
2590 
2591  return anim;
2592 }
2593 
2596 /* -------------------------------------------------------------------- */
2600 /* Notes about Image storage
2601  * - packedfile
2602  * -> written in .blend
2603  * - filename
2604  * -> written in .blend
2605  * - movie
2606  * -> comes from packedfile or filename
2607  * - renderresult
2608  * -> comes from packedfile or filename
2609  * - listbase
2610  * -> ibufs from EXR-handle.
2611  * - flip-book array
2612  * -> ibufs come from movie, temporary renderresult or sequence
2613  * - ibuf
2614  * -> comes from packedfile or filename or generated
2615  */
2616 
2617 Image *BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
2618 {
2619  Image *ima;
2620 
2621  for (ima = static_cast<Image *>(bmain->images.first); ima;
2622  ima = static_cast<Image *>(ima->id.next)) {
2623  if (ima->source == IMA_SRC_VIEWER) {
2624  if (ima->type == type) {
2625  break;
2626  }
2627  }
2628  }
2629 
2630  if (ima == nullptr) {
2631  ima = image_alloc(bmain, name, IMA_SRC_VIEWER, type);
2632  }
2633 
2634  /* Happens on reload, imagewindow cannot be image user when hidden. */
2635  if (ima->id.us == 0) {
2636  id_us_ensure_real(&ima->id);
2637  }
2638 
2639  return ima;
2640 }
2641 
2642 static void image_viewer_create_views(const RenderData *rd, Image *ima)
2643 {
2644  if ((rd->scemode & R_MULTIVIEW) == 0) {
2645  image_add_view(ima, "", "");
2646  }
2647  else {
2648  for (SceneRenderView *srv = static_cast<SceneRenderView *>(rd->views.first); srv;
2649  srv = srv->next) {
2650  if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
2651  continue;
2652  }
2653  image_add_view(ima, srv->name, "");
2654  }
2655  }
2656 }
2657 
2659 {
2660  bool do_reset;
2661  const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0;
2662 
2664 
2666  iuser->flag &= ~IMA_SHOW_STEREO;
2667  }
2668 
2669  /* see if all scene render views are in the image view list */
2670  do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views));
2671 
2672  /* multiview also needs to be sure all the views are synced */
2673  if (is_multiview && !do_reset) {
2674  SceneRenderView *srv;
2675  ImageView *iv;
2676 
2677  for (iv = static_cast<ImageView *>(ima->views.first); iv; iv = iv->next) {
2678  srv = static_cast<SceneRenderView *>(
2679  BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name)));
2680  if ((srv == nullptr) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) {
2681  do_reset = true;
2682  break;
2683  }
2684  }
2685  }
2686 
2687  if (do_reset) {
2688  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
2689 
2691  BKE_image_free_views(ima);
2692 
2693  /* add new views */
2694  image_viewer_create_views(rd, ima);
2695 
2696  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
2697  }
2698 
2700 }
2701 
2703  bNodeTree *ntree,
2704  ID *id,
2705  void *customdata,
2706  void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
2707 {
2708  switch (ntree->type) {
2709  case NTREE_SHADER:
2711  if (node->id) {
2712  if (node->type == SH_NODE_TEX_IMAGE) {
2713  NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
2714  Image *ima = (Image *)node->id;
2715  callback(ima, id, &tex->iuser, customdata);
2716  }
2717  if (node->type == SH_NODE_TEX_ENVIRONMENT) {
2718  NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
2719  Image *ima = (Image *)node->id;
2720  callback(ima, id, &tex->iuser, customdata);
2721  }
2722  }
2723  }
2724  break;
2725  case NTREE_TEXTURE:
2727  if (node->id && node->type == TEX_NODE_IMAGE) {
2728  Image *ima = (Image *)node->id;
2729  ImageUser *iuser = static_cast<ImageUser *>(node->storage);
2730  callback(ima, id, iuser, customdata);
2731  }
2732  }
2733  break;
2734  case NTREE_COMPOSIT:
2736  if (node->id && node->type == CMP_NODE_IMAGE) {
2737  Image *ima = (Image *)node->id;
2738  ImageUser *iuser = static_cast<ImageUser *>(node->storage);
2739  callback(ima, id, iuser, customdata);
2740  }
2741  }
2742  break;
2743  }
2744 }
2745 
2747  ID *id,
2748  ListBase *gpu_materials,
2749  void *customdata,
2750  void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
2751 {
2752  LISTBASE_FOREACH (LinkData *, link, gpu_materials) {
2753  GPUMaterial *gpu_material = (GPUMaterial *)link->data;
2754  ListBase textures = GPU_material_textures(gpu_material);
2755  LISTBASE_FOREACH (GPUMaterialTexture *, gpu_material_texture, &textures) {
2756  if (gpu_material_texture->iuser_available) {
2757  callback(gpu_material_texture->ima, id, &gpu_material_texture->iuser, customdata);
2758  }
2759  }
2760  }
2761 }
2762 
2764  ID *id,
2765  bool skip_nested_nodes,
2766  void *customdata,
2767  void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
2768 {
2769  switch (GS(id->name)) {
2770  case ID_OB: {
2771  Object *ob = (Object *)id;
2772  if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) {
2773  callback(static_cast<Image *>(ob->data), &ob->id, ob->iuser, customdata);
2774  }
2775  break;
2776  }
2777  case ID_MA: {
2778  Material *ma = (Material *)id;
2779  if (ma->nodetree && ma->use_nodes && !skip_nested_nodes) {
2780  image_walk_ntree_all_users(ma->nodetree, &ma->id, customdata, callback);
2781  }
2782  image_walk_gpu_materials(id, &ma->gpumaterial, customdata, callback);
2783  break;
2784  }
2785  case ID_LA: {
2786  Light *light = (Light *)id;
2787  if (light->nodetree && light->use_nodes && !skip_nested_nodes) {
2788  image_walk_ntree_all_users(light->nodetree, &light->id, customdata, callback);
2789  }
2790  break;
2791  }
2792  case ID_WO: {
2793  World *world = (World *)id;
2794  if (world->nodetree && world->use_nodes && !skip_nested_nodes) {
2796  }
2797  image_walk_gpu_materials(id, &world->gpumaterial, customdata, callback);
2798  break;
2799  }
2800  case ID_TE: {
2801  Tex *tex = (Tex *)id;
2802  if (tex->type == TEX_IMAGE && tex->ima) {
2803  callback(tex->ima, &tex->id, &tex->iuser, customdata);
2804  }
2805  if (tex->nodetree && tex->use_nodes && !skip_nested_nodes) {
2807  }
2808  break;
2809  }
2810  case ID_NT: {
2811  bNodeTree *ntree = (bNodeTree *)id;
2813  break;
2814  }
2815  case ID_CA: {
2816  Camera *cam = (Camera *)id;
2817  LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
2818  callback(bgpic->ima, nullptr, &bgpic->iuser, customdata);
2819  }
2820  break;
2821  }
2822  case ID_WM: {
2823  wmWindowManager *wm = (wmWindowManager *)id;
2824  LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
2825  const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
2826 
2827  LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
2828  if (area->spacetype == SPACE_IMAGE) {
2829  SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
2830  callback(sima->image, nullptr, &sima->iuser, customdata);
2831  }
2832  }
2833  }
2834  break;
2835  }
2836  case ID_SCE: {
2837  Scene *scene = (Scene *)id;
2838  if (scene->nodetree && scene->use_nodes && !skip_nested_nodes) {
2840  }
2841  break;
2842  }
2843  case ID_SIM: {
2844  Simulation *simulation = (Simulation *)id;
2846  break;
2847  }
2848  default:
2849  break;
2850  }
2851 }
2852 
2854  const Main *mainp,
2855  void *customdata,
2856  void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
2857 {
2858  for (Scene *scene = static_cast<Scene *>(mainp->scenes.first); scene;
2859  scene = static_cast<Scene *>(scene->id.next)) {
2860  image_walk_id_all_users(&scene->id, false, customdata, callback);
2861  }
2862 
2863  for (Object *ob = static_cast<Object *>(mainp->objects.first); ob;
2864  ob = static_cast<Object *>(ob->id.next)) {
2865  image_walk_id_all_users(&ob->id, false, customdata, callback);
2866  }
2867 
2868  for (bNodeTree *ntree = static_cast<bNodeTree *>(mainp->nodetrees.first); ntree;
2869  ntree = static_cast<bNodeTree *>(ntree->id.next)) {
2870  image_walk_id_all_users(&ntree->id, false, customdata, callback);
2871  }
2872 
2873  for (Material *ma = static_cast<Material *>(mainp->materials.first); ma;
2874  ma = static_cast<Material *>(ma->id.next)) {
2875  image_walk_id_all_users(&ma->id, false, customdata, callback);
2876  }
2877 
2878  for (Light *light = static_cast<Light *>(mainp->materials.first); light;
2879  light = static_cast<Light *>(light->id.next)) {
2880  image_walk_id_all_users(&light->id, false, customdata, callback);
2881  }
2882 
2883  for (World *world = static_cast<World *>(mainp->materials.first); world;
2884  world = static_cast<World *>(world->id.next)) {
2885  image_walk_id_all_users(&world->id, false, customdata, callback);
2886  }
2887 
2888  for (Tex *tex = static_cast<Tex *>(mainp->textures.first); tex;
2889  tex = static_cast<Tex *>(tex->id.next)) {
2890  image_walk_id_all_users(&tex->id, false, customdata, callback);
2891  }
2892 
2893  for (Camera *cam = static_cast<Camera *>(mainp->cameras.first); cam;
2894  cam = static_cast<Camera *>(cam->id.next)) {
2895  image_walk_id_all_users(&cam->id, false, customdata, callback);
2896  }
2897 
2898  for (wmWindowManager *wm = static_cast<wmWindowManager *>(mainp->wm.first); wm;
2899  wm = static_cast<wmWindowManager *>(wm->id.next)) { /* only 1 wm */
2900  image_walk_id_all_users(&wm->id, false, customdata, callback);
2901  }
2902 }
2903 
2904 static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
2905 {
2906  Image *changed_image = static_cast<Image *>(customdata);
2907 
2908  if (ima == changed_image && BKE_image_is_animated(ima)) {
2909  iuser->flag |= IMA_NEED_FRAME_RECALC;
2910 
2911  if (iuser_id) {
2912  /* Must copy image user changes to CoW data-block. */
2914  }
2915  }
2916 }
2917 
2918 static void image_tag_reload(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
2919 {
2920  Image *changed_image = static_cast<Image *>(customdata);
2921 
2922  if (ima == changed_image) {
2923  if (iuser->scene) {
2924  image_update_views_format(ima, iuser);
2925  }
2926  if (iuser_id) {
2927  /* Must copy image user changes to CoW data-block. */
2929  }
2931  }
2932 }
2933 
2935 {
2936  memset(iuser, 0, sizeof(ImageUser));
2937  iuser->frames = 100;
2938  iuser->sfra = 1;
2939 }
2940 
2942 {
2943  RenderResult *rr = ima->rr;
2944 
2945  iuser->multi_index = 0;
2946  iuser->layer = iuser->pass = iuser->view = 0;
2947 
2948  if (rr) {
2949  BKE_image_multilayer_index(rr, iuser);
2950  }
2951 }
2952 
2954 {
2955  for (int i = 0; i < TEXTARGET_COUNT; i++) {
2956  /* Only two textures depends on all tiles, so if this is a secondary tile we can keep the other
2957  * two. */
2958  if (tile != ima->tiles.first && !(ELEM(i, TEXTARGET_2D_ARRAY, TEXTARGET_TILE_MAPPING))) {
2959  continue;
2960  }
2961 
2962  for (int eye = 0; eye < 2; eye++) {
2963  if (ima->gputexture[i][eye] != nullptr) {
2964  GPU_texture_free(ima->gputexture[i][eye]);
2965  ima->gputexture[i][eye] = nullptr;
2966  }
2967  }
2968  }
2970 
2971  if (BKE_image_is_multiview(ima)) {
2972  const int totviews = BLI_listbase_count(&ima->views);
2973  for (int i = 0; i < totviews; i++) {
2974  image_remove_ibuf(ima, i, tile->tile_number);
2975  }
2976  }
2977  else {
2978  image_remove_ibuf(ima, 0, tile->tile_number);
2979  }
2980 }
2981 
2982 void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
2983 {
2984  if (ima == nullptr) {
2985  return;
2986  }
2987 
2988  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
2989 
2990  switch (signal) {
2991  case IMA_SIGNAL_FREE:
2993 
2994  if (iuser) {
2995  if (iuser->scene) {
2996  image_update_views_format(ima, iuser);
2997  }
2998  }
2999  break;
3000  case IMA_SIGNAL_SRC_CHANGE:
3001  if (ima->type == IMA_TYPE_UV_TEST) {
3002  if (ima->source != IMA_SRC_GENERATED) {
3003  ima->type = IMA_TYPE_IMAGE;
3004  }
3005  }
3006 
3007  if (ima->source == IMA_SRC_GENERATED) {
3008  if (ima->gen_x == 0 || ima->gen_y == 0) {
3009  ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
3010  if (ibuf) {
3011  ima->gen_x = ibuf->x;
3012  ima->gen_y = ibuf->y;
3013  IMB_freeImBuf(ibuf);
3014  }
3015  }
3016 
3017  /* Changing source type to generated will likely change file format
3018  * used by generated image buffer. Saving different file format to
3019  * the old name might confuse other applications.
3020  *
3021  * Here we ensure original image path wouldn't be used when saving
3022  * generated image.
3023  */
3024  ima->filepath[0] = '\0';
3025  }
3026 
3027  if (ima->source != IMA_SRC_TILED) {
3028  /* Free all but the first tile. */
3029  ImageTile *base_tile = BKE_image_get_tile(ima, 0);
3030  BLI_assert(base_tile == ima->tiles.first);
3031  for (ImageTile *tile = base_tile->next, *tile_next; tile; tile = tile_next) {
3032  tile_next = tile->next;
3033  image_free_tile(ima, tile);
3034  MEM_freeN(tile);
3035  }
3036  base_tile->next = nullptr;
3037  base_tile->tile_number = 1001;
3038  ima->tiles.last = base_tile;
3039  }
3040 
3041  /* image buffers for non-sequence multilayer will share buffers with RenderResult,
3042  * however sequence multilayer will own buffers. Such logic makes switching from
3043  * single multilayer file to sequence completely unstable
3044  * since changes in nodes seems this workaround isn't needed anymore, all sockets
3045  * are nicely detecting anyway, but freeing buffers always here makes multilayer
3046  * sequences behave stable
3047  */
3049 
3050  if (iuser) {
3051  image_tag_frame_recalc(ima, nullptr, iuser, ima);
3052  }
3054 
3055  break;
3056 
3057  case IMA_SIGNAL_RELOAD:
3058  /* try to repack file */
3059  if (BKE_image_has_packedfile(ima)) {
3060  const int tot_viewfiles = image_num_viewfiles(ima);
3061  const int tot_files = tot_viewfiles * BLI_listbase_count(&ima->tiles);
3062 
3063  if (tot_files != BLI_listbase_count_at_most(&ima->packedfiles, tot_files + 1)) {
3064  /* in case there are new available files to be loaded */
3066  BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
3067  }
3068  else {
3069  ImagePackedFile *imapf;
3070  for (imapf = static_cast<ImagePackedFile *>(ima->packedfiles.first); imapf;
3071  imapf = imapf->next) {
3072  PackedFile *pf;
3073  pf = BKE_packedfile_new(nullptr, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
3074  if (pf) {
3076  imapf->packedfile = pf;
3077  }
3078  else {
3079  printf("ERROR: Image \"%s\" not available. Keeping packed image\n", imapf->filepath);
3080  }
3081  }
3082  }
3083 
3084  if (BKE_image_has_packedfile(ima)) {
3086  }
3087  }
3088  else {
3090  }
3091 
3092  if (ima->source == IMA_SRC_TILED) {
3093  ListBase new_tiles = {nullptr, nullptr};
3094  int new_start, new_range;
3095 
3096  char filepath[FILE_MAX];
3097  BLI_strncpy(filepath, ima->filepath, sizeof(filepath));
3098  BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
3099  bool result = BKE_image_get_tile_info(filepath, &new_tiles, &new_start, &new_range);
3100  if (result) {
3101  /* Because the prior and new list of tiles are both sparse sequences, we need to be sure
3102  * to account for how the two sets might or might not overlap. To be complete, we start
3103  * the refresh process by clearing all existing tiles, stopping when there's only 1 tile
3104  * left. */
3105  while (BKE_image_remove_tile(ima, static_cast<ImageTile *>(ima->tiles.last))) {
3106  ;
3107  }
3108 
3109  int remaining_tile_number = ((ImageTile *)ima->tiles.first)->tile_number;
3110  bool needs_final_cleanup = true;
3111 
3112  /* Add in all the new tiles. */
3113  LISTBASE_FOREACH (LinkData *, new_tile, &new_tiles) {
3114  int new_tile_number = POINTER_AS_INT(new_tile->data);
3115  BKE_image_add_tile(ima, new_tile_number, nullptr);
3116  if (new_tile_number == remaining_tile_number) {
3117  needs_final_cleanup = false;
3118  }
3119  }
3120 
3121  /* Final cleanup if the prior remaining tile was never encountered in the new list. */
3122  if (needs_final_cleanup) {
3123  BKE_image_remove_tile(ima, BKE_image_get_tile(ima, remaining_tile_number));
3124  }
3125  }
3126  BLI_freelistN(&new_tiles);
3127  }
3128 
3129  if (iuser) {
3130  image_tag_reload(ima, nullptr, iuser, ima);
3131  }
3133  break;
3135  if (iuser) {
3137  if (ima->type == IMA_TYPE_MULTILAYER) {
3138  BKE_image_init_imageuser(ima, iuser);
3139  }
3140  }
3141  }
3142  break;
3145  break;
3146  }
3147 
3148  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
3149 
3150  BKE_ntree_update_tag_id_changed(bmain, &ima->id);
3151  BKE_ntree_update_main(bmain, nullptr);
3152 }
3153 
3159  const int pass,
3160  const int view,
3161  int *r_passindex)
3162 {
3163  RenderPass *rpass_ret = nullptr;
3164  RenderPass *rpass;
3165 
3166  int rp_index = 0;
3167  const char *rp_name = "";
3168 
3169  for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass;
3170  rpass = rpass->next, rp_index++) {
3171  if (rp_index == pass) {
3172  rpass_ret = rpass;
3173  if (view == 0) {
3174  /* no multiview or left eye */
3175  break;
3176  }
3177 
3178  rp_name = rpass->name;
3179  }
3180  /* multiview */
3181  else if (rp_name[0] && STREQ(rpass->name, rp_name) && (rpass->view_id == view)) {
3182  rpass_ret = rpass;
3183  break;
3184  }
3185  }
3186 
3187  /* fallback to the first pass in the layer */
3188  if (rpass_ret == nullptr) {
3189  rp_index = 0;
3190  rpass_ret = static_cast<RenderPass *>(rl->passes.first);
3191  }
3192 
3193  if (r_passindex) {
3194  *r_passindex = (rpass == rpass_ret ? rp_index : pass);
3195  }
3196 
3197  return rpass_ret;
3198 }
3199 
3200 void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_label)
3201 {
3202  label[0] = '\0';
3203  if (ima == nullptr || tile == nullptr) {
3204  return;
3205  }
3206 
3207  if (tile->label[0]) {
3208  BLI_strncpy(label, tile->label, len_label);
3209  }
3210  else {
3211  BLI_snprintf(label, len_label, "%d", tile->tile_number);
3212  }
3213 }
3214 
3215 bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, int *r_tile_range)
3216 {
3217  char filename[FILE_MAXFILE], dirname[FILE_MAXDIR];
3218  BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
3219 
3220  if (!BKE_image_is_filename_tokenized(filename)) {
3221  BKE_image_ensure_tile_token(filename);
3222  }
3223 
3224  eUDIM_TILE_FORMAT tile_format;
3225  char *udim_pattern = BKE_image_get_tile_strformat(filename, &tile_format);
3226 
3227  bool all_valid_udim = true;
3228  int min_udim = IMA_UDIM_MAX + 1;
3229  int max_udim = 0;
3230  int id;
3231 
3232  struct direntry *dirs;
3233  const uint dirs_num = BLI_filelist_dir_contents(dirname, &dirs);
3234  for (int i = 0; i < dirs_num; i++) {
3235  if (!(dirs[i].type & S_IFREG)) {
3236  continue;
3237  }
3238 
3240  dirs[i].relname, udim_pattern, tile_format, &id)) {
3241  continue;
3242  }
3243 
3244  if (id < 1001 || id > IMA_UDIM_MAX) {
3245  all_valid_udim = false;
3246  break;
3247  }
3248 
3250  min_udim = min_ii(min_udim, id);
3251  max_udim = max_ii(max_udim, id);
3252  }
3253  BLI_filelist_free(dirs, dirs_num);
3254  MEM_SAFE_FREE(udim_pattern);
3255 
3256  if (all_valid_udim && min_udim <= IMA_UDIM_MAX) {
3257  BLI_join_dirfile(filepath, FILE_MAX, dirname, filename);
3258 
3259  *r_tile_start = min_udim;
3260  *r_tile_range = max_udim - min_udim + 1;
3261  return true;
3262  }
3263  return false;
3264 }
3265 
3266 ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label)
3267 {
3268  if (ima->source != IMA_SRC_TILED) {
3269  return nullptr;
3270  }
3271 
3272  if (tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
3273  return nullptr;
3274  }
3275 
3276  /* Search the first tile that has a higher number.
3277  * We then insert before that to keep the list sorted. */
3278  ImageTile *next_tile;
3279  for (next_tile = static_cast<ImageTile *>(ima->tiles.first); next_tile;
3280  next_tile = next_tile->next) {
3281  if (next_tile->tile_number == tile_number) {
3282  /* Tile already exists. */
3283  return nullptr;
3284  }
3285  if (next_tile->tile_number > tile_number) {
3286  break;
3287  }
3288  }
3289 
3290  ImageTile *tile = MEM_cnew<ImageTile>("image new tile");
3291  tile->tile_number = tile_number;
3292 
3293  if (next_tile) {
3294  BLI_insertlinkbefore(&ima->tiles, next_tile, tile);
3295  }
3296  else {
3297  BLI_addtail(&ima->tiles, tile);
3298  }
3299 
3300  if (label) {
3301  BLI_strncpy(tile->label, label, sizeof(tile->label));
3302  }
3303 
3304  for (int eye = 0; eye < 2; eye++) {
3305  /* Reallocate GPU tile array. */
3306  if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != nullptr) {
3308  ima->gputexture[TEXTARGET_2D_ARRAY][eye] = nullptr;
3309  }
3310  if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != nullptr) {
3312  ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = nullptr;
3313  }
3314  }
3316 
3317  return tile;
3318 }
3319 
3321 {
3322  if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
3323  return false;
3324  }
3325 
3326  if (BLI_listbase_is_single(&ima->tiles)) {
3327  /* Can't remove the last remaining tile. */
3328  return false;
3329  }
3330 
3331  image_free_tile(ima, tile);
3332  BLI_remlink(&ima->tiles, tile);
3333  MEM_freeN(tile);
3334 
3335  return true;
3336 }
3337 
3338 void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number)
3339 {
3340  if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
3341  return;
3342  }
3343 
3344  if (new_tile_number < 1001 || new_tile_number > IMA_UDIM_MAX) {
3345  return;
3346  }
3347 
3348  const int old_tile_number = tile->tile_number;
3349  tile->tile_number = new_tile_number;
3350 
3351  if (BKE_image_is_multiview(ima)) {
3352  const int totviews = BLI_listbase_count(&ima->views);
3353  for (int i = 0; i < totviews; i++) {
3354  ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number, nullptr);
3355  image_remove_ibuf(ima, i, old_tile_number);
3356  image_assign_ibuf(ima, ibuf, i, new_tile_number);
3357  IMB_freeImBuf(ibuf);
3358  }
3359  }
3360  else {
3361  ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number, nullptr);
3362  image_remove_ibuf(ima, 0, old_tile_number);
3363  image_assign_ibuf(ima, ibuf, 0, new_tile_number);
3364  IMB_freeImBuf(ibuf);
3365  }
3366 
3367  for (int eye = 0; eye < 2; eye++) {
3368  /* Reallocate GPU tile array. */
3369  if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != nullptr) {
3371  ima->gputexture[TEXTARGET_2D_ARRAY][eye] = nullptr;
3372  }
3373  if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != nullptr) {
3375  ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = nullptr;
3376  }
3377  }
3379 }
3380 
3381 static int tile_sort_cb(const void *a, const void *b)
3382 {
3383  const ImageTile *tile_a = static_cast<const ImageTile *>(a);
3384  const ImageTile *tile_b = static_cast<const ImageTile *>(b);
3385  return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0;
3386 }
3387 
3388 void BKE_image_sort_tiles(struct Image *ima)
3389 {
3390  if (ima == nullptr || ima->source != IMA_SRC_TILED) {
3391  return;
3392  }
3393 
3395 }
3396 
3397 bool BKE_image_fill_tile(struct Image *ima,
3398  ImageTile *tile,
3399  int width,
3400  int height,
3401  const float color[4],
3402  int gen_type,
3403  int planes,
3404  bool is_float)
3405 {
3406  if (ima == nullptr || tile == nullptr || ima->source != IMA_SRC_TILED) {
3407  return false;
3408  }
3409 
3410  image_free_tile(ima, tile);
3411 
3412  ImBuf *tile_ibuf = add_ibuf_size(
3413  width, height, ima->filepath, planes, is_float, gen_type, color, &ima->colorspace_settings);
3414 
3415  if (tile_ibuf != nullptr) {
3416  image_assign_ibuf(ima, tile_ibuf, 0, tile->tile_number);
3417  BKE_image_release_ibuf(ima, tile_ibuf, nullptr);
3418  return true;
3419  }
3420  return false;
3421 }
3422 
3424 {
3425  const char *filename = BLI_path_basename(filepath);
3426  return strstr(filename, "<UDIM>") != nullptr || strstr(filename, "<UVTILE>") != nullptr;
3427 }
3428 
3429 void BKE_image_ensure_tile_token(char *filename)
3430 {
3431  BLI_assert_msg(BLI_path_slash_find(filename) == nullptr,
3432  "Only the file-name component should be used!");
3433 
3434  if (BKE_image_is_filename_tokenized(filename)) {
3435  return;
3436  }
3437 
3438  std::string path(filename);
3439  std::smatch match;
3440 
3441  /* General 4-digit "udim" pattern. As this format is susceptible to ambiguity
3442  * with other digit sequences, we can leverage the supported range of roughly
3443  * 1000 through 2000 to provide better detection. */
3444  std::regex pattern(R"((.*[._-])([12]\d{3})([._-].*))");
3445  if (std::regex_search(path, match, pattern)) {
3446  BLI_strncpy(filename, match.format("$1<UDIM>$3").c_str(), FILE_MAX);
3447  return;
3448  }
3449 
3450  /* General `u##_v###` `uvtile` pattern. */
3451  pattern = std::regex(R"((.*)(u\d{1,2}_v\d{1,3})(\D.*))");
3452  if (std::regex_search(path, match, pattern)) {
3453  BLI_strncpy(filename, match.format("$1<UVTILE>$3").c_str(), FILE_MAX);
3454  return;
3455  }
3456 }
3457 
3458 bool BKE_image_tile_filepath_exists(const char *filepath)
3459 {
3460  BLI_assert(!BLI_path_is_rel(filepath));
3461 
3462  char dirname[FILE_MAXDIR];
3463  BLI_split_dir_part(filepath, dirname, sizeof(dirname));
3464 
3465  eUDIM_TILE_FORMAT tile_format;
3466  char *udim_pattern = BKE_image_get_tile_strformat(filepath, &tile_format);
3467 
3468  bool found = false;
3469  struct direntry *dirs;
3470  const uint dirs_num = BLI_filelist_dir_contents(dirname, &dirs);
3471  for (int i = 0; i < dirs_num; i++) {
3472  if (!(dirs[i].type & S_IFREG)) {
3473  continue;
3474  }
3475 
3476  int id;
3477  if (!BKE_image_get_tile_number_from_filepath(dirs[i].path, udim_pattern, tile_format, &id)) {
3478  continue;
3479  }
3480 
3481  if (id < 1001 || id > IMA_UDIM_MAX) {
3482  continue;
3483  }
3484 
3485  found = true;
3486  break;
3487  }
3488  BLI_filelist_free(dirs, dirs_num);
3489  MEM_SAFE_FREE(udim_pattern);
3490 
3491  return found;
3492 }
3493 
3494 char *BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_tile_format)
3495 {
3496  if (filepath == nullptr || r_tile_format == nullptr) {
3497  return nullptr;
3498  }
3499 
3500  if (strstr(filepath, "<UDIM>") != nullptr) {
3501  *r_tile_format = UDIM_TILE_FORMAT_UDIM;
3502  return BLI_str_replaceN(filepath, "<UDIM>", "%d");
3503  }
3504  if (strstr(filepath, "<UVTILE>") != nullptr) {
3505  *r_tile_format = UDIM_TILE_FORMAT_UVTILE;
3506  return BLI_str_replaceN(filepath, "<UVTILE>", "u%d_v%d");
3507  }
3508 
3509  *r_tile_format = UDIM_TILE_FORMAT_NONE;
3510  return nullptr;
3511 }
3512 
3514  const char *pattern,
3515  eUDIM_TILE_FORMAT tile_format,
3516  int *r_tile_number)
3517 {
3518  if (filepath == nullptr || pattern == nullptr || r_tile_number == nullptr) {
3519  return false;
3520  }
3521 
3522  int u, v;
3523  bool result = false;
3524 
3525  if (tile_format == UDIM_TILE_FORMAT_UDIM) {
3526  if (sscanf(filepath, pattern, &u) == 1) {
3527  *r_tile_number = u;
3528  result = true;
3529  }
3530  }
3531  else if (tile_format == UDIM_TILE_FORMAT_UVTILE) {
3532  if (sscanf(filepath, pattern, &u, &v) == 2) {
3533  *r_tile_number = 1001 + (u - 1) + ((v - 1) * 10);
3534  result = true;
3535  }
3536  }
3537 
3538  return result;
3539 }
3540 
3542  const char *pattern,
3543  eUDIM_TILE_FORMAT tile_format,
3544  int tile_number)
3545 {
3546  if (filepath == nullptr || pattern == nullptr) {
3547  return;
3548  }
3549 
3550  if (tile_format == UDIM_TILE_FORMAT_UDIM) {
3551  sprintf(filepath, pattern, tile_number);
3552  }
3553  else if (tile_format == UDIM_TILE_FORMAT_UVTILE) {
3554  int u = ((tile_number - 1001) % 10);
3555  int v = ((tile_number - 1001) / 10);
3556  sprintf(filepath, pattern, u + 1, v + 1);
3557  }
3558 }
3559 
3560 /* if layer or pass changes, we need an index for the imbufs list */
3561 /* note it is called for rendered results, but it doesn't use the index! */
3563 {
3564  RenderLayer *rl;
3565  RenderPass *rpass = nullptr;
3566 
3567  if (rr == nullptr) {
3568  return nullptr;
3569  }
3570 
3571  if (iuser) {
3572  short index = 0, rv_index, rl_index = 0;
3573  bool is_stereo = (iuser->flag & IMA_SHOW_STEREO) && RE_RenderResult_is_stereo(rr);
3574 
3575  rv_index = is_stereo ? iuser->multiview_eye : iuser->view;
3576  if (RE_HasCombinedLayer(rr)) {
3577  rl_index += 1;
3578  }
3579 
3580  for (rl = static_cast<RenderLayer *>(rr->layers.first); rl; rl = rl->next, rl_index++) {
3581  if (iuser->layer == rl_index) {
3582  int rp_index;
3583  rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index);
3584  iuser->multi_index = index + rp_index;
3585  break;
3586  }
3587 
3588  index += BLI_listbase_count(&rl->passes);
3589  }
3590  }
3591 
3592  return rpass;
3593 }
3594 
3596 {
3597  if (iuser) {
3598  bool is_stereo = BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO);
3599  if (is_stereo) {
3600  iuser->multi_index = iuser->multiview_eye;
3601  }
3602  else {
3603  if ((iuser->view < 0) ||
3604  (iuser->view >= BLI_listbase_count_at_most(&ima->views, iuser->view + 1))) {
3605  iuser->multi_index = iuser->view = 0;
3606  }
3607  else {
3608  iuser->multi_index = iuser->view;
3609  }
3610  }
3611  }
3612 }
3613 
3614 /* if layer or pass changes, we need an index for the imbufs list */
3615 /* note it is called for rendered results, but it doesn't use the index! */
3617 {
3619  if (ima->type == IMA_TYPE_MULTILAYER) {
3620  return true;
3621  }
3622  }
3623  else if (ima->source == IMA_SRC_VIEWER) {
3624  if (ima->type == IMA_TYPE_R_RESULT) {
3625  return true;
3626  }
3627  }
3628  return false;
3629 }
3630 
3632 {
3633  ImageView *view = static_cast<ImageView *>(ima->views.first);
3634  return (view && (view->next || view->name[0]));
3635 }
3636 
3637 bool BKE_image_is_stereo(const Image *ima)
3638 {
3639  return BKE_image_is_multiview(ima) &&
3640  (BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)) &&
3641  BLI_findstring(&ima->views, STEREO_RIGHT_NAME, offsetof(ImageView, name)));
3642 }
3643 
3645 {
3646  /* update image views from render views, but only if they actually changed,
3647  * to avoid invalid memory access during render. ideally these should always
3648  * be acquired with a mutex along with the render result, but there are still
3649  * some places with just an image pointer that need to access views */
3650  if (rr && BLI_listbase_count(&ima->views) == BLI_listbase_count(&rr->views)) {
3651  ImageView *iv = static_cast<ImageView *>(ima->views.first);
3652  RenderView *rv = static_cast<RenderView *>(rr->views.first);
3653  bool modified = false;
3654  for (; rv; rv = rv->next, iv = iv->next) {
3655  modified |= !STREQ(rv->name, iv->name);
3656  }
3657  if (!modified) {
3658  return;
3659  }
3660  }
3661 
3662  BKE_image_free_views(ima);
3663 
3664  if (rr) {
3665  LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
3666  ImageView *iv = MEM_cnew<ImageView>("Viewer Image View");
3667  STRNCPY(iv->name, rv->name);
3668  BLI_addtail(&ima->views, iv);
3669  }
3670  }
3671 }
3672 
3674 {
3675  RenderResult *rr = nullptr;
3676  if (ima->rr) {
3677  rr = ima->rr;
3678  }
3679  else if (ima->type == IMA_TYPE_R_RESULT) {
3680  if (ima->render_slot == ima->last_render_slot) {
3682  }
3683  else {
3684  rr = BKE_image_get_renderslot(ima, ima->render_slot)->render;
3686  }
3687 
3688  /* set proper views */
3690  }
3691 
3692  return rr;
3693 }
3694 
3696 {
3697  if (ima->rr) {
3698  /* pass */
3699  }
3700  else if (ima->type == IMA_TYPE_R_RESULT) {
3701  if (ima->render_slot == ima->last_render_slot) {
3703  }
3704  }
3705 }
3706 
3707 bool BKE_image_is_openexr(struct Image *ima)
3708 {
3709 #ifdef WITH_OPENEXR
3711  return BLI_path_extension_check(ima->filepath, ".exr");
3712  }
3713 #else
3714  UNUSED_VARS(ima);
3715 #endif
3716  return false;
3717 }
3718 
3719 void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
3720 {
3721  /* called right before rendering, ima->renderslots contains render
3722  * result pointers for everything but the current render */
3724 
3725  /* Ensure we always have a valid render slot. */
3726  if (!ima->renderslots.first) {
3727  BKE_image_add_renderslot(ima, nullptr);
3728  ima->render_slot = 0;
3729  ima->last_render_slot = 0;
3730  }
3731  else if (ima->render_slot >= BLI_listbase_count(&ima->renderslots)) {
3732  ima->render_slot = 0;
3733  ima->last_render_slot = 0;
3734  }
3735 
3736  RenderSlot *last_slot = BKE_image_get_renderslot(ima, ima->last_render_slot);
3737  RenderSlot *cur_slot = BKE_image_get_renderslot(ima, ima->render_slot);
3738 
3739  if (last_slot && ima->render_slot != ima->last_render_slot) {
3740  last_slot->render = nullptr;
3741  RE_SwapResult(re, &last_slot->render);
3742 
3743  if (cur_slot->render) {
3744  if (free_current_slot) {
3745  BKE_image_clear_renderslot(ima, nullptr, ima->render_slot);
3746  }
3747  else {
3748  RE_SwapResult(re, &cur_slot->render);
3749  }
3750  }
3751  }
3752 
3753  ima->last_render_slot = ima->render_slot;
3754 }
3755 
3758 /* -------------------------------------------------------------------- */
3762 static void image_add_view(Image *ima, const char *viewname, const char *filepath)
3763 {
3764  ImageView *iv;
3765 
3766  iv = static_cast<ImageView *>(MEM_mallocN(sizeof(ImageView), "Viewer Image View"));
3767  STRNCPY(iv->name, viewname);
3768  STRNCPY(iv->filepath, filepath);
3769 
3770  /* For stereo drawing we need to ensure:
3771  * STEREO_LEFT_NAME == STEREO_LEFT_ID and
3772  * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
3773 
3774  if (STREQ(viewname, STEREO_LEFT_NAME)) {
3775  BLI_addhead(&ima->views, iv);
3776  }
3777  else if (STREQ(viewname, STEREO_RIGHT_NAME)) {
3778  ImageView *left_iv = static_cast<ImageView *>(
3779  BLI_findstring(&ima->views, STEREO_LEFT_NAME, offsetof(ImageView, name)));
3780 
3781  if (left_iv == nullptr) {
3782  BLI_addhead(&ima->views, iv);
3783  }
3784  else {
3785  BLI_insertlinkafter(&ima->views, left_iv, iv);
3786  }
3787  }
3788  else {
3789  BLI_addtail(&ima->views, iv);
3790  }
3791 }
3792 
3793 /* After imbuf load, OpenEXR type can return with a EXR-handle open
3794  * in that case we have to build a render-result. */
3795 #ifdef WITH_OPENEXR
3796 static void image_create_multilayer(Image *ima, ImBuf *ibuf, int framenr)
3797 {
3798  const char *colorspace = ima->colorspace_settings.name;
3799  bool predivide = (ima->alpha_mode == IMA_ALPHA_PREMUL);
3800 
3801  /* only load rr once for multiview */
3802  if (!ima->rr) {
3803  ima->rr = RE_MultilayerConvert(ibuf->userdata, colorspace, predivide, ibuf->x, ibuf->y);
3804  }
3805 
3806  IMB_exr_close(ibuf->userdata);
3807 
3808  ibuf->userdata = nullptr;
3809  if (ima->rr != nullptr) {
3810  ima->rr->framenr = framenr;
3811  BKE_stamp_info_from_imbuf(ima->rr, ibuf);
3812  }
3813 
3814  /* set proper views */
3816 }
3817 #endif /* WITH_OPENEXR */
3818 
3820 static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf))
3821 {
3822  /* Preview is null when it has never been used as an icon before.
3823  * Never handle previews/icons outside of main thread. */
3824  if (G.background == 0 && ima->preview == nullptr && BLI_thread_is_main()) {
3826  }
3827 
3828  /* timer */
3829  BKE_image_tag_time(ima);
3830 
3832  /* Images should never get loaded if the corresponding tile does not exist,
3833  * but we should at least not crash if it happens due to a bug elsewhere. */
3834  BLI_assert(tile != nullptr);
3836 }
3837 
3839 {
3840  switch (ima->alpha_mode) {
3841  case IMA_ALPHA_STRAIGHT:
3842  return 0;
3843  case IMA_ALPHA_PREMUL:
3844  return IB_alphamode_premul;
3847  case IMA_ALPHA_IGNORE:
3848  return IB_alphamode_ignore;
3849  }
3850 
3851  return 0;
3852 }
3853 
3857 static int image_num_viewfiles(Image *ima)
3858 {
3859  const bool is_multiview = BKE_image_is_multiview(ima);
3860 
3861  if (!is_multiview) {
3862  return 1;
3863  }
3864  if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
3865  return 1;
3866  }
3867  /* R_IMF_VIEWS_INDIVIDUAL */
3868 
3869  return BLI_listbase_count(&ima->views);
3870 }
3871 
3872 static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
3873 {
3874  struct ImBuf *ibuf = nullptr;
3875 
3876  /* either we load from RenderResult, or we have to load a new one */
3877 
3878  /* check for new RenderResult */
3879  if (ima->rr == nullptr || frame != ima->rr->framenr) {
3880  if (ima->rr) {
3881  /* Cached image buffers shares pointers with render result,
3882  * need to ensure there's no image buffers are hanging around
3883  * with dead links after freeing the render result.
3884  */
3886  RE_FreeRenderResult(ima->rr);
3887  ima->rr = nullptr;
3888  }
3889 
3890  ibuf = image_load_image_file(ima, iuser, entry, frame, true);
3891 
3892  if (ibuf) { /* actually an error */
3893  ima->type = IMA_TYPE_IMAGE;
3894  printf("error, multi is normal image\n");
3895  }
3896  }
3897  if (ima->rr) {
3898  RenderPass *rpass = BKE_image_multilayer_index(ima->rr, iuser);
3899 
3900  if (rpass) {
3901  // printf("load from pass %s\n", rpass->name);
3902  /* since we free render results, we copy the rect */
3903  ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
3904  ibuf->rect_float = static_cast<float *>(MEM_dupallocN(rpass->rect));
3905  ibuf->flags |= IB_rectfloat;
3906  ibuf->mall = IB_rectfloat;
3907  ibuf->channels = rpass->channels;
3908 
3909  BKE_imbuf_stamp_info(ima->rr, ibuf);
3910 
3911  image_init_after_load(ima, iuser, ibuf);
3912  image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : 0, entry);
3913  }
3914  // else printf("pass not found\n");
3915  }
3916 
3917  return ibuf;
3918 }
3919 
3920 static ImBuf *load_movie_single(Image *ima, ImageUser *iuser, int frame, const int view_id)
3921 {
3922  struct ImBuf *ibuf = nullptr;
3923  ImageAnim *ia;
3924 
3925  ia = static_cast<ImageAnim *>(BLI_findlink(&ima->anims, view_id));
3926 
3927  if (ia->anim == nullptr) {
3928  char str[FILE_MAX];
3929  int flags = IB_rect;
3930  ImageUser iuser_t{};
3931 
3932  if (ima->flag & IMA_DEINTERLACE) {
3934  }
3935 
3936  if (iuser) {
3937  iuser_t = *iuser;
3938  }
3939 
3940  iuser_t.view = view_id;
3941 
3942  BKE_image_user_file_path(&iuser_t, ima, str);
3943 
3944  /* FIXME: make several stream accessible in image editor, too. */
3945  ia->anim = openanim(str, flags, 0, ima->colorspace_settings.name);
3946 
3947  /* let's initialize this user */
3948  if (ia->anim && iuser && iuser->frames == 0) {
3950  }
3951  }
3952 
3953  if (ia->anim) {
3955  int fra = frame - 1;
3956 
3957  if (fra < 0) {
3958  fra = 0;
3959  }
3960  if (fra > (dur - 1)) {
3961  fra = dur - 1;
3962  }
3964 
3965  if (ibuf) {
3966  image_init_after_load(ima, iuser, ibuf);
3967  }
3968  }
3969 
3970  return ibuf;
3971 }
3972 
3973 static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
3974 {
3975  struct ImBuf *ibuf = nullptr;
3976  const bool is_multiview = BKE_image_is_multiview(ima);
3977  const int tot_viewfiles = image_num_viewfiles(ima);
3978 
3979  if (tot_viewfiles != BLI_listbase_count_at_most(&ima->anims, tot_viewfiles + 1)) {
3980  image_free_anims(ima);
3981 
3982  for (int i = 0; i < tot_viewfiles; i++) {
3983  /* allocate the ImageAnim */
3984  ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim");
3985  BLI_addtail(&ima->anims, ia);
3986  }
3987  }
3988 
3989  if (!is_multiview) {
3990  ibuf = load_movie_single(ima, iuser, frame, 0);
3991  image_assign_ibuf(ima, ibuf, 0, frame);
3992  }
3993  else {
3994  const int totviews = BLI_listbase_count(&ima->views);
3995  Array<ImBuf *> ibuf_arr(totviews);
3996 
3997  for (int i = 0; i < tot_viewfiles; i++) {
3998  ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
3999  }
4000 
4002  IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]);
4003  }
4004 
4005  for (int i = 0; i < totviews; i++) {
4006  image_assign_ibuf(ima, ibuf_arr[i], i, frame);
4007  }
4008 
4009  /* return the original requested ImBuf */
4010  ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
4011 
4012  /* "remove" the others (decrease their refcount) */
4013  for (int i = 0; i < totviews; i++) {
4014  if (ibuf_arr[i] != ibuf) {
4015  IMB_freeImBuf(ibuf_arr[i]);
4016  }
4017  }
4018  }
4019 
4020  return ibuf;
4021 }
4022 
4024  ImageUser *iuser,
4025  int cfra,
4026  const int view_id,
4027  const bool has_packed,
4028  const bool is_sequence,
4029  bool *r_cache_ibuf)
4030 {
4031  char filepath[FILE_MAX];
4032  struct ImBuf *ibuf = nullptr;
4033  int flag = IB_rect | IB_multilayer;
4034 
4035  *r_cache_ibuf = true;
4036  const int tile_number = image_get_tile_number_from_iuser(ima, iuser);
4037 
4038  /* is there a PackedFile with this image ? */
4039  if (has_packed && !is_sequence) {
4040  flag |= imbuf_alpha_flags_for_image(ima);
4041 
4042  LISTBASE_FOREACH (ImagePackedFile *, imapf, &ima->packedfiles) {
4043  if (imapf->view == view_id && imapf->tile_number == tile_number) {
4044  if (imapf->packedfile) {
4045  ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
4046  imapf->packedfile->size,
4047  flag,
4049  "<packed data>");
4050  }
4051  break;
4052  }
4053  }
4054  }
4055  else {
4056  if (is_sequence) {
4057  ima->lastframe = cfra;
4058  }
4059 
4060  /* get the correct filepath */
4061  const bool is_tiled = (ima->source == IMA_SRC_TILED);
4062  if (!(is_sequence || is_tiled)) {
4063  BKE_image_user_frame_calc(ima, iuser, cfra);
4064  }
4065 
4066  ImageUser iuser_t{};
4067  if (iuser) {
4068  iuser_t = *iuser;
4069  }
4070  else {
4071  iuser_t.framenr = ima->lastframe;
4072  }
4073 
4074  iuser_t.view = view_id;
4075 
4076  BKE_image_user_file_path(&iuser_t, ima, filepath);
4077 
4078  /* read ibuf */
4079  flag |= IB_metadata;
4080  flag |= imbuf_alpha_flags_for_image(ima);
4081  ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name);
4082  }
4083 
4084  if (ibuf) {
4085 #ifdef WITH_OPENEXR
4086  if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
4087  /* Handle multilayer and multiview cases, don't assign ibuf here.
4088  * will be set layer in BKE_image_acquire_ibuf from ima->rr. */
4089  if (IMB_exr_has_multilayer(ibuf->userdata)) {
4090  image_create_multilayer(ima, ibuf, cfra);
4091  ima->type = IMA_TYPE_MULTILAYER;
4092  IMB_freeImBuf(ibuf);
4093  ibuf = nullptr;
4094  /* Null ibuf in the cache means the image failed to load. However for multilayer we load
4095  * pixels into RenderResult instead and intentionally leave ibuf null. */
4096  *r_cache_ibuf = false;
4097  }
4098  }
4099  else
4100 #endif
4101  {
4102  image_init_after_load(ima, iuser, ibuf);
4103 
4104  /* Make packed file for auto-pack. */
4105  if (!is_sequence && (has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
4106  ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
4107  MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"));
4108  BLI_addtail(&ima->packedfiles, imapf);
4109 
4110  STRNCPY(imapf->filepath, filepath);
4111  imapf->view = view_id;
4112  imapf->tile_number = tile_number;
4113  imapf->packedfile = BKE_packedfile_new(
4114  nullptr, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
4115  }
4116  }
4117  }
4118 
4119  return ibuf;
4120 }
4121 
4122 /* warning, 'iuser' can be null
4123  * NOTE: Image->views was already populated (in image_update_views_format)
4124  */
4126  Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence)
4127 {
4128  struct ImBuf *ibuf = nullptr;
4129  const bool is_multiview = BKE_image_is_multiview(ima);
4130  const bool is_tiled = (ima->source == IMA_SRC_TILED);
4131  const int tot_viewfiles = image_num_viewfiles(ima);
4132  bool has_packed = BKE_image_has_packedfile(ima);
4133 
4134  if (!(is_sequence || is_tiled)) {
4135  /* ensure clean ima */
4137  }
4138 
4139  /* this should never happen, but just playing safe */
4140  if (!is_sequence && has_packed) {
4141  const int totfiles = tot_viewfiles * BLI_listbase_count(&ima->tiles);
4142  if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
4144  has_packed = false;
4145  }
4146  }
4147 
4148  if (!is_multiview) {
4149  bool put_in_cache;
4150  ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, is_sequence, &put_in_cache);
4151  if (put_in_cache) {
4152  const int index = (is_sequence || is_tiled) ? 0 : IMA_NO_INDEX;
4153  image_assign_ibuf(ima, ibuf, index, entry);
4154  }
4155  }
4156  else {
4157  const int totviews = BLI_listbase_count(&ima->views);
4158  BLI_assert(totviews > 0);
4159 
4160  Array<ImBuf *> ibuf_arr(totviews);
4161  Array<bool> cache_ibuf_arr(totviews);
4162 
4163  for (int i = 0; i < tot_viewfiles; i++) {
4164  ibuf_arr[i] = load_image_single(
4165  ima, iuser, cfra, i, has_packed, is_sequence, &cache_ibuf_arr[i]);
4166  }
4167 
4168  /* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */
4169  if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] &&
4170  tot_viewfiles == 1 && totviews >= 2) {
4171  IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]);
4172  }
4173 
4174  /* return the original requested ImBuf */
4175  const int ibuf_index = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
4176  ibuf = ibuf_arr[ibuf_index];
4177 
4178  for (int i = 0; i < totviews; i++) {
4179  if (cache_ibuf_arr[i]) {
4180  image_assign_ibuf(ima, ibuf_arr[i], i, entry);
4181  }
4182  }
4183 
4184  /* "remove" the others (decrease their refcount) */
4185  for (int i = 0; i < totviews; i++) {
4186  if (ibuf_arr[i] != ibuf) {
4187  IMB_freeImBuf(ibuf_arr[i]);
4188  }
4189  }
4190  }
4191 
4192  return ibuf;
4193 }
4194 
4196 {
4197  ImBuf *ibuf = nullptr;
4198 
4199  if (ima->rr == nullptr) {
4200  ibuf = image_load_image_file(ima, iuser, 0, 0, false);
4201  if (ibuf) { /* actually an error */
4202  ima->type = IMA_TYPE_IMAGE;
4203  return ibuf;
4204  }
4205  }
4206  if (ima->rr) {
4207  RenderPass *rpass = BKE_image_multilayer_index(ima->rr, iuser);
4208 
4209  if (rpass) {
4210  ibuf = IMB_allocImBuf(ima->rr->rectx, ima->rr->recty, 32, 0);
4211 
4212  image_init_after_load(ima, iuser, ibuf);
4213 
4214  ibuf->rect_float = rpass->rect;
4215  ibuf->flags |= IB_rectfloat;
4216  ibuf->channels = rpass->channels;
4217 
4218  BKE_imbuf_stamp_info(ima->rr, ibuf);
4219 
4220  image_assign_ibuf(ima, ibuf, iuser ? iuser->multi_index : IMA_NO_INDEX, 0);
4221  }
4222  }
4223 
4224  return ibuf;
4225 }
4226 
4227 /* showing RGBA result itself (from compo/sequence) or
4228  * like exr, using layers etc */
4229 /* always returns a single ibuf, also during render progress */
4230 static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock)
4231 {
4232  Render *re;
4233  RenderView *rv;
4234  float *rectf, *rectz;
4235  unsigned int *rect;
4236  float dither;
4237  int channels, layer, pass;
4238  ImBuf *ibuf;
4239  int from_render = (ima->render_slot == ima->last_render_slot);
4240  int actview;
4241 
4242  if (!(iuser && iuser->scene)) {
4243  return nullptr;
4244  }
4245 
4246  /* if we the caller is not going to release the lock, don't give the image */
4247  if (!r_lock) {
4248  return nullptr;
4249  }
4250 
4251  re = RE_GetSceneRender(iuser->scene);
4252 
4253  channels = 4;
4254  layer = iuser->layer;
4255  pass = iuser->pass;
4256  actview = iuser->view;
4257 
4258  if (BKE_image_is_stereo(ima) && (iuser->flag & IMA_SHOW_STEREO)) {
4259  actview = iuser->multiview_eye;
4260  }
4261 
4262  RenderResult rres{};
4263  RenderSlot *slot;
4264  if (from_render) {
4265  RE_AcquireResultImage(re, &rres, actview);
4266  }
4267  else if ((slot = BKE_image_get_renderslot(ima, ima->render_slot))->render) {
4268  rres = *(slot->render);
4269  rres.have_combined = ((RenderView *)rres.views.first)->rectf != nullptr;
4270  }
4271 
4272  if (!(rres.rectx > 0 && rres.recty > 0)) {
4273  if (from_render) {
4275  }
4276  return nullptr;
4277  }
4278 
4279  /* release is done in BKE_image_release_ibuf using r_lock */
4280  if (from_render) {
4282  *r_lock = re;
4283  rv = nullptr;
4284  }
4285  else {
4286  rv = static_cast<RenderView *>(BLI_findlink(&rres.views, actview));
4287  if (rv == nullptr) {
4288  rv = static_cast<RenderView *>(rres.views.first);
4289  }
4290  }
4291 
4292  /* this gives active layer, composite or sequence result */
4293  if (rv == nullptr) {
4294  rect = (unsigned int *)rres.rect32;
4295  rectf = rres.rectf;
4296  rectz = rres.rectz;
4297  }
4298  else {
4299  rect = (unsigned int *)rv->rect32;
4300  rectf = rv->rectf;
4301  rectz = rv->rectz;
4302  }
4303 
4304  dither = iuser->scene->r.dither_intensity;
4305 
4306  /* combined layer gets added as first layer */
4307  if (rres.have_combined && layer == 0) {
4308  /* pass */
4309  }
4310  else if (rect && layer == 0) {
4311  /* rect32 is set when there's a Sequence pass, this pass seems
4312  * to have layer=0 (this is from image_buttons.c)
4313  * in this case we ignore float buffer, because it could have
4314  * hung from previous pass which was float
4315  */
4316  rectf = nullptr;
4317  }
4318  else if (rres.layers.first) {
4319  RenderLayer *rl = static_cast<RenderLayer *>(
4320  BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0)));
4321  if (rl) {
4322  RenderPass *rpass = image_render_pass_get(rl, pass, actview, nullptr);
4323  if (rpass) {
4324  rectf = rpass->rect;
4325  if (pass != 0) {
4326  channels = rpass->channels;
4327  dither = 0.0f; /* don't dither passes */
4328  }
4329  }
4330 
4331  for (rpass = static_cast<RenderPass *>(rl->passes.first); rpass; rpass = rpass->next) {
4332  if (STREQ(rpass->name, RE_PASSNAME_Z) && rpass->view_id == actview) {
4333  rectz = rpass->rect;
4334  }
4335  }
4336  }
4337  }
4338 
4339  ibuf = image_get_cached_ibuf_for_index_entry(ima, IMA_NO_INDEX, 0, nullptr);
4340 
4341  /* make ibuf if needed, and initialize it */
4342  if (ibuf == nullptr) {
4343  ibuf = IMB_allocImBuf(rres.rectx, rres.recty, 32, 0);
4344  image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
4345  }
4346 
4347  /* Set color space settings for a byte buffer.
4348  *
4349  * This is mainly to make it so color management treats byte buffer
4350  * from render result with Save Buffers enabled as final display buffer
4351  * and doesn't apply any color management on it.
4352  *
4353  * For other cases we need to be sure it stays to default byte buffer space.
4354  */
4355  if (ibuf->rect != rect) {
4358  }
4359 
4360  /* invalidate color managed buffers if render result changed */
4362  if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) {
4364  }
4365 
4366  ibuf->x = rres.rectx;
4367  ibuf->y = rres.recty;
4368 
4369  if (rect) {
4370  imb_freerectImBuf(ibuf);
4371  ibuf->rect = rect;
4372  }
4373  else {
4374  /* byte buffer of render result has been freed, make sure image buffers
4375  * does not reference to this buffer anymore
4376  * need check for whether byte buffer was allocated and owned by image itself
4377  * or if it's reusing buffer from render result
4378  */
4379  if ((ibuf->mall & IB_rect) == 0) {
4380  ibuf->rect = nullptr;
4381  }
4382  }
4383 
4384  if (rectf) {
4385  ibuf->rect_float = rectf;
4386  ibuf->flags |= IB_rectfloat;
4387  ibuf->channels = channels;
4388  }
4389  else {
4390  ibuf->rect_float = nullptr;
4391  ibuf->flags &= ~IB_rectfloat;
4392  }
4393 
4394  if (rectz) {
4395  ibuf->zbuf_float = rectz;
4396  ibuf->flags |= IB_zbuffloat;
4397  }
4398  else {
4399  ibuf->zbuf_float = nullptr;
4400  ibuf->flags &= ~IB_zbuffloat;
4401  }
4402 
4403  /* TODO(sergey): Make this faster by either simply referencing the stamp
4404  * or by changing both ImBug and RenderResult to use same data type to
4405  * store metadata. */
4406  if (ibuf->metadata != nullptr) {
4407  IMB_metadata_free(ibuf->metadata);
4408  ibuf->metadata = nullptr;
4409  }
4410  BKE_imbuf_stamp_info(&rres, ibuf);
4411 
4413 
4414  ibuf->dither = dither;
4415 
4416  return ibuf;
4417 }
4418 
4420 {
4421  const bool is_multilayer = BKE_image_is_multilayer(ima);
4422  const bool is_backdrop = (ima->source == IMA_SRC_VIEWER) && (ima->type == IMA_TYPE_COMPOSITE) &&
4423  (iuser == nullptr);
4425 
4426  if (is_multilayer) {
4427  return iuser ? iuser->multi_index : index;
4428  }
4429  if (is_backdrop) {
4430  if (BKE_image_is_stereo(ima)) {
4431  /* Backdrop hack / workaround (since there is no `iuser`). */
4432  return ima->eye;
4433  }
4434  }
4435  else if (BKE_image_is_multiview(ima)) {
4436  return iuser ? iuser->multi_index : index;
4437  }
4438 
4439  return index;
4440 }
4441 
4442 static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry, int *r_index)
4443 {
4444  int frame = 0, index = image_get_multiview_index(ima, iuser);
4445 
4446  /* see if we already have an appropriate ibuf, with image source and type */
4447  if (ima->source == IMA_SRC_MOVIE) {
4448  frame = iuser ? iuser->framenr : ima->lastframe;
4449  }
4450  else if (ima->source == IMA_SRC_SEQUENCE) {
4451  if (ima->type == IMA_TYPE_IMAGE) {
4452  frame = iuser ? iuser->framenr : ima->lastframe;
4453  }
4454  else if (ima->type == IMA_TYPE_MULTILAYER) {
4455  frame = iuser ? iuser->framenr : ima->lastframe;
4456  }
4457  }
4458  else if (ima->source == IMA_SRC_TILED) {
4459  frame = image_get_tile_number_from_iuser(ima, iuser);
4460  }
4461 
4462  *r_entry = frame;
4463  *r_index = index;
4464 }
4465 
4466 /* Get the ibuf from an image cache for a given image user.
4467  *
4468  * Returns referenced image buffer if it exists, callee is to
4469  * call IMB_freeImBuf to de-reference the image buffer after
4470  * it's done handling it.
4471  */
4473  Image *ima, ImageUser *iuser, int *r_entry, int *r_index, bool *r_is_cached_empty)
4474 {
4475  ImBuf *ibuf = nullptr;
4476  int entry = 0, index = image_get_multiview_index(ima, iuser);
4477 
4478  /* see if we already have an appropriate ibuf, with image source and type */
4479  if (ima->source == IMA_SRC_MOVIE) {
4480  entry = iuser ? iuser->framenr : ima->lastframe;
4481  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, r_is_cached_empty);
4482  ima->lastframe = entry;
4483  }
4484  else if (ima->source == IMA_SRC_SEQUENCE) {
4485  if (ima->type == IMA_TYPE_IMAGE) {
4486  entry = iuser ? iuser->framenr : ima->lastframe;
4487  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, r_is_cached_empty);
4488  ima->lastframe = entry;
4489  }
4490  else if (ima->type == IMA_TYPE_MULTILAYER) {
4491  entry = iuser ? iuser->framenr : ima->lastframe;
4492  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, r_is_cached_empty);
4493  }
4494  }
4495  else if (ima->source == IMA_SRC_FILE) {
4496  if (ima->type == IMA_TYPE_IMAGE) {
4497  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0, r_is_cached_empty);
4498  }
4499  else if (ima->type == IMA_TYPE_MULTILAYER) {
4500  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0, r_is_cached_empty);
4501  }
4502  }
4503  else if (ima->source == IMA_SRC_GENERATED) {
4504  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, 0, r_is_cached_empty);
4505  }
4506  else if (ima->source == IMA_SRC_VIEWER) {
4507  /* always verify entirely, not that this shouldn't happen
4508  * as part of texture sampling in rendering anyway, so not
4509  * a big bottleneck */
4510  }
4511  else if (ima->source == IMA_SRC_TILED) {
4513  entry = image_get_tile_number_from_iuser(ima, iuser);
4514  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, r_is_cached_empty);
4515  }
4516  }
4517 
4518  if (r_entry) {
4519  *r_entry = entry;
4520  }
4521 
4522  if (r_index) {
4523  *r_index = index;
4524  }
4525 
4526  return ibuf;
4527 }
4528 
4529 BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser)
4530 {
4531  if (ima == nullptr) {
4532  return false;
4533  }
4534 
4536  if (tile == nullptr) {
4537  return false;
4538  }
4539 
4540  return true;
4541 }
4542 
4548 static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
4549 {
4550  ImBuf *ibuf = nullptr;
4551  int entry = 0, index = 0;
4552 
4553  if (r_lock) {
4554  *r_lock = nullptr;
4555  }
4556 
4557  /* quick reject tests */
4558  if (!image_quick_test(ima, iuser)) {
4559  return nullptr;
4560  }
4561 
4562  bool is_cached_empty = false;
4563  ibuf = image_get_cached_ibuf(ima, iuser, &entry, &index, &is_cached_empty);
4564  if (is_cached_empty) {
4565  return nullptr;
4566  }
4567 
4568  if (ibuf == nullptr) {
4569  /* We are sure we have to load the ibuf, using source and type. */
4570  if (ima->source == IMA_SRC_MOVIE) {
4571  /* Source is from single file, use flip-book to store ibuf. */
4572  ibuf = image_load_movie_file(ima, iuser, entry);
4573  }
4574  else if (ima->source == IMA_SRC_SEQUENCE) {
4575  if (ima->type == IMA_TYPE_IMAGE) {
4576  /* Regular files, ibufs in flip-book, allows saving. */
4577  ibuf = image_load_image_file(ima, iuser, entry, entry, true);
4578  }
4579  /* no else; on load the ima type can change */
4580  if (ima->type == IMA_TYPE_MULTILAYER) {
4581  /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
4582  ibuf = image_load_sequence_multilayer(ima, iuser, entry, entry);
4583  }
4584  }
4585  else if (ima->source == IMA_SRC_TILED) {
4586  if (ima->type == IMA_TYPE_IMAGE) {
4587  /* Regular files, ibufs in flip-book, allows saving */
4588  ibuf = image_load_image_file(ima, iuser, entry, 0, false);
4589  }
4590  /* no else; on load the ima type can change */
4591  if (ima->type == IMA_TYPE_MULTILAYER) {
4592  /* Only 1 layer/pass stored in imbufs, no EXR-handle anim storage, no saving. */
4593  ibuf = image_load_sequence_multilayer(ima, iuser, entry, 0);
4594  }
4595  }
4596  else if (ima->source == IMA_SRC_FILE) {
4597 
4598  if (ima->type == IMA_TYPE_IMAGE) {
4599  ibuf = image_load_image_file(
4600  ima, iuser, 0, entry, false); /* cfra only for '#', this global is OK */
4601  }
4602  /* no else; on load the ima type can change */
4603  if (ima->type == IMA_TYPE_MULTILAYER) {
4604  /* keeps render result, stores ibufs in listbase, allows saving */
4605  ibuf = image_get_ibuf_multilayer(ima, iuser);
4606  }
4607  }
4608  else if (ima->source == IMA_SRC_GENERATED) {
4609  /* Generated is: `ibuf` is allocated dynamically. */
4610  /* UV test-grid or black or solid etc. */
4611  if (ima->gen_x == 0) {
4612  ima->gen_x = 1024;
4613  }
4614  if (ima->gen_y == 0) {
4615  ima->gen_y = 1024;
4616  }
4617  if (ima->gen_depth == 0) {
4618  ima->gen_depth = 24;
4619  }
4620  ibuf = add_ibuf_size(ima->gen_x,
4621  ima->gen_y,
4622  ima->filepath,
4623  ima->gen_depth,
4624  (ima->gen_flag & IMA_GEN_FLOAT) != 0,
4625  ima->gen_type,
4626  ima->gen_color,
4627  &ima->colorspace_settings);
4628  image_assign_ibuf(ima, ibuf, index, 0);
4629  }
4630  else if (ima->source == IMA_SRC_VIEWER) {
4631  if (ima->type == IMA_TYPE_R_RESULT) {
4632  /* always verify entirely, and potentially
4633  * returns pointer to release later */
4634  ibuf = image_get_render_result(ima, iuser, r_lock);
4635  }
4636  else if (ima->type == IMA_TYPE_COMPOSITE) {
4637  /* requires lock/unlock, otherwise don't return image */
4638  if (r_lock) {
4639  /* unlock in BKE_image_release_ibuf */
4641  *r_lock = ima;
4642 
4643  /* XXX anim play for viewer nodes not yet supported */
4644  entry = 0; // XXX iuser ? iuser->framenr : 0;
4645  ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry, nullptr);
4646 
4647  if (!ibuf) {
4648  /* Composite Viewer, all handled in compositor */
4649  /* fake ibuf, will be filled in compositor */
4650  ibuf = IMB_allocImBuf(256, 256, 32, IB_rect | IB_rectfloat);
4651  image_assign_ibuf(ima, ibuf, index, entry);
4652  }
4653  }
4654  }
4655  }
4656 
4657  /* We only want movies and sequences to be memory limited. */
4658  if (ibuf != nullptr && !ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
4659  ibuf->userflags |= IB_PERSISTENT;
4660  }
4661  }
4662 
4663  BKE_image_tag_time(ima);
4664 
4665  return ibuf;
4666 }
4667 
4668 ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
4669 {
4670  /* NOTE: same as #image_acquire_ibuf, but can be used to retrieve images being rendered in
4671  * a thread safe way, always call both acquire and release. */
4672 
4673  if (ima == nullptr) {
4674  return nullptr;
4675  }
4676 
4677  ImBuf *ibuf;
4678 
4679  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4680 
4681  ibuf = image_acquire_ibuf(ima, iuser, r_lock);
4682 
4683  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4684 
4685  return ibuf;
4686 }
4687 
4688 void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
4689 {
4690  if (lock != nullptr) {
4691  /* for getting image during threaded render / compositing, need to release */
4692  if (lock == ima) {
4693  BLI_thread_unlock(LOCK_VIEWER); /* viewer image */
4694  }
4695  else {
4696  RE_ReleaseResultImage(static_cast<Render *>(lock)); /* render result */
4697  BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */
4698  }
4699  }
4700 
4701  if (ibuf) {
4702  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4703  IMB_freeImBuf(ibuf);
4704  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4705  }
4706 }
4707 
4709 {
4710  ImBuf *ibuf;
4711 
4712  /* quick reject tests */
4713  if (!image_quick_test(ima, iuser)) {
4714  return false;
4715  }
4716 
4717  BLI_mutex_lock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4718 
4719  ibuf = image_get_cached_ibuf(ima, iuser, nullptr, nullptr, nullptr);
4720 
4721  if (!ibuf) {
4722  ibuf = image_acquire_ibuf(ima, iuser, nullptr);
4723  }
4724 
4725  BLI_mutex_unlock(static_cast<ThreadMutex *>(ima->runtime.cache_mutex));
4726 
4727  IMB_freeImBuf(ibuf);
4728 
4729  return ibuf != nullptr;
4730 }
4731 
4734 /* -------------------------------------------------------------------- */
4742  int index;
4743  int entry;
4744 };
4745 
4746 struct ImagePool {
4750 };
4751 
4753 {
4754  ImagePool *pool = MEM_cnew<ImagePool>("Image Pool");
4755  pool->memory_pool = BLI_mempool_create(sizeof(ImagePoolItem), 0, 128, BLI_MEMPOOL_NOP);
4756 
4757  BLI_mutex_init(&pool->mutex);
4758 
4759  return pool;
4760 }
4761 
4763 {
4764  /* Use single lock to dereference all the image buffers. */
4765  BLI_mutex_lock(&pool->mutex);
4766  for (ImagePoolItem *item = static_cast<ImagePoolItem *>(pool->image_buffers.first);
4767  item != nullptr;
4768  item = item->next) {
4769  if (item->ibuf != nullptr) {
4770  BLI_mutex_lock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex));
4771  IMB_freeImBuf(item->ibuf);
4772  BLI_mutex_unlock(static_cast<ThreadMutex *>(item->image->runtime.cache_mutex));
4773  }
4774  }
4775  BLI_mutex_unlock(&pool->mutex);
4776 
4777  BLI_mempool_destroy(pool->memory_pool);
4778 
4779  BLI_mutex_end(&pool->mutex);
4780 
4781  MEM_freeN(pool);
4782 }
4783 
4785  ImagePool *pool, Image *image, int entry, int index, bool *found)
4786 {
4787  ImagePoolItem *item;
4788 
4789  *found = false;
4790 
4791  for (item = static_cast<ImagePoolItem *>(pool->image_buffers.first); item; item = item->next) {
4792  if (item->image == image && item->entry == entry && item->index == index) {
4793  *found = true;
4794  return item->ibuf;
4795  }
4796  }
4797 
4798  return nullptr;
4799 }
4800 
4802 {
4803  ImBuf *ibuf;
4804  int index, entry;
4805  bool found;
4806 
4807  if (!image_quick_test(ima, iuser)) {
4808  return nullptr;
4809  }
4810 
4811  if (pool == nullptr) {
4812  /* Pool could be null, in this case use general acquire function. */
4813  return BKE_image_acquire_ibuf(ima, iuser, nullptr);
4814  }
4815 
4816  image_get_entry_and_index(ima, iuser, &entry, &index);
4817 
4818  /* Use double-checked locking, to avoid locking when the requested image buffer is already in the
4819  * pool. */
4820 
4821  ibuf = image_pool_find_item(pool, ima, entry, index, &found);
4822  if (found) {
4823  return ibuf;
4824  }
4825 
4826  /* Lock the pool, to allow thread-safe modification of the content of the pool. */
4827  BLI_mutex_lock(&pool->mutex);
4828 
4829  ibuf = image_pool_find_item(pool, ima, entry, index, &found);
4830 
4831  /* Will also create item even in cases image buffer failed to load,
4832  * prevents trying to load the same buggy file multiple times. */
4833  if (!found) {
4834  ImagePoolItem *item;
4835 
4836  /* Thread-safe acquisition of an image buffer from the image.
4837  * The acquisition does not use image pools, so there is no risk of recursive or out-of-order
4838  * mutex locking. */
4839  ibuf = BKE_image_acquire_ibuf(ima, iuser, nullptr);
4840 
4841  item = static_cast<ImagePoolItem *>(BLI_mempool_alloc(pool->memory_pool));
4842  item->image = ima;
4843  item->entry = entry;
4844  item->index = index;
4845  item->ibuf = ibuf;
4846 
4847  BLI_addtail(&pool->image_buffers, item);
4848  }
4849 
4850  BLI_mutex_unlock(&pool->mutex);
4851 
4852  return ibuf;
4853 }
4854 
4856 {
4857  /* if pool wasn't actually used, use general release stuff,
4858  * for pools image buffers will be dereferenced on pool free
4859  */
4860  if (pool == nullptr) {
4861  BKE_image_release_ibuf(ima, ibuf, nullptr);
4862  }
4863 }
4864 
4865 int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, bool *r_is_in_range)
4866 {
4867  const int len = iuser->frames;
4868 
4869  if (r_is_in_range) {
4870  *r_is_in_range = false;
4871  }
4872 
4873  if (len == 0) {
4874  return 0;
4875  }
4876 
4877  int framenr;
4878  cfra = cfra - iuser->sfra + 1;
4879 
4880  /* cyclic */
4881  if (iuser->cycl) {
4882  cfra = ((cfra) % len);
4883  if (cfra < 0) {
4884  cfra += len;
4885  }
4886  if (cfra == 0) {
4887  cfra = len;
4888  }
4889 
4890  if (r_is_in_range) {
4891  *r_is_in_range = true;
4892  }
4893  }
4894 
4895  if (cfra < 0) {
4896  cfra = 0;
4897  }
4898  else if (cfra > len) {
4899  cfra = len;
4900  }
4901  else {
4902  if (r_is_in_range) {
4903  *r_is_in_range = true;
4904  }
4905  }
4906 
4907  /* transform to images space */
4908  framenr = cfra;
4909  if (framenr > iuser->frames) {
4910  framenr = iuser->frames;
4911  }
4912 
4913  if (iuser->cycl) {
4914  framenr = ((framenr) % len);
4915  while (framenr < 0) {
4916  framenr += len;
4917  }
4918  if (framenr == 0) {
4919  framenr = len;
4920  }
4921  }
4922 
4923  /* important to apply after else we can't loop on frames 100 - 110 for eg. */
4924  framenr += iuser->offset;
4925 
4926  return framenr;
4927 }
4928 
4929 void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
4930 {
4931  if (iuser) {
4932  if (ima && BKE_image_is_animated(ima)) {
4933  /* Compute current frame for animated image. */
4934  bool is_in_range;
4935  const int framenr = BKE_image_user_frame_get(iuser, cfra, &is_in_range);
4936 
4937  if (is_in_range) {
4938  iuser->flag |= IMA_USER_FRAME_IN_RANGE;
4939  }
4940  else {
4941  iuser->flag &= ~IMA_USER_FRAME_IN_RANGE;
4942  }
4943 
4944  iuser->framenr = framenr;
4945  }
4946  else {
4947  /* Set fixed frame number for still image. */
4948  iuser->framenr = 0;
4949  iuser->flag |= IMA_USER_FRAME_IN_RANGE;
4950  }
4951 
4952  if (ima && ima->gpuframenr != iuser->framenr) {
4953  /* NOTE: a single texture and refresh doesn't really work when
4954  * multiple image users may use different frames, this is to
4955  * be improved with perhaps a GPU texture cache. */
4957  ima->gpuframenr = iuser->framenr;
4958  }
4959 
4960  iuser->flag &= ~IMA_NEED_FRAME_RECALC;
4961  }
4962 }
4963 
4964 /* goes over all ImageUsers, and sets frame numbers if auto-refresh is set */
4966  ID *UNUSED(iuser_id),
4967  ImageUser *iuser,
4968  void *customdata)
4969 {
4970  if (ima && BKE_image_is_animated(ima)) {
4971  if ((iuser->flag & IMA_ANIM_ALWAYS) || (iuser->flag & IMA_NEED_FRAME_RECALC)) {
4972  int cfra = *(int *)customdata;
4973 
4974  BKE_image_user_frame_calc(ima, iuser, cfra);
4975  }
4976  }
4977 }
4978 
4979 void BKE_image_editors_update_frame(const Main *bmain, int cfra)
4980 {
4981  /* This only updates images used by the user interface. For others the
4982  * dependency graph will call BKE_image_user_id_eval_animation. */
4983  wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
4985 }
4986 
4988  ID *UNUSED(iuser_id),
4989  ImageUser *UNUSED(iuser),
4990  void *customdata)
4991 {
4992  if (ima && BKE_image_is_animated(ima)) {
4993  *(bool *)customdata = true;
4994  }
4995 }
4996 
4998 {
4999  /* For the dependency graph, this does not consider nested node
5000  * trees as these are handled as their own data-block. */
5001  bool has_animation = false;
5002  bool skip_nested_nodes = true;
5003  image_walk_id_all_users(id, skip_nested_nodes, &has_animation, image_user_id_has_animation);
5004  return has_animation;
5005 }
5006 
5008  ID *UNUSED(iduser_id),
5009  ImageUser *iuser,
5010  void *customdata)
5011 {
5012  if (ima && BKE_image_is_animated(ima)) {
5013  Depsgraph *depsgraph = (Depsgraph *)customdata;
5014 
5015  if ((iuser->flag & IMA_ANIM_ALWAYS) || (iuser->flag & IMA_NEED_FRAME_RECALC) ||
5017  float cfra = DEG_get_ctime(depsgraph);
5018 
5019  BKE_image_user_frame_calc(ima, iuser, cfra);
5020  }
5021  }
5022 }
5023 
5025 {
5026  /* This is called from the dependency graph to update the image
5027  * users in data-blocks. It computes the current frame number
5028  * and tags the image to be refreshed.
5029  * This does not consider nested node trees as these are handled
5030  * as their own data-block. */
5031  bool skip_nested_nodes = true;
5033 }
5034 
5035 void BKE_image_user_file_path(const ImageUser *iuser, const Image *ima, char *filepath)
5036 {
5037  BKE_image_user_file_path_ex(G_MAIN, iuser, ima, filepath, true, true);
5038 }
5039 
5041  const ImageUser *iuser,
5042  const Image *ima,
5043  char *filepath,
5044  const bool resolve_udim,
5045  const bool resolve_multiview)
5046 {
5047  if (resolve_multiview && BKE_image_is_multiview(ima)) {
5048  ImageView *iv = static_cast<ImageView *>(BLI_findlink(&ima->views, iuser->view));
5049  if (iv->filepath[0]) {
5050  BLI_strncpy(filepath, iv->filepath, FILE_MAX);
5051  }
5052  else {
5053  BLI_strncpy(filepath, ima->filepath, FILE_MAX);
5054  }
5055  }
5056  else {
5057  BLI_strncpy(filepath, ima->filepath, FILE_MAX);
5058  }
5059 
5060  if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
5061  char head[FILE_MAX], tail[FILE_MAX];
5062  unsigned short numlen;
5063 
5064  int index;
5065  if (ima->source == IMA_SRC_SEQUENCE) {
5066  index = iuser ? iuser->framenr : ima->lastframe;
5067  BLI_path_sequence_decode(filepath, head, tail, &numlen);
5068  BLI_path_sequence_encode(filepath, head, tail, numlen, index);
5069  }
5070  else if (resolve_udim) {
5071  index = image_get_tile_number_from_iuser(ima, iuser);
5072 
5073  eUDIM_TILE_FORMAT tile_format;
5074  char *udim_pattern = BKE_image_get_tile_strformat(filepath, &tile_format);
5075  BKE_image_set_filepath_from_tile_number(filepath, udim_pattern, tile_format, index);
5076  MEM_SAFE_FREE(udim_pattern);
5077  }
5078  }
5079 
5080  BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &ima->id));
5081 }
5082 
5084 {
5085  void *lock;
5086  ImBuf *ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock);
5087  const int planes = (ibuf ? ibuf->planes : 0);
5089 
5090  if (planes == 32 || planes == 16) {
5091  return true;
5092  }
5093 
5094  return false;
5095 }
5096 
5097 void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height)
5098 {
5099  ImBuf *ibuf = nullptr;
5100  void *lock;
5101 
5102  if (image != nullptr) {
5103  ibuf = BKE_image_acquire_ibuf(image, iuser, &lock);
5104  }
5105 
5106  if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
5107  *r_width = ibuf->x;
5108  *r_height = ibuf->y;
5109  }
5110  else if (image != nullptr && image->type == IMA_TYPE_R_RESULT && iuser != nullptr &&
5111  iuser->scene != nullptr) {
5112  BKE_render_resolution(&iuser->scene->r, true, r_width, r_height);
5113  }
5114  else {
5115  *r_width = IMG_SIZE_FALLBACK;
5116  *r_height = IMG_SIZE_FALLBACK;
5117  }
5118 
5119  if (image != nullptr) {
5121  }
5122 }
5123 
5124 void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float r_size[2])
5125 {
5126  int width, height;
5127  BKE_image_get_size(image, iuser, &width, &height);
5128 
5129  r_size[0] = (float)width;
5130  r_size[1] = (float)height;
5131 }
5132 
5133 void BKE_image_get_aspect(Image *image, float *r_aspx, float *r_aspy)
5134 {
5135  *r_aspx = 1.0;
5136 
5137  /* x is always 1 */
5138  if (image) {
5139  *r_aspy = image->aspy / image->aspx;
5140  }
5141  else {
5142  *r_aspy = 1.0f;
5143  }
5144 }
5145 
5146 unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, int tile)
5147 {
5148  ImageUser iuser;
5149  BKE_imageuser_default(&iuser);
5150  void *lock;
5151  ImBuf *ibuf;
5152  unsigned char *pixels = nullptr;
5153 
5154  iuser.framenr = frame;
5155  iuser.tile = tile;
5156 
5157  ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
5158 
5159  if (ibuf) {
5160  pixels = (unsigned char *)ibuf->rect;
5161 
5162  if (pixels) {
5163  pixels = static_cast<unsigned char *>(MEM_dupallocN(pixels));
5164  }
5165 
5167  }
5168 
5169  if (!pixels) {
5170  return nullptr;
5171  }
5172 
5173  return pixels;
5174 }
5175 
5176 float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int tile)
5177 {
5178  ImageUser iuser;
5179  BKE_imageuser_default(&iuser);
5180  void *lock;
5181  ImBuf *ibuf;
5182  float *pixels = nullptr;
5183 
5184  iuser.framenr = frame;
5185  iuser.tile = tile;
5186 
5187  ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
5188 
5189  if (ibuf) {
5190  pixels = ibuf->rect_float;
5191 
5192  if (pixels) {
5193  pixels = static_cast<float *>(MEM_dupallocN(pixels));
5194  }
5195 
5197  }
5198 
5199  if (!pixels) {
5200  return nullptr;
5201  }
5202 
5203  return pixels;
5204 }
5205 
5207 {
5208  return BLI_path_sequence_decode(image->filepath, nullptr, nullptr, nullptr);
5209 }
5210 
5212 {
5213  return (BLI_listbase_is_empty(&ima->anims) == false);
5214 }
5215 
5217 {
5218  return (BLI_listbase_is_empty(&ima->packedfiles) == false);
5219 }
5220 
5222 {
5223  /* This could be improved to detect cases like //../../, currently path
5224  * remapping empty file paths empty. */
5225  return ima->filepath[0] != '\0';
5226 }
5227 
5229 {
5230  return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE);
5231 }
5232 
5234 {
5236 }
5237 
5238 bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
5239 {
5240  bool is_dirty = false;
5241  bool is_writable = false;
5242 
5243  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5244  if (image->cache != nullptr) {
5245  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
5246 
5247  while (!IMB_moviecacheIter_done(iter)) {
5248  ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
5249  if (ibuf != nullptr && ibuf->userflags & IB_BITMAPDIRTY) {
5250  is_writable = BKE_image_buffer_format_writable(ibuf);
5251  is_dirty = true;
5252  break;
5253  }
5255  }
5257  }
5258  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5259 
5260  if (r_is_writable) {
5261  *r_is_writable = is_writable;
5262  }
5263 
5264  return is_dirty;
5265 }
5266 
5268 {
5269  return BKE_image_is_dirty_writable(image, nullptr);
5270 }
5271 
5273 {
5274  ibuf->userflags |= IB_BITMAPDIRTY;
5275 }
5276 
5278 {
5279  ImageFormatData im_format;
5280  ImbFormatOptions options_dummy;
5281  BKE_image_format_from_imbuf(&im_format, ibuf);
5282  return (BKE_imtype_to_ftype(im_format.imtype, &options_dummy) == ibuf->ftype);
5283 }
5284 
5286 {
5287  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5288  if (image->cache != nullptr) {
5289  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
5290 
5291  while (!IMB_moviecacheIter_done(iter)) {
5292  ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
5293  if (ibuf != nullptr) {
5294  ibuf->ftype = static_cast<eImbFileType>(ftype);
5295  ibuf->foptions = *options;
5296  }
5298  }
5300  }
5301  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5302 }
5303 
5305 {
5306  bool has_loaded_ibuf = false;
5307 
5308  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5309  if (image->cache != nullptr) {
5310  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
5311 
5312  while (!IMB_moviecacheIter_done(iter)) {
5313  ImBuf *ibuf = IMB_moviecacheIter_getImBuf(iter);
5314  if (ibuf != nullptr) {
5315  has_loaded_ibuf = true;
5316  break;
5317  }
5319  }
5321  }
5322  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5323 
5324  return has_loaded_ibuf;
5325 }
5326 
5328 {
5329  ImBuf *ibuf = nullptr;
5330 
5331  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5332  if (image->cache != nullptr) {
5333  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
5334 
5335  while (!IMB_moviecacheIter_done(iter)) {
5336  ImBuf *current_ibuf = IMB_moviecacheIter_getImBuf(iter);
5337  if (current_ibuf != nullptr && STREQ(current_ibuf->name, name)) {
5338  ibuf = current_ibuf;
5339  IMB_refImBuf(ibuf);
5340  break;
5341  }
5343  }
5345  }
5346  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5347 
5348  return ibuf;
5349 }
5350 
5352 {
5353  ImBuf *ibuf = nullptr;
5354 
5355  BLI_mutex_lock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5356  if (image->cache != nullptr) {
5357  struct MovieCacheIter *iter = IMB_moviecacheIter_new(image->cache);
5358 
5359  while (!IMB_moviecacheIter_done(iter)) {
5360  ibuf = IMB_moviecacheIter_getImBuf(iter);
5361  if (ibuf != nullptr) {
5362  IMB_refImBuf(ibuf);
5363  }
5364  break;
5365  }
5367  }
5368  BLI_mutex_unlock(static_cast<ThreadMutex *>(image->runtime.cache_mutex));
5369 
5370  return ibuf;
5371 }
5372 
5373 static void image_update_views_format(Image *ima, ImageUser *iuser)
5374 {
5375  SceneRenderView *srv;
5376  ImageView *iv;
5377  Scene *scene = iuser->scene;
5378  const bool is_multiview = ((scene->r.scemode & R_MULTIVIEW) != 0) &&
5379  ((ima->flag & IMA_USE_VIEWS) != 0);
5380 
5381  /* reset the image views */
5382  BKE_image_free_views(ima);
5383 
5384  if (!is_multiview) {
5385  /* nothing to do */
5386  }
5387  else if (ima->views_format == R_IMF_VIEWS_STEREO_3D) {
5388  const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
5389 
5390  for (int i = 0; i < 2; i++) {
5391  image_add_view(ima, names[i], ima->filepath);
5392  }
5393  return;
5394  }
5395  else {
5396  /* R_IMF_VIEWS_INDIVIDUAL */
5397  char prefix[FILE_MAX] = {'\0'};
5398  char *name = ima->filepath;
5399  const char *ext = nullptr;
5400 
5401  BKE_scene_multiview_view_prefix_get(scene, name, prefix, &ext);
5402 
5403  if (prefix[0] == '\0') {
5404  BKE_image_free_views(ima);
5405  return;
5406  }
5407 
5408  /* create all the image views */
5409  for (srv = static_cast<SceneRenderView *>(scene->r.views.first); srv; srv = srv->next) {
5411  char filepath[FILE_MAX];
5412  SNPRINTF(filepath, "%s%s%s", prefix, srv->suffix, ext);
5413  image_add_view(ima, srv->name, filepath);
5414  }
5415  }
5416 
5417  /* check if the files are all available */
5418  iv = static_cast<ImageView *>(ima->views.last);
5419  while (iv) {
5420  int file;
5421  char str[FILE_MAX];
5422 
5423  STRNCPY(str, iv->filepath);
5425 
5426  /* exists? */
5427  file = BLI_open(str, O_BINARY | O_RDONLY, 0);
5428  if (file == -1) {
5429  ImageView *iv_del = iv;
5430  iv = iv->prev;
5431  BLI_remlink(&ima->views, iv_del);
5432  MEM_freeN(iv_del);
5433  }
5434  else {
5435  iv = iv->prev;
5436  close(file);
5437  }
5438  }
5439 
5440  /* all good */
5441  if (!BKE_image_is_multiview(ima)) {
5442  BKE_image_free_views(ima);
5443  }
5444  }
5445 }
5446 
5449 /* -------------------------------------------------------------------- */
5454 {
5455  RenderSlot *slot = MEM_cnew<RenderSlot>("Image new Render Slot");
5456  if (name && name[0]) {
5457  BLI_strncpy(slot->name, name, sizeof(slot->name));
5458  }
5459  else {
5460  int n = BLI_listbase_count(&ima->renderslots) + 1;
5461  BLI_snprintf(slot->name, sizeof(slot->name), DATA_("Slot %d"), n);
5462  }
5463  BLI_addtail(&ima->renderslots, slot);
5464  return slot;
5465 }
5466 
5467 bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int slot)
5468 {
5469  if (slot == ima->last_render_slot) {
5470  /* Don't remove render slot while rendering to it. */
5471  if (G.is_rendering) {
5472  return false;
5473  }
5474  }
5475 
5476  int num_slots = BLI_listbase_count(&ima->renderslots);
5477  if (slot >= num_slots || num_slots == 1) {
5478  return false;
5479  }
5480 
5481  RenderSlot *remove_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot));
5482  RenderSlot *current_slot = static_cast<RenderSlot *>(
5483  BLI_findlink(&ima->renderslots, ima->render_slot));
5484  RenderSlot *current_last_slot = static_cast<RenderSlot *>(
5486 
5487  RenderSlot *next_slot;
5488  if (current_slot == remove_slot) {
5489  next_slot = static_cast<RenderSlot *>(
5490  BLI_findlink(&ima->renderslots, (slot == num_slots - 1) ? slot - 1 : slot + 1));
5491  }
5492  else {
5493  next_slot = current_slot;
5494  }
5495 
5496  /* If the slot to be removed is the slot with the last render,
5497  * make another slot the last render slot. */
5498  if (remove_slot == current_last_slot) {
5499  /* Choose the currently selected slot unless that one is being removed,
5500  * in that case take the next one. */
5501  RenderSlot *next_last_slot;
5502  if (current_slot == remove_slot) {
5503  next_last_slot = next_slot;
5504  }
5505  else {
5506  next_last_slot = current_slot;
5507  }
5508 
5509  if (iuser == nullptr || iuser->scene == nullptr) {
5510  return false;
5511  }
5512  Render *re = RE_GetSceneRender(iuser->scene);
5513  if (re != nullptr) {
5514  RE_SwapResult(re, &current_last_slot->render);
5515  RE_SwapResult(re, &next_last_slot->render);
5516  }
5517  current_last_slot = next_last_slot;
5518  }
5519 
5520  current_slot = next_slot;
5521 
5522  BLI_remlink(&ima->renderslots, remove_slot);
5523 
5524  ima->render_slot = BLI_findindex(&ima->renderslots, current_slot);
5525  ima->last_render_slot = BLI_findindex(&ima->renderslots, current_last_slot);
5526 
5527  if (remove_slot->render) {
5528  RE_FreeRenderResult(remove_slot->render);
5529  }
5530  MEM_freeN(remove_slot);
5531 
5532  return true;
5533 }
5534 
5535 bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int slot)
5536 {
5537  if (slot == ima->last_render_slot) {
5538  if (!iuser) {
5539  return false;
5540  }
5541  if (G.is_rendering) {
5542  return false;
5543  }
5544  Render *re = RE_GetSceneRender(iuser->scene);
5545  if (!re) {
5546  return false;
5547  }
5548  RE_ClearResult(re);
5549  return true;
5550  }
5551 
5552  RenderSlot *render_slot = static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, slot));
5553  if (!render_slot) {
5554  return false;
5555  }
5556  if (render_slot->render) {
5557  RE_FreeRenderResult(render_slot->render);
5558  render_slot->render = nullptr;
5559  }
5560  return true;
5561 }
5562 
5564 {
5565  /* Can be null for images without render slots. */
5566  return static_cast<RenderSlot *>(BLI_findlink(&ima->renderslots, index));
5567 }
5568 
typedef float(TangentPoint)[2]
bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path)
Definition: bpath.c:121
eBPathForeachFlag
Definition: BKE_bpath.h:27
@ BKE_BPATH_FOREACH_PATH_SKIP_PACKED
Definition: BKE_bpath.h:37
@ BKE_BPATH_FOREACH_PATH_RESOLVE_TOKEN
Definition: BKE_bpath.h:39
@ BKE_BPATH_FOREACH_PATH_RELOAD_EDITED
Definition: BKE_bpath.h:58
void BKE_color_managed_colorspace_settings_copy(struct ColorManagedColorspaceSettings *colorspace_settings, const struct ColorManagedColorspaceSettings *settings)
void BKE_color_managed_colorspace_settings_init(struct ColorManagedColorspaceSettings *colorspace_settings)
Definition: colortools.c:1882
@ G_FILE_AUTOPACK
Definition: BKE_global.h:209
#define G_MAIN
Definition: BKE_global.h:267
void BKE_icon_id_delete(struct ID *id)
Definition: icons.cc:870
void BKE_previewimg_free(struct PreviewImage **prv)
Definition: icons.cc:283
void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id)
void BKE_icon_changed(int icon_id)
Definition: icons.cc:637
void BKE_previewimg_blend_read(struct BlendDataReader *reader, struct PreviewImage *prv)
Definition: icons.cc:615
void BKE_previewimg_blend_write(struct BlendWriter *writer, const struct PreviewImage *prv)
int BKE_icon_id_ensure(struct ID *id)
Definition: icons.cc:699
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition: BKE_idtype.h:39
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition: BKE_idtype.h:41
void(* IDTypeForeachCacheFunctionCallback)(struct ID *id, const struct IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data)
Definition: BKE_idtype.h:77
eUDIM_TILE_FORMAT
Definition: BKE_image.h:378
@ UDIM_TILE_FORMAT_UVTILE
Definition: BKE_image.h:381
@ UDIM_TILE_FORMAT_NONE
Definition: BKE_image.h:379
@ UDIM_TILE_FORMAT_UDIM
Definition: BKE_image.h:380
void() StampCallback(void *data, const char *propname, char *propvalue, int len)
Definition: BKE_image.h:53
void BKE_image_partial_update_free(struct PartialUpdateUser *user)
free a partial update user.
#define IMA_MAX_SPACE
Definition: BKE_image.h:35
#define IMA_UDIM_MAX
Definition: BKE_image.h:36
void BKE_image_partial_update_mark_full_update(struct Image *image)
Mark the whole image to be updated.
void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int width, int height)
Definition: image_gen.c:445
void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
Definition: image_gen.c:196
#define IMA_SIGNAL_COLORMANAGE
Definition: BKE_image.h:135
#define IMA_SIGNAL_FREE
Definition: BKE_image.h:130
void BKE_image_partial_update_register_free(struct Image *image)
void BKE_image_free_gputextures(struct Image *ima)
Definition: image_gpu.cc:516
#define IMA_SIGNAL_SRC_CHANGE
Definition: BKE_image.h:132
#define IMA_SIGNAL_USER_NEW_IMAGE
Definition: BKE_image.h:134
#define IMA_SIGNAL_RELOAD
Definition: BKE_image.h:129
void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4])
Definition: image_gen.c:68
void BKE_image_format_from_imbuf(struct ImageFormatData *im_format, const struct ImBuf *imbuf)
void BKE_image_format_to_imbuf(struct ImBuf *ibuf, const struct ImageFormatData *imf)
int BKE_imtype_to_ftype(char imtype, struct ImbFormatOptions *r_options)
Definition: image_format.cc:69
@ LIB_ID_COPY_NO_PREVIEW
Definition: BKE_lib_id.h:150
void * BKE_libblock_alloc(struct Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition: lib_id.c:1050
void BKE_id_free(struct Main *bmain, void *idv)
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:260
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:562
#define SH_NODE_TEX_ENVIRONMENT
Definition: BKE_node.h:1128
#define TEX_NODE_IMAGE
Definition: BKE_node.h:1355
#define CMP_NODE_IMAGE
Definition: BKE_node.h:1215
void BKE_ntree_update_tag_id_changed(struct Main *bmain, struct ID *id)
void BKE_ntree_update_main(struct Main *bmain, struct NodeTreeUpdateExtraParams *params)
struct PackedFile * BKE_packedfile_new(struct ReportList *reports, const char *filepath, const char *basepath)
Definition: packedFile.c:177
struct PackedFile * BKE_packedfile_new_from_memory(void *mem, int memlen)
Definition: packedFile.c:166
struct PackedFile * BKE_packedfile_duplicate(const struct PackedFile *pf_src)
void BKE_packedfile_blend_write(struct BlendWriter *writer, struct PackedFile *pf)
Definition: packedFile.c:855
void BKE_packedfile_blend_read(struct BlendDataReader *reader, struct PackedFile **pf_p)
Definition: packedFile.c:864
void BKE_packedfile_free(struct PackedFile *pf)
Definition: packedFile.c:140
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd)
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv)
void BKE_render_resolution(const struct RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition: scene.cc:2960
void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char *name, char *r_prefix, const char **r_ext)
Definition: scene.cc:3233
const char * BKE_scene_find_last_marker_name(const struct Scene *scene, int frame)
int BKE_scene_multiview_num_views_get(const struct RenderData *rd)
struct bScreen * BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS
@ BLF_WORD_WRAP
Definition: BLF_api.h:340
void BLF_draw_buffer(int fontid, const char *str, size_t str_len) ATTR_NONNULL(2)
Definition: blf.c:881
int BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT
Definition: blf.c:744
int BLF_width_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition: blf.c:733
int blf_mono_font_render
Definition: blf.c:49
void BLF_disable(int fontid, int option)
Definition: blf.c:279
void BLF_buffer_col(int fontid, const float rgba[4]) ATTR_NONNULL(2)
Definition: blf.c:836
void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch, struct ColorManagedDisplay *display)
Definition: blf.c:816
void BLF_enable(int fontid, int option)
Definition: blf.c:270
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
Definition: blf.c:722
void BLF_size(int fontid, float size, int dpi)
Definition: blf.c:363
void BLF_wordwrap(int fontid, int wrap_width)
Definition: blf.c:787
void BLF_position(int fontid, float x, float y, float z)
Definition: blf.c:308
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define BLI_INLINE
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
#define O_BINARY
Definition: BLI_fileops.h:319
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
Definition: BLI_filelist.c:218
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
Definition: BLI_filelist.c:420
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:920
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
int BLI_listbase_count_at_most(const struct ListBase *listbase, int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:265
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:340
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE int integer_digits_i(int i)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void zero_v2(float r[2])
@ BLI_MEMPOOL_NOP
Definition: BLI_mempool.h:99
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition: BLI_mempool.c:253
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
Definition: BLI_mempool.c:319
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
Definition: BLI_mempool.c:707
const char * BLI_path_slash_find(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1750
bool BLI_path_extension_check_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1326
void BLI_split_dir_part(const char *string, char *dir, size_t dirlen)
Definition: path_util.c:1490
int BLI_path_sequence_decode(const char *string, char *head, char *tail, unsigned short *r_digits_len)
Definition: path_util.c:56
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1653
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1197
#define FILE_MAXFILE
void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen)
Definition: path_util.c:1465
#define FILE_MAX
bool BLI_path_extension_check(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1299
void BLI_path_sequence_encode(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
Definition: path_util.c:123
void BLI_split_file_part(const char *string, char *file, size_t filelen)
Definition: path_util.c:1495
bool BLI_path_extension_check_n(const char *str,...) ATTR_NONNULL(1) ATTR_SENTINEL(0)
Definition: path_util.c:1304
#define FILE_MAXDIR
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
#define BLI_path_cmp
void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1531
bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char *sep) ATTR_NONNULL()
Definition: path_util.c:588
#define STRNCPY(dst, src)
Definition: BLI_string.h:483
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:485
char * BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:448
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_hostname_get(char *buffer, size_t bufsize)
Definition: system.c:149
void BLI_task_isolate(void(*func)(void *userdata), void *userdata)
void BLI_thread_unlock(int type)
Definition: threads.cc:361
@ LOCK_DRAW_IMAGE
Definition: BLI_threads.h:67
@ LOCK_COLORMANAGE
Definition: BLI_threads.h:72
@ LOCK_VIEWER
Definition: BLI_threads.h:68
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:388
void BLI_thread_lock(int type)
Definition: threads.cc:356
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:368
int BLI_thread_is_main(void)
Definition: threads.cc:207
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:373
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:378
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:82
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxncpy, double time_seconds) ATTR_NONNULL()
Definition: timecode.c:169
size_t BLI_timecode_string_from_time(char *str, size_t maxncpy, int brevity_level, float time_seconds, double fps, short timecode_style) ATTR_NONNULL()
Definition: timecode.c:22
#define UNUSED_VARS(...)
#define POINTER_FROM_INT(i)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
const char * dirname(char *path)
#define BLO_read_data_address(reader, ptr_p)
bool BLO_read_data_is_undo(BlendDataReader *reader)
Definition: readfile.c:5288
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5172
#define BLO_write_struct_list(writer, struct_name, list_ptr)
bool BLO_write_is_undo(BlendWriter *writer)
Definition: writefile.c:1608
#define BLT_I18NCONTEXT_ID_IMAGE
#define DATA_(msgid)
#define CLOG_STR_ERROR(clg_ref, str)
Definition: CLG_log.h:196
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
void DEG_id_tag_update(struct ID *id, int flag)
float DEG_get_ctime(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ INDEX_ID_IM
Definition: DNA_ID.h:1007
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:561
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
#define FILTER_ID_IM
Definition: DNA_ID.h:906
@ ID_WM
Definition: DNA_ID_enums.h:72
@ ID_CA
Definition: DNA_ID_enums.h:56
@ ID_TE
Definition: DNA_ID_enums.h:52
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_LA
Definition: DNA_ID_enums.h:55
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_WO
Definition: DNA_ID_enums.h:59
@ ID_SIM
Definition: DNA_ID_enums.h:84
@ ID_MA
Definition: DNA_ID_enums.h:51
@ ID_OB
Definition: DNA_ID_enums.h:47
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
@ IMA_GENTYPE_GRID_COLOR
@ IMA_GENTYPE_GRID
@ IMA_DEINTERLACE
@ IMA_USER_FRAME_IN_RANGE
@ IMA_USE_VIEWS
@ IMA_VIEW_AS_RENDER
@ IMA_GEN_FLOAT
#define IMA_NEED_FRAME_RECALC
#define IMA_ANIM_ALWAYS
@ IMA_ALPHA_IGNORE
@ IMA_ALPHA_STRAIGHT
@ IMA_ALPHA_PREMUL
@ IMA_ALPHA_CHANNEL_PACKED
eImageSource
@ IMA_SRC_FILE
@ IMA_SRC_MOVIE
@ IMA_SRC_GENERATED
@ IMA_SRC_VIEWER
@ IMA_SRC_TILED
@ IMA_SRC_SEQUENCE
@ IMA_TYPE_MULTILAYER
@ IMA_TYPE_UV_TEST
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
@ IMA_TYPE_IMAGE
#define IMA_SHOW_STEREO
struct Image Image
@ TEXTARGET_2D_ARRAY
@ TEXTARGET_COUNT
@ TEXTARGET_TILE_MAPPING
#define NTREE_TEXTURE
#define NTREE_COMPOSIT
#define NTREE_SHADER
Object is a sort of wrapper for general info.
@ OB_EMPTY_IMAGE
@ OB_CAMERA
#define R_STAMP_ALL
#define STEREO_LEFT_NAME
#define R_STAMP_RENDERTIME
#define R_STAMP_HOSTNAME
#define R_MULTIVIEW
#define R_STAMP_MARKER
#define R_STAMP_MEMORY
#define R_STAMP_FRAME_RANGE
#define R_STAMP_HIDE_LABELS
#define R_STAMP_NOTE
#define R_STAMP_FRAME
#define R_STAMP_CAMERA
#define R_STAMP_DATE
#define STEREO_LEFT_SUFFIX
#define R_STAMP_FILENAME
#define RE_PASSNAME_Z
#define STEREO_RIGHT_NAME
#define STEREO_RIGHT_SUFFIX
#define R_STAMP_SCENE
#define FPS
@ R_IMF_VIEWS_STEREO_3D
@ R_IMF_VIEWS_INDIVIDUAL
#define R_STAMP_SEQSTRIP
#define R_STAMP_CAMERALENS
#define R_STAMP_TIME
#define FRA2TIME(a)
@ SPACE_IMAGE
#define IMG_SIZE_FALLBACK
@ USER_TIMECODE_SMPTE_FULL
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint * textures
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
ListBase GPU_material_textures(GPUMaterial *material)
Definition: gpu_material.c:221
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
@ COLOR_ROLE_DEFAULT_FLOAT
@ COLOR_ROLE_DATA
@ COLOR_ROLE_DEFAULT_BYTE
bool IMB_colormanagement_space_name_is_data(const char *name)
const char * IMB_colormanagement_colorspace_get_name(const struct ColorSpace *colorspace)
void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name)
struct ColorManagedDisplay * IMB_colormanagement_display_get_named(const char *name)
struct ImBuf * IMB_makeSingleUser(struct ImBuf *ibuf)
Definition: allocimbuf.c:227
bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
Definition: scaling.c:1644
void IMB_free_anim(struct anim *anim)
Definition: anim_movie.c:193
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
@ IMB_PROXY_NONE
Definition: IMB_imbuf.h:341
void imb_freerectImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:97
void IMB_refImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:220
struct anim * IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
Definition: anim_movie.c:268
void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2)
Definition: rectop.c:1128
void IMB_ImBufFromStereo3d(const struct Stereo3dFormat *s3d, struct ImBuf *ibuf_stereo, struct ImBuf **r_ibuf_left, struct ImBuf **r_ibuf_right)
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
Definition: readimage.c:209
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
Definition: readimage.c:84
struct ImBuf * IMB_anim_absolute(struct anim *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
Definition: anim_movie.c:1571
bool IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags)
Definition: writeimage.c:22
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
Definition: anim_movie.c:1658
@ IMB_TC_NONE
Definition: IMB_imbuf.h:318
@ IMB_TC_RECORD_RUN
Definition: IMB_imbuf.h:324
Contains defines and structs used throughout the imbuf module.
@ IB_PERSISTENT
@ IB_BITMAPDIRTY
@ IB_DISPLAY_BUFFER_INVALID
const char * imb_ext_movie[]
Definition: util.c:81
#define IMB_MIPMAP_LEVELS
@ IB_zbuf
@ IB_animdeinterlace
@ IB_alphamode_channel_packed
@ IB_alphamode_premul
@ IB_alphamode_ignore
@ IB_rectfloat
@ IB_metadata
@ IB_multilayer
@ IB_alphamode_detect
@ IB_zbuffloat
@ IB_mem
@ IB_test
@ IB_rect
void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value)
Definition: metadata.c:73
bool IMB_metadata_get_field(struct IDProperty *metadata, const char *key, char *value, size_t len)
Definition: metadata.c:44
void IMB_metadata_foreach(struct ImBuf *ibuf, IMBMetadataForeachCb callback, void *userdata)
Definition: metadata.c:91
void IMB_metadata_ensure(struct IDProperty **metadata)
Definition: metadata.c:25
void IMB_metadata_free(struct IDProperty *metadata)
Definition: metadata.c:35
struct MovieCache * IMB_moviecache_create(const char *name, int keysize, GHashHashFP hashfp, GHashCmpFP cmpfp)
Definition: moviecache.cc:265
struct ImBuf * IMB_moviecache_get(struct MovieCache *cache, void *userkey, bool *r_is_cached_empty)
Definition: moviecache.cc:401
void IMB_moviecache_set_getdata_callback(struct MovieCache *cache, MovieCacheGetKeyDataFP getdatafp)
Definition: moviecache.cc:292
void IMB_moviecacheIter_free(struct MovieCacheIter *iter)
Definition: moviecache.cc:585
void IMB_moviecache_remove(struct MovieCache *cache, void *userkey)
Definition: moviecache.cc:393
void IMB_moviecache_cleanup(struct MovieCache *cache, bool(cleanup_check_cb)(struct ImBuf *ibuf, void *userkey, void *userdata), void *userdata)
struct MovieCacheIter * IMB_moviecacheIter_new(struct MovieCache *cache)
Definition: moviecache.cc:575
void IMB_moviecache_put(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf)
Definition: moviecache.cc:367
void IMB_moviecache_free(struct MovieCache *cache)
Definition: moviecache.cc:444
bool IMB_moviecacheIter_done(struct MovieCacheIter *iter)
Definition: moviecache.cc:590
void IMB_moviecacheIter_step(struct MovieCacheIter *iter)
Definition: moviecache.cc:595
void * IMB_moviecacheIter_getUserKey(struct MovieCacheIter *iter)
Definition: moviecache.cc:606
struct ImBuf * IMB_moviecacheIter_getImBuf(struct MovieCacheIter *iter)
Definition: moviecache.cc:600
bool IMB_exr_has_multilayer(void *handle)
void IMB_exr_close(void *handle)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block TEX_IMAGE
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block SH_NODE_TEX_IMAGE
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
Platform independent time functions.
int pad[32 - sizeof(int)]
volatile int lock
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
short gpuflag
struct MovieCache * cache
struct ListBase packedfiles
struct PreviewImage * preview
char gen_type
short last_render_slot
Image_Runtime runtime
ListBase anims
ColorManagedColorspaceSettings colorspace_settings
int lastused
ListBase renderslots
char views_format
char filepath[1024]
int gpuframenr
ListBase tiles
short type
struct GPUTexture * gputexture[3][2]
short source
short render_slot
short gen_depth
struct RenderResult * rr
char gen_flag
ListBase views
char alpha_mode
int lastframe
struct Stereo3dFormat * stereo3d_format
float gen_color[4]
const T * data() const
Definition: BLI_array.hh:300
CCL_NAMESPACE_BEGIN struct Options options
OperationNode * node
FILE * file
double time
const char * label
Scene scene
World world
Simulation simulation
const Depsgraph * depsgraph
void * user_data
DEGForeachIDComponentCallback callback
SyclQueue void * dest
int len
Definition: draw_manager.c:108
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img image(1, GPU_R32F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_weight_img") .image(3
bNodeTree * ntree
#define str(s)
#define pf(_x, _i)
Prefetch 64.
Definition: gim_memory.h:48
void IMB_freeImBuf(ImBuf *UNUSED(ibuf))
eImbFileType
@ IMB_FTYPE_OPENEXR
@ IMB_FTYPE_PNG
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
const int tile_index
ccl_global const KernelWorkTile * tile
static char ** names
Definition: makesdna.c:65
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:26
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
static void area(int d1, int d2, int e1, int e2, float weights[2])
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
RenderResult * RE_AcquireResultRead(Render *re)
Definition: pipeline.c:314
void RE_ReleaseResultImage(Render *re)
Definition: pipeline.c:474
Render * RE_GetSceneRender(const Scene *scene)
Definition: pipeline.c:551
void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id)
Definition: pipeline.c:428
void RE_ClearResult(Render *re)
Definition: pipeline.c:335
void RE_SwapResult(Render *re, RenderResult **rr)
Definition: pipeline.c:343
void RE_FreeRenderResult(RenderResult *rr)
Definition: pipeline.c:233
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:351
RenderResult * RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
Definition: pipeline.c:258
RenderStats * RE_GetStats(Render *re)
Definition: pipeline.c:511
bool RE_RenderResult_is_stereo(const RenderResult *rr)
bool RE_HasCombinedLayer(const RenderResult *rr)
void BKE_imbuf_stamp_info(const RenderResult *rr, ImBuf *ibuf)
static void image_blend_read_lib(BlendLibReader *UNUSED(reader), ID *id)
int BKE_image_get_tile_from_pos(Image *ima, const float uv[2], float r_uv[2], float r_ofs[2])
static void image_init_color_management(Image *ima)
ImBuf * BKE_image_get_first_ibuf(Image *image)
static void image_free_tile(Image *ima, ImageTile *tile)
static RenderPass * image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
bool BKE_image_is_multilayer(const Image *ima)
ImageTile * BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser)
bool BKE_image_has_alpha(Image *image)
void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser)
static void image_walk_ntree_all_users(bNodeTree *ntree, ID *id, void *customdata, void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
void BKE_image_user_frame_calc(Image *ima, ImageUser *iuser, int cfra)
RenderSlot * BKE_image_get_renderslot(Image *ima, int index)
void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number)
static int image_num_viewfiles(Image *ima)
BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser)
void BKE_stamp_info_from_imbuf(RenderResult *rr, ImBuf *ibuf)
void BKE_image_alpha_mode_from_extension(Image *image)
static void image_viewer_create_views(const RenderData *rd, Image *ima)
void BKE_image_sort_tiles(struct Image *ima)
void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float r_size[2])
void BKE_image_free_buffers_ex(Image *ima, bool do_lock)
static void stampdata(const Scene *scene, Object *camera, StampData *stamp_data, int do_prefix, bool use_dynamic)
bool BKE_image_user_id_has_animation(ID *id)
bool BKE_image_has_filepath(const Image *ima)
void BKE_image_set_filepath_from_tile_number(char *filepath, const char *pattern, eUDIM_TILE_FORMAT tile_format, int tile_number)
static ImBuf * image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
ImageTile * BKE_image_get_tile(Image *ima, int tile_number)
void BKE_image_get_aspect(Image *image, float *r_aspx, float *r_aspy)
bool BKE_image_fill_tile(struct Image *ima, ImageTile *tile, int width, int height, const float color[4], int gen_type, int planes, bool is_float)
static void imagecache_keydata(void *userkey, int *framenr, int *proxy, int *render_flags)
static void metadata_copy_custom_fields(const char *field, const char *value, void *rr_v)
static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
#define BUFF_MARGIN_X
bool BKE_image_has_multiple_ibufs(Image *image)
static int tile_sort_cb(const void *a, const void *b)
static void image_remove_ibuf(Image *ima, int index, int entry)
void BKE_image_release_renderresult(Scene *scene, Image *ima)
static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry, int *r_index)
static void image_init_data(ID *id)
static ImBuf * add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], ColorManagedColorspaceSettings *colorspace_settings)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_free_data(Image *ima)
static bool imagecache_check_free_anim(ImBuf *ibuf, void *UNUSED(userkey), void *userdata)
static unsigned int imagecache_hashhash(const void *key_v)
static uintptr_t image_mem_size(Image *image)
static void image_tag_reload(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
void BKE_image_user_file_path(const ImageUser *iuser, const Image *ima, char *filepath)
static ImBuf * image_get_cached_ibuf_for_index_entry(Image *ima, int index, int entry, bool *r_is_cached_empty)
void BKE_image_tag_time(Image *ima)
static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
void BKE_image_merge(Main *bmain, Image *dest, Image *source)
static void image_user_id_has_animation(Image *ima, ID *UNUSED(iuser_id), ImageUser *UNUSED(iuser), void *customdata)
bool BKE_image_memorypack(Image *ima)
void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
#define IMA_MAKE_INDEX(entry, index)
Image * BKE_image_load(Main *bmain, const char *filepath)
void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, const size_t data_len)
static ImBuf * image_load_image_file(Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence)
bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
bool BKE_image_is_dirty(Image *image)
static const char * stamp_metadata_fields[]
void BKE_stamp_data_free(StampData *stamp_data)
struct StampData * BKE_stamp_info_from_scene_static(const Scene *scene)
void BKE_image_free_anim_ibufs(Image *ima, int except_frame)
Image * BKE_image_add_from_imbuf(Main *bmain, ImBuf *ibuf, const char *name)
void BKE_image_pool_free(ImagePool *pool)
int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, bool *r_is_in_range)
static void image_tag_frame_recalc(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata)
static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data)
static void stampdata_from_template(StampData *stamp_data, const Scene *scene, const StampData *stamp_data_template, bool do_prefix)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
ImagePool * BKE_image_pool_new(void)
#define CALL(member, value_str)
static void image_user_id_eval_animation(Image *ima, ID *UNUSED(iduser_id), ImageUser *iuser, void *customdata)
struct anim * openanim_noload(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
Image * BKE_image_load_exists(Main *bmain, const char *filepath)
static void image_editors_update_frame(Image *ima, ID *UNUSED(iuser_id), ImageUser *iuser, void *customdata)
static ImBuf * image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry, int *r_index, bool *r_is_cached_empty)
void BKE_image_free_packedfiles(Image *ima)
static void image_walk_id_all_users(ID *id, bool skip_nested_nodes, void *customdata, void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
void BKE_image_free_buffers(Image *ima)
void BKE_image_stamp_buf(Scene *scene, Object *camera, const StampData *stamp_data_template, unsigned char *rect, float *rectf, int width, int height, int channels)
static void image_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
void BKE_image_backup_render(Scene *scene, Image *ima, bool free_current_slot)
float * BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int tile)
#define BUFF_MARGIN_Y
void BKE_image_user_file_path_ex(const Main *bmain, const ImageUser *iuser, const Image *ima, char *filepath, const bool resolve_udim, const bool resolve_multiview)
bool BKE_image_get_tile_number_from_filepath(const char *filepath, const char *pattern, eUDIM_TILE_FORMAT tile_format, int *r_tile_number)
StampData * BKE_stamp_data_copy(const StampData *stamp_data)
bool BKE_image_has_opengl_texture(Image *ima)
static ImBuf * image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
static void image_free_anims(Image *ima)
bool BKE_image_scale(Image *image, int width, int height)
BLI_INLINE ImBuf * image_pool_find_item(ImagePool *pool, Image *image, int entry, int index, bool *found)
void BKE_image_get_tile_uv(const Image *ima, const int tile_number, float r_uv[2])
int BKE_imbuf_write(ImBuf *ibuf, const char *name, const ImageFormatData *imf)
struct anim * openanim(const char *name, int flags, int streamindex, char colorspace[IMA_MAX_SPACE])
bool BKE_imbuf_alpha_test(ImBuf *ibuf)
static void image_assign_ibuf(Image *ima, ImBuf *ibuf, int index, int entry)
static void image_walk_gpu_materials(ID *id, ListBase *gpu_materials, void *customdata, void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
static int image_get_tile_number_from_iuser(const Image *ima, const ImageUser *iuser)
void BKE_imageuser_default(ImageUser *iuser)
bool BKE_image_has_anim(Image *ima)
#define TEXT_SIZE_CHECK(str, w, h)
RenderSlot * BKE_image_add_renderslot(Image *ima, const char *name)
static ImBuf * image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_free_all_textures(Main *bmain)
ImBuf * BKE_image_get_ibuf_with_name(Image *image, const char *name)
void BKE_image_get_tile_label(Image *ima, ImageTile *tile, char *label, int len_label)
static int imbuf_alpha_flags_for_image(Image *ima)
void BKE_image_ensure_tile_token(char *filename)
Image * BKE_image_load_exists_ex(Main *bmain, const char *filepath, bool *r_exists)
int BKE_image_sequence_guess_offset(Image *image)
bool BKE_image_is_stereo(const Image *ima)
static ImBuf * image_get_render_result(Image *ima, ImageUser *iuser, void **r_lock)
bool BKE_image_is_multiview(const Image *ima)
void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip)
void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height)
static void imagecache_put(Image *image, int index, ImBuf *ibuf)
void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderResult *rr, bool allocate_only)
static void image_free_data(ID *id)
static bool image_memorypack_imbuf(Image *ima, ImBuf *ibuf, int view, int tile_number, const char *filepath)
static void image_runtime_reset(struct Image *image)
static void image_update_views_format(Image *ima, ImageUser *iuser)
bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, int *r_tile_range)
bool BKE_image_is_openexr(struct Image *ima)
static void image_free_packedfiles(Image *ima)
static void image_init_after_load(Image *ima, ImageUser *iuser, ImBuf *UNUSED(ibuf))
char BKE_image_alpha_mode_from_extension_ex(const char *filepath)
void BKE_image_free_views(Image *image)
void BKE_image_all_free_anim_ibufs(Main *bmain, int cfra)
void BKE_image_walk_all_users(const Main *mainp, void *customdata, void callback(Image *ima, ID *iuser_id, ImageUser *iuser, void *customdata))
RenderResult * BKE_image_acquire_renderresult(Scene *scene, Image *ima)
bool BKE_image_remove_renderslot(Image *ima, ImageUser *iuser, int slot)
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
static void image_colorspace_from_imbuf(Image *image, const ImBuf *ibuf)
void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char *value)
static bool imagecache_check_dirty(ImBuf *ibuf, void *UNUSED(userkey), void *UNUSED(userdata))
static void image_blend_read_data(BlendDataReader *reader, ID *id)
int BKE_imbuf_write_stamp(const Scene *scene, const struct RenderResult *rr, ImBuf *ibuf, const char *name, const struct ImageFormatData *imf)
bool BKE_image_is_animated(Image *image)
bool BKE_stamp_is_known_field(const char *field_name)
bool BKE_image_clear_renderslot(Image *ima, ImageUser *iuser, int slot)
bool BKE_image_is_filename_tokenized(char *filepath)
int BKE_image_find_nearest_tile_with_offset(const Image *image, const float co[2], float r_uv_offset[2])
RenderPass * BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
static bool imagecache_hashcmp(const void *a_v, const void *b_v)
static ImBuf * image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
static void imagecache_remove(Image *image, int index)
void BKE_image_user_id_eval_animation(Depsgraph *depsgraph, ID *id)
static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
char * BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_tile_format)
static CLG_LogRef LOG
void BKE_image_mark_dirty(Image *UNUSED(image), ImBuf *ibuf)
void BKE_image_editors_update_frame(const Main *bmain, int cfra)
void BKE_image_replace_imbuf(Image *image, ImBuf *ibuf)
void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
#define IMA_INDEX_ENTRY(index)
#define TEXT_SIZE_CHECK_WORD_WRAP(str, w, h)
static void image_buf_fill_isolated(void *usersata_v)
static struct ImBuf * imagecache_get(Image *image, int index, bool *r_is_cached_empty)
constexpr IDTypeInfo get_type_info()
unsigned char * BKE_image_get_pixels_for_frame(struct Image *image, int frame, int tile)
static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address)
static Image * image_alloc(Main *bmain, const char *name, short source, short type)
Image * BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d, const bool is_data, const bool tiled)
static void image_free_cached_frames(Image *image)
static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, const ImageFormatData *imf, const bool save_copy)
void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options)
static void image_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
static void image_runtime_free_data(struct Image *image)
ImageTile * BKE_image_add_tile(struct Image *ima, int tile_number, const char *label)
static int image_get_multiview_index(Image *ima, ImageUser *iuser)
ImBuf * BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
static void image_add_view(Image *ima, const char *viewname, const char *filepath)
bool BKE_image_has_ibuf(Image *ima, ImageUser *iuser)
bool BKE_image_has_packedfile(const Image *ima)
static ImBuf * load_image_single(Image *ima, ImageUser *iuser, int cfra, const int view_id, const bool has_packed, const bool is_sequence, bool *r_cache_ibuf)
void BKE_image_multiview_index(const Image *ima, ImageUser *iuser)
bool BKE_image_has_loaded_ibuf(Image *image)
static void image_runtime_reset_on_copy(struct Image *image)
int BKE_image_find_nearest_tile(const struct Image *image, const float co[2])
bool BKE_image_tile_filepath_exists(const char *filepath)
static ImBuf * load_movie_single(Image *ima, ImageUser *iuser, int frame, const int view_id)
void BKE_image_print_memlist(Main *bmain)
bool BKE_image_is_dirty_writable(Image *image, bool *r_is_writable)
static void image_init(Image *ima, short source, short type)
Image * BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
bool BKE_image_buffer_format_writable(ImBuf *ibuf)
_W64 unsigned int uintptr_t
Definition: stdint.h:119
eBPathForeachFlag flag
Definition: BKE_bpath.h:78
struct Main * bmain
Definition: BKE_bpath.h:75
struct ListBase bg_images
unsigned int id_session_uuid
Definition: BKE_idtype.h:46
size_t offset_in_ID
Definition: BKE_idtype.h:49
short id_code
Definition: BKE_idtype.h:114
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
int us
Definition: DNA_ID.h:388
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
struct IDProperty * metadata
void * userdata
struct ImBuf * mipmap[IMB_MIPMAP_LEVELS]
float * zbuf_float
int channels
int userflags
struct ColorSpace * rect_colorspace
ImbFormatOptions foptions
unsigned char * encodedbuffer
float dither
unsigned char planes
char name[IMB_FILENAME_SIZE]
enum eImbFileType ftype
unsigned int * rect
unsigned int encodedsize
float * rect_float
struct ColorSpace * float_colorspace
struct anim * anim
struct PackedFile * packedfile
struct ImagePackedFile * next
char filepath[1024]
struct ImageTile * next
char multiview_eye
short multi_index
struct Scene * scene
char name[64]
char filepath[1024]
struct ImageView * next
struct ImageView * prev
struct PartialUpdateUser * partial_update_user
Partial update user for GPUTextures stored inside the Image.
struct PartialUpdateRegister * partial_update_register
Register containing partial updates.
short use_nodes
struct bNodeTree * nodetree
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase scenes
Definition: BKE_main.h:168
ListBase wm
Definition: BKE_main.h:197
ListBase textures
Definition: BKE_main.h:175
char filepath[1024]
Definition: BKE_main.h:124
ListBase nodetrees
Definition: BKE_main.h:192
ListBase materials
Definition: BKE_main.h:174
ListBase cameras
Definition: BKE_main.h:179
ListBase images
Definition: BKE_main.h:176
ListBase objects
Definition: BKE_main.h:170
struct bNodeTree * nodetree
ListBase gpumaterial
char empty_drawtype
ImageUser * iuser
void * data
char stamp_udata[768]
float fg_stamp[4]
short stamp_font_id
float bg_stamp[4]
float dither_intensity
ListBase views
ListBase passes
Definition: RE_pipeline.h:95
struct RenderLayer * next
Definition: RE_pipeline.h:84
char name[64]
Definition: RE_pipeline.h:65
int channels
Definition: RE_pipeline.h:64
float * rect
Definition: RE_pipeline.h:67
struct RenderPass * next
Definition: RE_pipeline.h:63
ListBase views
Definition: RE_pipeline.h:125
ListBase layers
Definition: RE_pipeline.h:122
struct StampData * stamp_data
Definition: RE_pipeline.h:141
struct RenderResult * render
char name[64]
float mem_peak
Definition: RE_pipeline.h:152
double lastframetime
Definition: RE_pipeline.h:149
float * rectf
Definition: RE_pipeline.h:54
float * rectz
Definition: RE_pipeline.h:56
int * rect32
Definition: RE_pipeline.h:58
struct RenderView * next
Definition: RE_pipeline.h:50
char name[64]
Definition: RE_pipeline.h:51
struct SceneRenderView * next
struct bNodeTree * nodetree
struct RenderData r
char use_nodes
ColorManagedDisplaySettings display_settings
struct bNodeTree * nodetree
struct ImageUser iuser
struct Image * image
char use_nodes
struct ImageUser iuser
short type
struct bNodeTree * nodetree
struct Image * ima
struct bNodeTree * nodetree
ListBase gpumaterial
short use_nodes
Definition: IMB_anim.h:71
char colorspace[64]
Definition: IMB_anim.h:138
int streamindex
Definition: IMB_anim.h:93
char name[1024]
Definition: IMB_anim.h:82
ListBase nodes
ListBase areabase
const char * relname
const char * path
long int PIL_check_seconds_timer_i(void)
Definition: time.c:74
const Sequence * SEQ_get_topmost_sequence(const Scene *scene, int frame)
Definition: utils.c:338