Blender V5.0
image_sequence.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_path_utils.hh"
15#include "BLI_string.h"
16#include "BLI_utildefines.h"
17
19
20#include "RNA_access.hh"
21
22#include "BKE_image.hh"
23
24#include "ED_image.hh"
25
32static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges, bool *r_was_relative)
33{
34 char dir[FILE_MAXDIR];
35 const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
36 ImageFrameRange *range = nullptr;
37 int range_first_frame = 0;
38 /* Track when a new series of files are found that aren't compatible with the previous file. */
39 char base_head[FILE_MAX], base_tail[FILE_MAX];
40
41 RNA_string_get(op->ptr, "directory", dir);
42 RNA_BEGIN (op->ptr, itemptr, "files") {
43 char head[FILE_MAX], tail[FILE_MAX];
44 ushort digits;
45 char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
46 ImageFrame *frame = MEM_callocN<ImageFrame>("image_frame");
47
48 /* use the first file in the list as base filename */
50 filename, head, sizeof(head), tail, sizeof(tail), &digits);
51
52 /* still in the same sequence */
53 if (do_frame_range && (range != nullptr) && STREQLEN(base_head, head, FILE_MAX) &&
54 STREQLEN(base_tail, tail, FILE_MAX))
55 {
56 /* Set filepath to first frame in the range. */
57 if (frame->framenr < range_first_frame) {
58 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
59 range_first_frame = frame->framenr;
60 }
61 }
62 else {
63 /* start a new frame range */
64 range = MEM_callocN<ImageFrameRange>(__func__);
65 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
66 BLI_addtail(ranges, range);
67
68 STRNCPY(base_head, head);
69 STRNCPY(base_tail, tail);
70
71 range_first_frame = frame->framenr;
72 }
73
74 BLI_addtail(&range->frames, frame);
75 MEM_freeN(filename);
76 }
77 RNA_END;
78
79 *r_was_relative = BLI_path_is_rel(dir);
80}
81
82static int image_cmp_frame(const void *a, const void *b)
83{
84 const ImageFrame *frame_a = static_cast<const ImageFrame *>(a);
85 const ImageFrame *frame_b = static_cast<const ImageFrame *>(b);
86
87 if (frame_a->framenr < frame_b->framenr) {
88 return -1;
89 }
90 if (frame_a->framenr > frame_b->framenr) {
91 return 1;
92 }
93 return 0;
94}
95
100static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
101{
102 /* UDIM detection relies on the paths resolving on the file-system (being absolute). */
104
105 /* UDIM */
106 if (detect_udim) {
107 int udim_start, udim_range;
109 range->filepath, &range->udim_tiles, &udim_start, &udim_range);
110
111 if (range->udims_detected) {
112 range->offset = udim_start;
113 range->length = udim_range;
114 return;
115 }
116 }
117
118 /* Image Sequence */
120
121 ImageFrame *frame = static_cast<ImageFrame *>(range->frames.first);
122 if (frame != nullptr) {
123 int frame_curr = frame->framenr;
124 range->offset = frame_curr;
125
126 while (frame != nullptr && (frame->framenr == frame_curr)) {
127 frame_curr++;
128 frame = frame->next;
129 }
130
131 range->length = frame_curr - range->offset;
132 }
133 else {
134 range->length = 1;
135 range->offset = 0;
136 }
137
138 ImageFrame *frame_last = static_cast<ImageFrame *>(range->frames.last);
139 if (frame_last != nullptr) {
140 range->max_framenr = frame_last->framenr;
141 }
142}
143
145 blender::StringRefNull root_path,
146 wmOperator *op,
147 const bool detect_udim)
148{
149 ListBase ranges;
150 BLI_listbase_clear(&ranges);
151
152 bool was_relative = false;
153
154 /* File browser. */
155 if (RNA_struct_property_is_set(op->ptr, "directory") &&
156 RNA_struct_property_is_set(op->ptr, "files"))
157 {
158 image_sequence_get_frame_ranges(op, &ranges, &was_relative);
159 }
160 /* Filepath property for drag & drop etc. */
161 else {
162 char filepath[FILE_MAX];
163 RNA_string_get(op->ptr, "filepath", filepath);
164
166 BLI_addtail(&ranges, range);
167
168 STRNCPY(range->filepath, filepath);
169 was_relative = BLI_path_is_rel(filepath);
170 }
171
172 LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
173 if (was_relative) {
174 BLI_path_abs(range->filepath, blendfile_path.c_str());
175 }
176 image_detect_frame_range(range, detect_udim);
177 if (was_relative) {
178 BLI_path_rel(range->filepath, root_path.c_str());
179 }
180 }
181
182 return ranges;
183}
bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, int *r_tile_range)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
#define FILE_MAX
#define BLI_path_join(...)
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
int BLI_path_sequence_decode(const char *path, char *head, size_t head_maxncpy, char *tail, size_t tail_maxncpy, unsigned short *r_digits_len)
Definition path_utils.cc:58
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
#define FILE_MAXDIR
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
unsigned short ushort
#define STREQLEN(a, b, n)
Read Guarded memory(de)allocation.
#define RNA_BEGIN(sptr, itemptr, propname)
#define RNA_END
constexpr const char * c_str() const
ListBase ED_image_filesel_detect_sequences(blender::StringRefNull blendfile_path, blender::StringRefNull root_path, wmOperator *op, const bool detect_udim)
static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges, bool *r_was_relative)
static int image_cmp_frame(const void *a, const void *b)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
ListBase frames
Definition ED_image.hh:211
char filepath[FILE_MAX]
Definition ED_image.hh:200
ListBase udim_tiles
Definition ED_image.hh:208
ImageFrame * next
Definition ED_image.hh:215
void * last
void * first
struct PointerRNA * ptr