124#include <glib/gstdio.h>
163static void _pop_undo_execute(
const int32_t imgid,
const gboolean before,
const gboolean after);
165 const gboolean reload);
166static void _image_remove(
const int32_t imgid,
const gboolean undo);
205 gboolean changed =
FALSE;
235 undomono->
imgid = imgid;
236 undomono->
before = mask_bw;
237 undomono->
after = mask;
243 fprintf(stderr,
"[image] could not dt_image_cache_get imgid %i\n", imgid);
259 for(
int i = 0;
i < count;
i++)
281 return (has_d65 || has_adobe) ?
TRUE :
FALSE;
365 default:
return "unknown";
377 img->
flags &= ~DT_IMAGE_MOSAIC;
457 const char *ctx = context ? context :
"image";
465 const gboolean mosaic = dsc->
filters != 0u;
466 const gboolean xtrans = dsc->
filters == 9u;
467 const gboolean bayer = mosaic && !xtrans;
468 const size_t bpp = dsc->
bpp;
489 const unsigned int flags = (
unsigned int)img->
flags;
492 "[image debug] %s id=%d filename='%s' fullpath='%s'\n",
495 "[image debug] %s size=%dx%d crop=%dx%d+%d+%d orientation=%d psize=%dx%d pixel_aspect=%.6f\n",
499 "[image debug] %s flags=0x%08x raw=%d non_raw=%d ldr=%d hdr=%d sraw=%d 4bayer=%d mosaic=%d xtrans=%d "
500 "bayer=%d mono=%d mono_flags=0x%x mono_workflow=%d mono_preview=%d mono_bayer=%d bw=%d bw_flow=%d "
501 "local_copy=%d has_txt=%d has_wav=%d addl_dng=%d auto_presets=%d no_legacy_presets=%d rejected=%d remove=%d "
502 "has_localcopy=%d has_audio=%d is_hdr_field=%d\n",
503 ctx,
flags, is_raw, !is_raw, is_ldr, is_hdr,
512 "[image debug] %s buf: channels=%u datatype=%s bit_depth=%d bpp=%" G_GSIZE_FORMAT
" filters=%u cst=%d colorspace=%s "
513 "processed_max=[%.4f %.4f %.4f %.4f]\n",
518 "[image debug] %s colorspace=enum:%s d65_color_matrix=[%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f]\n",
523 "[image debug] %s raw: black=%u separate=[%u %u %u %u] white=%u rawprepare=[%u %u]\n",
528 "[image debug] %s class=%s state=%s needs_rawprepare=%d needs_demosaic=%d is_mosaiced=%d is_sraw=%d has_matrix=%d\n",
537 const char *
folder = path + strlen(path);
547 if(*
folder == G_DIR_SEPARATOR)
550 if(++count >= numparts)
565 g_strlcpy(pathname,
folder, pathname_len);
568 pathname[pathname_len - 1] =
'\0';
575 g_strlcpy(pathname, _(
"orphaned image"), pathname_len);
587 g_strlcpy(pathname, _(
"orphaned image"), pathname_len);
589 pathname[pathname_len - 1] =
'\0';
618 if(!strcmp(config,
"after edit") || !strcmp(config,
"on import") || !strcmp(config,
"always"))
res =
TRUE;
621 else if(!strcmp(config,
"TRUE"))
628 const char *sanitized =
res ?
"TRUE" :
"FALSE";
643 gboolean from_cache =
TRUE;
654 g_strlcat(pathname,
".xmp",
sizeof(pathname));
655 return !g_file_test(pathname, G_FILE_TEST_EXISTS);
660 size_t pathname_len, gboolean force_cache)
682 if(!force_cache && img->
fullpath[0] && g_file_test(img->
fullpath, G_FILE_TEST_EXISTS))
684 g_strlcpy(pathname, img->
fullpath, pathname_len);
693 g_strlcpy(pathname, img->
fullpath, pathname_len);
718void dt_image_full_path(
const int32_t imgid,
char *pathname,
size_t pathname_len, gboolean *from_cache,
const char *calling_func)
720 if(imgid < 0)
return;
722 const gboolean prefer_cache = (from_cache && *from_cache);
749 size_t local_copy_len,
char *local_copy_legacy_path,
750 size_t local_copy_legacy_len)
752 if(local_copy_path) local_copy_path[0] =
'\0';
753 if(local_copy_legacy_path) local_copy_legacy_path[0] =
'\0';
756 char *md5_filename = g_compute_checksum_for_string(G_CHECKSUM_MD5, fullpath, strlen(fullpath));
762 const char *c = fullpath + strlen(fullpath);
763 while(*c !=
'.' && c > fullpath) c--;
767 snprintf(local_copy_legacy_path, local_copy_legacy_len,
"%s/img-%d-%s%s", cachedir, imgid, md5_filename, c);
770 snprintf(local_copy_path, local_copy_len,
"%s/img-%s%s", cachedir, md5_filename, c);
781 char *filename = g_strdup(pathname);
783 char *c = pathname + strlen(pathname);
784 while(*c !=
'.' && c > pathname) c--;
785 snprintf(c, pathname + pathname_len - c,
"_%02d", version);
786 c = pathname + strlen(pathname);
787 char *
c2 = filename + strlen(filename);
788 while(*
c2 !=
'.' &&
c2 > filename)
c2--;
789 g_strlcpy(c,
c2, pathname + pathname_len - c);
833 else if(rating == -1)
878 for(GList *list = (GList *)data; list; list = g_list_next(list))
885 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undogeotag->
imgid));
889 ? _(
"geo-location undone for %d images")
890 : _(
"geo-location re-applied to %d images"),
i);
899 for(GList *list = (GList *)data; list; list = g_list_next(list))
906 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undodatetime->
imgid));
910 ? _(
"date/time undone for %d images")
911 : _(
"date/time re-applied to %d images"),
i);
927 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undo->
new_imgid));
938 GList *one = g_list_prepend(NULL, GINT_TO_POINTER(undo->
imgid));
967 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undo->
imgid));
970 fprintf(stderr,
"[dt_image_remove] fails to restore image %" PRId32
"\n", undo->
imgid);
991 *imgs = g_list_prepend(*imgs, GINT_TO_POINTER(undomono->
imgid));
997 GList *l = (GList *)data;
1004 for(GList *images = imgs; images; images = g_list_next(images))
1006 const int32_t imgid = GPOINTER_TO_INT(images->data);
1011 undogeotag->
imgid = imgid;
1016 *undo = g_list_append(*undo, undogeotag);
1046 imgs = g_list_prepend(imgs, GINT_TO_POINTER(imgid));
1054 GList **undo,
const gboolean undo_on)
1057 for(GList *imgs = (GList *)img; imgs; imgs = g_list_next(imgs))
1059 const int32_t imgid = GPOINTER_TO_INT(imgs->data);
1064 undogeotag->
imgid = imgid;
1069 *undo = g_list_prepend(*undo, undogeotag);
1095 if(imgid <= 0)
return;
1119 const int iop_flip_MODVER = 2;
1137 float bottom = in[2];
1138 float right = in[3];
1145 const float new_left = 1.0f - right;
1146 right = 1.0f - left;
1152 const float new_top = 1.0f - bottom;
1153 bottom = 1.0f -
top;
1159 const float swap_top = left;
1160 const float swap_bottom = right;
1164 bottom = swap_bottom;
1175 box[0] = box[1] = 0.0f;
1176 box[2] = box[3] = 1.0f;
1186 box[0] = box[1] = 0.0f;
1187 box[2] = box[3] = 1.0f;
1215 const gboolean has_file
1218 if(!has_file)
return FALSE;
1263 if(!strcmp(module->op,
"flip"))
1276 void *params = NULL;
1277 int32_t params_len = 0;
1344 hist->
imgid = imgid;
1393 const gboolean reload)
1403 dupundo->
version = newversion;
1480 fprintf(stderr,
"[dt_image_remove] fails to snapshot image %" PRId32
", removing it without undo\n", imgid);
1517static int _valid_glob_match(
const char *
const name,
size_t offset)
1521 if(strlen(
name) < offset ||
name[offset] !=
'_')
1526 if(!isdigit(
name[
i]))
1529 return name[
i] ==
'.';
1542 const size_t fn_len = strlen(filename);
1543 const char* ext = strrchr(filename,
'.');
1545 const size_t ext_offset = ext - filename;
1548 GList* files = NULL;
1551 static const char xmp[] =
".xmp";
1552 const size_t xmp_len = strlen(xmp);
1554 g_strlcpy(pattern, filename,
sizeof(pattern));
1555 g_strlcpy(pattern + fn_len, xmp,
sizeof(pattern) - fn_len);
1559 files = g_list_prepend(files, g_strdup(pattern));
1563 static const char glob_pattern[] =
"_[0-9]*[0-9]";
1564 const size_t gp_len = strlen(glob_pattern);
1565 if(fn_len + gp_len + xmp_len <
sizeof(pattern))
1568 g_strlcpy(pattern + ext_offset, glob_pattern,
sizeof(pattern) - fn_len);
1569 g_strlcpy(pattern + ext_offset + gp_len, ext,
sizeof(pattern) - ext_offset - gp_len);
1570 g_strlcpy(pattern + fn_len + gp_len, xmp,
sizeof(pattern) - fn_len - gp_len);
1572 if(!glob(pattern, 0, NULL, &globbuf))
1575 for(
size_t i = 0;
i < globbuf.gl_pathc;
i++)
1577 if(_valid_glob_match(globbuf.gl_pathv[
i], ext_offset))
1580 files = g_list_prepend(files, g_strdup(globbuf.gl_pathv[
i]));
1587 return g_list_reverse(files);
1597 int count_xmps_processed = 0;
1603 g_snprintf(pattern,
sizeof(pattern),
"%s.xmp", filename);
1605 for(GList *file_iter = files; file_iter; file_iter = g_list_next(file_iter))
1607 gchar *xmpfilename = file_iter->data;
1611 if(!strncmp(xmpfilename, pattern,
sizeof(pattern)))
1620 gchar *
c3 = xmpfilename + strlen(xmpfilename)
1622 while(*
c3 !=
'.' &&
c3 > xmpfilename)
1625 while(*c4 !=
'_' && c4 > xmpfilename) c4--;
1628 gchar *idfield = g_strndup(c4,
c3 - c4);
1630 version = atoi(idfield);
1637 if(count_xmps_processed == 0)
1667 fprintf(stderr,
"[dt_image_read_duplicates] could not load image %i for sidecar '%s', skipping it\n",
1668 newid, xmpfilename);
1682 count_xmps_processed++;
1687 return count_xmps_processed;
1691 gboolean lua_locking, gboolean raise_signals)
1699 const char *cc = normalized_filename + strlen(normalized_filename);
1700 for(; *cc !=
'.' && cc > normalized_filename; cc--)
1702 if(!strcasecmp(cc,
".dt") || !strcasecmp(cc,
".dttags") || !strcasecmp(cc,
".xmp"))
1707 char *ext = g_ascii_strdown(cc + 1, -1);
1715 gchar *imgfname = g_path_get_basename(normalized_filename);
1719 dt_control_log(_(
"Image %s is already in library and will not be re-imported.\n"), imgfname);
1730 gchar *
extension = g_strrstr(imgfname,
".");
1752 gchar *basename = g_strdup(imgfname);
1753 gchar *cc2 = basename + strlen(basename);
1754 for(; *cc2 !=
'.' && cc2 > basename; cc2--)
1757 gchar *sql_pattern = g_strconcat(basename,
".%", NULL);
1760 if(strcmp(ext,
"jpg") != 0 && strcmp(ext,
"jpeg") != 0)
1764 if(other_group != -1)
1766 int other_id = other_group;
1768 gchar *other_basename = g_strdup(other_img->
filename);
1769 gchar *cc3 = other_basename + strlen(other_img->
filename);
1770 for(; *cc3 !=
'.' && cc3 > other_basename; cc3--)
1773 gchar *ext_lowercase = g_ascii_strdown(cc3, -1);
1775 if(!strcmp(ext_lowercase,
"jpg") || !strcmp(ext_lowercase,
"jpeg"))
1780 for(GList *l = members; l; l = g_list_next(l))
1782 other_id = GPOINTER_TO_INT(l->data);
1787 g_list_free(members);
1793 group_id = other_id;
1806 group_id = (other_group != -1) ? other_group : id;
1819 g_strlcpy(dtfilename, normalized_filename,
sizeof(dtfilename));
1821 g_strlcat(dtfilename,
".xmp",
sizeof(dtfilename));
1831 if((
res != 0) && (nb_xmp == 0))
1840 snprintf(tagname,
sizeof(tagname),
"darktable|format|%s", ext);
1861 GList *imgs = g_list_prepend(NULL, GINT_TO_POINTER(
id));
1875 gchar *dir = g_path_get_dirname(filename);
1876 gchar *file = g_path_get_basename(filename);
1905int32_t
dt_image_import(
const int32_t film_id,
const char *filename, gboolean raise_signals)
1917 memset(img, 0,
sizeof(*img));
1996 for(
int k=0;
k<4;
k++)
1997 for(
int i=0;
i<3;
i++)
2022 int32_t result = -1;
2025 gboolean from_cache =
FALSE;
2027 gchar *newdir = NULL;
2033 GFile *old = NULL, *
new = NULL;
2036 old = g_file_new_for_path(oldimg);
2040 g_snprintf(newimg,
sizeof(newimg),
"%s%c%s", newdir, G_DIR_SEPARATOR, newname);
2041 new = g_file_new_for_path(newimg);
2044 gchar *newBasename = g_file_get_basename(
new);
2045 if(g_strcmp0(newname, newBasename) != 0)
2047 g_object_unref(old);
2049 g_object_unref(
new);
2056 gchar *imgbname = g_path_get_basename(oldimg);
2057 g_snprintf(newimg,
sizeof(newimg),
"%s%c%s", newdir, G_DIR_SEPARATOR, imgbname);
2058 new = g_file_new_for_path(newimg);
2075 GError *moveError = NULL;
2076 gboolean moveStatus = g_file_move(old,
new, 0, NULL, NULL, NULL, &moveError);
2084 for(GList *l = dup_list; l; l = g_list_next(l))
2086 const int32_t
id = GPOINTER_TO_INT(l->data);
2088 g_strlcpy(oldxmp, oldimg,
sizeof(oldxmp));
2089 g_strlcpy(newxmp, newimg,
sizeof(newxmp));
2092 g_strlcat(oldxmp,
".xmp",
sizeof(oldxmp));
2093 g_strlcat(newxmp,
".xmp",
sizeof(newxmp));
2095 GFile *goldxmp = g_file_new_for_path(oldxmp);
2096 GFile *gnewxmp = g_file_new_for_path(newxmp);
2098 g_file_move(goldxmp, gnewxmp, 0, NULL, NULL, NULL, NULL);
2100 g_object_unref(goldxmp);
2101 g_object_unref(gnewxmp);
2109 const int id = GPOINTER_TO_INT(dup_list->data);
2115 dup_list = g_list_delete_link(dup_list, dup_list);
2117 g_list_free(dup_list);
2121 if(g_file_test(copysrcpath, G_FILE_TEST_EXISTS))
2131 GFile *cold = g_file_new_for_path(copysrcpath);
2132 GFile *cnew = g_file_new_for_path(copydestpath);
2134 g_clear_error(&moveError);
2135 moveStatus = g_file_move(cold, cnew, 0, NULL, NULL, NULL, &moveError);
2138 fprintf(stderr,
"[dt_image_rename] error moving local copy `%s' -> `%s'\n", copysrcpath, copydestpath);
2140 if(g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
2142 gchar *oldBasename = g_path_get_basename(copysrcpath);
2146 else if(g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_EXISTS)
2147 || g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY))
2149 gchar *newBasename = g_path_get_basename(copydestpath);
2155 gchar *oldBasename = g_path_get_basename(copysrcpath);
2156 gchar *newBasename = g_path_get_basename(copydestpath);
2157 dt_control_log(_(
"error moving local copy `%s' -> `%s'"), oldBasename, newBasename);
2163 g_object_unref(cold);
2164 g_object_unref(cnew);
2171 if(g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
2180 && (g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_EXISTS)
2181 || g_error_matches(moveError, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)))
2183 dt_control_log(_(
"error moving `%s' -> `%s': file exists"), oldimg, newimg);
2191 g_clear_error(&moveError);
2192 g_object_unref(old);
2193 g_object_unref(
new);
2208 gchar *newdir = NULL;
2209 gboolean from_cache =
FALSE;
2210 gchar *oldFilename = NULL;
2211 gchar *newFilename = NULL;
2215 GFile *src = NULL, *dest = NULL;
2219 oldFilename = g_path_get_basename(srcpath);
2223 newFilename = g_strdup(newname);
2224 destpath = g_build_filename(newdir, newname, NULL);
2225 dest = g_file_new_for_path(destpath);
2228 gchar *destBasename = g_file_get_basename(dest);
2229 if(g_strcmp0(newname, destBasename) != 0)
2231 g_object_unref(dest);
2238 newFilename = g_path_get_basename(srcpath);
2239 destpath = g_build_filename(newdir, newFilename, NULL);
2240 dest = g_file_new_for_path(destpath);
2244 src = g_file_new_for_path(srcpath);
2254 GError *gerror = NULL;
2255 gboolean copyStatus = g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &gerror);
2257 if(copyStatus || g_error_matches(gerror, G_IO_ERROR, G_IO_ERROR_EXISTS))
2259 gchar *dest_image_path = g_file_get_path(dest);
2281 fprintf(stderr,
"Failed to copy image %s: %s\n", srcpath, gerror->message);
2283 g_object_unref(dest);
2284 g_object_unref(src);
2285 g_clear_error(&gerror);
2309 g_strlcpy(local_copy_path, img->
local_copy_path,
sizeof(local_copy_path));
2314 g_strlcpy(destpath, existing,
sizeof(destpath));
2316 g_strlcpy(destpath, local_copy_path,
sizeof(destpath));
2325 if(!g_file_test(srcpath, G_FILE_TEST_IS_REGULAR))
2327 dt_control_log(_(
"cannot create local copy when the original file is not accessible."));
2333 GFile *src = g_file_new_for_path(srcpath);
2334 GFile *dest = g_file_new_for_path(destpath);
2337 GError *gerror = NULL;
2339 if(!g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &gerror))
2342 g_object_unref(dest);
2343 g_object_unref(src);
2347 g_object_unref(dest);
2348 g_object_unref(src);
2380 if(!local_copy_exists)
2385 gboolean from_cache =
FALSE;
2391 g_strlcat(locppath,
".xmp",
sizeof(locppath));
2395 if(g_file_test(locppath, G_FILE_TEST_EXISTS) && !g_file_test(destpath, G_FILE_TEST_EXISTS))
2397 dt_control_log(_(
"cannot remove local copy when the original file is not accessible."));
2416 if(g_file_test(locppath, G_FILE_TEST_EXISTS) && strstr(locppath, cachedir))
2418 GFile *dest = g_file_new_for_path(locppath);
2430 g_file_delete(dest, NULL, NULL);
2433 g_object_unref(dest);
2437 g_strlcat(locppath,
".xmp",
sizeof(locppath));
2438 dest = g_file_new_for_path(locppath);
2440 if(g_file_test(locppath, G_FILE_TEST_EXISTS)) g_file_delete(dest, NULL, NULL);
2441 g_object_unref(dest);
2449 img->
flags &= ~DT_IMAGE_LOCAL_COPY;
2467 if(write_timestamp <= 0)
return FALSE;
2471 const int64_t change_timestamp_unix = g_date_time_to_unix(gdt);
2472 g_date_time_unref(gdt);
2474 "[xmp] imgid %d change_ts=%lld write_ts=%lld\n",
2475 img->
id, (
long long)change_timestamp_unix, (
long long)write_timestamp);
2476 return change_timestamp_unix <= write_timestamp;
2480 const gboolean force_write)
2492 g_strlcpy(filename, imgpath,
sizeof(filename));
2494 g_strlcat(filename,
".xmp",
sizeof(filename));
2496 if(!force_write && g_file_test(filename, G_FILE_TEST_EXISTS))
2565 GList *imgs = g_list_append(NULL, GINT_TO_POINTER(
selected));
2586 GList *imgs = g_list_append(NULL, GINT_TO_POINTER(imgid));
2599 for(GList *l = candidates; l; l = g_list_next(l))
2601 const int32_t imgid = GPOINTER_TO_INT(l->data);
2602 gboolean from_cache =
FALSE;
2606 if(g_file_test(filename, G_FILE_TEST_EXISTS))
2608 imgs = g_list_prepend(imgs, GINT_TO_POINTER(imgid));
2611 g_list_free(candidates);
2613 const int count = g_list_length(imgs);
2618 "%d local copies have been synchronized", count),
2637 GList *l = (GList *)data;
2648 GList **undo,
const gboolean undo_on)
2651 for(GList *imgs = (GList *)img; imgs; imgs = g_list_next(imgs))
2653 const int32_t imgid = GPOINTER_TO_INT(imgs->data);
2659 undodatetime->
imgid = imgid;
2664 *undo = g_list_prepend(*undo, undodatetime);
2689 GList **undo,
const gboolean undo_on)
2691 for(GList *imgs = (GList *)img; imgs; imgs = g_list_next(imgs))
2693 const int32_t imgid = GPOINTER_TO_INT(imgs->data);
2697 undodatetime->
imgid = imgid;
2702 *undo = g_list_prepend(*undo, undodatetime);
2727 size_t len = strlen(image_path);
2728 const char *c = image_path + len;
2729 while((c > image_path) && (*c !=
'.')) c--;
2730 len = c - image_path + 1;
2732 char *result = g_strndup(image_path, len + 3);
2735 result[len + 1] =
'a';
2736 result[len + 2] =
'v';
2737 if(g_file_test(result, G_FILE_TEST_EXISTS))
return result;
2740 result[len + 1] =
'A';
2741 result[len + 2] =
'V';
2742 if(g_file_test(result, G_FILE_TEST_EXISTS))
return result;
2750 gboolean from_cache =
FALSE;
2752 dt_image_full_path(imgid, image_path,
sizeof(image_path), &from_cache, __FUNCTION__);
2759 size_t len = strlen(image_path);
2760 const char *c = image_path + len;
2761 while((c > image_path) && (*c !=
'.')) c--;
2762 len = c - image_path + 1;
2764 char *result = g_strndup(image_path, len + 3);
2767 result[len + 1] =
'x';
2768 result[len + 2] =
't';
2769 if(g_file_test(result, G_FILE_TEST_EXISTS))
return result;
2772 result[len + 1] =
'X';
2773 result[len + 2] =
'T';
2774 if(g_file_test(result, G_FILE_TEST_EXISTS))
return result;
2782 size_t len = strlen(image_path);
2783 const char *c = image_path + len;
2784 while((c > image_path) && (*c !=
'.')) c--;
2785 len = c - image_path + 1;
2787 char *result = g_strndup(image_path, len + 3);
2789 result[len + 1] =
'x';
2790 result[len + 2] =
't';
2818 GFile *src = g_file_new_for_path(src_txt);
2819 GFile *dest = g_file_new_for_path(dest_txt);
2820 GError *gerror = NULL;
2821 gboolean copyStatus = g_file_copy(src, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &gerror);
2823 if(!copyStatus && g_error_matches(gerror, G_IO_ERROR, G_IO_ERROR_EXISTS))
2826 if(!copyStatus && gerror)
2827 fprintf(stderr,
"[dt_image] failed to copy text sidecar `%s' -> `%s': %s\n",
2828 src_txt, dest_txt, gerror->message);
2830 g_clear_error(&gerror);
2831 g_object_unref(dest);
2832 g_object_unref(src);
2849 GFile *src = g_file_new_for_path(src_txt);
2850 GFile *dest = g_file_new_for_path(dest_txt);
2851 GError *gerror = NULL;
2852 const GFileCopyFlags
flags = overwrite ? G_FILE_COPY_OVERWRITE : G_FILE_COPY_NONE;
2853 gboolean moveStatus = g_file_move(src, dest,
flags, NULL, NULL, NULL, &gerror);
2855 if(!moveStatus && gerror)
2856 fprintf(stderr,
"[dt_image] failed to move text sidecar `%s' -> `%s': %s\n",
2857 src_txt, dest_txt, gerror->message);
2859 g_clear_error(&gerror);
2860 g_object_unref(dest);
2861 g_object_unref(src);
2872 gboolean from_cache =
FALSE;
2873 dt_image_full_path(imgid, image_path,
sizeof(image_path), &from_cache, __FUNCTION__);
2875 if(image_path[0] !=
'\0' && g_file_test(image_path, G_FILE_TEST_EXISTS))
2879 dt_image_full_path(imgid, image_path,
sizeof(image_path), &from_cache, __FUNCTION__);
2881 if(from_cache && image_path[0] !=
'\0' && g_file_test(image_path, G_FILE_TEST_EXISTS))
2905 const char *T1 = _(
"<b>WARNING</b>: camera is missing samples!");
2906 const char *T2 = _(
"You must provide samples in <a href='https://raw.pixls.us/'>https://raw.pixls.us/</a>");
2907 char *T3 = g_strdup_printf(_(
"for `%s' `%s'\n"
2908 "in as many format/compression/bit depths as possible"),
2910 const char *T4 = _(
"or the <b>RAW won't be readable</b> in next version.");
2912 char *NL = logmsg ?
"\n\n" :
"\n";
2913 char *PREFIX = logmsg ?
"<big>" :
"";
2914 char *SUFFIX = logmsg ?
"</big>" :
"";
2916 char *msg = g_strconcat(PREFIX, T1, NL, T2, NL, T3, NL, T4, SUFFIX, NULL);
2943 gboolean from_cache =
FALSE;
2945 gchar *
folder = g_path_get_dirname(path);
GList * dt_act_on_get_images()
void dt_atomic_set_int(dt_atomic_int *var, int value)
int dt_atomic_get_int(dt_atomic_int *var)
const char * extension(dt_imageio_module_data_t *data)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static void transform(float *x, float *o, const float *m, const float t_h, const float t_v)
void dt_collection_update_query(const dt_collection_t *collection, dt_collection_change_t query_change, dt_collection_properties_t changed_property, GList *list)
dt_collection_t * dt_collection_get_global(void)
@ DT_COLLECTION_PROP_UNDEF
@ DT_COLLECTION_CHANGE_RELOAD
const dt_colormatrix_t dt_aligned_pixel_t out
const dt_colormatrix_t matrix
gchar * dt_conf_get_string(const char *name)
Read the stored string for name as a private copy.
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
void dt_conf_set_string(const char *name, const char *val)
static dt_atomic_int _xmp_mode_cache
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
int32_t dt_image_copy_rename(const int32_t imgid, const int32_t filmid, const gchar *newname)
int32_t dt_image_move(const int32_t imgid, const int32_t filmid)
void dt_image_synch_xmps(const GList *img)
static void _pop_undo(gpointer user_data, const dt_undo_type_t type, dt_undo_data_t data, const dt_undo_action_t action, GList **imgs)
char * dt_image_get_audio_path(const int32_t imgid)
gboolean dt_image_is_raw(const dt_image_t *img)
dt_image_pipe_class_t dt_image_pipe_class(const dt_image_t *img)
int dt_image_get_xmp_rating(const dt_image_t *img)
int32_t dt_image_import(const int32_t film_id, const char *filename, gboolean raise_signals)
void dt_image_check_camera_missing_sample(const struct dt_image_t *img)
dt_image_orientation_t dt_image_get_orientation(const int32_t imgid)
static void _image_set_monochrome_flag(const int32_t imgid, gboolean monochrome, gboolean undo_on)
dt_image_flags_t dt_image_flags_from_extension(const char *extension)
void dt_image_path_append_version(const int32_t imgid, char *pathname, size_t pathname_len)
static void _set_location(const int32_t imgid, const dt_image_geoloc_t *geoloc)
static gboolean _image_matrix_has_data(const float *matrix, const int count)
int32_t dt_image_get_id(int32_t film_id, const gchar *filename)
int32_t dt_image_copy(const int32_t imgid, const int32_t filmid)
void dt_image_refresh_makermodel(dt_image_t *img)
static dt_image_orientation_t _orientation_mirror_horizontally(dt_image_orientation_t orientation)
Toggle the stored bit that mirrors the image along the axis the USER calls horizontal.
int32_t dt_image_duplicate_no_reload(const int32_t imgid)
static const char * _image_buf_type_to_string(const dt_iop_buffer_type_t type)
int dt_image_monochrome_flags(const dt_image_t *img)
uint32_t dt_image_altered(const int32_t imgid)
int32_t dt_image_import_lua(const int32_t film_id, const char *filename)
void dt_image_get_datetime(const int32_t imgid, char *datetime)
const char * dt_image_pipe_class_name(const dt_image_pipe_class_t klass)
static void _geotag_undo_data_free(gpointer data)
char * dt_image_get_text_path_from_path(const char *image_path)
void dt_image_set_location(const int32_t imgid, const dt_image_geoloc_t *geoloc, const gboolean undo_on, const gboolean group_on)
void dt_image_film_roll(const dt_image_t *img, char *pathname, size_t pathname_len)
void dt_image_print_exif(const dt_image_t *img, char *line, size_t line_len)
void dt_image_synch_all_xmp(const gchar *pathname)
void dt_image_get_location(const int32_t imgid, dt_image_geoloc_t *geoloc)
static void _datetime_undo_data_free(gpointer data)
gboolean dt_image_is_hdr(const dt_image_t *img)
int32_t dt_image_duplicate_with_version(const int32_t imgid, const int32_t newversion)
gboolean dt_image_is_monochrome(const dt_image_t *img)
void dt_image_print_debug_info(const dt_image_t *img, const char *context)
static dt_image_orientation_t _orientation_mirror_vertically(dt_image_orientation_t orientation)
The same, along the axis the user calls vertical.
void dt_image_init(dt_image_t *img)
void dt_image_buffer_resolve_flags(dt_image_t *img)
static void _move_text_sidecar_if_present(const char *src_image_path, const char *dest_image_path, const gboolean overwrite)
void dt_image_set_datetimes(const GList *imgs, const GArray *dtime, const gboolean undo_on)
static int32_t _image_duplicate_with_version(const int32_t imgid, const int32_t newversion, const gboolean undo, const gboolean reload)
static void _image_set_datetimes(const GList *img, const GArray *dtime, GList **undo, const gboolean undo_on)
const char * dt_image_film_roll_name(const char *path)
float dt_image_get_exposure_bias(const struct dt_image_t *image_storage)
GList * dt_image_find_xmps(const char *filename)
void dt_image_flip(const int32_t imgid, const dt_image_transform_t transform)
Apply an orientation change to one image, on top of the orientation it already has.
static dt_image_write_sidecar_result_t _write_sidecar_file_from_image_locked(const dt_image_t *img, const gboolean force_write)
void dt_image_set_datetime(const GList *imgs, const char *datetime, const gboolean undo_on)
static void _pop_undo_execute(const int32_t imgid, const gboolean before, const gboolean after)
gboolean dt_image_is_ldr(const dt_image_t *img)
static int _nb_other_local_copy_for(const int32_t imgid)
gboolean dt_image_pipe_class_is_provisional(const dt_image_t *img)
void dt_image_path_append_version_no_db(int version, char *pathname, size_t pathname_len)
gboolean dt_image_needs_rawprepare(const dt_image_t *img)
static dt_image_orientation_t _image_get_history_orientation(const int32_t imgid)
void dt_image_set_monochrome_flag(const int32_t imgid, gboolean monochrome)
static void _image_set_datetime(const GList *img, const char *datetime, GList **undo, const gboolean undo_on)
static void _set_datetime(const int32_t imgid, const char *datetime)
void dt_image_set_images_locations(const GList *imgs, const GArray *gloc, const gboolean undo_on)
char * dt_image_get_audio_path_from_path(const char *image_path)
void dt_image_remove_undoable(const int32_t imgid)
Same as dt_image_remove(), and records the removal on the undo stack.
gboolean dt_image_use_monochrome_workflow(const dt_image_t *img)
int dt_image_local_copy_set(const int32_t imgid)
static void _image_set_location(GList *imgs, const dt_image_geoloc_t *geoloc, GList **undo, const gboolean undo_on)
void dt_image_film_roll_directory(const dt_image_t *img, char *pathname, size_t pathname_len)
gboolean dt_image_get_usercrop_oriented(const dt_image_t *img, const dt_image_orientation_t orientation, dt_boundingbox_t box)
dt_image_path_source_t dt_image_choose_input_path(const dt_image_t *img, char *pathname, size_t pathname_len, gboolean force_cache)
dt_image_write_sidecar_result_t dt_image_write_sidecar_file(const int32_t imgid)
static void _remove_undo_data_free(gpointer data)
void dt_image_xmp_mode_refresh_from_conf(void)
dt_image_orientation_t dt_image_get_effective_orientation(const dt_image_t *img)
void dt_image_remove(const int32_t imgid)
gboolean dt_image_is_sraw(const dt_image_t *img)
void dt_image_set_flip(const int32_t imgid, const dt_image_orientation_t orientation)
static void _image_remove(const int32_t imgid, const gboolean undo)
gboolean dt_image_is_mosaiced(const dt_image_t *img)
char * dt_image_camera_missing_sample_message(const struct dt_image_t *img, gboolean logmsg)
int dt_image_get_xmp_rating_from_flags(const int flags)
void dt_image_set_locations(const GList *imgs, const dt_image_geoloc_t *geoloc, const gboolean undo_on)
static void _copy_text_sidecar_if_present(const char *src_image_path, const char *dest_image_path)
int dt_image_read_duplicates(const uint32_t id, const char *filename, const gboolean clear_selection)
void dt_image_orient_boundingbox(const dt_boundingbox_t in, const dt_image_orientation_t orientation, dt_boundingbox_t out)
gboolean dt_image_resolve_usercrop(const int32_t imgid, dt_boundingbox_t box)
static void _image_set_images_locations(const GList *img, const GArray *gloc, GList **undo, const gboolean undo_on)
int dt_image_local_copy_reset(const int32_t imgid)
static int32_t _image_import_internal(const int32_t film_id, const char *filename, gboolean lua_locking, gboolean raise_signals)
gboolean dt_image_get_xmp_mode()
static char * _text_path_legacy_if_exists(const char *image_path)
char * dt_image_get_text_path(const int32_t imgid)
int32_t dt_image_get_id_full_path(const gchar *filename)
gboolean dt_image_safe_remove(const int32_t imgid)
void dt_image_set_xmp_rating(dt_image_t *img, const int rating)
char * dt_image_build_text_path_from_path(const char *image_path)
static const char * _image_colorspace_to_string(const dt_image_colorspace_t colorspace)
static char * _text_path_legacy_build(const char *image_path)
static gboolean _sidecar_is_up_to_date(const dt_image_t *img)
dt_image_write_sidecar_result_t dt_image_write_sidecar_file_forced(const int32_t imgid)
int32_t dt_image_duplicate(const int32_t imgid)
gboolean dt_image_get_usercrop(const dt_image_t *img, dt_boundingbox_t box)
void dt_image_local_copy_synch()
int32_t dt_image_rename(const int32_t imgid, const int32_t filmid, const gchar *newname)
void dt_image_synch_xmp(const int selected)
void dt_get_dirname_from_imgid(gchar *dir, const int32_t imgid)
void dt_image_full_path(const int32_t imgid, char *pathname, size_t pathname_len, gboolean *from_cache, const char *calling_func)
Get the full path of an image out of the database.
void dt_image_history_changed(const int32_t imgid, const gboolean refresh_filmstrip)
gboolean dt_image_needs_demosaic(const dt_image_t *img)
void dt_image_set_provisional_dsc(dt_image_t *img)
void dt_image_local_copy_paths_from_fullpath(const char *fullpath, int32_t imgid, char *local_copy_path, size_t local_copy_len, char *local_copy_legacy_path, size_t local_copy_legacy_len)
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
void dt_control_save_xmp(const int32_t imgid)
void dt_control_save_xmps(const GList *imgids, const gboolean check_history)
void dt_control_save_xmps_forced(const GList *imgids)
struct dt_develop_t * dt_dev_get_global(void)
GList * dt_iop_get_modules_so(void)
struct dt_view_manager_t * dt_view_manager_get_global(void)
gboolean dt_database_is_open(void)
gboolean dt_datetime_img_to_exif(char *exif, const size_t exif_size, const dt_image_t *img)
GDateTime * dt_datetime_gtimespan_to_gdatetime(const GTimeSpan gts)
GTimeSpan dt_datetime_now_to_gtimespan()
void dt_datetime_exif_to_img(dt_image_t *img, const char *exif)
#define DT_DATETIME_LENGTH
GHashTable * selected
set of checked row labels, mirrored to conf on every change
GtkWidget * folder
destination folder chooser
int dt_exif_read(dt_image_t *img, const char *path)
void dt_exif_read_usercrop(dt_image_t *img, const char *filename)
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
void dt_loc_get_user_cache_dir(char *cachedir, size_t bufsize)
GList * win_image_find_duplicates(const char *filename)
void dt_film_notify_rolls_changed(void)
State that the film-roll list changed.
char * dt_film_repository_get_folder(const int32_t id)
int dt_grouping_remove_from_group(const int32_t image_id)
void dt_grouping_add_grouped_images(GList **images)
void dt_grouping_add_to_group(const int32_t group_id, const int32_t image_id)
gboolean dt_history_copy_and_paste_on_image(const int32_t imgid, const int32_t dest_imgid, GList *ops, const gboolean copy_full, const dt_history_merge_strategy_t mode, const gboolean copy_iop_order, dt_hm_batch_state_t *batch)
@ DT_HISTORY_MERGE_REPLACE
gboolean dt_history_repository_get_last_enabled_params(const int32_t imgid, const char *operation, void **params, int32_t *params_len)
gboolean dt_history_repository_write_item(const int32_t imgid, const int num, const char *operation, const void *op_params, const int op_params_size, const int module_version, const gboolean enabled, const void *blendop_params, const int blendop_params_size, const int blendop_version, const int multi_priority, const char *multi_name)
int dt_history_repository_count_items(const int32_t imgid)
gboolean dt_history_repository_set_end(const int32_t imgid, const int32_t history_end)
int32_t dt_history_repository_get_next_num(const int32_t imgid)
void dt_history_snapshot_undo_create(const int32_t imgid, int *snap_id, int *history_end)
void dt_history_snapshot_undo_lt_history_data_free(gpointer data)
dt_undo_lt_history_t * dt_history_snapshot_item_init(void)
void dt_history_snapshot_undo_pop(gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, dt_undo_action_t action, GList **imgs)
@ DT_IMAGE_COLORSPACE_NONE
@ DT_IMAGE_COLORSPACE_ADOBE_RGB
@ DT_IMAGE_COLORSPACE_SRGB
@ DT_IMAGE_PATH_LOCAL_COPY_LEGACY
@ DT_IMAGE_PATH_LOCAL_COPY
float dt_boundingbox_t[4]
@ DT_IMAGE_NO_LEGACY_PRESETS
@ DT_IMAGE_HAS_ADDITIONAL_DNG_TAGS
@ DT_IMAGE_AUTO_PRESETS_APPLIED
@ DT_IMAGE_MONOCHROME_BAYER
@ DT_IMAGE_BUFFER_RESOLVED
@ DT_IMAGE_MONOCHROME_WORKFLOW
@ DT_IMAGE_MONOCHROME_PREVIEW
dt_image_write_sidecar_result_t
@ DT_IMAGE_WRITE_SIDECAR_OK
@ DT_IMAGE_WRITE_SIDECAR_IO_ERROR
@ DT_IMAGE_WRITE_SIDECAR_CACHE_BUSY
@ DT_IMAGE_WRITE_SIDECAR_NO_SOURCE_PATH
@ DT_IMAGE_WRITE_SIDECAR_DISABLED
dt_image_transform_t
An orientation change the user asks for, in the coordinates they are looking at.
@ DT_IMAGE_TRANSFORM_FLIP_VERTICALLY
mirror top <-> bottom, as displayed
@ DT_IMAGE_TRANSFORM_ROTATE_CW
quarter turn clockwise
@ DT_IMAGE_TRANSFORM_RESET
back to ORIENTATION_NULL, i.e. what EXIF says
@ DT_IMAGE_TRANSFORM_FLIP_HORIZONTALLY
mirror left <-> right, as displayed
@ DT_IMAGE_TRANSFORM_ROTATE_CCW
quarter turn counter-clockwise
dt_image_pipe_class_t
Mutually-exclusive classification of an image by the early-pipeline processing it requires....
@ DT_IMAGE_PIPE_MOSAIC_RAW
@ DT_IMAGE_PIPE_LINEAR_RAW
static dt_image_orientation_t dt_image_orientation(const dt_image_t *img)
@ DT_IMAGE_USERCROP_UNKNOWN
@ DT_IMAGE_USERCROP_VALID
void dt_image_cache_write_release(dt_image_t *img, dt_image_cache_write_mode_t mode)
gboolean dt_image_cache_is_ready(void)
Has the image cache been initialised? Callers that run before dt_image_cache_init() or after its clea...
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
dt_image_t * dt_image_cache_get_reload(const int32_t imgid, char mode)
void dt_image_cache_remove(const int32_t imgid)
void dt_image_cache_read_release(const dt_image_t *img)
gboolean dt_image_ext_is_ambiguous(const char *ext)
gboolean dt_image_ext_is_supported(const char *ext)
gboolean dt_image_ext_is_ldr(const char *ext)
gboolean dt_image_ext_is_raw(const char *ext)
gboolean dt_image_ext_is_hdr(const char *ext)
void dt_image_notify_imported(const int32_t imgid)
Raise it. Internal to common/image.c.
common/image.c states that an image entered the library; whoever is showing the collection decides wh...
int dt_image_repository_get_version(const int32_t imgid)
The duplicate version number of imgid, or 0.
void dt_image_repository_touch_write_timestamp(const int32_t imgid)
Set write_timestamp of imgid to now.
int dt_image_repository_count_others_with_flag(const int32_t imgid, const int flag)
How many OTHER images share this image's film roll and filename and carry flag.
int64_t dt_image_repository_get_write_timestamp(const int32_t imgid)
main.images.write_timestamp for imgid, or 0.
gboolean dt_image_repository_set_group(const int32_t imgid, const int32_t group_id)
Set imgid's group_id.
int32_t dt_image_repository_find_group_for_pattern(const int32_t film_id, const char *filename_pattern, const gboolean leader_only, const int32_t exclude_imgid)
The group leader of an existing image in film_id matching filename_pattern (a LIKE pattern),...
gboolean dt_image_repository_delete(const int32_t imgid)
Delete imgid from main.images and main.meta_data.
int32_t dt_image_repository_copy_to_film(const int32_t imgid, const int32_t filmid, const char *new_filename, const char *old_filename)
Copy imgid into film roll filmid under new_filename, returning the new id.
GList * dt_image_repository_get_duplicate_ids(const int32_t imgid)
Every image id sharing imgid's film roll and filename, itself included, in row order – an image and i...
GList * dt_image_repository_get_ids_with_flag(const int flag)
Every image id whose flags carry flag, in row order.
gboolean dt_image_repository_clear_flag_among(GList *imgids, const int flag)
Clear flag on every image in imgids – the counterpart of dt_image_repository_set_flag_among(),...
int32_t dt_image_repository_duplicate(const int32_t imgid, const int32_t newversion)
Duplicate imgid as a new version, returning the new image id (-1 on failure).
int32_t dt_image_repository_find_by_film_and_filename(const int32_t film_id, const char *filename)
The image id for filename inside film roll film_id, or -1.
gboolean dt_image_repository_set_version(const int32_t imgid, const int version)
Set both version and max_version of imgid to version.
int32_t dt_image_repository_find_by_folder_and_filename(const char *folder, const char *filename)
The image id for a full path, split into its folder and filename, or -1.
GList * dt_image_repository_get_group_members(const int32_t group_id, const int32_t exclude_imgid)
Image ids in group group_id.
gboolean dt_image_repository_insert_import(const int32_t film_id, const char *filename, const int flags, const int64_t import_timestamp)
Insert a bare row for a file being imported, returning TRUE on success.
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
gboolean dt_imageio_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
gboolean dt_lightroom_import(int32_t imgid, dt_develop_t *dev, gboolean iauto)
_lib_location_type_t type
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
void dt_mipmap_cache_remove(const int32_t imgid, const gboolean flush_disk)
void dt_mipmap_cache_remove_all_sizes(const int32_t imgid, const gboolean flush_disk)
void dt_mipmap_cache_copy_thumbnails(const uint32_t dst_imgid, const uint32_t src_imgid)
dt_mipmap_buffer_dsc_flags flags
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
#define DT_MAX_FILENAME_LEN
#define DT_VIEW_RATINGS_MASK
void dt_removed_image_repository_clear(const int snap_id, const int32_t imgid)
Drop snapshot snap_id of imgid, making the removal permanent.
gboolean dt_removed_image_repository_restore(const int snap_id, const int32_t imgid)
Copy snapshot snap_id of imgid back into main, film roll included.
int dt_removed_image_repository_create(const int32_t imgid)
Copy every row imgid owns out of main, so the removal about to happen can be undone.
memory.removed_*: the staging area behind "undo remove from library".
struct dt_selection_t * dt_selection_get_global(void)
void dt_selection_clear(dt_selection_t *selection)
const float const int flip
char dt[DT_DATETIME_LENGTH]
gboolean camera_missing_sample
GTimeSpan export_timestamp
float exif_focus_distance
dt_boundingbox_t usercrop
GTimeSpan import_timestamp
char camera_makermodel[128]
char local_copy_path[DT_PATH_MAX]
char camera_legacy_makermodel[128]
dt_image_usercrop_status_t usercrop_status
dt_image_orientation_t orientation
GTimeSpan change_timestamp
GTimeSpan print_timestamp
float d65_color_matrix[9]
char filmroll[DT_PATH_MAX]
dt_image_colorspace_t colorspace
float adobe_XYZ_to_CAM[4][3]
struct dt_colorspaces_color_profile_t * embedded_profile
struct dt_cache_entry_t * cache_entry
char local_copy_legacy_path[DT_PATH_MAX]
dt_image_raw_parameters_t legacy_flip
char filename[DT_MAX_FILENAME_LEN]
uint16_t raw_black_level_separate[4]
dt_aligned_pixel_t wb_coeffs
char fullpath[DT_PATH_MAX]
uint32_t fuji_rotation_pos
struct dt_iop_buffer_dsc_t::@55 rawprepare
dt_iop_buffer_type_t datatype
dt_aligned_pixel_t processed_maximum
char after[DT_DATETIME_LENGTH]
char before[DT_DATETIME_LENGTH]
void dt_thumbnail_notify_image_changed(int32_t imgid, gboolean refresh_filmstrip)
void dt_undo_end_group(dt_undo_t *self)
void dt_undo_start_group(dt_undo_t *self, dt_undo_type_t type)
void dt_undo_record(dt_undo_t *self, gpointer user_data, dt_undo_type_t type, dt_undo_data_t data, void(*undo)(gpointer user_data, dt_undo_type_t type, dt_undo_data_t item, dt_undo_action_t action, GList **imgs), void(*free_data)(gpointer data))
dt_undo_t * dt_undo_get_global(void)
gchar * dt_util_str_replace(const gchar *string, const gchar *pattern, const gchar *substitute)
gboolean dt_util_test_image_file(const char *filename)
gchar * dt_util_normalize_path(const gchar *_input)
char * dt_util_format_exposure(const float exposuretime)
const dt_view_t * dt_view_manager_get_current_view(dt_view_manager_t *vm)
int dt_exif_xmp_write_with_imgpath(const dt_image_t *image, const char *filename, const char *imgpath)
int dt_exif_xmp_read(dt_image_t *img, const char *filename, const int history_only)
The XMP document that carries an image's development: history stack, mask shapes, module order,...