Blender  V3.3
image_sequence.c
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 <string.h>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_fileops.h"
13 #include "BLI_fileops_types.h"
14 #include "BLI_listbase.h"
15 #include "BLI_math_base.h"
16 #include "BLI_path_util.h"
17 #include "BLI_string.h"
18 #include "BLI_utildefines.h"
19 
20 #include "DNA_image_types.h"
22 
23 #include "RNA_access.h"
24 
25 #include "BKE_image.h"
26 #include "BKE_main.h"
27 
28 #include "ED_image.h"
29 
30 typedef struct ImageFrame {
31  struct ImageFrame *next, *prev;
32  int framenr;
34 
42 {
43  char dir[FILE_MAXDIR];
44  const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
45  ImageFrameRange *range = NULL;
46  int range_first_frame = 0;
47  /* Track when a new series of files are found that aren't compatible with the previous file. */
48  char base_head[FILE_MAX], base_tail[FILE_MAX];
49 
50  RNA_string_get(op->ptr, "directory", dir);
51  RNA_BEGIN (op->ptr, itemptr, "files") {
52  char head[FILE_MAX], tail[FILE_MAX];
53  ushort digits;
54  char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0, NULL);
55  ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
56 
57  /* use the first file in the list as base filename */
58  frame->framenr = BLI_path_sequence_decode(filename, head, tail, &digits);
59 
60  /* still in the same sequence */
61  if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
62  (STREQLEN(base_tail, tail, FILE_MAX))) {
63  /* Set filepath to first frame in the range. */
64  if (frame->framenr < range_first_frame) {
65  BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
66  range_first_frame = frame->framenr;
67  }
68  }
69  else {
70  /* start a new frame range */
71  range = MEM_callocN(sizeof(*range), __func__);
72  BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
73  BLI_addtail(ranges, range);
74 
75  BLI_strncpy(base_head, head, sizeof(base_head));
76  BLI_strncpy(base_tail, tail, sizeof(base_tail));
77 
78  range_first_frame = frame->framenr;
79  }
80 
81  BLI_addtail(&range->frames, frame);
82  MEM_freeN(filename);
83  }
84  RNA_END;
85 }
86 
87 static int image_cmp_frame(const void *a, const void *b)
88 {
89  const ImageFrame *frame_a = a;
90  const ImageFrame *frame_b = b;
91 
92  if (frame_a->framenr < frame_b->framenr) {
93  return -1;
94  }
95  if (frame_a->framenr > frame_b->framenr) {
96  return 1;
97  }
98  return 0;
99 }
100 
105 static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
106 {
107  /* UDIM */
108  if (detect_udim) {
109  int udim_start, udim_range;
111  range->filepath, &range->udim_tiles, &udim_start, &udim_range);
112 
113  if (range->udims_detected) {
114  range->offset = udim_start;
115  range->length = udim_range;
116  return;
117  }
118  }
119 
120  /* Image Sequence */
122 
123  ImageFrame *frame = range->frames.first;
124  if (frame != NULL) {
125  int frame_curr = frame->framenr;
126  range->offset = frame_curr;
127 
128  while (frame != NULL && (frame->framenr == frame_curr)) {
129  frame_curr++;
130  frame = frame->next;
131  }
132 
133  range->length = frame_curr - range->offset;
134  }
135  else {
136  range->length = 1;
137  range->offset = 0;
138  }
139 }
140 
141 ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim)
142 {
143  ListBase ranges;
144  BLI_listbase_clear(&ranges);
145 
146  char filepath[FILE_MAX];
147  RNA_string_get(op->ptr, "filepath", filepath);
148 
149  /* File browser. */
150  if (RNA_struct_property_is_set(op->ptr, "directory") &&
151  RNA_struct_property_is_set(op->ptr, "files")) {
152  const bool was_relative = BLI_path_is_rel(filepath);
153 
154  image_sequence_get_frame_ranges(op, &ranges);
155  LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
156  image_detect_frame_range(range, detect_udim);
157  BLI_freelistN(&range->frames);
158 
159  if (was_relative) {
160  BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain));
161  }
162  }
163  }
164  /* Filepath property for drag & drop etc. */
165  else {
166  ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__);
167  BLI_addtail(&ranges, range);
168 
169  BLI_strncpy(range->filepath, filepath, FILE_MAX);
170  image_detect_frame_range(range, detect_udim);
171  }
172 
173  return ranges;
174 }
bool BKE_image_get_tile_info(char *filepath, struct ListBase *tiles, int *r_tile_start, int *r_tile_range)
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
File and directory operations.
Some types for dealing with directories.
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
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
int BLI_path_sequence_decode(const char *string, char *head, char *tail, unsigned short *r_digits_len)
Definition: path_util.c:56
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
#define FILE_MAX
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL()
Definition: path_util.c:450
#define FILE_MAXDIR
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
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
unsigned short ushort
Definition: BLI_sys_types.h:68
#define STREQLEN(a, b, n)
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
Definition: RNA_access.h:543
#define RNA_END
Definition: RNA_access.h:550
static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim)
static int image_cmp_frame(const void *a, const void *b)
struct ImageFrame ImageFrame
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:5129
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
ListBase frames
Definition: ED_image.h:215
char filepath[FILE_MAX]
Definition: ED_image.h:206
bool udims_detected
Definition: ED_image.h:211
ListBase udim_tiles
Definition: ED_image.h:212
struct ImageFrame * next
struct ImageFrame * prev
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct PointerRNA * ptr