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