Blender V4.5
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
30
38{
39 char dir[FILE_MAXDIR];
40 const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
41 ImageFrameRange *range = nullptr;
42 int range_first_frame = 0;
43 /* Track when a new series of files are found that aren't compatible with the previous file. */
44 char base_head[FILE_MAX], base_tail[FILE_MAX];
45
46 RNA_string_get(op->ptr, "directory", dir);
47 RNA_BEGIN (op->ptr, itemptr, "files") {
48 char head[FILE_MAX], tail[FILE_MAX];
49 ushort digits;
50 char *filename = RNA_string_get_alloc(&itemptr, "name", nullptr, 0, nullptr);
51 ImageFrame *frame = MEM_callocN<ImageFrame>("image_frame");
52
53 /* use the first file in the list as base filename */
55 filename, head, sizeof(head), tail, sizeof(tail), &digits);
56
57 /* still in the same sequence */
58 if (do_frame_range && (range != nullptr) && STREQLEN(base_head, head, FILE_MAX) &&
59 STREQLEN(base_tail, tail, FILE_MAX))
60 {
61 /* Set filepath to first frame in the range. */
62 if (frame->framenr < range_first_frame) {
63 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
64 range_first_frame = frame->framenr;
65 }
66 }
67 else {
68 /* start a new frame range */
69 range = MEM_callocN<ImageFrameRange>(__func__);
70 BLI_path_join(range->filepath, sizeof(range->filepath), dir, filename);
71 BLI_addtail(ranges, range);
72
73 STRNCPY(base_head, head);
74 STRNCPY(base_tail, tail);
75
76 range_first_frame = frame->framenr;
77 }
78
79 BLI_addtail(&range->frames, frame);
80 MEM_freeN(filename);
81 }
82 RNA_END;
83}
84
85static int image_cmp_frame(const void *a, const void *b)
86{
87 const ImageFrame *frame_a = static_cast<const ImageFrame *>(a);
88 const ImageFrame *frame_b = static_cast<const ImageFrame *>(b);
89
90 if (frame_a->framenr < frame_b->framenr) {
91 return -1;
92 }
93 if (frame_a->framenr > frame_b->framenr) {
94 return 1;
95 }
96 return 0;
97}
98
103static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
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
140 wmOperator *op,
141 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 {
153 const bool was_relative = BLI_path_is_rel(filepath);
154
156 LISTBASE_FOREACH (ImageFrameRange *, range, &ranges) {
157 image_detect_frame_range(range, detect_udim);
158 BLI_freelistN(&range->frames);
159
160 if (was_relative) {
161 BLI_path_rel(range->filepath, root_path.c_str());
162 }
163 }
164 }
165 /* Filepath property for drag & drop etc. */
166 else {
168 BLI_addtail(&ranges, range);
169
170 STRNCPY(range->filepath, filepath);
171 image_detect_frame_range(range, detect_udim);
172 }
173
174 return ranges;
175}
bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *r_tile_start, int *r_tile_range)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
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
#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
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
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
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_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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)
ListBase frames
Definition ED_image.hh:204
char filepath[FILE_MAX]
Definition ED_image.hh:195
ListBase udim_tiles
Definition ED_image.hh:201
ImageFrame * next
ImageFrame * prev
void * first
struct PointerRNA * ptr