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);
176 params->data->file_ext = NULL;
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;
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)
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;
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);
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);
556 result = g_strdup(buffer);
565 result = g_strdup((
char *)
res->data);
575 const guint count = g_list_length(versions);
576 g_list_free(versions);
580 result = g_strdup_printf(
"%d",
params->data->version);
583 result = g_strdup_printf(
"%d",
params->data->version);
585 result = g_strdup(
params->jobcode);
591 gchar *dirname = g_path_get_dirname(
params->filename);
592 result = g_path_get_basename(dirname);
621 result = g_path_get_dirname(
params->filename);
626 result = g_path_get_dirname(
params->filename);
630 if(
params->data->file_datetime)
631 result = g_date_time_format(
params->data->file_datetime,
"%Y");
635 if(
params->data->file_datetime)
636 result = g_date_time_format(
params->data->file_datetime,
"%m");
640 if(
params->data->file_datetime)
641 result = g_date_time_format(
params->data->file_datetime,
"%d");
645 if(
params->data->file_datetime)
646 result = g_date_time_format(
params->data->file_datetime,
"%H");
650 if(
params->data->file_datetime)
651 result = g_date_time_format(
params->data->file_datetime,
"%M");
655 if(
params->data->file_datetime)
656 result = g_date_time_format(
params->data->file_datetime,
"%S");
662 result = g_strdup(
params->filename);
668 const char *basename = strrchr(
params->filename,
'/');
669 const char *windows_basename = strrchr(
params->filename,
'\\');
671 basename = windows_basename;
679 result = g_strdup(
params->data->file_ext);
682 uint8_t nb_digit = 4;
683 if(g_ascii_isdigit(*variable[0]))
685 nb_digit = (uint8_t)*variable[0] & 0b1111;
688 result = g_strdup_printf(
"%.*d", nb_digit,
params->sequence);
691 result = g_strdup(g_get_user_name());
693 result = g_strdup(
params->data->homedir);
695 result = g_strdup(
params->data->pictures_folder);
697 result = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP));
699 result = g_strdup(g_get_user_special_dir(G_USER_DIRECTORY_DESKTOP));
723 result = g_strdup_printf(
"%d",
params->data->stars);
726 switch(
params->data->stars)
729 result = g_strdup(
"X");
732 result = g_strdup(
"\342\230\205");
735 result = g_strdup(
"\342\230\205\342\230\205");
738 result = g_strdup(
"\342\230\205\342\230\205\342\230\205");
741 result = g_strdup(
"\342\230\205\342\230\205\342\230\205\342\230\205");
744 result = g_strdup(
"\342\230\205\342\230\205\342\230\205\342\230\205\342\230\205");
747 result = g_strdup(
"");
753 && g_strcmp0(
params->jobcode,
"infos") == 0)
757 for(GList *res_iter =
res; res_iter; res_iter = g_list_next(res_iter))
759 const int dot_index = GPOINTER_TO_INT(res_iter->data);
762 "<span foreground='#%02x%02x%02x'>\342\254\244 </span>",
763 (guint)(c.red*255), (guint)(c.green*255), (guint)(c.blue*255));
775 GList *labels = NULL;
776 for(GList *res_iter =
res; res_iter; res_iter = g_list_next(res_iter))
780 labels = g_list_reverse(labels);
793 result = g_strdup((
char *)
res->data);
803 result = g_strdup((
char *)
res->data);
813 result = g_strdup((
char *)
res->data);
823 result = g_strdup((
char *)
res->data);
833 result = g_strdup((
char *)
res->data);
841 result = g_strdup(_(
"yes"));
843 result = g_strdup(_(
"no"));
867 result = g_strdup_printf(
"%d",
params->data->max_width);
869 result = g_strdup_printf(
"%d",
params->data->sensor_width);
871 result = g_strdup_printf(
"%d",
params->data->raw_width);
873 result = g_strdup_printf(
"%d",
params->data->crop_width);
875 result = g_strdup_printf(
"%d",
params->data->export_width);
877 result = g_strdup_printf(
"%d",
params->data->max_height);
879 result = g_strdup_printf(
"%d",
params->data->sensor_height);
881 result = g_strdup_printf(
"%d",
params->data->raw_height);
883 result = g_strdup_printf(
"%d",
params->data->crop_height);
885 result = g_strdup_printf(
"%d",
params->data->export_height);
889 if (g_ascii_isdigit(*variable[0]))
891 const uint8_t level = (uint8_t)*variable[0] & 0b1111;
893 if (*variable[0] ==
'(')
895 char *category = g_strdup(*variable + 1);
896 char *end = g_strstr_len(category, -1,
")");
901 (*variable) += strlen(category) + 1;
905 result = g_strdup(tag);
919 result = g_strdup(tags);
922 else if(
_has_prefix(variable,
"SIDECAR_TXT") && g_strcmp0(
params->jobcode,
"infos") == 0
929 if(g_file_get_contents(path, &txt, NULL, NULL))
931 result = g_strdup_printf(
"\n%s", txt);
969 gboolean escape =
TRUE;
980 while(g_ascii_isalpha(**variable)) (*variable)++;
982 if(!result) result = g_strdup(
"");
984 if(
params->escape_markup && escape)
986 gchar *e_res = g_markup_escape_text(result, -1);
1004 const size_t base_value_length = strlen(base_value);
1007 const char operation = **variable;
1008 if(operation !=
'\0' && operation !=
')') (*variable)++;
1018 if(*base_value ==
'\0')
1021 base_value = replacement;
1034 if(*base_value !=
'\0')
1037 base_value = replacement;
1057 const glong base_value_utf8_length = g_utf8_strlen(base_value, -1);
1058 const glong offset = strtol(*variable, variable, 10);
1063 start = g_utf8_offset_to_pointer(base_value,
MIN(offset, base_value_utf8_length));
1065 start = g_utf8_offset_to_pointer(base_value + base_value_length,
MAX(offset, -base_value_utf8_length));
1068 char *end = base_value + base_value_length;
1069 if(start && **variable ==
':')
1072 const size_t start_utf8_length = g_utf8_strlen(start, -1);
1073 const int length = strtol(*variable, variable, 10);
1075 end = g_utf8_offset_to_pointer(start,
MIN(length, start_utf8_length));
1077 end = g_utf8_offset_to_pointer(base_value + base_value_length,
MAX(length, -start_utf8_length));
1080 char *_base_value = g_strndup(start, end - start);
1082 base_value = _base_value;
1092 const size_t pattern_length = strlen(pattern);
1093 if(!strncmp(base_value, pattern, pattern_length))
1095 char *_base_value = g_strdup(base_value + pattern_length);
1097 base_value = _base_value;
1109 const size_t pattern_length = strlen(pattern);
1110 if(!strncmp(base_value + base_value_length - pattern_length, pattern, pattern_length))
1111 base_value[base_value_length - pattern_length] =
'\0';
1134 const char mode = **variable;
1136 if(mode ==
'/' || mode ==
'#' || mode ==
'%') (*variable)++;
1138 const size_t pattern_length = strlen(pattern);
1141 const size_t replacement_length = strlen(replacement);
1148 char *
p = g_strndup(pattern, pattern_length);
1152 base_value = _base_value;
1157 if(!strncmp(base_value, pattern, pattern_length))
1159 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1160 char *end = g_stpcpy(_base_value, replacement);
1161 g_stpcpy(end, base_value + pattern_length);
1163 base_value = _base_value;
1169 if(!strncmp(base_value + base_value_length - pattern_length, pattern, pattern_length))
1171 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1172 base_value[base_value_length - pattern_length] =
'\0';
1173 char *end = g_stpcpy(_base_value, base_value);
1174 g_stpcpy(end, replacement);
1176 base_value = _base_value;
1183 char *
p = g_strndup(pattern, pattern_length);
1184 gchar *found = g_strstr_len(base_value, -1,
p);
1189 char *_base_value = g_malloc(base_value_length - pattern_length + replacement_length + 1);
1190 char *end = g_stpcpy(_base_value, base_value);
1191 end = g_stpcpy(end, replacement);
1192 g_stpcpy(end, found + pattern_length);
1194 base_value = _base_value;
1219 const char mode = **variable;
1220 char *_base_value = NULL;
1221 if(operation ==
'^' && mode ==
'^')
1223 _base_value = g_utf8_strup (base_value, -1);
1226 else if(operation ==
',' && mode ==
',')
1228 _base_value = g_utf8_strdown(base_value, -1);
1233 gunichar changed = g_utf8_get_char(base_value);
1234 changed = operation ==
'^' ? g_unichar_toupper(changed) : g_unichar_tolower(changed);
1235 int utf8_length = g_unichar_to_utf8(changed, NULL);
1236 char *next = g_utf8_next_char(base_value);
1237 _base_value = g_malloc0(base_value_length - (next - base_value) + utf8_length + 1);
1238 g_unichar_to_utf8(changed, _base_value);
1239 g_stpcpy(_base_value + utf8_length, next);
1242 base_value = _base_value;
1247 if(**variable ==
')')
1258static void _grow_buffer(
char **result,
char **result_iter,
size_t *result_length,
size_t extra_space)
1260 const size_t used_length = *result_iter - *result;
1261 if(used_length + extra_space > *result_length)
1263 *result_length = used_length + extra_space;
1264 *result = g_realloc(*result, *result_length + 1);
1265 *result_iter = *result + used_length;
1271 char *result = g_strdup(
"");
1273 char *result_iter = result;
1274 size_t result_length = 0;
1275 char *source_iter = *source;
1276 const size_t source_length = strlen(*source);
1278 while(*source_iter && *source_iter != extra_stop)
1281 while(*source_iter && *source_iter != extra_stop)
1283 char c = *source_iter;
1284 if(c ==
'$' && source_iter[1] ==
'(')
1287 if(result_iter - result >= result_length)
1288 _grow_buffer(&result, &result_iter, &result_length, source_length - (source_iter - *source));
1296 if(*source_iter ==
'$')
1298 char *old_source_iter = source_iter;
1302 const size_t replacement_length = strlen(replacement);
1303 _grow_buffer(&result, &result_iter, &result_length, replacement_length);
1304 memcpy(result_iter, replacement, replacement_length);
1305 result_iter += replacement_length;
1311 source_iter = old_source_iter;
1312 _grow_buffer(&result, &result_iter, &result_length, source_length - (source_iter - *source));
1313 *result_iter++ = *source_iter++;
1318 *result_iter =
'\0';
1319 *source = source_iter;
1338 (*params)->data->time = g_date_time_new_now_local();
1339 (*params)->data->file_datetime = NULL;
1340 (*params)->data->exif_time[0] = 0;
1341 (*params)->sequence = -1;
1342 (*params)->img = NULL;
1348 g_date_time_unref(
params->data->time);
1350 if(
params->data->file_datetime)
1351 g_date_time_unref(
params->data->file_datetime);
1359 if(
params->data->time) g_date_time_unref(
params->data->time);
1360 params->data->time = g_date_time_ref(datetime);
1365 params->data->max_width = max_width;
1366 params->data->max_height = max_height;
1371 params->data->sequence = 0;
const char * extension(dt_imageio_module_data_t *data)
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 ...
static const dt_iop_drawlayer_params_t * params
#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)
const char * dt_util_path_get_extension(const char *path)
Locate a normal filename extension in a path basename.
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,...)