Blender V4.3
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
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_fileops_types.h"
14#include "BLI_listbase.h"
15#include "BLI_math_base.h"
16#include "BLI_path_utils.hh"
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "DNA_image_types.h"
22
23#include "RNA_access.hh"
24
25#include "BKE_image.hh"
26#include "BKE_main.hh"
27
28#include "ED_image.hh"
29
34
42{
43 char dir[FILE_MAXDIR];
44 const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
45 ImageFrameRange *range = nullptr;
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", nullptr, 0, nullptr);
55 ImageFrame *frame = static_cast<ImageFrame *>(MEM_callocN(sizeof(ImageFrame), "image_frame"));
56
57 /* use the first file in the list as base filename */
59 filename, head, sizeof(head), tail, sizeof(tail), &digits);
60
61 /* still in the same sequence */
62 if (do_frame_range && (range != nullptr) && STREQLEN(base_head, head, FILE_MAX) &&
63 STREQLEN(base_tail, tail, FILE_MAX))
64 {
65 /* Set filepath to first frame in the range. */
66 if (frame->framenr < range_first_frame) {
67 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
68 range_first_frame = frame->framenr;
69 }
70 }
71 else {
72 /* start a new frame range */
73 range = static_cast<ImageFrameRange *>(MEM_callocN(sizeof(*range), __func__));
74 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
75 BLI_addtail(ranges, range);
76
77 STRNCPY(base_head, head);
78 STRNCPY(base_tail, tail);
79
80 range_first_frame = frame->framenr;
81 }
82
83 BLI_addtail(&range->frames, frame);
84 MEM_freeN(filename);
85 }
86 RNA_END;
87}
88
89static int image_cmp_frame(const void *a, const void *b)
90{
91 const ImageFrame *frame_a = static_cast<const ImageFrame *>(a);
92 const ImageFrame *frame_b = static_cast<const ImageFrame *>(b);
93
94 if (frame_a->framenr < frame_b->framenr) {
95 return -1;
96 }
97 if (frame_a->framenr > frame_b->framenr) {
98 return 1;
99 }
100 return 0;
101}
102
107static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
108{
109 /* UDIM */
110 if (detect_udim) {
111 int udim_start, udim_range;
112 range->udims_detected = BKE_image_get_tile_info(
113 range->filepath, &range->udim_tiles, &udim_start, &udim_range);
114
115 if (range->udims_detected) {
116 range->offset = udim_start;
117 range->length = udim_range;
118 return;
119 }
120 }
121
122 /* Image Sequence */
123 BLI_listbase_sort(&range->frames, image_cmp_frame);
124
125 ImageFrame *frame = static_cast<ImageFrame *>(range->frames.first);
126 if (frame != nullptr) {
127 int frame_curr = frame->framenr;
128 range->offset = frame_curr;
129
130 while (frame != nullptr && (frame->framenr == frame_curr)) {
131 frame_curr++;
132 frame = frame->next;
133 }
134
135 range->length = frame_curr - range->offset;
136 }
137 else {
138 range->length = 1;
139 range->offset = 0;
140 }
141}
142
144 wmOperator *op,
145 const bool detect_udim)
146{
147 ListBase ranges;
148 BLI_listbase_clear(&ranges);
149
150 char filepath[FILE_MAX];
151 RNA_string_get(op->ptr, "filepath", filepath);
152
153 /* File browser. */
154 if (RNA_struct_property_is_set(op->ptr, "directory") &&
155 RNA_struct_property_is_set(op->ptr, "files"))
156 {
157 const bool was_relative = BLI_path_is_rel(filepath);
158
160 LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
161 image_detect_frame_range(range, detect_udim);
162 BLI_freelistN(&range->frames);
163
164 if (was_relative) {
165 BLI_path_rel(range->filepath, root_path.c_str());
166 }
167 }
168 }
169 /* Filepath property for drag & drop etc. */
170 else {
171 ImageFrameRange *range = static_cast<ImageFrameRange *>(MEM_callocN(sizeof(*range), __func__));
172 BLI_addtail(&ranges, range);
173
174 STRNCPY(range->filepath, filepath);
175 image_detect_frame_range(range, detect_udim);
176 }
177
178 return ranges;
179}
bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, int *r_tile_range)
Some types for dealing with directories.
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
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.cc:110
#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:57
bool void BLI_path_rel(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1)
#define FILE_MAXDIR
#define STRNCPY(dst, src)
Definition BLI_string.h:593
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
local_group_size(16, 16) .push_constant(Type b
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(blender::StringRefNull root_path, wmOperator *op, const bool detect_udim)
static int image_cmp_frame(const void *a, const void *b)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
ImageFrame * next
ImageFrame * prev
struct PointerRNA * ptr