Blender V4.5
thumbs.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cstdlib>
11
12#include "MEM_guardedalloc.h"
13
14#include "BKE_blendfile.hh"
15
16#include "BLI_fileops.h"
17#include "BLI_ghash.h"
18#include "BLI_hash_md5.hh"
19#include "BLI_path_utils.hh"
20#include "BLI_string.h"
21#include "BLI_string_utils.hh"
22#include "BLI_system.h"
23#include "BLI_threads.h"
24#include "BLI_utildefines.h"
25#include BLI_SYSTEM_PID_H
26
27#include "DNA_space_types.h" /* For FILE_MAX_LIBEXTRA */
28
29#include "IMB_imbuf.hh"
30#include "IMB_imbuf_types.hh"
31#include "IMB_metadata.hh"
32#include "IMB_thumbs.hh"
33
34#include "MOV_read.hh"
35
36#include <cctype>
37#include <cstring>
38#include <ctime>
39#include <sys/stat.h>
40#include <sys/types.h>
41
42#ifdef WIN32
43/* Need to include windows.h so _WIN32_IE is defined. */
44# include <windows.h>
45# ifndef _WIN32_IE
46/* Minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already. */
47# define _WIN32_IE 0x0400
48# endif
49/* For SHGetSpecialFolderPath, has to be done before BLI_winstuff
50 * because 'near' is disabled through BLI_windstuff */
51# include "BLI_winstuff.h"
52# include "utfconv.hh"
53# include <direct.h> /* #chdir */
54# include <shlobj.h>
55#endif
56
57#if defined(WIN32) || defined(__APPLE__)
58/* pass */
59#else
60# define USE_FREEDESKTOP
61#endif
62
63/* '$HOME/.cache/thumbnails' or '$HOME/.thumbnails' */
64#ifdef USE_FREEDESKTOP
65# define THUMBNAILS "thumbnails"
66#else
67# define THUMBNAILS ".thumbnails"
68#endif
69
70#define URI_MAX (FILE_MAX * 3 + 8)
71
72static bool get_thumb_dir(char *dir, ThumbSize size)
73{
74 char *s = dir;
75 const char *subdir;
76#ifdef WIN32
77 wchar_t dir_16[MAX_PATH];
78 /* Yes, applications shouldn't store data there, but so does GIMP :). */
79 SHGetSpecialFolderPathW(0, dir_16, CSIDL_PROFILE, 0);
80 conv_utf_16_to_8(dir_16, dir, FILE_MAX);
81 s += strlen(dir);
82#else
83# if defined(USE_FREEDESKTOP)
84 const char *home_cache = BLI_getenv("XDG_CACHE_HOME");
85 const char *home = home_cache ? home_cache : BLI_dir_home();
86# else
87 const char *home = BLI_dir_home();
88# endif
89 if (!home) {
90 return false;
91 }
92 s += BLI_strncpy_rlen(s, home, FILE_MAX);
93
94# ifdef USE_FREEDESKTOP
95 if (!home_cache) {
96 s += BLI_strncpy_rlen(s, "/.cache", FILE_MAX - (s - dir));
97 }
98# endif
99#endif
100 switch (size) {
101 case THB_NORMAL:
102 subdir = SEP_STR THUMBNAILS SEP_STR "normal" SEP_STR;
103 break;
104 case THB_LARGE:
105 subdir = SEP_STR THUMBNAILS SEP_STR "large" SEP_STR;
106 break;
107 case THB_FAIL:
108 subdir = SEP_STR THUMBNAILS SEP_STR "fail" SEP_STR "blender" SEP_STR;
109 break;
110 default:
111 return false; /* unknown size */
112 }
113
114 s += BLI_strncpy_rlen(s, subdir, FILE_MAX - (s - dir));
115 (void)s;
116
117 return true;
118}
119
120#undef THUMBNAILS
121
122/* --- Begin of adapted code from glib. --- */
123
124/* -------------------------------------------------------------------- */
132
134 UNSAFE_ALL = 0x1, /* Escape all unsafe characters. */
135 UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */
136 UNSAFE_PATH = 0x8, /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */
137 UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */
138 UNSAFE_SLASHES = 0x20, /* Allows all characters except for '/' and '%' */
139};
140
141/* Don't lose comment alignment. */
142/* clang-format off */
143static const uchar acceptable[96] = {
144 /* A table of the ASCII chars from space (32) to DEL (127) */
145 /* ! " # $ % & ' ( ) * + , - . / */
146 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C,
147 /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
148 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20,
149 /* @ A B C D E F G H I J K L M N O */
150 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
151 /* P Q R S T U V W X Y Z [ \ ] ^ _ */
152 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
153 /* ` a b c d e f g h i j k l m n o */
154 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
155 /* p q r s t u v w x y z { | } ~ DEL */
156 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20,
157};
158/* clang-format on */
159
160static const char hex[17] = "0123456789abcdef";
161
162/* NOTE: This escape function works on file: URIs, but if you want to
163 * escape something else, please read RFC-2396 */
164static void escape_uri_string(const char *string,
165 char *escaped_string,
166 const int escaped_string_size,
168{
169#define ACCEPTABLE(a) ((a) >= 32 && (a) < 128 && (acceptable[(a)-32] & mask))
170
171 BLI_assert(escaped_string_size > 0);
172 /* Remove space for \0. */
173 int escaped_string_len = escaped_string_size - 1;
174
175 const char *p;
176 char *q;
177 int c;
178
179 for (q = escaped_string, p = string; (*p != '\0') && escaped_string_len; p++) {
180 c = uchar(*p);
181
182 if (!ACCEPTABLE(c)) {
183 if (escaped_string_len < 3) {
184 break;
185 }
186
187 *q++ = '%'; /* means hex coming */
188 *q++ = hex[c >> 4];
189 *q++ = hex[c & 15];
190 escaped_string_len -= 3;
191 }
192 else {
193 *q++ = *p;
194 escaped_string_len -= 1;
195 }
196 }
197
198 *q = '\0';
199}
200
202
203/* --- End of adapted code from glib. --- */
204
205static bool thumbhash_from_path(const char * /*path*/, ThumbSource source, char *r_hash)
206{
207 switch (source) {
208 case THB_SOURCE_FONT:
209 return IMB_thumb_load_font_get_hash(r_hash);
210 default:
211 r_hash[0] = '\0';
212 return false;
213 }
214}
215
216static bool uri_from_filepath(const char *path, char *uri)
217{
218 char orig_uri[URI_MAX];
219
220#ifdef WIN32
221 bool path_is_unc = BLI_path_is_unc(path);
222 char path_unc_normalized[FILE_MAX];
223 if (path_is_unc) {
224 STRNCPY(path_unc_normalized, path);
225 BLI_path_normalize_unc(path_unc_normalized, sizeof(path_unc_normalized));
226 path = path_unc_normalized;
227 /* Assign again because a normalized UNC path may resolve to a drive letter. */
228 path_is_unc = BLI_path_is_unc(path);
229 }
230
231 if (path_is_unc) {
232 /* Skip over the `\\` prefix, it's not needed for a URI. */
233 SNPRINTF(orig_uri, "file://%s", BLI_path_slash_skip(path));
234 }
235 else if (BLI_path_is_win32_drive(path)) {
236 SNPRINTF(orig_uri, "file:///%s", path);
237 /* Always use an uppercase drive/volume letter in the URI. */
238 orig_uri[8] = char(toupper(orig_uri[8]));
239 }
240 else {
241 /* Not a correct absolute path with a drive letter or UNC prefix. */
242 return false;
243 }
244 BLI_string_replace_char(orig_uri, '\\', '/');
245#else
246 SNPRINTF(orig_uri, "file://%s", path);
247#endif
248
249 escape_uri_string(orig_uri, uri, URI_MAX, UNSAFE_PATH);
250
251 return true;
252}
253
254static bool thumbpathname_from_uri(const char *uri,
255 char *r_path,
256 const int path_maxncpy,
257 char *r_name,
258 int name_maxncpy,
260{
261 char name_buff[40];
262
263 if (r_path && !r_name) {
264 r_name = name_buff;
265 name_maxncpy = sizeof(name_buff);
266 }
267
268 if (r_name) {
269 char hexdigest[33];
270 uchar digest[16];
271 BLI_hash_md5_buffer(uri, strlen(uri), digest);
272 hexdigest[0] = '\0';
273 BLI_snprintf(r_name, name_maxncpy, "%s.png", BLI_hash_md5_to_hexdigest(digest, hexdigest));
274 // printf("%s: '%s' --> '%s'\n", __func__, uri, r_name);
275 }
276
277 if (r_path) {
278 char tmppath[FILE_MAX];
279
280 if (get_thumb_dir(tmppath, size)) {
281 BLI_snprintf(r_path, path_maxncpy, "%s%s", tmppath, r_name);
282 // printf("%s: '%s' --> '%s'\n", __func__, uri, r_path);
283 return true;
284 }
285 }
286 return false;
287}
288
289static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_maxncpy)
290{
291 thumbpathname_from_uri(uri, nullptr, 0, thumb, thumb_maxncpy, THB_FAIL);
292}
293
294static bool thumbpath_from_uri(const char *uri, char *path, const int path_maxncpy, ThumbSize size)
295{
296 return thumbpathname_from_uri(uri, path, path_maxncpy, nullptr, 0, size);
297}
298
300{
301 char tpath[FILE_MAX];
302#if 0 /* UNUSED */
303 if (get_thumb_dir(tpath, THB_NORMAL)) {
305 }
306#endif
307 if (get_thumb_dir(tpath, THB_LARGE)) {
309 }
310 if (get_thumb_dir(tpath, THB_FAIL)) {
312 }
313}
314
315/* create thumbnail for file and returns new imbuf for thumbnail */
316static ImBuf *thumb_create_ex(const char *file_path,
317 const char *uri,
318 const char *thumb,
319 const bool use_hash,
320 const char *hash,
321 const char *blen_group,
322 const char *blen_id,
324 ThumbSource source,
325 ImBuf *img)
326{
327 char desc[URI_MAX + 22];
328 char tpath[FILE_MAX];
329 char tdir[FILE_MAX];
330 char temp[FILE_MAX];
331 char mtime[40] = "0"; /* in case we can't stat the file */
332 short tsize = 128;
333 BLI_stat_t info;
334
335 switch (size) {
336 case THB_NORMAL:
338 break;
339 case THB_LARGE:
341 break;
342 case THB_FAIL:
343 tsize = 1;
344 break;
345 default:
346 return nullptr; /* unknown size */
347 }
348
349 if (get_thumb_dir(tdir, size)) {
350 SNPRINTF(tpath, "%s%s", tdir, thumb);
351 // thumb[8] = '\0'; /* shorten for `temp` name, not needed anymore */
352 SNPRINTF(temp, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb);
353 if (BLI_path_ncmp(file_path, tdir, sizeof(tdir)) == 0) {
354 return nullptr;
355 }
356 if (size == THB_FAIL) {
357 img = IMB_allocImBuf(1, 1, 32, IB_byte_data | IB_metadata);
358 if (!img) {
359 return nullptr;
360 }
361 }
362 else {
364 {
365 /* only load if we didn't give an image */
366 if (img == nullptr) {
367 switch (source) {
368 case THB_SOURCE_IMAGE:
369 img = IMB_thumb_load_image(file_path, tsize, nullptr);
370 break;
371 case THB_SOURCE_BLEND:
372 img = IMB_thumb_load_blend(file_path, blen_group, blen_id);
373 break;
374 case THB_SOURCE_FONT:
375 img = IMB_thumb_load_font(file_path, tsize, tsize);
376 break;
378 if (BLI_path_extension_check(file_path, ".svg")) {
379 img = IMB_thumb_load_image(file_path, tsize, nullptr);
380 }
381 break;
382 }
383 default:
384 BLI_assert_unreachable(); /* This should never happen */
385 }
386 }
387
388 if (img != nullptr) {
389 if (BLI_stat(file_path, &info) != -1) {
390 SNPRINTF(mtime, "%ld", (long int)info.st_mtime);
391 }
392 }
393 }
394 else if (THB_SOURCE_MOVIE == source) {
395 MovieReader *anim = nullptr;
396 anim = MOV_open_file(file_path, IB_byte_data | IB_metadata, 0, nullptr);
397 if (anim != nullptr) {
399 if (img == nullptr) {
400 // printf("not an anim; %s\n", file_path);
401 }
402 else {
403 IMB_freeImBuf(img);
404 img = MOV_decode_preview_frame(anim);
405 }
406 MOV_close(anim);
407 }
408 if (BLI_stat(file_path, &info) != -1) {
409 SNPRINTF(mtime, "%ld", (long int)info.st_mtime);
410 }
411 }
412 if (!img) {
413 return nullptr;
414 }
415
416 if (img->x > tsize || img->y > tsize) {
417 float scale = std::min(float(tsize) / float(img->x), float(tsize) / float(img->y));
418 /* Scaling down must never assign zero width/height, see: #89868. */
419 short ex = std::max(short(1), short(img->x * scale));
420 short ey = std::max(short(1), short(img->y * scale));
421 /* Save some time by only scaling byte buffer. */
422 if (img->float_buffer.data) {
423 if (img->byte_buffer.data == nullptr) {
425 }
427 }
428 IMB_scale(img, ex, ey, IMBScaleFilter::Box, false);
429 }
430 }
431 SNPRINTF(desc, "Thumbnail for %s", uri);
433 IMB_metadata_set_field(img->metadata, "Software", "Blender");
434 IMB_metadata_set_field(img->metadata, "Thumb::URI", uri);
435 IMB_metadata_set_field(img->metadata, "Description", desc);
436 IMB_metadata_set_field(img->metadata, "Thumb::MTime", mtime);
437 if (use_hash) {
438 IMB_metadata_set_field(img->metadata, "X-Blender::Hash", hash);
439 }
440 img->ftype = IMB_FTYPE_PNG;
441 img->planes = 32;
442
443 /* If we generated from a 16bit PNG e.g., we have a float rect, not a byte one - fix this. */
446
447 if (IMB_save_image(img, temp, IB_byte_data | IB_metadata)) {
448#ifndef WIN32
449 chmod(temp, S_IRUSR | S_IWUSR);
450#endif
451 // printf("%s saving thumb: '%s'\n", __func__, tpath);
452
453 BLI_rename_overwrite(temp, tpath);
454 }
455 }
456 return img;
457}
458
459static ImBuf *thumb_create_or_fail(const char *file_path,
460 const char *uri,
461 const char *thumb,
462 const bool use_hash,
463 const char *hash,
464 const char *blen_group,
465 const char *blen_id,
467 ThumbSource source)
468{
469 ImBuf *img = thumb_create_ex(
470 file_path, uri, thumb, use_hash, hash, blen_group, blen_id, size, source, nullptr);
471
472 if (!img) {
473 /* thumb creation failed, write fail thumb */
474 img = thumb_create_ex(
475 file_path, uri, thumb, use_hash, hash, blen_group, blen_id, THB_FAIL, source, nullptr);
476 if (img) {
477 /* we don't need failed thumb anymore */
478 IMB_freeImBuf(img);
479 img = nullptr;
480 }
481 }
482
483 return img;
484}
485
486ImBuf *IMB_thumb_create(const char *filepath, ThumbSize size, ThumbSource source, ImBuf *img)
487{
488 char uri[URI_MAX] = "";
489 char thumb_name[40];
490
491 if (!uri_from_filepath(filepath, uri)) {
492 return nullptr;
493 }
494 thumbname_from_uri(uri, thumb_name, sizeof(thumb_name));
495
496 return thumb_create_ex(
497 filepath, uri, thumb_name, false, THUMB_DEFAULT_HASH, nullptr, nullptr, size, source, img);
498}
499
500ImBuf *IMB_thumb_read(const char *file_or_lib_path, ThumbSize size)
501{
502 char thumb[FILE_MAX];
503 char uri[URI_MAX];
504 ImBuf *img = nullptr;
505
506 if (!uri_from_filepath(file_or_lib_path, uri)) {
507 return nullptr;
508 }
509 if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
511 }
512
513 return img;
514}
515
516void IMB_thumb_delete(const char *file_or_lib_path, ThumbSize size)
517{
518 char thumb[FILE_MAX];
519 char uri[URI_MAX];
520
521 if (!uri_from_filepath(file_or_lib_path, uri)) {
522 return;
523 }
524 if (thumbpath_from_uri(uri, thumb, sizeof(thumb), size)) {
525 if (BLI_path_ncmp(file_or_lib_path, thumb, sizeof(thumb)) == 0) {
526 return;
527 }
528 if (BLI_exists(thumb)) {
529 BLI_delete(thumb, false, false);
530 }
531 }
532}
533
534ImBuf *IMB_thumb_manage(const char *file_or_lib_path, ThumbSize size, ThumbSource source)
535{
536 char path_buff[FILE_MAX_LIBEXTRA];
537 char *blen_group = nullptr, *blen_id = nullptr;
538
539 /* Will be the actual path to the file, i.e. the same as #file_or_lib_path, or if that points
540 * into a .blend, the path of the .blend. */
541 const char *file_path = file_or_lib_path;
542 if (source == THB_SOURCE_BLEND) {
543 if (BKE_blendfile_library_path_explode(file_or_lib_path, path_buff, &blen_group, &blen_id)) {
544 if (blen_group) {
545 if (!blen_id) {
546 /* No preview for blen groups */
547 return nullptr;
548 }
549 file_path = path_buff; /* path needs to be a valid file! */
550 }
551 }
552 }
553
554 BLI_stat_t st;
555 if (BLI_stat(file_path, &st) == -1) {
556 return nullptr;
557 }
558 char uri[URI_MAX];
559 if (!uri_from_filepath(file_or_lib_path, uri)) {
560 return nullptr;
561 }
562
563 /* Don't access offline files, only use already existing thumbnails (don't recreate). */
564 const eFileAttributes file_attributes = BLI_file_attributes(file_path);
565 if (file_attributes & FILE_ATTR_OFFLINE) {
566 char thumb_path[FILE_MAX];
567 if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), size)) {
569 }
570 return nullptr;
571 }
572
573 char thumb_path[FILE_MAX];
574 if (thumbpath_from_uri(uri, thumb_path, sizeof(thumb_path), THB_FAIL)) {
575 /* failure thumb exists, don't try recreating */
576 if (BLI_exists(thumb_path)) {
577 /* clear out of date fail case (note for blen IDs we use blender file itself here) */
578 if (BLI_file_older(thumb_path, file_path)) {
579 BLI_delete(thumb_path, false, false);
580 }
581 else {
582 return nullptr;
583 }
584 }
585 }
586
587 ImBuf *img = nullptr;
588 char thumb_name[40];
590 uri, thumb_path, sizeof(thumb_path), thumb_name, sizeof(thumb_name), size))
591 {
592 /* The requested path points to a generated thumbnail already (path into the thumbnail cache
593 * directory). Attempt to load that, there's nothing we can recreate. */
594 if (BLI_path_ncmp(file_or_lib_path, thumb_path, sizeof(thumb_path)) == 0) {
595 img = IMB_load_image_from_filepath(file_or_lib_path, IB_byte_data);
596 }
597 else {
599 if (img) {
600 bool regenerate = false;
601
602 char mtime[40];
603 char thumb_hash[33];
604 char thumb_hash_curr[33];
605
606 const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
607
608 if (IMB_metadata_get_field(img->metadata, "Thumb::MTime", mtime, sizeof(mtime))) {
609 regenerate = (st.st_mtime != atol(mtime));
610 }
611 else {
612 /* illegal thumb, regenerate it! */
613 regenerate = true;
614 }
615
616 if (use_hash && !regenerate) {
618 img->metadata, "X-Blender::Hash", thumb_hash_curr, sizeof(thumb_hash_curr)))
619 {
620 regenerate = !STREQ(thumb_hash, thumb_hash_curr);
621 }
622 else {
623 regenerate = true;
624 }
625 }
626
627 if (regenerate) {
628 /* recreate all thumbs */
629 IMB_freeImBuf(img);
630 img = nullptr;
631 IMB_thumb_delete(file_or_lib_path, THB_NORMAL);
632 IMB_thumb_delete(file_or_lib_path, THB_LARGE);
633 IMB_thumb_delete(file_or_lib_path, THB_FAIL);
635 file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source);
636 }
637 }
638 else {
639 char thumb_hash[33];
640 const bool use_hash = thumbhash_from_path(file_path, source, thumb_hash);
641
643 file_path, uri, thumb_name, use_hash, thumb_hash, blen_group, blen_id, size, source);
644 }
645 }
646 }
647
648 /* Our imbuf **must** have a valid rect (i.e. 8-bits/channels)
649 * data, we rely on this in draw code.
650 * However, in some cases we may end loading 16bits PNGs, which generated float buffers.
651 * This should be taken care of in generation step, but add also a safeguard here! */
652 if (img) {
655 }
656
657 return img;
658}
659
660/* ***** Threading ***** */
661/* Thumbnail handling is not really threadsafe in itself.
662 * However, as long as we do not operate on the same file, we shall have no collision.
663 * So idea is to 'lock' a given source file path.
664 */
665
671
673{
675
676 if (thumb_locks.lock_counter == 0) {
677 BLI_assert(thumb_locks.locked_paths == nullptr);
678 thumb_locks.locked_paths = BLI_gset_str_new(__func__);
680 }
681 thumb_locks.lock_counter++;
682
683 BLI_assert(thumb_locks.locked_paths != nullptr);
684 BLI_assert(thumb_locks.lock_counter > 0);
686}
687
689{
691 BLI_assert((thumb_locks.locked_paths != nullptr) && (thumb_locks.lock_counter > 0));
692
693 thumb_locks.lock_counter--;
694 if (thumb_locks.lock_counter == 0) {
695 BLI_gset_free(thumb_locks.locked_paths, MEM_freeN);
696 thumb_locks.locked_paths = nullptr;
698 }
699
701}
702
703void IMB_thumb_path_lock(const char *path)
704{
705 void *key = BLI_strdup(path);
706
708 BLI_assert((thumb_locks.locked_paths != nullptr) && (thumb_locks.lock_counter > 0));
709
710 if (thumb_locks.locked_paths) {
711 while (!BLI_gset_add(thumb_locks.locked_paths, key)) {
713 }
714 }
715
717}
718
719void IMB_thumb_path_unlock(const char *path)
720{
721 const void *key = path;
722
724 BLI_assert((thumb_locks.locked_paths != nullptr) && (thumb_locks.lock_counter > 0));
725
726 if (thumb_locks.locked_paths) {
727 if (!BLI_gset_remove(thumb_locks.locked_paths, key, MEM_freeN)) {
729 }
731 }
732
734}
bool BKE_blendfile_library_path_explode(const char *path, char *r_dir, char **r_group, char **r_name)
Definition blendfile.cc:90
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
File and directory operations.
eFileAttributes BLI_file_attributes(const char *path)
Definition storage.cc:250
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:373
bool BLI_file_older(const char *file1, const char *file2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:627
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
struct stat BLI_stat_t
int BLI_rename_overwrite(const char *from, const char *to) ATTR_NONNULL()
Definition fileops_c.cc:505
eFileAttributes
@ FILE_ATTR_OFFLINE
const char * BLI_dir_home(void)
Definition storage.cc:110
struct GSet GSet
Definition BLI_ghash.h:337
GSet * BLI_gset_str_new(const char *info)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.cc:999
char * BLI_hash_md5_to_hexdigest(const void *resblock, char r_hex_digest[33])
Definition hash_md5.cc:382
void * BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock)
Definition hash_md5.cc:346
#define BLI_path_ncmp
#define FILE_MAX
const char * BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_is_win32_drive(const char *path)
const char * BLI_path_slash_skip(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
bool BLI_path_is_unc(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char char size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void BLI_string_replace_char(char *str, char src, char dst) ATTR_NONNULL(1)
unsigned char uchar
void BLI_condition_notify_all(ThreadCondition *cond)
Definition threads.cc:595
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_thread_lock(int type)
Definition threads.cc:328
void BLI_condition_wait_global_mutex(ThreadCondition *cond, int type)
Definition threads.cc:585
pthread_cond_t ThreadCondition
void BLI_condition_end(ThreadCondition *cond)
Definition threads.cc:600
void BLI_condition_init(ThreadCondition *cond)
Definition threads.cc:575
@ LOCK_IMAGE
Definition BLI_threads.h:63
#define ELEM(...)
#define STREQ(a, b)
Compatibility-like things for windows.
#define FILE_MAX_LIBEXTRA
ImBuf * IMB_load_image_from_filepath(const char *filepath, const int flags, char r_colorspace[IM_MAX_SPACE]=nullptr)
Definition readimage.cc:204
ImBuf * IMB_thumb_load_image(const char *filepath, const size_t max_thumb_size, char colorspace[IM_MAX_SPACE], const IMBThumbLoadFlags load_flags=IMBThumbLoadFlags::Zero)
Definition readimage.cc:229
void IMB_byte_from_float(ImBuf *ibuf)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_free_float_pixels(ImBuf *ibuf)
bool IMB_save_image(ImBuf *ibuf, const char *filepath, const int flags)
Definition writeimage.cc:20
bool IMB_scale(ImBuf *ibuf, unsigned int newx, unsigned int newy, IMBScaleFilter filter, bool threaded=true)
Definition scaling.cc:777
@ IMB_FTYPE_PNG
@ IMB_PROXY_NONE
@ IB_byte_data
@ IB_metadata
void IMB_metadata_set_field(IDProperty *metadata, const char *key, const char *value)
Definition metadata.cc:68
bool IMB_metadata_get_field(const IDProperty *metadata, const char *key, char *value, size_t value_maxncpy)
Definition metadata.cc:41
void IMB_metadata_ensure(IDProperty **metadata)
Definition metadata.cc:23
#define PREVIEW_RENDER_DEFAULT_HEIGHT
Definition IMB_thumbs.hh:40
ThumbSize
Definition IMB_thumbs.hh:21
@ THB_FAIL
Definition IMB_thumbs.hh:24
@ THB_NORMAL
Definition IMB_thumbs.hh:22
@ THB_LARGE
Definition IMB_thumbs.hh:23
bool IMB_thumb_load_font_get_hash(char *r_hash)
ThumbSource
Definition IMB_thumbs.hh:27
@ THB_SOURCE_IMAGE
Definition IMB_thumbs.hh:28
@ THB_SOURCE_FONT
Definition IMB_thumbs.hh:31
@ THB_SOURCE_BLEND
Definition IMB_thumbs.hh:30
@ THB_SOURCE_MOVIE
Definition IMB_thumbs.hh:29
@ THB_SOURCE_OBJECT_IO
Definition IMB_thumbs.hh:32
#define PREVIEW_RENDER_LARGE_HEIGHT
Definition IMB_thumbs.hh:41
ImBuf * IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const char *blen_id)
ImBuf * IMB_thumb_load_font(const char *filepath, unsigned int x, unsigned int y)
#define THUMB_DEFAULT_HASH
Definition IMB_thumbs.hh:48
Read Guarded memory(de)allocation.
@ IMB_TC_NONE
Definition MOV_enums.hh:46
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define abs
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
ImBuf * MOV_decode_preview_frame(MovieReader *anim)
void MOV_close(MovieReader *anim)
Definition movie_read.cc:58
MovieReader * MOV_open_file(const char *filepath, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
ImBuf * MOV_decode_frame(MovieReader *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
#define hash
Definition noise_c.cc:154
ThreadCondition cond
Definition thumbs.cc:669
int lock_counter
Definition thumbs.cc:668
GSet * locked_paths
Definition thumbs.cc:667
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
enum eImbFileType ftype
IDProperty * metadata
static bool uri_from_filepath(const char *path, char *uri)
Definition thumbs.cc:216
static bool thumbpathname_from_uri(const char *uri, char *r_path, const int path_maxncpy, char *r_name, int name_maxncpy, ThumbSize size)
Definition thumbs.cc:254
static ImBuf * thumb_create_or_fail(const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source)
Definition thumbs.cc:459
ImBuf * IMB_thumb_create(const char *filepath, ThumbSize size, ThumbSource source, ImBuf *img)
Definition thumbs.cc:486
ImBuf * IMB_thumb_read(const char *file_or_lib_path, ThumbSize size)
Definition thumbs.cc:500
void IMB_thumb_delete(const char *file_or_lib_path, ThumbSize size)
Definition thumbs.cc:516
static void thumbname_from_uri(const char *uri, char *thumb, const int thumb_maxncpy)
Definition thumbs.cc:289
void IMB_thumb_path_unlock(const char *path)
Definition thumbs.cc:719
void IMB_thumb_locks_acquire()
Definition thumbs.cc:672
ImBuf * IMB_thumb_manage(const char *file_or_lib_path, ThumbSize size, ThumbSource source)
Definition thumbs.cc:534
void IMB_thumb_path_lock(const char *path)
Definition thumbs.cc:703
#define URI_MAX
Definition thumbs.cc:70
static void escape_uri_string(const char *string, char *escaped_string, const int escaped_string_size, const eUnsafeCharacterSet mask)
Definition thumbs.cc:164
static const uchar acceptable[96]
Definition thumbs.cc:143
static const char hex[17]
Definition thumbs.cc:160
static bool thumbhash_from_path(const char *, ThumbSource source, char *r_hash)
Definition thumbs.cc:205
#define THUMBNAILS
Definition thumbs.cc:65
#define ACCEPTABLE(a)
static bool thumbpath_from_uri(const char *uri, char *path, const int path_maxncpy, ThumbSize size)
Definition thumbs.cc:294
void IMB_thumb_locks_release()
Definition thumbs.cc:688
static struct IMBThumbLocks thumb_locks
eUnsafeCharacterSet
Definition thumbs.cc:133
@ UNSAFE_HOST
Definition thumbs.cc:137
@ UNSAFE_ALLOW_PLUS
Definition thumbs.cc:135
@ UNSAFE_ALL
Definition thumbs.cc:134
@ UNSAFE_PATH
Definition thumbs.cc:136
@ UNSAFE_SLASHES
Definition thumbs.cc:138
static ImBuf * thumb_create_ex(const char *file_path, const char *uri, const char *thumb, const bool use_hash, const char *hash, const char *blen_group, const char *blen_id, ThumbSize size, ThumbSource source, ImBuf *img)
Definition thumbs.cc:316
void IMB_thumb_makedirs()
Definition thumbs.cc:299
static bool get_thumb_dir(char *dir, ThumbSize size)
Definition thumbs.cc:72
#define SEP_STR
Definition unit.cc:39
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)
Definition utfconv.cc:116