144 const gchar *special_pictures_dir = g_get_user_special_dir(G_USER_DIRECTORY_PICTURES);
146 g_snprintf(dir,
sizeof(dir),
"%s" G_DIR_SEPARATOR_S
"Pictures", homedir);
148 g_strlcpy(dir, special_pictures_dir,
sizeof(dir));
151 fprintf(stderr,
"Error: Can't get user's pictures folder.\n");
153 return g_strlcpy(picdir, dir, picdir_size) >= 1;
161 if(iterate) params->data->sequence++;
167 params->data->pictures_folder = g_strdup(picture_folder);
171 params->data->file_ext = (g_strrstr(params->filename,
".") + 1);
172 if(params->data->file_ext == (gchar *)1) params->data->file_ext = params->filename + strlen(params->filename);
176 params->data->file_ext = NULL;
179 params->data->have_exif_dt =
FALSE;
180 params->data->exif_iso = 100;
181 params->data->camera_maker = NULL;
182 params->data->camera_alias = NULL;
183 params->data->exif_lens = NULL;
184 params->data->version = 0;
185 params->data->stars = 0;
186 params->data->exif_exposure = 0.0f;
187 params->data->exif_exposure_bias = NAN;
188 params->data->exif_aperture = 0.0f;
189 params->data->exif_focal_length = 0.0f;
190 params->data->exif_focus_distance = 0.0f;
191 params->data->longitude = NAN;
192 params->data->latitude = NAN;
193 params->data->elevation = NAN;
194 params->data->crop_width = 0;
195 params->data->crop_height = 0;
196 params->data->import_timestamp = 0;
197 params->data->change_timestamp = 0;
198 params->data->export_timestamp = 0;
199 params->data->print_timestamp = 0;
218 if(params->data->datetime)
219 params->data->have_exif_dt =
TRUE;
220 params->data->exif_iso = img->
exif_iso;
221 params->data->camera_maker = g_strdup(img->
camera_maker);
222 params->data->camera_alias = g_strdup(img->
camera_alias);
223 params->data->exif_lens = g_strdup(img->
exif_lens);
224 params->data->version = img->
version;
225 params->data->stars = (img->
flags & 0x7);
238 params->data->flags = img->
flags;
240 params->data->raw_height = img->
p_height;
241 params->data->raw_width = img->
p_width;
242 params->data->sensor_height = img->
height;
243 params->data->sensor_width = img->
width;
244 params->data->export_height = 0;
245 params->data->export_width = 0;
271 if(params->data->datetime)
273 g_date_time_unref(params->data->datetime);
274 params->data->datetime = NULL;
276 dt_free(params->data->homedir);
277 dt_free(params->data->pictures_folder);
278 dt_free(params->data->camera_maker);
279 dt_free(params->data->camera_alias);
280 dt_free(params->data->exif_lens);
285 gboolean
res = g_str_has_prefix(*str, prefix);
286 if(
res) *str += strlen(prefix);
292 if(isnan(params->data->longitude))
295 && g_strcmp0(params->jobcode,
"infos") == 0)
301 gchar NS = params->data->longitude < 0 ?
'W' :
'E';
302 return g_strdup_printf(
"%c%010.6f", NS, fabs(params->data->longitude));
308 if(isnan(params->data->latitude))
311 && g_strcmp0(params->jobcode,
"infos") == 0)
317 gchar NS = params->data->latitude < 0 ?
'S' :
'N';
318 return g_strdup_printf(
"%c%09.6f", NS, fabs(params->data->latitude));
324 if(gts <= 0)
return NULL;
329 char *result = g_date_time_format(gdt,
"%Y-%m-%d %H:%M:%S");
330 g_date_time_unref(gdt);
350 result = g_date_time_format(params->data->time,
"%y");
352 result = g_date_time_format(params->data->time,
"%Y");
354 result = g_date_time_format(params->data->time,
"%b");
356 result = g_date_time_format(params->data->time,
"%B");
358 result = g_date_time_format(params->data->time,
"%m");
360 result = g_date_time_format(params->data->time,
"%d");
362 result = g_date_time_format(params->data->time,
"%I %p");
364 result = g_date_time_format(params->data->time,
"%H");
366 result = g_date_time_format(params->data->time,
"%M");
368 result = g_date_time_format(params->data->time,
"%S");
371 result = g_date_time_format(params->data->time,
"%f");
396 result = g_strdup(exif_datetime);
419 GDateTime *datetime = params->data->have_exif_dt ? params->data->datetime : params->data->time;
423 result = g_date_time_format(datetime,
"%y");
425 result = g_date_time_format(datetime,
"%Y");
427 result = g_date_time_format(datetime,
"%b");
429 result = g_date_time_format(datetime,
"%B");
431 result = g_date_time_format(datetime,
"%m");
433 result = g_date_time_format(datetime,
"%d");
435 result = g_date_time_format(datetime,
"%I %p");
437 result = g_date_time_format(datetime,
"%H");
439 result = g_date_time_format(datetime,
"%M");
441 result = g_date_time_format(datetime,
"%S");
444 result = g_date_time_format(datetime,
"%f");
451 result = g_strdup(exif_datetime);
475 result = g_strdup_printf(
"%d", params->data->exif_iso);
476 else if(
_has_prefix(variable,
"NL") && g_strcmp0(params->jobcode,
"infos") == 0)
477 result = g_strdup_printf(
"\n");
480 if(!isnan(params->data->exif_exposure_bias))
481 result = g_strdup_printf(
"%+.2f", params->data->exif_exposure_bias);
487 if(g_strcmp0(params->jobcode,
"infos") != 0)
495 result = g_strdup_printf(
"%.1f", params->data->exif_aperture);
497 result = g_strdup_printf(
"%d", (
int)params->data->exif_focal_length);
499 result = g_strdup_printf(
"%.2f", params->data->exif_focus_distance);
505 result = g_strdup_printf(
"%.2f", params->data->elevation);
509 gchar *parts[4] = { 0 };
513 if(!isnan(params->data->elevation)) parts[
i++] = g_strdup_printf(
"%.2f", params->data->elevation);
514 result = g_strjoinv(
", ", parts);
515 for(
int j = 0; j <
i; j++)
519 result = g_strdup(params->data->camera_maker);
521 result = g_strdup(params->data->camera_alias);
523 result = g_strdup(params->data->exif_lens);
546 result = g_strdup_printf(
"%d", params->imgid);
554 result = g_strdup(buffer);
561 result = g_strdup((
char *)
res->data);
571 const guint count = g_list_length(versions);
572 g_list_free(versions);
576 result = g_strdup_printf(
"%d", params->data->version);
579 result = g_strdup_printf(
"%d", params->data->version);
581 result = g_strdup(params->jobcode);
587 gchar *dirname = g_path_get_dirname(params->filename);
588 result = g_path_get_basename(dirname);
617 result = g_path_get_dirname(params->filename);
622 result = g_path_get_dirname(params->filename);
626 if(params->data->file_datetime)
627 result = g_date_time_format(params->data->file_datetime,
"%Y");
631 if(params->data->file_datetime)
632 result = g_date_time_format(params->data->file_datetime,
"%m");
636 if(params->data->file_datetime)
637 result = g_date_time_format(params->data->file_datetime,
"%d");
641 if(params->data->file_datetime)
642 result = g_date_time_format(params->data->file_datetime,
"%H");
646 if(params->data->file_datetime)
647 result = g_date_time_format(params->data->file_datetime,
"%M");
651 if(params->data->file_datetime)
652 result = g_date_time_format(params->data->file_datetime,
"%S");
658 result = g_strdup(params->filename);
664 result = g_path_get_basename(params->filename);
665 char *dot = g_strrstr(result,
".");
670 result = g_strdup(params->data->file_ext);
673 uint8_t nb_digit = 4;
674 if(g_ascii_isdigit(*variable[0]))
676 nb_digit = (uint8_t)*variable[0] & 0b1111;
679 result = g_strdup_printf(
"%.*d", nb_digit, params->sequence);
682 result = g_strdup(g_get_user_name());
684 result = g_strdup(params->data->homedir);
686 result = g_strdup(params->data->pictures_folder);
688 result = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP));
690 result = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP));
714 result = g_strdup_printf(
"%d", params->data->stars);
717 switch(params->data->stars)
720 result = g_strdup(
"X");
723 result = g_strdup(
"\342\230\205");
726 result = g_strdup(
"\342\230\205\342\230\205");
729 result = g_strdup(
"\342\230\205\342\230\205\342\230\205");
732 result = g_strdup(
"\342\230\205\342\230\205\342\230\205\342\230\205");
735 result = g_strdup(
"\342\230\205\342\230\205\342\230\205\342\230\205\342\230\205");
738 result = g_strdup(
"");
744 && g_strcmp0(params->jobcode,
"infos") == 0)
748 for(GList *res_iter =
res; res_iter; res_iter = g_list_next(res_iter))
750 const int dot_index = GPOINTER_TO_INT(res_iter->data);
753 "<span foreground='#%02x%02x%02x'>\342\254\244 </span>",
754 (guint)(c.red*255), (guint)(c.green*255), (guint)(c.blue*255));
766 GList *labels = NULL;
767 for(GList *res_iter =
res; res_iter; res_iter = g_list_next(res_iter))
771 labels = g_list_reverse(labels);
784 result = g_strdup((
char *)
res->data);
794 result = g_strdup((
char *)
res->data);
804 result = g_strdup((
char *)
res->data);
814 result = g_strdup((
char *)
res->data);
824 result = g_strdup((
char *)
res->data);
832 result = g_strdup(_(
"yes"));
834 result = g_strdup(_(
"no"));
858 result = g_strdup_printf(
"%d", params->data->max_width);
860 result = g_strdup_printf(
"%d", params->data->sensor_width);
862 result = g_strdup_printf(
"%d", params->data->raw_width);
864 result = g_strdup_printf(
"%d", params->data->crop_width);
866 result = g_strdup_printf(
"%d", params->data->export_width);
868 result = g_strdup_printf(
"%d", params->data->max_height);
870 result = g_strdup_printf(
"%d", params->data->sensor_height);
872 result = g_strdup_printf(
"%d", params->data->raw_height);
874 result = g_strdup_printf(
"%d", params->data->crop_height);
876 result = g_strdup_printf(
"%d", params->data->export_height);
880 if (g_ascii_isdigit(*variable[0]))
882 const uint8_t level = (uint8_t)*variable[0] & 0b1111;
884 if (*variable[0] ==
'(')
886 char *category = g_strdup(*variable + 1);
887 char *end = g_strstr_len(category, -1,
")");
892 (*variable) += strlen(category) + 1;
896 result = g_strdup(tag);
910 result = g_strdup(tags);
913 else if(
_has_prefix(variable,
"SIDECAR_TXT") && g_strcmp0(params->jobcode,
"infos") == 0
920 if(g_file_get_contents(path, &txt, NULL, NULL))
922 result = g_strdup_printf(
"\n%s", txt);
960 gboolean escape =
TRUE;
971 while(g_ascii_isalpha(**variable)) (*variable)++;
973 if(!result) result = g_strdup(
"");
975 if(params->escape_markup && escape)
977 gchar *e_res = g_markup_escape_text(result, -1);
995 const size_t base_value_length = strlen(base_value);
998 const char operation = **variable;
999 if(operation !=
'\0' && operation !=
')') (*variable)++;
1009 if(*base_value ==
'\0')
1012 base_value = replacement;
1025 if(*base_value !=
'\0')
1028 base_value = replacement;
1048 const glong base_value_utf8_length = g_utf8_strlen(base_value, -1);
1049 const glong offset = strtol(*variable, variable, 10);
1054 start = g_utf8_offset_to_pointer(base_value,
MIN(offset, base_value_utf8_length));
1056 start = g_utf8_offset_to_pointer(base_value + base_value_length,
MAX(offset, -base_value_utf8_length));
1059 char *end = base_value + base_value_length;
1060 if(start && **variable ==
':')
1063 const size_t start_utf8_length = g_utf8_strlen(start, -1);
1064 const int length = strtol(*variable, variable, 10);
1066 end = g_utf8_offset_to_pointer(start,
MIN(length, start_utf8_length));
1068 end = g_utf8_offset_to_pointer(base_value + base_value_length,
MAX(length, -start_utf8_length));
1071 char *_base_value = g_strndup(start, end - start);
1073 base_value = _base_value;
1083 const size_t pattern_length = strlen(pattern);
1084 if(!strncmp(base_value, pattern, pattern_length))
1086 char *_base_value = g_strdup(base_value + pattern_length);
1088 base_value = _base_value;
1100 const size_t pattern_length = strlen(pattern);
1101 if(!strncmp(base_value + base_value_length - pattern_length, pattern, pattern_length))
1102 base_value[base_value_length - pattern_length] =
'\0';
1125 const char mode = **variable;
1127 if(mode ==
'/' || mode ==
'#' || mode ==
'%') (*variable)++;
1129 const size_t pattern_length = strlen(pattern);
1132 const size_t replacement_length = strlen(replacement);
1139 char *
p = g_strndup(pattern, pattern_length);
1143 base_value = _base_value;
1148 if(!strncmp(base_value, pattern, pattern_length))
1150 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1151 char *end = g_stpcpy(_base_value, replacement);
1152 g_stpcpy(end, base_value + pattern_length);
1154 base_value = _base_value;
1160 if(!strncmp(base_value + base_value_length - pattern_length, pattern, pattern_length))
1162 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1163 base_value[base_value_length - pattern_length] =
'\0';
1164 char *end = g_stpcpy(_base_value, base_value);
1165 g_stpcpy(end, replacement);
1167 base_value = _base_value;
1174 char *
p = g_strndup(pattern, pattern_length);
1175 gchar *found = g_strstr_len(base_value, -1,
p);
1180 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1181 char *end = g_stpcpy(_base_value, base_value);
1182 end = g_stpcpy(end, replacement);
1183 g_stpcpy(end, found + pattern_length);
1185 base_value = _base_value;
1210 const char mode = **variable;
1211 char *_base_value = NULL;
1212 if(operation ==
'^' && mode ==
'^')
1214 _base_value = g_utf8_strup (base_value, -1);
1217 else if(operation ==
',' && mode ==
',')
1219 _base_value = g_utf8_strdown(base_value, -1);
1224 gunichar changed = g_utf8_get_char(base_value);
1225 changed = operation ==
'^' ? g_unichar_toupper(changed) : g_unichar_tolower(changed);
1226 int utf8_length = g_unichar_to_utf8(changed, NULL);
1227 char *next = g_utf8_next_char(base_value);
1228 _base_value = g_malloc0(base_value_length - (next - base_value) + utf8_length + 1);
1229 g_unichar_to_utf8(changed, _base_value);
1230 g_stpcpy(_base_value + utf8_length, next);
1233 base_value = _base_value;
1238 if(**variable ==
')')
1249static void _grow_buffer(
char **result,
char **result_iter,
size_t *result_length,
size_t extra_space)
1251 const size_t used_length = *result_iter - *result;
1252 if(used_length + extra_space > *result_length)
1254 *result_length = used_length + extra_space;
1255 *result = g_realloc(*result, *result_length + 1);
1256 *result_iter = *result + used_length;
1262 char *result = g_strdup(
"");
1264 char *result_iter = result;
1265 size_t result_length = 0;
1266 char *source_iter = *source;
1267 const size_t source_length = strlen(*source);
1269 while(*source_iter && *source_iter != extra_stop)
1272 while(*source_iter && *source_iter != extra_stop)
1274 char c = *source_iter;
1275 if(c ==
'$' && source_iter[1] ==
'(')
1278 if(result_iter - result >= result_length)
1279 _grow_buffer(&result, &result_iter, &result_length, source_length - (source_iter - *source));
1287 if(*source_iter ==
'$')
1289 char *old_source_iter = source_iter;
1293 const size_t replacement_length = strlen(replacement);
1294 _grow_buffer(&result, &result_iter, &result_length, replacement_length);
1295 memcpy(result_iter, replacement, replacement_length);
1296 result_iter += replacement_length;
1302 source_iter = old_source_iter;
1303 _grow_buffer(&result, &result_iter, &result_length, source_length - (source_iter - *source));
1304 *result_iter++ = *source_iter++;
1309 *result_iter =
'\0';
1310 *source = source_iter;
1329 (*params)->data->time = g_date_time_new_now_local();
1330 (*params)->data->file_datetime = NULL;
1331 (*params)->data->exif_time[0] = 0;
1332 (*params)->sequence = -1;
1333 (*params)->img = NULL;
1338 if(params->data->time)
1339 g_date_time_unref(params->data->time);
1341 if(params->data->file_datetime)
1342 g_date_time_unref(params->data->file_datetime);
1350 if(params->data->time) g_date_time_unref(params->data->time);
1351 params->data->time = g_date_time_ref(datetime);
1356 params->data->max_width = max_width;
1357 params->data->max_height = max_height;
1362 params->data->sequence = 0;
1367 params->data->tags_flags =
flags;
const char * dt_colorlabels_to_string(int label)
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_conf_get_bool(const char *name)
void dt_image_print_exif(const dt_image_t *img, char *line, size_t line_len)
char * dt_image_get_text_path(const int32_t imgid)
const char darktable_package_version[]
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
gboolean dt_datetime_gdatetime_to_exif(char *exif, const size_t exif_size, GDateTime *gdt)
GTimeZone * dt_datetime_utc_tz(void)
GDateTime * dt_datetime_origin(void)
GDateTime * dt_datetime_img_to_gdatetime(const dt_image_t *img, const GTimeZone *tz)
#define DT_DATETIME_LENGTH
#define DT_DATETIME_EXIF_LENGTH
gchar * dt_loc_get_home_dir(const gchar *user)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
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...
Reading and writing one dt_image_t to and from the library database. The SQL half of what used to be ...
#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.
dt_mipmap_buffer_dsc_flags flags
int dt_opencl_is_enabled(void)
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
static char * _expand_source(dt_variables_params_t *params, char **source, char extra_stop)
char * dt_variables_expand(dt_variables_params_t *params, gchar *source, gboolean iterate)
static gboolean _expand_rating_and_metadata(dt_variables_params_t *params, char **variable, char **out, gboolean *escape)
Expand star rating, colour labels and the Dublin Core fields.
static void _grow_buffer(char **result, char **result_iter, size_t *result_length, size_t extra_space)
static char * _variables_get_iso_timestamp(const GTimeSpan gts)
void dt_variables_params_destroy(dt_variables_params_t *params)
static void _init_expansion(dt_variables_params_t *params, gboolean iterate)
static gboolean _has_prefix(char **str, const char *prefix)
static char * _variables_get_latitude(dt_variables_params_t *params)
static gboolean _expand_datetime_now(dt_variables_params_t *params, char **variable, char **out)
Expand the current time, and the import/change/export/print timestamps.
gboolean dt_get_user_pictures_dir(const gchar *homedir, gchar *picdir, size_t picdir_size)
Gets the path to the current OS pictures directory.
static gboolean _expand_file_and_folder(dt_variables_params_t *params, char **variable, char **out)
Expand the source file's path, name and mtime, plus the user's folders.
static gboolean _expand_geometry_and_misc(dt_variables_params_t *params, char **variable, char **out)
Expand image dimensions, category, tags and build identity.
void dt_variables_set_max_width_height(dt_variables_params_t *params, int max_width, int max_height)
void dt_variables_params_init(dt_variables_params_t **params)
static char * _variable_get_value(dt_variables_params_t *params, char **variable)
void dt_variables_set_tags_flags(dt_variables_params_t *params, uint32_t flags)
static void _cleanup_expansion(dt_variables_params_t *params)
static char * _get_base_value(dt_variables_params_t *params, char **variable)
Expand one into its text.
void dt_variables_set_datetime(dt_variables_params_t *params, GDateTime *datetime)
static char * _variables_get_longitude(dt_variables_params_t *params)
static gboolean _expand_exif_datetime(dt_variables_params_t *params, char **variable, char **out)
Expand the capture time read from EXIF.
static gboolean _expand_exif_and_gps(dt_variables_params_t *params, char **variable, char **out)
Expand EXIF exposure settings, GPS position and camera identity.
void dt_variables_reset_sequence(dt_variables_params_t *params)
static gboolean _expand_image_and_version(dt_variables_params_t *params, char **variable, char **out)
Expand image id, duplicate version, job code and film roll.
GdkRGBA colorlabels[DT_COLORLABELS_LAST]
GTimeSpan export_timestamp
float exif_focus_distance
GTimeSpan import_timestamp
GTimeSpan change_timestamp
GTimeSpan print_timestamp
char exif_time[DT_DATETIME_LENGTH]
GDateTime * file_datetime
float exif_focus_distance
GTimeSpan change_timestamp
GTimeSpan export_timestamp
GTimeSpan import_timestamp
GTimeSpan print_timestamp
gchar * dt_util_str_replace(const gchar *string, const gchar *pattern, const gchar *substitute)
gchar * dt_util_longitude_str(float longitude)
GDateTime * dt_util_get_file_datetime(const char *const path)
char * dt_util_format_exposure(const float exposuretime)
gchar * dt_util_latitude_str(float latitude)
gchar * dt_util_glist_to_str(const gchar *separator, GList *items)
gchar * dt_util_dstrcat(gchar *str, const gchar *format,...)