1 // weed-effects-utils.c
2 // - will probaly become libweed-effects-utils or something
3 // LiVES
4 // (c) G. Finch 2003 - 2019 <salsaman+lives@gmail.com>
5 // released under the GNU GPL 3 or later
6 // see file ../COPYING for licensing details
7
8 // weed filter utility functions
9
10 // TODO: get in_paramtmpl(ptmpl, n)
11 /// get_colorspace
12 /// get_max / min
13
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17
18 #include "main.h" // TODO
19
20 #if NEED_LOCAL_WEED
21 #include "../libweed/weed-host.h"
22 #include "../libweed/weed.h"
23 #include "../libweed/weed-utils.h"
24 #include "../libweed/weed-effects.h"
25 #include "../libweed/weed-palettes.h"
26 #else
27 #include <weed/weed-host.h>
28 #include <weed/weed.h>
29 #include <weed/weed-utils.h>
30 #include <weed/weed-effects.h>
31 #include <weed/weed-palettes.h>
32 #endif
33
34 #include "weed-effects-utils.h"
35
36 #ifndef WEED_GLOBAL_INLINE
37 #define WEED_GLOBAL_INLINE inline
38 #endif
39
40 #ifndef WEED_LOCAL_INLINE
41 #define WEED_LOCAL_INLINE static inline
42 #endif
43
weed_plant_get_type(weed_plant_t * plant)44 WEED_GLOBAL_INLINE int32_t weed_plant_get_type(weed_plant_t *plant) {
45 if (!plant) return WEED_PLANT_UNKNOWN;
46 return weed_get_int_value(plant, WEED_LEAF_TYPE, NULL);
47 }
48
weed_leaf_set_flagbits(weed_plant_t * plant,const char * leaf,uint32_t flagbits)49 WEED_GLOBAL_INLINE uint32_t weed_leaf_set_flagbits(weed_plant_t *plant, const char *leaf, uint32_t flagbits) {
50 uint32_t flags = 0;
51 if (plant) {
52 flags = weed_leaf_get_flags(plant, leaf);
53 weed_leaf_set_flags(plant, leaf, flags | flagbits);
54 }
55 return flags;
56 }
57
weed_leaf_clear_flagbits(weed_plant_t * plant,const char * leaf,uint32_t flagbits)58 WEED_GLOBAL_INLINE uint32_t weed_leaf_clear_flagbits(weed_plant_t *plant, const char *leaf, uint32_t flagbits) {
59 uint32_t flags = 0;
60 if (plant) {
61 flags = weed_leaf_get_flags(plant, leaf);
62 weed_leaf_set_flags(plant, leaf, flags & ~flagbits);
63 }
64 return flags;
65 }
66
weed_add_plant_flags(weed_plant_t * plant,uint32_t flags,const char * ign_prefix)67 void weed_add_plant_flags(weed_plant_t *plant, uint32_t flags, const char *ign_prefix) {
68 if (!plant) return;
69 else {
70 size_t ign_prefix_len = 0;
71 char **leaves = weed_plant_list_leaves(plant, NULL);
72 if (leaves) {
73 if (ign_prefix) ign_prefix_len = strlen(ign_prefix);
74 for (register int i = 0; leaves[i]; i++) {
75 if (!ign_prefix || strncmp(leaves[i], ign_prefix, ign_prefix_len)) {
76 weed_leaf_set_flagbits(plant, leaves[i], flags);
77 }
78 free(leaves[i]);
79 }
80 free(leaves);
81 }
82 }
83 }
84
weed_clear_plant_flags(weed_plant_t * plant,uint32_t flags,const char * ign_prefix)85 void weed_clear_plant_flags(weed_plant_t *plant, uint32_t flags, const char *ign_prefix) {
86 if (!plant) return;
87 else {
88 size_t ign_prefix_len = 0;
89 char **leaves = weed_plant_list_leaves(plant, NULL);
90 if (leaves) {
91 if (ign_prefix) ign_prefix_len = strlen(ign_prefix);
92 for (register int i = 0; leaves[i]; i++) {
93 if (!ign_prefix || strncmp(leaves[i], ign_prefix, ign_prefix_len)) {
94 weed_leaf_clear_flagbits(plant, leaves[i], flags);
95 }
96 free(leaves[i]);
97 }
98 free(leaves);
99 }
100 }
101 }
102
_weed_get_gui(weed_plant_t * plant,int create_if_not_exists)103 WEED_LOCAL_INLINE weed_plant_t *_weed_get_gui(weed_plant_t *plant, int create_if_not_exists) {
104 weed_plant_t *gui = NULL;
105 int type = weed_plant_get_type(plant);
106 if (type != WEED_PLANT_FILTER_CLASS && type != WEED_PLANT_PARAMETER_TEMPLATE
107 && type != WEED_PLANT_PARAMETER && type != WEED_PLANT_FILTER_INSTANCE) return NULL;
108 gui = weed_get_plantptr_value(plant, WEED_LEAF_GUI, NULL);
109 if (!gui && create_if_not_exists == WEED_TRUE) {
110 gui = weed_plant_new(WEED_PLANT_GUI);
111 weed_leaf_set(plant, WEED_LEAF_GUI, WEED_SEED_PLANTPTR, 1, &gui);
112 }
113 return gui;
114 }
115
weed_host_info_get_flags(weed_plant_t * hinfo)116 WEED_GLOBAL_INLINE int weed_host_info_get_flags(weed_plant_t *hinfo) {
117 if (!WEED_PLANT_IS_HOST_INFO(hinfo)) return 0;
118 return weed_get_int_value(hinfo, WEED_LEAF_FLAGS, NULL);
119 }
120
weed_host_info_set_flags(weed_plant_t * hinfo,int flags)121 WEED_GLOBAL_INLINE void weed_host_info_set_flags(weed_plant_t *hinfo, int flags) {
122 if (!WEED_PLANT_IS_HOST_INFO(hinfo)) return;
123 weed_set_int_value(hinfo, WEED_LEAF_FLAGS, flags);
124 }
125
weed_host_set_verbosity(weed_plant_t * hinfo,int verbosity)126 WEED_GLOBAL_INLINE void weed_host_set_verbosity(weed_plant_t *hinfo, int verbosity) {
127 if (WEED_PLANT_IS_HOST_INFO(hinfo))
128 weed_set_int_value(hinfo, WEED_LEAF_VERBOSITY, verbosity);
129 }
130
weed_host_set_supports_linear_gamma(weed_plant_t * hinfo)131 WEED_GLOBAL_INLINE void weed_host_set_supports_linear_gamma(weed_plant_t *hinfo) {
132 if (WEED_PLANT_IS_HOST_INFO(hinfo))
133 weed_host_info_set_flags(hinfo, weed_host_info_get_flags(hinfo) | WEED_HOST_SUPPORTS_LINEAR_GAMMA);
134 }
135
weed_host_set_supports_premult_alpha(weed_plant_t * hinfo)136 WEED_GLOBAL_INLINE void weed_host_set_supports_premult_alpha(weed_plant_t *hinfo) {
137 if (WEED_PLANT_IS_HOST_INFO(hinfo))
138 weed_host_info_set_flags(hinfo, weed_host_info_get_flags(hinfo) | WEED_HOST_SUPPORTS_PREMULTIPLIED_ALPHA);
139 }
140
weed_plugin_info_get_package_name(weed_plant_t * pinfo)141 WEED_GLOBAL_INLINE char *weed_plugin_info_get_package_name(weed_plant_t *pinfo) {
142 if (!WEED_PLANT_IS_PLUGIN_INFO(pinfo)) return NULL;
143 return weed_get_string_value(pinfo, WEED_LEAF_PACKAGE_NAME, NULL);
144 }
145
weed_filter_get_gui(weed_plant_t * filter,int create_if_not_exists)146 WEED_GLOBAL_INLINE weed_plant_t *weed_filter_get_gui(weed_plant_t *filter, int create_if_not_exists) {
147 return _weed_get_gui(filter, create_if_not_exists);
148 }
149
weed_filter_get_plugin_info(weed_plant_t * filter)150 WEED_GLOBAL_INLINE weed_plant_t *weed_filter_get_plugin_info(weed_plant_t *filter) {
151 return weed_get_plantptr_value(filter, WEED_LEAF_PLUGIN_INFO, NULL);
152 }
153
weed_filter_get_package_name(weed_plant_t * filter)154 WEED_GLOBAL_INLINE char *weed_filter_get_package_name(weed_plant_t *filter) {
155 return weed_plugin_info_get_package_name(weed_filter_get_plugin_info(filter));
156 }
157
weed_instance_get_gui(weed_plant_t * inst,int create_if_not_exists)158 WEED_GLOBAL_INLINE weed_plant_t *weed_instance_get_gui(weed_plant_t *inst, int create_if_not_exists) {
159 return _weed_get_gui(inst, create_if_not_exists);
160 }
161
weed_paramtmpl_get_gui(weed_plant_t * paramt,int create_if_not_exists)162 WEED_GLOBAL_INLINE weed_plant_t *weed_paramtmpl_get_gui(weed_plant_t *paramt, int create_if_not_exists) {
163 return _weed_get_gui(paramt, create_if_not_exists);
164 }
165
weed_param_get_gui(weed_plant_t * param,int create_if_not_exists)166 WEED_GLOBAL_INLINE weed_plant_t *weed_param_get_gui(weed_plant_t *param, int create_if_not_exists) {
167 return _weed_get_gui(param, create_if_not_exists);
168 }
169
weed_param_is_hidden(weed_plant_t * param,int temporary)170 WEED_GLOBAL_INLINE int weed_param_is_hidden(weed_plant_t *param, int temporary) {
171 weed_plant_t *gui = weed_param_get_gui(param, WEED_FALSE);
172 if (!temporary || !gui) return weed_paramtmpl_hints_hidden(weed_param_get_template(param));
173 return weed_get_boolean_value(gui, WEED_LEAF_HIDDEN, NULL);
174 }
175
weed_filter_get_flags(weed_plant_t * filter)176 WEED_GLOBAL_INLINE int weed_filter_get_flags(weed_plant_t *filter) {
177 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return 0;
178 return weed_get_int_value(filter, WEED_LEAF_FLAGS, NULL);
179 }
180
weed_filter_hints_unstable(weed_plant_t * filter)181 WEED_GLOBAL_INLINE int weed_filter_hints_unstable(weed_plant_t *filter) {
182 if (weed_filter_get_flags(filter) & WEED_FILTER_HINT_MAYBE_UNSTABLE) return WEED_TRUE;
183 return WEED_FALSE;
184 }
185
weed_filter_hints_stateless(weed_plant_t * filter)186 WEED_GLOBAL_INLINE int weed_filter_hints_stateless(weed_plant_t *filter) {
187 if (weed_filter_get_flags(filter) & WEED_FILTER_HINT_STATELESS) return WEED_TRUE;
188 return WEED_FALSE;
189 }
190
weed_filter_non_realtime(weed_plant_t * filter)191 WEED_GLOBAL_INLINE int weed_filter_non_realtime(weed_plant_t *filter) {
192 if (weed_filter_get_flags(filter) & WEED_FILTER_NON_REALTIME) return WEED_TRUE;
193 return WEED_FALSE;
194 }
195
weed_filter_may_thread(weed_plant_t * filter)196 WEED_GLOBAL_INLINE int weed_filter_may_thread(weed_plant_t *filter) {
197 if (weed_filter_get_flags(filter) & WEED_FILTER_HINT_MAY_THREAD) return WEED_TRUE;
198 return WEED_FALSE;
199 }
200
weed_filter_channel_sizes_vary(weed_plant_t * filter)201 WEED_GLOBAL_INLINE int weed_filter_channel_sizes_vary(weed_plant_t *filter) {
202 if (weed_filter_get_flags(filter) & WEED_FILTER_CHANNEL_SIZES_MAY_VARY) return WEED_TRUE;
203 return WEED_FALSE;
204 }
205
weed_filter_palettes_vary(weed_plant_t * filter)206 WEED_GLOBAL_INLINE int weed_filter_palettes_vary(weed_plant_t *filter) {
207 if (weed_filter_get_flags(filter) & WEED_FILTER_PALETTES_MAY_VARY) return WEED_TRUE;
208 return WEED_FALSE;
209 }
210
weed_filter_prefers_linear_gamma(weed_plant_t * filter)211 WEED_GLOBAL_INLINE int weed_filter_prefers_linear_gamma(weed_plant_t *filter) {
212 if (weed_filter_get_flags(filter) & WEED_FILTER_PREF_LINEAR_GAMMA) return WEED_TRUE;
213 return WEED_FALSE;
214 }
215
weed_filter_prefers_premult_alpha(weed_plant_t * filter)216 WEED_GLOBAL_INLINE int weed_filter_prefers_premult_alpha(weed_plant_t *filter) {
217 if (weed_filter_get_flags(filter) & WEED_FILTER_PREF_PREMULTIPLIED_ALPHA) return WEED_TRUE;
218 return WEED_FALSE;
219 }
220
weed_filter_is_converter(weed_plant_t * filter)221 WEED_GLOBAL_INLINE int weed_filter_is_converter(weed_plant_t *filter) {
222 if (weed_filter_get_flags(filter) & WEED_FILTER_IS_CONVERTER) return WEED_TRUE;
223 return WEED_FALSE;
224 }
225
weed_filter_is_process_last(weed_plant_t * filter)226 WEED_GLOBAL_INLINE int weed_filter_is_process_last(weed_plant_t *filter) {
227 if (weed_filter_get_flags(filter) & WEED_FILTER_HINT_PROCESS_LAST) return WEED_TRUE;
228 return WEED_FALSE;
229 }
230
weed_filter_hints_hidden(weed_plant_t * filter)231 WEED_GLOBAL_INLINE int weed_filter_hints_hidden(weed_plant_t *filter) {
232 weed_plant_t *gui;
233 if (WEED_PLANT_IS_FILTER_CLASS(filter)
234 && (gui = weed_filter_get_gui(filter, WEED_FALSE))
235 && weed_get_boolean_value(gui, WEED_LEAF_HIDDEN, NULL) == WEED_TRUE)
236 return WEED_TRUE;
237 return WEED_FALSE;
238 }
239
weed_filter_get_name(weed_plant_t * filter)240 WEED_GLOBAL_INLINE char *weed_filter_get_name(weed_plant_t *filter) {
241 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
242 return weed_get_string_value(filter, WEED_LEAF_NAME, NULL);
243 }
244
weed_filter_get_in_chantmpls(weed_plant_t * filter,int * ntmpls)245 WEED_GLOBAL_INLINE weed_plant_t **weed_filter_get_in_chantmpls(weed_plant_t *filter, int *ntmpls) {
246 if (ntmpls) *ntmpls = 0;
247 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
248 return weed_get_plantptr_array_counted(filter, WEED_LEAF_IN_CHANNEL_TEMPLATES, ntmpls);
249 }
250
weed_filter_get_out_chantmpls(weed_plant_t * filter,int * ntmpls)251 WEED_GLOBAL_INLINE weed_plant_t **weed_filter_get_out_chantmpls(weed_plant_t *filter, int *ntmpls) {
252 if (ntmpls) *ntmpls = 0;
253 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
254 return weed_get_plantptr_array_counted(filter, WEED_LEAF_OUT_CHANNEL_TEMPLATES, ntmpls);
255 }
256
weed_filter_get_in_paramtmpls(weed_plant_t * filter,int * ntmpls)257 WEED_GLOBAL_INLINE weed_plant_t **weed_filter_get_in_paramtmpls(weed_plant_t *filter, int *ntmpls) {
258 if (ntmpls) *ntmpls = 0;
259 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
260 return weed_get_plantptr_array_counted(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES, ntmpls);
261 }
262
weed_filter_get_out_paramtmpls(weed_plant_t * filter,int * ntmpls)263 WEED_GLOBAL_INLINE weed_plant_t **weed_filter_get_out_paramtmpls(weed_plant_t *filter, int *ntmpls) {
264 if (ntmpls) *ntmpls = 0;
265 if (!WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
266 return weed_get_plantptr_array_counted(filter, WEED_LEAF_OUT_PARAMETER_TEMPLATES, ntmpls);
267 }
268
269 /* int weed_filter_get_transition_param(weed_plant_t *filter, const char *skip) { */
270 /* int num_params, count = 0; */
271 /* weed_plant_t **in_ptmpls = weed_filter_get_in_paramtmpls(filter, &num_params); */
272 /* if (num_params == 0) return -1; */
273 /* for (int i = 0; i < num_params; i++) { */
274 /* if (skip != NULL && weed_plant_has_leaf(in_ptmpls[i], skip)) continue; */
275 /* if (weed_get_boolean_value(in_ptmpls[i], WEED_LEAF_IS_TRANSITION, NULL) == WEED_TRUE) { */
276 /* free_func(in_ptmpls); */
277 /* return count; */
278 /* } */
279 /* count++; */
280 /* } */
281 /* free_func(in_ptmpls); */
282 /* return -1; */
283 /* } */
284
weed_chantmpl_get_name(weed_plant_t * chantmpl)285 WEED_GLOBAL_INLINE char *weed_chantmpl_get_name(weed_plant_t *chantmpl) {
286 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return NULL;
287 return weed_get_string_value(chantmpl, WEED_LEAF_NAME, NULL);
288 }
289
weed_chantmpl_get_flags(weed_plant_t * chantmpl)290 WEED_GLOBAL_INLINE int weed_chantmpl_get_flags(weed_plant_t *chantmpl) {
291 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return 0;
292 return weed_get_int_value(chantmpl, WEED_LEAF_FLAGS, NULL);
293 }
294
weed_chantmpl_get_max_audio_length(weed_plant_t * chantmpl)295 WEED_GLOBAL_INLINE int weed_chantmpl_get_max_audio_length(weed_plant_t *chantmpl) {
296 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return 0;
297 return weed_get_int_value(chantmpl, WEED_LEAF_MAX_AUDIO_LENGTH, NULL);
298 }
299
weed_paramtmpl_get_flags(weed_plant_t * paramtmpl)300 WEED_GLOBAL_INLINE int weed_paramtmpl_get_flags(weed_plant_t *paramtmpl) {
301 if (!WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) return 0;
302 return weed_get_int_value(paramtmpl, WEED_LEAF_FLAGS, NULL);
303 }
304
weed_paramtmpl_value_type(weed_plant_t * paramtmpl)305 WEED_GLOBAL_INLINE uint32_t weed_paramtmpl_value_type(weed_plant_t *paramtmpl) {
306 if (!WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) return WEED_SEED_INVALID;
307 if (weed_paramtmpl_has_variable_size(paramtmpl) && weed_plant_has_leaf(paramtmpl, WEED_LEAF_NEW_DEFAULT))
308 return weed_leaf_seed_type(paramtmpl, WEED_LEAF_NEW_DEFAULT);
309 return weed_leaf_seed_type(paramtmpl, WEED_LEAF_DEFAULT);
310 }
311
weed_paramtmpl_get_type(weed_plant_t * paramtmpl)312 WEED_GLOBAL_INLINE int weed_paramtmpl_get_type(weed_plant_t *paramtmpl) {
313 if (!WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) return 0;
314 return weed_get_int_value(paramtmpl, WEED_LEAF_PARAM_TYPE, NULL);
315 }
316
weed_paramtmpl_get_name(weed_plant_t * paramtmpl)317 WEED_GLOBAL_INLINE char *weed_paramtmpl_get_name(weed_plant_t *paramtmpl) {
318 if (!WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) return NULL;
319 return weed_get_string_value(paramtmpl, WEED_LEAF_NAME, NULL);
320 }
321
weed_paramtmpl_has_variable_size(weed_plant_t * paramtmpl)322 WEED_GLOBAL_INLINE int weed_paramtmpl_has_variable_size(weed_plant_t *paramtmpl) {
323 if (WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)
324 && (weed_paramtmpl_get_flags(paramtmpl) & WEED_PARAMETER_VARIABLE_SIZE)) return WEED_TRUE;
325 return WEED_FALSE;
326 }
327
weed_paramtmpl_has_value_perchannel(weed_plant_t * paramtmpl)328 WEED_GLOBAL_INLINE int weed_paramtmpl_has_value_perchannel(weed_plant_t *paramtmpl) {
329 if (WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)
330 && (weed_paramtmpl_get_flags(paramtmpl) & WEED_PARAMETER_VALUE_PER_CHANNEL)) return WEED_TRUE;
331 return WEED_FALSE;
332 }
333
weed_paramtmpl_does_wrap(weed_plant_t * paramtmpl)334 WEED_GLOBAL_INLINE int weed_paramtmpl_does_wrap(weed_plant_t *paramtmpl) {
335 weed_plant_t *gui;
336 if (!WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) return -1;
337 if ((gui = weed_paramtmpl_get_gui(paramtmpl, WEED_FALSE))
338 && weed_get_boolean_value(gui, WEED_LEAF_WRAP, NULL) == WEED_TRUE) return WEED_TRUE;
339 return WEED_FALSE;
340 }
341
weed_paramtmpl_hints_string_choice(weed_plant_t * paramtmpl)342 WEED_GLOBAL_INLINE int weed_paramtmpl_hints_string_choice(weed_plant_t *paramtmpl) {
343 weed_plant_t *gui;
344 if (WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)
345 && (gui = weed_paramtmpl_get_gui(weed_param_get_template(paramtmpl), WEED_FALSE))
346 && weed_plant_has_leaf(gui, WEED_LEAF_CHOICES))
347 return WEED_TRUE;
348 return WEED_FALSE;
349 }
350
weed_paramtmpl_hints_hidden(weed_plant_t * paramtmpl)351 WEED_GLOBAL_INLINE int weed_paramtmpl_hints_hidden(weed_plant_t *paramtmpl) {
352 weed_plant_t *gui;
353 if (WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)
354 && (gui = weed_paramtmpl_get_gui(paramtmpl, WEED_FALSE))
355 && weed_get_boolean_value(gui, WEED_LEAF_HIDDEN, NULL) == WEED_TRUE)
356 return WEED_TRUE;
357 return WEED_FALSE;
358 }
359
weed_paramtmpl_value_irrelevant(weed_plant_t * paramtmpl)360 WEED_GLOBAL_INLINE int weed_paramtmpl_value_irrelevant(weed_plant_t *paramtmpl) {
361 if (WEED_PLANT_IS_PARAMETER_TEMPLATE(paramtmpl)) {
362 if (weed_paramtmpl_get_flags(paramtmpl) & WEED_PARAMETER_VALUE_IRRELEVANT) return WEED_TRUE;
363 }
364 return WEED_FALSE;
365 }
366
weed_chantmpl_is_optional(weed_plant_t * chantmpl)367 WEED_GLOBAL_INLINE int weed_chantmpl_is_optional(weed_plant_t *chantmpl) {
368 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return WEED_TRUE;
369 if (weed_chantmpl_get_flags(chantmpl) & WEED_CHANNEL_OPTIONAL) return WEED_TRUE;
370 return WEED_FALSE;
371 }
372
weed_chantmpl_get_max_repeats(weed_plant_t * chantmpl)373 WEED_GLOBAL_INLINE int weed_chantmpl_get_max_repeats(weed_plant_t *chantmpl) {
374 /// a return value of zero means unlimited repeats
375 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return -1;
376 if (weed_plant_has_leaf(chantmpl, WEED_LEAF_MAX_REPEATS))
377 return weed_get_int_value(chantmpl, WEED_LEAF_MAX_REPEATS, NULL);
378 return 1;
379 }
380
weed_chantmpl_is_audio(weed_plant_t * chantmpl)381 WEED_GLOBAL_INLINE int weed_chantmpl_is_audio(weed_plant_t *chantmpl) {
382 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl)) return WEED_TRUE;
383 return weed_get_boolean_value(chantmpl, WEED_LEAF_IS_AUDIO, NULL);
384 }
385
weed_chantmpl_get_palette_list(weed_plant_t * filter,weed_plant_t * chantmpl,int * nvals)386 WEED_GLOBAL_INLINE int *weed_chantmpl_get_palette_list(weed_plant_t *filter, weed_plant_t *chantmpl, int *nvals) {
387 int *pals, npals;
388 if (nvals) *nvals = 0;
389 if (!WEED_PLANT_IS_CHANNEL_TEMPLATE(chantmpl) || !WEED_PLANT_IS_FILTER_CLASS(filter)) return NULL;
390 if ((weed_filter_get_flags(filter) & WEED_FILTER_PALETTES_MAY_VARY)
391 && weed_plant_has_leaf(chantmpl, WEED_LEAF_PALETTE_LIST)) {
392 pals = weed_get_int_array_counted(chantmpl, WEED_LEAF_PALETTE_LIST, &npals);
393 for (register int i = 0; i < npals; i++) {
394 }
395 } else {
396 if (!weed_plant_has_leaf(filter, WEED_LEAF_PALETTE_LIST)) return NULL;
397 pals = weed_get_int_array_counted(filter, WEED_LEAF_PALETTE_LIST, &npals);
398 }
399 if (npals > 0 && pals[npals - 1] == WEED_PALETTE_END) npals--;
400 if (nvals) *nvals = npals;
401 return pals;
402 }
403
weed_channel_get_pixel_data(weed_plant_t * channel)404 WEED_GLOBAL_INLINE void *weed_channel_get_pixel_data(weed_plant_t *channel) {
405 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
406 return weed_get_voidptr_value(channel, WEED_LEAF_PIXEL_DATA, NULL);
407 }
408
weed_channel_get_pixel_data_planar(weed_plant_t * channel,int * nplanes)409 WEED_GLOBAL_INLINE void **weed_channel_get_pixel_data_planar(weed_plant_t *channel, int *nplanes) {
410 if (nplanes) *nplanes = 0;
411 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
412 return weed_get_voidptr_array_counted(channel, WEED_LEAF_PIXEL_DATA, NULL);
413 }
414
weed_channel_get_width(weed_plant_t * channel)415 WEED_GLOBAL_INLINE int weed_channel_get_width(weed_plant_t *channel) {
416 /// width in macropixels
417 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
418 return weed_get_int_value(channel, WEED_LEAF_WIDTH, NULL);
419 }
420
weed_channel_set_width(weed_plant_t * channel,int width)421 WEED_GLOBAL_INLINE void weed_channel_set_width(weed_plant_t *channel, int width) {
422 /// width in macropixels
423 if (!WEED_PLANT_IS_CHANNEL(channel)) return;
424 weed_set_int_value(channel, WEED_LEAF_WIDTH, width);
425 }
426
weed_channel_get_width_pixels(weed_plant_t * channel)427 WEED_GLOBAL_INLINE int weed_channel_get_width_pixels(weed_plant_t *channel) {
428 /// width in pixels: only relevant when comparing widths of diferrent palettes
429 return weed_channel_get_width(channel) * weed_palette_get_pixels_per_macropixel(weed_channel_get_palette(channel));
430 }
431
weed_channel_get_height(weed_plant_t * channel)432 WEED_GLOBAL_INLINE int weed_channel_get_height(weed_plant_t *channel) {
433 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
434 return weed_get_int_value(channel, WEED_LEAF_HEIGHT, NULL);
435 }
436
weed_channel_set_height(weed_plant_t * channel,int height)437 WEED_GLOBAL_INLINE void weed_channel_set_height(weed_plant_t *channel, int height) {
438 if (!WEED_PLANT_IS_CHANNEL(channel)) return;
439 weed_set_int_value(channel, WEED_LEAF_HEIGHT, height);
440 }
441
weed_channel_set_size(weed_plant_t * channel,int width,int height)442 WEED_GLOBAL_INLINE void weed_channel_set_size(weed_plant_t *channel, int width, int height) {
443 if (!WEED_PLANT_IS_CHANNEL(channel)) return;
444 weed_set_int_value(channel, WEED_LEAF_WIDTH, width);
445 weed_set_int_value(channel, WEED_LEAF_HEIGHT, height);
446 }
447
weed_channel_set_palette(weed_plant_t * channel,int palette)448 WEED_GLOBAL_INLINE void weed_channel_set_palette(weed_plant_t *channel, int palette) {
449 if (!WEED_PLANT_IS_CHANNEL(channel)) return;
450 weed_set_int_value(channel, WEED_LEAF_CURRENT_PALETTE, palette);
451 }
452
weed_channel_get_palette(weed_plant_t * channel)453 WEED_GLOBAL_INLINE int weed_channel_get_palette(weed_plant_t *channel) {
454 if (!WEED_PLANT_IS_CHANNEL(channel)) return WEED_PALETTE_NONE;
455 return weed_get_int_value(channel, WEED_LEAF_CURRENT_PALETTE, NULL);
456 }
457
weed_channel_get_gamma_type(weed_plant_t * channel)458 WEED_GLOBAL_INLINE int weed_channel_get_gamma_type(weed_plant_t *channel) {
459 if (!WEED_PLANT_IS_CHANNEL(channel)) return WEED_PALETTE_NONE;
460 return weed_get_int_value(channel, WEED_LEAF_GAMMA_TYPE, NULL);
461 }
462
weed_channel_set_gamma_type(weed_plant_t * channel,int gamma_type)463 WEED_GLOBAL_INLINE weed_plant_t *weed_channel_set_gamma_type(weed_plant_t *channel, int gamma_type) {
464 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
465 weed_set_int_value(channel, WEED_LEAF_GAMMA_TYPE, gamma_type);
466 return channel;
467 }
468
weed_channel_get_palette_yuv(weed_plant_t * channel,int * clamping,int * sampling,int * subspace)469 WEED_GLOBAL_INLINE int weed_channel_get_palette_yuv(weed_plant_t *channel, int *clamping, int *sampling, int *subspace) {
470 if (!WEED_PLANT_IS_CHANNEL(channel)) return WEED_PALETTE_NONE;
471 else {
472 int palette = weed_channel_get_palette(channel);
473 if (weed_palette_is_yuv(palette)) {
474 if (clamping) *clamping = weed_get_int_value(channel, WEED_LEAF_YUV_CLAMPING, NULL);
475 if (sampling) *sampling = weed_get_int_value(channel, WEED_LEAF_YUV_SAMPLING, NULL);
476 if (subspace) *subspace = weed_get_int_value(channel, WEED_LEAF_YUV_SUBSPACE, NULL);
477 }
478 return palette;
479 }
480 }
481
weed_channel_get_rowstride(weed_plant_t * channel)482 WEED_GLOBAL_INLINE int weed_channel_get_rowstride(weed_plant_t *channel) {
483 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
484 return weed_get_int_value(channel, WEED_LEAF_ROWSTRIDES, NULL);
485 }
486
weed_channel_get_rowstrides(weed_plant_t * channel,int * nplanes)487 WEED_GLOBAL_INLINE int *weed_channel_get_rowstrides(weed_plant_t *channel, int *nplanes) {
488 if (nplanes) *nplanes = 0;
489 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
490 return weed_get_int_array_counted(channel, WEED_LEAF_ROWSTRIDES, nplanes);
491 }
492
weed_channel_get_audio_rate(weed_plant_t * channel)493 WEED_GLOBAL_INLINE int weed_channel_get_audio_rate(weed_plant_t *channel) {
494 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
495 return weed_get_int_value(channel, WEED_LEAF_AUDIO_RATE, NULL);
496 }
497
weed_channel_get_naudchans(weed_plant_t * channel)498 WEED_GLOBAL_INLINE int weed_channel_get_naudchans(weed_plant_t *channel) {
499 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
500 return weed_get_int_value(channel, WEED_LEAF_AUDIO_CHANNELS, NULL);
501 }
502
weed_channel_get_audio_length(weed_plant_t * channel)503 WEED_GLOBAL_INLINE int weed_channel_get_audio_length(weed_plant_t *channel) {
504 if (!WEED_PLANT_IS_CHANNEL(channel)) return 0;
505 return weed_get_int_value(channel, WEED_LEAF_AUDIO_DATA_LENGTH, NULL);
506 }
507
weed_channel_is_disabled(weed_plant_t * channel)508 WEED_GLOBAL_INLINE int weed_channel_is_disabled(weed_plant_t *channel) {
509 if (!WEED_PLANT_IS_CHANNEL(channel)) return WEED_TRUE;
510 return weed_get_boolean_value(channel, WEED_LEAF_DISABLED, NULL);
511 }
512
weed_channel_get_template(weed_plant_t * channel)513 WEED_GLOBAL_INLINE weed_plant_t *weed_channel_get_template(weed_plant_t *channel) {
514 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
515 return weed_get_plantptr_value(channel, WEED_LEAF_TEMPLATE, NULL);
516 }
517
weed_param_get_template(weed_plant_t * param)518 WEED_GLOBAL_INLINE weed_plant_t *weed_param_get_template(weed_plant_t *param) {
519 if (!WEED_PLANT_IS_PARAMETER(param)) return NULL;
520 return weed_get_plantptr_value(param, WEED_LEAF_TEMPLATE, NULL);
521 }
522
weed_param_get_type(weed_plant_t * param)523 WEED_GLOBAL_INLINE int weed_param_get_type(weed_plant_t *param) {
524 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_PARAM_UNSPECIFIED;
525 return weed_paramtmpl_get_type(weed_param_get_template(param));
526 }
527
weed_param_get_value_type(weed_plant_t * param)528 WEED_GLOBAL_INLINE int weed_param_get_value_type(weed_plant_t *param) {
529 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_SEED_INVALID;
530 return weed_paramtmpl_value_type(weed_param_get_template(param));
531 }
532
weed_param_has_variable_size(weed_plant_t * param)533 WEED_GLOBAL_INLINE int weed_param_has_variable_size(weed_plant_t *param) {
534 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_FALSE;
535 return weed_paramtmpl_has_variable_size(weed_param_get_template(param));
536 }
537
weed_param_has_value_perchannel(weed_plant_t * param)538 WEED_GLOBAL_INLINE int weed_param_has_value_perchannel(weed_plant_t *param) {
539 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_FALSE;
540 return weed_paramtmpl_has_value_perchannel(weed_param_get_template(param));
541 }
542
weed_param_value_irrelevant(weed_plant_t * param)543 WEED_GLOBAL_INLINE int weed_param_value_irrelevant(weed_plant_t *param) {
544 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_FALSE;
545 return weed_paramtmpl_value_irrelevant(weed_param_get_template(param));
546 }
547
weed_param_does_wrap(weed_plant_t * param)548 WEED_GLOBAL_INLINE int weed_param_does_wrap(weed_plant_t *param) {
549 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_FALSE;
550 return weed_paramtmpl_does_wrap(weed_param_get_template(param));
551 }
552
weed_param_get_nchoices(weed_plant_t * param)553 WEED_GLOBAL_INLINE int weed_param_get_nchoices(weed_plant_t *param) {
554 weed_plant_t *gui;
555 if (!WEED_PLANT_IS_PARAMETER(param)) return 0;
556 if ((gui = weed_param_get_gui(param, WEED_FALSE)) != NULL && weed_plant_has_leaf(gui, WEED_LEAF_CHOICES))
557 return weed_leaf_num_elements(gui, WEED_LEAF_CHOICES);
558 if ((gui = weed_paramtmpl_get_gui(weed_param_get_template(param), WEED_FALSE))
559 && weed_plant_has_leaf(gui, WEED_LEAF_CHOICES))
560 return weed_leaf_num_elements(gui, WEED_LEAF_CHOICES);
561 return 0;
562 }
563
weed_channel_get_audio_data(weed_plant_t * channel,int * naudchans)564 WEED_GLOBAL_INLINE float **weed_channel_get_audio_data(weed_plant_t *channel, int *naudchans) {
565 if (naudchans) *naudchans = 0;
566 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
567 return (float **)weed_get_voidptr_array_counted(channel, WEED_LEAF_AUDIO_DATA, naudchans);
568 }
569
weed_channel_set_audio_data(weed_plant_t * channel,float ** data,int arate,int naudchans,int nsamps)570 WEED_GLOBAL_INLINE weed_layer_t *weed_channel_set_audio_data(weed_plant_t *channel, float **data,
571 int arate, int naudchans, int nsamps) {
572 if (!WEED_PLANT_IS_CHANNEL(channel)) return NULL;
573 weed_set_voidptr_array(channel, WEED_LEAF_AUDIO_DATA, naudchans, (void **)data);
574 weed_set_int_value(channel, WEED_LEAF_AUDIO_RATE, arate);
575 weed_set_int_value(channel, WEED_LEAF_AUDIO_DATA_LENGTH, nsamps);
576 weed_set_int_value(channel, WEED_LEAF_AUDIO_CHANNELS, naudchans);
577 return channel;
578 }
579
weed_instance_get_flags(weed_plant_t * inst)580 WEED_GLOBAL_INLINE int weed_instance_get_flags(weed_plant_t *inst) {
581 if (!WEED_PLANT_IS_FILTER_INSTANCE(inst)) return 0;
582 return weed_get_int_value(inst, WEED_LEAF_FLAGS, NULL);
583 }
584
weed_instance_set_flags(weed_plant_t * inst,int flags)585 WEED_GLOBAL_INLINE void weed_instance_set_flags(weed_plant_t *inst, int flags) {
586 if (!WEED_PLANT_IS_FILTER_INSTANCE(inst)) return;
587 weed_set_int_value(inst, WEED_LEAF_FLAGS, flags);
588 }
589
weed_instance_get_in_channels(weed_plant_t * instance,int * nchans)590 WEED_GLOBAL_INLINE weed_plant_t **weed_instance_get_in_channels(weed_plant_t *instance, int *nchans) {
591 if (nchans) *nchans = 0;
592 if (!WEED_PLANT_IS_FILTER_INSTANCE(instance)) return NULL;
593 return weed_get_plantptr_array_counted(instance, WEED_LEAF_IN_CHANNELS, nchans);
594 }
595
weed_instance_get_out_channels(weed_plant_t * instance,int * nchans)596 WEED_GLOBAL_INLINE weed_plant_t **weed_instance_get_out_channels(weed_plant_t *instance, int *nchans) {
597 if (nchans) *nchans = 0;
598 if (!WEED_PLANT_IS_FILTER_INSTANCE(instance)) return NULL;
599 return weed_get_plantptr_array_counted(instance, WEED_LEAF_OUT_CHANNELS, nchans);
600 }
601
weed_instance_get_in_params(weed_plant_t * instance,int * nparams)602 WEED_GLOBAL_INLINE weed_plant_t **weed_instance_get_in_params(weed_plant_t *instance, int *nparams) {
603 if (nparams) *nparams = 0;
604 if (!WEED_PLANT_IS_FILTER_INSTANCE(instance)) return NULL;
605 return weed_get_plantptr_array_counted(instance, WEED_LEAF_IN_PARAMETERS, nparams);
606 }
607
weed_instance_get_out_params(weed_plant_t * instance,int * nparams)608 WEED_GLOBAL_INLINE weed_plant_t **weed_instance_get_out_params(weed_plant_t *instance, int *nparams) {
609 if (nparams) *nparams = 0;
610 if (!WEED_PLANT_IS_FILTER_INSTANCE(instance)) return NULL;
611 return weed_get_plantptr_array_counted(instance, WEED_LEAF_OUT_PARAMETERS, nparams);
612 }
613
weed_param_get_value_int(weed_plant_t * param)614 WEED_GLOBAL_INLINE int weed_param_get_value_int(weed_plant_t *param) {
615 if (!WEED_PLANT_IS_PARAMETER(param)) return 0;
616 return weed_get_int_value(param, WEED_LEAF_VALUE, NULL);
617 }
618
weed_param_get_value_boolean(weed_plant_t * param)619 WEED_GLOBAL_INLINE int weed_param_get_value_boolean(weed_plant_t *param) {
620 if (!WEED_PLANT_IS_PARAMETER(param)) return WEED_FALSE;
621 return weed_get_boolean_value(param, WEED_LEAF_VALUE, NULL);
622 }
623
weed_param_get_value_double(weed_plant_t * param)624 WEED_GLOBAL_INLINE double weed_param_get_value_double(weed_plant_t *param) {
625 if (!WEED_PLANT_IS_PARAMETER(param)) return 0.;
626 return weed_get_double_value(param, WEED_LEAF_VALUE, NULL);
627 }
628
weed_param_get_value_int64(weed_plant_t * param)629 WEED_GLOBAL_INLINE int64_t weed_param_get_value_int64(weed_plant_t *param) {
630 if (!WEED_PLANT_IS_PARAMETER(param)) return 0;
631 return weed_get_int64_value(param, WEED_LEAF_VALUE, NULL);
632 }
633
weed_param_get_value_string(weed_plant_t * param)634 WEED_GLOBAL_INLINE char *weed_param_get_value_string(weed_plant_t *param) {
635 if (!WEED_PLANT_IS_PARAMETER(param)) return NULL;
636 if (weed_leaf_num_elements(param, WEED_LEAF_VALUE) == 0) return NULL;
637 return weed_get_string_value(param, WEED_LEAF_VALUE, NULL);
638 }
639
weed_gui_get_flags(weed_plant_t * gui)640 WEED_GLOBAL_INLINE int weed_gui_get_flags(weed_plant_t *gui) {
641 if (!WEED_PLANT_IS_GUI(gui)) return 0;
642 return weed_get_int_value(gui, WEED_LEAF_FLAGS, NULL);
643 }
644
645 //////////////////////////////////////////// utilities ///////////////////////
646
weed_error_to_text(weed_error_t error)647 char *weed_error_to_text(weed_error_t error) {
648 // return value should be freed after use
649 switch (error) {
650 case (WEED_ERROR_MEMORY_ALLOCATION):
651 return strdup("Memory allocation error");
652 /* case (WEED_ERROR_CONCURRENCY): */
653 return strdup("Thread concurrency failure");
654 case (WEED_ERROR_IMMUTABLE):
655 return strdup("Read only property");
656 case (WEED_ERROR_UNDELETABLE):
657 return strdup("Undeletable property");
658 case (WEED_ERROR_BADVERSION):
659 return strdup("Bad version number");
660 case (WEED_ERROR_NOSUCH_ELEMENT):
661 return strdup("Invalid element");
662 case (WEED_ERROR_NOSUCH_LEAF):
663 return strdup("Invalid property");
664 case (WEED_ERROR_WRONG_SEED_TYPE):
665 return strdup("Incorrect property type");
666 case (WEED_ERROR_TOO_MANY_INSTANCES):
667 return strdup("Too many instances");
668 case (WEED_ERROR_PLUGIN_INVALID):
669 return strdup("Fatal plugin error");
670 case (WEED_ERROR_FILTER_INVALID):
671 return strdup("Invalid filter in plugin");
672 case (WEED_ERROR_REINIT_NEEDED):
673 return strdup("Filter needs reiniting");
674 default:
675 break;
676 }
677 return strdup("No error");
678 }
679
weed_seed_type_to_text(uint32_t seed_type)680 char *weed_seed_type_to_text(uint32_t seed_type) {
681 switch (seed_type) {
682 case WEED_SEED_INT:
683 return strdup("integer");
684 case WEED_SEED_INT64:
685 return strdup("int64");
686 case WEED_SEED_BOOLEAN:
687 return strdup("boolean");
688 case WEED_SEED_DOUBLE:
689 return strdup("double");
690 case WEED_SEED_STRING:
691 return strdup("string");
692 case WEED_SEED_FUNCPTR:
693 return strdup("function pointer");
694 case WEED_SEED_VOIDPTR:
695 return strdup("void *");
696 case WEED_SEED_PLANTPTR:
697 return strdup("weed_plant_t *");
698 default:
699 return strdup("custom pointer type");
700 }
701 }
702
weed_palette_get_name(int pal)703 const char *weed_palette_get_name(int pal) {
704 switch (pal) {
705 case WEED_PALETTE_RGB24:
706 return "RGB24";
707 case WEED_PALETTE_RGBA32:
708 return "RGBA32";
709 case WEED_PALETTE_BGR24:
710 return "BGR24";
711 case WEED_PALETTE_BGRA32:
712 return "BGRA32";
713 case WEED_PALETTE_ARGB32:
714 return "ARGB32";
715 case WEED_PALETTE_RGBFLOAT:
716 return "RGBFLOAT";
717 case WEED_PALETTE_RGBAFLOAT:
718 return "RGBAFLOAT";
719 case WEED_PALETTE_YUV888:
720 return "YUV888";
721 case WEED_PALETTE_YUVA8888:
722 return "YUVA8888";
723 case WEED_PALETTE_YUV444P:
724 return "YUV444P";
725 case WEED_PALETTE_YUVA4444P:
726 return "YUVA4444P";
727 case WEED_PALETTE_YUV422P:
728 return "YUV4422P";
729 case WEED_PALETTE_YUV420P:
730 return "YUV420P";
731 case WEED_PALETTE_YVU420P:
732 return "YVU420P";
733 case WEED_PALETTE_YUV411:
734 return "YUV411";
735 case WEED_PALETTE_UYVY8888:
736 return "UYVY";
737 case WEED_PALETTE_YUYV8888:
738 return "YUYV";
739 case WEED_PALETTE_A8:
740 return "8 BIT ALPHA";
741 case WEED_PALETTE_A1:
742 return "1 BIT ALPHA";
743 case WEED_PALETTE_AFLOAT:
744 return "FLOAT ALPHA";
745 default:
746 if (pal >= 2048) return "custom";
747 return "unknown";
748 }
749 }
750
weed_yuv_clamping_get_name(int clamping)751 const char *weed_yuv_clamping_get_name(int clamping) {
752 if (clamping == WEED_YUV_CLAMPING_UNCLAMPED) return "unclamped";
753 if (clamping == WEED_YUV_CLAMPING_CLAMPED) return "clamped";
754 return NULL;
755 }
756
weed_yuv_subspace_get_name(int subspace)757 const char *weed_yuv_subspace_get_name(int subspace) {
758 if (subspace == WEED_YUV_SUBSPACE_YUV) return "Y'UV";
759 if (subspace == WEED_YUV_SUBSPACE_YCBCR) return "Y'CbCr";
760 if (subspace == WEED_YUV_SUBSPACE_BT709) return "BT.709";
761 return NULL;
762 }
763
weed_palette_get_name_full(int pal,int clamping,int subspace)764 char *weed_palette_get_name_full(int pal, int clamping, int subspace) {
765 const char *pname = weed_palette_get_name(pal);
766 if (weed_palette_is_yuv(pal)) {
767 const char *clamp = weed_yuv_clamping_get_name(clamping);
768 const char *sspace = weed_yuv_subspace_get_name(subspace);
769 return lives_strdup_printf("%s:%s (%s)", pname, sspace, clamp); // TODO
770 }
771 return strdup(pname);
772 }
773
weed_gamma_get_name(int gamma)774 const char *weed_gamma_get_name(int gamma) {
775 if (gamma == WEED_GAMMA_LINEAR) return "linear";
776 if (gamma == WEED_GAMMA_SRGB) return "sRGB";
777 if (gamma == WEED_GAMMA_BT709) return "bt709";
778 return "unknown";
779 }
780
781 #ifndef WEED_ADVANCED_PALETTES
782
weed_palette_get_bits_per_macropixel(int pal)783 WEED_GLOBAL_INLINE int weed_palette_get_bits_per_macropixel(int pal) {
784 if (pal == WEED_PALETTE_A8 || pal == WEED_PALETTE_YUV420P || pal == WEED_PALETTE_YVU420P ||
785 pal == WEED_PALETTE_YUV422P || pal == WEED_PALETTE_YUV444P || pal == WEED_PALETTE_YUVA4444P) return 8;
786 if (pal == WEED_PALETTE_RGB24 || pal == WEED_PALETTE_BGR24) return 24;
787 if (pal == WEED_PALETTE_RGBA32 || pal == WEED_PALETTE_BGRA32 || pal == WEED_PALETTE_ARGB32 ||
788 pal == WEED_PALETTE_UYVY8888 || pal == WEED_PALETTE_YUYV8888 || pal == WEED_PALETTE_YUV888
789 || pal == WEED_PALETTE_YUVA8888)
790 return 32;
791 if (pal == WEED_PALETTE_YUV411) return 48;
792 if (pal == WEED_PALETTE_AFLOAT) return sizeof(float);
793 if (pal == WEED_PALETTE_A1) return 1;
794 if (pal == WEED_PALETTE_RGBFLOAT) return (3 * sizeof(float));
795 if (pal == WEED_PALETTE_RGBAFLOAT) return (4 * sizeof(float));
796 return 0; // unknown palette
797 }
798
799 #endif
800
801 // just as an example: 1.0 == RGB(A), 0.5 == compressed to 50%, etc
802
weed_palette_get_compression_ratio(int pal)803 double weed_palette_get_compression_ratio(int pal) {
804 double tbits = 0.;
805
806 int nplanes = weed_palette_get_nplanes(pal);
807 int pbits;
808
809 register int i;
810
811 if (!weed_palette_is_valid(pal)) return 0.;
812 if (weed_palette_is_alpha(pal)) return 0.; // invalid for alpha palettes
813 for (i = 0; i < nplanes; i++) {
814 pbits = weed_palette_get_bits_per_macropixel(pal) / weed_palette_get_pixels_per_macropixel(pal);
815 tbits += pbits * weed_palette_get_plane_ratio_vertical(pal, i) * weed_palette_get_plane_ratio_horizontal(pal, i);
816 }
817 if (weed_palette_has_alpha(pal)) return tbits / 32.;
818 return tbits / 24.;
819 }
820
821
weed_filter_is_resizer(weed_plant_t * filter)822 WEED_GLOBAL_INLINE int weed_filter_is_resizer(weed_plant_t *filter) {
823 if (weed_filter_is_converter(filter) && weed_filter_channel_sizes_vary(filter)) return WEED_TRUE;
824 return WEED_FALSE;
825 }
826
weed_filter_is_palette_converter(weed_plant_t * filter)827 WEED_GLOBAL_INLINE int weed_filter_is_palette_converter(weed_plant_t *filter) {
828 if (weed_filter_is_converter(filter) && weed_filter_palettes_vary(filter)) return WEED_TRUE;
829 return WEED_FALSE;
830 }
831
weed_audio_filter_is_resampler(weed_plant_t * filter)832 WEED_GLOBAL_INLINE int weed_audio_filter_is_resampler(weed_plant_t *filter) {
833 int flags = weed_filter_get_flags(filter);
834 if (weed_filter_is_converter(filter)
835 && (flags & WEED_FILTER_AUDIO_RATES_MAY_VARY)) return WEED_TRUE;
836 return WEED_FALSE;
837 }
838
839