static int import_images(lua_State *L) { char *full_name = g_realpath(luaL_checkstring(L, -1)); int result; if(!full_name || !g_file_test(full_name, G_FILE_TEST_EXISTS)) { g_free(full_name); return luaL_error(L, "no such file or directory"); } else if(g_file_test(full_name, G_FILE_TEST_IS_DIR)) { result = dt_film_import(full_name); if(result == 0) { g_free(full_name); return luaL_error(L, "error while importing"); } luaA_push(L, dt_lua_film_t, &result); } else { dt_film_t new_film; dt_film_init(&new_film); char *dirname = g_path_get_dirname(full_name); char *expanded_path = dt_util_fix_path(dirname); g_free(dirname); char *final_path = g_realpath(expanded_path); g_free(expanded_path); if(!final_path) { g_free(full_name); return luaL_error(L, "Error while importing : %s\n", strerror(errno)); } result = dt_film_new(&new_film, final_path); free(final_path); if(result == 0) { if(dt_film_is_empty(new_film.id)) dt_film_remove(new_film.id); dt_film_cleanup(&new_film); g_free(full_name); return luaL_error(L, "error while importing"); } result = dt_image_import(new_film.id, full_name, TRUE); if(dt_film_is_empty(new_film.id)) dt_film_remove(new_film.id); dt_film_cleanup(&new_film); if(result == 0) { g_free(full_name); return luaL_error(L, "error while importing"); } luaA_push(L, dt_lua_image_t, &result); } g_free(full_name); return 1; }
void dt_import_session_import(struct dt_import_session_t *self) { int id = dt_image_import(self->film->id, self->current_filename, TRUE); if(id) { dt_view_filmstrip_set_active_image(darktable.view_manager,id); dt_control_queue_redraw(); } }
/** Listener interface for import job */ void _camera_image_downloaded(const dt_camera_t *camera,const char *filename,void *data) { // Import downloaded image to import filmroll dt_camera_import_t *t = (dt_camera_import_t *)data; dt_image_import(t->film->id, filename, FALSE); dt_control_queue_redraw_center(); dt_control_log(_("%d/%d imported to %s"), t->import_count+1,g_list_length(t->images), g_path_get_basename(filename)); t->fraction+=1.0/g_list_length(t->images); dt_control_backgroundjobs_progress(darktable.control, t->bgj, t->fraction ); t->import_count++; }
/** Listener interface for import job */ void _camera_import_image_downloaded(const dt_camera_t *camera,const char *filename,void *data) { // Import downloaded image to import filmroll dt_camera_import_t *t = (dt_camera_import_t *)data; dt_image_import(dt_import_session_film_id(t->shared.session), filename, FALSE); dt_control_queue_redraw_center(); gchar* basename = g_path_get_basename(filename); dt_control_log(_("%d/%d imported to %s"), t->import_count+1,g_list_length(t->images), basename); g_free(basename); t->fraction+=1.0/g_list_length(t->images); dt_control_progress_set_progress(darktable.control, t->progress, t->fraction); t->import_count++; }
static int import_images(lua_State *L) { char* full_name= realpath(luaL_checkstring(L,-1), NULL); int result; if (!g_file_test(full_name, G_FILE_TEST_EXISTS)) { free(full_name); return luaL_error(L,"no such file or directory"); } else if (g_file_test(full_name, G_FILE_TEST_IS_DIR)) { result =dt_film_import(full_name); if(result == 0) { free(full_name); return luaL_error(L,"error while importing"); } luaA_push(L,dt_lua_film_t,&result); } else { dt_film_t new_film; dt_film_init(&new_film); char* dirname =g_path_get_dirname(full_name); result = dt_film_new(&new_film,dirname); if(result == 0) { free(full_name); dt_film_cleanup(&new_film); free(dirname); return luaL_error(L,"error while importing"); } result =dt_image_import(new_film.id,full_name,TRUE); free(dirname); dt_film_cleanup(&new_film); if(result == 0) { free(full_name); return luaL_error(L,"error while importing"); } luaA_push(L,dt_lua_image_t,&result); } free(full_name); return 1; }
int32_t dt_captured_image_import_job_run(dt_job_t *job) { dt_captured_image_import_t *t = (dt_captured_image_import_t *)job->param; char message[512]= {0}; snprintf(message, 512, _("importing image %s"), t->filename); const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message ); int id = dt_image_import(t->film_id, t->filename, TRUE); if(id) { //dt_film_open(1); dt_view_filmstrip_set_active_image(darktable.view_manager,id); dt_control_queue_redraw(); //dt_ctl_switch_mode_to(DT_DEVELOP); } dt_control_backgroundjobs_progress(darktable.control, jid, 1.0); dt_control_backgroundjobs_destroy(darktable.control, jid); return 0; }
static int import_images(lua_State *L) { char* full_name= realpath(luaL_checkstring(L,-1), NULL); int result; if (g_file_test(full_name, G_FILE_TEST_IS_DIR)) { result =dt_film_import_blocking(full_name); if(result == 0) { free(full_name); return luaL_error(L,"error while importing"); } } else { dt_film_t new_film; dt_film_init(&new_film); char* dirname =g_path_get_dirname(full_name); result = dt_film_new(&new_film,dirname); if(result == 0) { free(full_name); dt_film_cleanup(&new_film); free(dirname); return luaL_error(L,"error while importing"); } result =dt_image_import(new_film.id,full_name,TRUE); free(dirname); dt_film_cleanup(&new_film); if(result == 0) { free(full_name); return luaL_error(L,"error while importing"); } } free(full_name); return 0; }
int32_t dt_image_import_job_run(dt_job_t *job) { int id; char message[512]; dt_image_import_t *t; const guint *jid; t = (dt_image_import_t *)job->param; message[0] = 0; snprintf(message, 512, _("importing image %s"), t->filename); jid = dt_control_backgroundjobs_create(darktable.control, 0, message ); id = dt_image_import(t->film_id, t->filename, TRUE); if(id) { dt_view_filmstrip_set_active_image(darktable.view_manager, id); dt_control_queue_redraw(); } dt_control_backgroundjobs_progress(darktable.control, jid, 1.0); dt_control_backgroundjobs_destroy(darktable.control, jid); return 0; }
static int32_t dt_image_import_job_run(dt_job_t *job) { int id; char message[512]; dt_image_import_t *params; params = dt_control_job_get_params(job); message[0] = 0; snprintf(message, sizeof(message), _("importing image %s"), params->filename); dt_progress_t *progress = dt_control_progress_create(darktable.control, TRUE, message); id = dt_image_import(params->film_id, params->filename, TRUE); if(id) { dt_view_filmstrip_set_active_image(darktable.view_manager, id); dt_control_queue_redraw(); } dt_control_progress_set_progress(darktable.control, progress, 1.0); dt_control_progress_destroy(darktable.control, progress); free(params); return 0; }
int main(int argc, char *arg[]) { bindtextdomain (GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); gtk_init (&argc, &arg); // parse command line arguments char *image_filename = NULL; char *xmp_filename = NULL; char *output_filename = NULL; int file_counter = 0; int width = 0, height = 0, bpp = 0; gboolean verbose = FALSE, high_quality = TRUE; for(int k=1; k<argc; k++) { if(arg[k][0] == '-') { if(!strcmp(arg[k], "--help")) { usage(arg[0]); exit(1); } else if(!strcmp(arg[k], "--version")) { printf("this is darktable-cli\ncopyright (c) 2012-2013 johannes hanika, tobias ellinghaus\n"); exit(1); } else if(!strcmp(arg[k], "--width")) { k++; width = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--height")) { k++; height = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--bpp")) { k++; bpp = MAX(atoi(arg[k]), 0); fprintf(stderr, "%s %d\n", _("TODO: sorry, due to api restrictions we currently cannot set the bpp to"), bpp); } else if(!strcmp(arg[k], "--hq")) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) high_quality = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) high_quality = TRUE; else { fprintf(stderr, "%s: %s\n", _("Unknown option for --hq"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "-v") || !strcmp(arg[k], "--verbose")) { verbose = TRUE; } } else { if(file_counter == 0) image_filename = arg[k]; else if(file_counter == 1) xmp_filename = arg[k]; else if(file_counter == 2) output_filename = arg[k]; file_counter++; } } if(file_counter < 2 || file_counter > 3) { usage(arg[0]); exit(1); } else if(file_counter == 2) { // no xmp file given output_filename = xmp_filename; xmp_filename = NULL; } // the output file already exists, so there will be a sequence number added if(g_file_test(output_filename, G_FILE_TEST_EXISTS)) { fprintf(stderr, "%s\n", _("output file already exists, it will get renamed")); } char *m_arg[] = {"darktable-cli", "--library", ":memory:", NULL}; // init dt without gui: if(dt_init(3, m_arg, 0)) exit(1); dt_film_t film; int id = 0; int filmid = 0; gchar *directory = g_path_get_dirname(image_filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, image_filename, TRUE); if(!id) { fprintf(stderr, _("error: can't open file %s"), image_filename); fprintf(stderr, "\n"); exit(1); } g_free(directory); // attach xmp, if requested: if(xmp_filename) { const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, id); dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); dt_exif_xmp_read(image, xmp_filename, 1); // don't write new xmp: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_RELAXED); dt_image_cache_read_release(darktable.image_cache, image); } // print the history stack if(verbose) { gchar *history = dt_history_get_items_as_string(id); if(history) printf("%s\n", history); else printf("[%s]\n", _("empty history stack")); } // try to find out the export format from the output_filename char *ext = output_filename + strlen(output_filename); while(ext > output_filename && *ext != '.') ext--; *ext = '\0'; ext++; if(!strcmp(ext, "jpg")) ext = "jpeg"; // init the export data structures int size = 0, dat_size = 0; dt_imageio_module_format_t *format; dt_imageio_module_storage_t *storage; dt_imageio_module_data_t *sdata, *fdata; storage = dt_imageio_get_storage_by_name("disk"); // only exporting to disk makes sense if(storage == NULL) { fprintf(stderr, "%s\n", _("cannot find disk storage module. please check your installation, something seems to be broken.")); exit(1); } sdata = storage->get_params(storage, &size); if(sdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from storage module, aborting export ...")); exit(1); } // and now for the really ugly hacks. don't tell your children about this one or they won't sleep at night any longer ... g_strlcpy((char*)sdata, output_filename, DT_MAX_PATH_LEN); // all is good now, the last line didn't happen. format = dt_imageio_get_format_by_name(ext); if(format == NULL) { fprintf(stderr, _("unknown extension '.%s'"), ext); fprintf(stderr, "\n"); exit(1); } fdata = format->get_params(format, &dat_size); if(fdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from format module, aborting export ...")); exit(1); } uint32_t w,h,fw,fh,sw,sh; fw=fh=sw=sh=0; storage->dimension(storage, &sw, &sh); format->dimension(format, &fw, &fh); if( sw==0 || fw==0) w=sw>fw?sw:fw; else w=sw<fw?sw:fw; if( sh==0 || fh==0) h=sh>fh?sh:fh; else h=sh<fh?sh:fh; fdata->max_width = width; fdata->max_height = height; fdata->max_width = (w!=0 && fdata->max_width >w)?w:fdata->max_width; fdata->max_height = (h!=0 && fdata->max_height >h)?h:fdata->max_height; fdata->style[0] = '\0'; //TODO: add a callback to set the bpp without going through the config storage->store(storage,sdata, id, format, fdata, 1, 1, high_quality); // cleanup time if(storage->finalize_store) storage->finalize_store(storage, sdata); storage->free_params(storage, sdata); format->free_params(format, fdata); dt_cleanup(); }
void dt_film_import1(dt_job_t *job, dt_film_t *film) { gboolean recursive = dt_conf_get_bool("ui_last/import_recursive"); /* first of all gather all images to import */ GList *images = NULL; images = _film_recursive_get_files(film->dirname, recursive, &images); if(g_list_length(images) == 0) { dt_control_log(_("no supported images were found to be imported")); return; } #ifdef USE_LUA /* pre-sort image list for easier handling in Lua code */ images = g_list_sort(images, (GCompareFunc)_film_filename_cmp); dt_lua_lock(); lua_State *L = darktable.lua_state.state; { GList *elt = images; lua_newtable(L); while(elt) { lua_pushstring(L, elt->data); luaL_ref(L, -2); elt = g_list_next(elt); } } lua_pushvalue(L, -1); dt_lua_event_trigger(L, "pre-import", 1); { g_list_free_full(images, g_free); // recreate list of images images = NULL; lua_pushnil(L); /* first key */ while(lua_next(L, -2) != 0) { /* uses 'key' (at index -2) and 'value' (at index -1) */ void *filename = strdup(luaL_checkstring(L, -1)); lua_pop(L, 1); images = g_list_prepend(images, filename); } } lua_pop(L, 1); // remove the table again from the stack dt_lua_unlock(); #endif if(g_list_length(images) == 0) { // no error message, lua probably emptied the list on purpose return; } /* we got ourself a list of images, lets sort and start import */ images = g_list_sort(images, (GCompareFunc)_film_filename_cmp); /* let's start import of images */ gchar message[512] = { 0 }; double fraction = 0; guint total = g_list_length(images); g_snprintf(message, sizeof(message) - 1, ngettext("importing %d image", "importing %d images", total), total); dt_control_job_set_progress_message(job, message); /* loop thru the images and import to current film roll */ dt_film_t *cfr = film; GList *image = g_list_first(images); do { gchar *cdn = g_path_get_dirname((const gchar *)image->data); /* check if we need to initialize a new filmroll */ if(!cfr || g_strcmp0(cfr->dirname, cdn) != 0) { // FIXME: maybe refactor into function and call it? if(cfr && cfr->dir) { /* check if we can find a gpx data file to be auto applied to images in the jsut imported filmroll */ g_dir_rewind(cfr->dir); const gchar *dfn = NULL; while((dfn = g_dir_read_name(cfr->dir)) != NULL) { /* check if we have a gpx to be auto applied to filmroll */ size_t len = strlen(dfn); if(strcmp(dfn + len - 4, ".gpx") == 0 || strcmp(dfn + len - 4, ".GPX") == 0) { gchar *gpx_file = g_build_path(G_DIR_SEPARATOR_S, cfr->dirname, dfn, NULL); gchar *tz = dt_conf_get_string("plugins/lighttable/geotagging/tz"); dt_control_gpx_apply(gpx_file, cfr->id, tz); g_free(gpx_file); g_free(tz); } } } /* cleanup previously imported filmroll*/ if(cfr && cfr != film) { if(dt_film_is_empty(cfr->id)) { dt_film_remove(cfr->id); } dt_film_cleanup(cfr); free(cfr); cfr = NULL; } /* initialize and create a new film to import to */ cfr = malloc(sizeof(dt_film_t)); dt_film_init(cfr); dt_film_new(cfr, cdn); } g_free(cdn); /* import image */ dt_image_import(cfr->id, (const gchar *)image->data, FALSE); fraction += 1.0 / total; dt_control_job_set_progress(job, fraction); } while((image = g_list_next(image)) != NULL); g_list_free_full(images, g_free); // only redraw at the end, to not spam the cpu with exposure events dt_control_queue_redraw_center(); dt_control_signal_raise(darktable.signals, DT_SIGNAL_TAG_CHANGED); dt_control_signal_raise(darktable.signals, DT_SIGNAL_FILMROLLS_IMPORTED, film->id); // FIXME: maybe refactor into function and call it? if(cfr && cfr->dir) { /* check if we can find a gpx data file to be auto applied to images in the just imported filmroll */ g_dir_rewind(cfr->dir); const gchar *dfn = NULL; while((dfn = g_dir_read_name(cfr->dir)) != NULL) { /* check if we have a gpx to be auto applied to filmroll */ size_t len = strlen(dfn); if(strcmp(dfn + len - 4, ".gpx") == 0 || strcmp(dfn + len - 4, ".GPX") == 0) { gchar *gpx_file = g_build_path(G_DIR_SEPARATOR_S, cfr->dirname, dfn, NULL); gchar *tz = dt_conf_get_string("plugins/lighttable/geotagging/tz"); dt_control_gpx_apply(gpx_file, cfr->id, tz); g_free(gpx_file); g_free(tz); } } } /* cleanup previously imported filmroll*/ if(cfr && cfr != film) { dt_film_cleanup(cfr); free(cfr); } }
int32_t dt_control_merge_hdr_job_run(dt_job_t *job) { long int imgid = -1; dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param; GList *t = t1->index; int total = g_list_length(t); char message[512]= {0}; double fraction=0; snprintf(message, 512, ngettext ("merging %d image", "merging %d images", total), total ); const guint *jid = dt_control_backgroundjobs_create(darktable.control, 1, message); float *pixels = NULL; float *weight = NULL; int wd = 0, ht = 0, first_imgid = -1; uint32_t filter = 0; float whitelevel = 0.0f; total ++; while(t) { imgid = (long int)t->data; dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); // just take a copy. also do it after blocking read, so filters and bpp will make sense. const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_t image = *img; dt_image_cache_read_release(darktable.image_cache, img); if(image.filters == 0 || image.bpp != sizeof(uint16_t)) { dt_control_log(_("exposure bracketing only works on raw images")); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); free(pixels); free(weight); goto error; } filter = dt_image_flipped_filter(img); if(buf.size != DT_MIPMAP_FULL) { dt_control_log(_("failed to get raw buffer from image `%s'"), image.filename); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); free(pixels); free(weight); goto error; } if(!pixels) { first_imgid = imgid; pixels = (float *)malloc(sizeof(float)*image.width*image.height); weight = (float *)malloc(sizeof(float)*image.width*image.height); memset(pixels, 0x0, sizeof(float)*image.width*image.height); memset(weight, 0x0, sizeof(float)*image.width*image.height); wd = image.width; ht = image.height; } else if(image.width != wd || image.height != ht) { dt_control_log(_("images have to be of same size!")); free(pixels); free(weight); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); goto error; } // if no valid exif data can be found, assume peleng fisheye at f/16, 8mm, with half of the light lost in the system => f/22 const float eap = image.exif_aperture > 0.0f ? image.exif_aperture : 22.0f; const float efl = image.exif_focal_length > 0.0f ? image.exif_focal_length : 8.0f; const float rad = .5f * efl/eap; const float aperture = M_PI * rad * rad; const float iso = image.exif_iso > 0.0f ? image.exif_iso : 100.0f; const float exp = image.exif_exposure > 0.0f ? image.exif_exposure : 1.0f; const float cal = 100.0f/(aperture*exp*iso); // about proportional to how many photons we can expect from this shot: const float photoncnt = 100.0f*aperture*exp/iso; // stupid, but we don't know the real sensor saturation level: uint16_t saturation = 0; for(int k=0; k<wd*ht; k++) saturation = MAX(saturation, ((uint16_t *)buf.buf)[k]); // seems to be around 64500--64700 for 5dm2 // fprintf(stderr, "saturation: %u\n", saturation); whitelevel = fmaxf(whitelevel, saturation*cal); #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(buf, pixels, weight, wd, ht, saturation) #endif for(int k=0; k<wd*ht; k++) { const uint16_t in = ((uint16_t *)buf.buf)[k]; // weights based on siggraph 12 poster // zijian zhu, zhengguo li, susanto rahardja, pasi fraenti // 2d denoising factor for high dynamic range imaging float w = envelope(in/(float)saturation) * photoncnt; // in case we are black and drop to zero weight, give it something // just so numerics don't collapse. blown out whites are handled below. if(w < 1e-3f && in < saturation/3) w = 1e-3f; pixels[k] += w * in * cal; weight[k] += w; } t = g_list_delete_link(t, t); /* update backgroundjob ui plate */ fraction+=1.0/total; dt_control_backgroundjobs_progress(darktable.control, jid, fraction); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); } // normalize by white level to make clipping at 1.0 work as expected (to be sure, scale down one more stop, thus the 0.5): #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(pixels, wd, ht, weight, whitelevel) #endif for(int k=0; k<wd*ht; k++) { // in case w == 0, all pixels were overexposed (too dark would have been clamped to w >= eps above) if(weight[k] < 1e-3f) pixels[k] = 1.f; // mark as blown out. else // normalize: pixels[k] = fmaxf(0.0f, pixels[k]/(whitelevel*weight[k])); } // output hdr as digital negative with exif data. uint8_t exif[65535]; char pathname[DT_MAX_PATH_LEN]; dt_image_full_path(first_imgid, pathname, DT_MAX_PATH_LEN); // last param is dng mode const int exif_len = dt_exif_read_blob(exif, pathname, first_imgid, 0, wd, ht, 1); char *c = pathname + strlen(pathname); while(*c != '.' && c > pathname) c--; g_strlcpy(c, "-hdr.dng", sizeof(pathname)-(c-pathname)); dt_imageio_write_dng(pathname, pixels, wd, ht, exif, exif_len, filter, 1.0f); dt_control_backgroundjobs_progress(darktable.control, jid, 1.0f); while(*c != '/' && c > pathname) c--; dt_control_log(_("wrote merged hdr `%s'"), c+1); // import new image gchar *directory = g_path_get_dirname((const gchar *)pathname); dt_film_t film; const int filmid = dt_film_new(&film, directory); dt_image_import(filmid, pathname, TRUE); g_free (directory); free(pixels); free(weight); error: dt_control_backgroundjobs_destroy(darktable.control, jid); dt_control_queue_redraw_center(); return 0; }
int dt_load_from_string(const gchar* input, gboolean open_image_in_dr) { int id = 0; if(input == NULL || input[0] == '\0') return 0; char* filename = dt_make_path_absolute(input); if(filename == NULL) { dt_control_log(_("found strange path `%s'"), input); return 0; } if(g_file_test(filename, G_FILE_TEST_IS_DIR)) { // import a directory into a film roll unsigned int last_char = strlen(filename)-1; if(filename[last_char] == '/') filename[last_char] = '\0'; id = dt_film_import(filename); if(id) { dt_film_open(id); dt_ctl_switch_mode_to(DT_LIBRARY); } else { dt_control_log(_("error loading directory `%s'"), filename); } } else { // import a single image gchar *directory = g_path_get_dirname((const gchar *)filename); dt_film_t film; const int filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, filename, TRUE); g_free (directory); if(id) { dt_film_open(filmid); // make sure buffers are loaded (load full for testing) dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); if(!buf.buf) { id = 0; dt_control_log(_("file `%s' has unknown format!"), filename); } else { dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); if(open_image_in_dr) { dt_control_set_mouse_over_id(id); dt_ctl_switch_mode_to(DT_DEVELOP); } } } else { dt_control_log(_("error loading file `%s'"), filename); } } g_free(filename); return id; }
static void _lib_import_single_image_callback(GtkWidget *widget, gpointer user_data) { GtkWidget *win = dt_ui_main_window(darktable.gui->ui); GtkWidget *filechooser = gtk_file_chooser_dialog_new( _("import image"), GTK_WINDOW(win), GTK_FILE_CHOOSER_ACTION_OPEN, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Open"), GTK_RESPONSE_ACCEPT, (char *)NULL); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), TRUE); char *last_directory = dt_conf_get_string("ui_last/import_last_directory"); if(last_directory != NULL) { gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(filechooser), last_directory); g_free(last_directory); } char *cp, **extensions, ext[1024]; GtkFileFilter *filter; filter = GTK_FILE_FILTER(gtk_file_filter_new()); extensions = g_strsplit(dt_supported_extensions, ",", 100); for(char **i = extensions; *i != NULL; i++) { snprintf(ext, sizeof(ext), "*.%s", *i); gtk_file_filter_add_pattern(filter, ext); gtk_file_filter_add_pattern(filter, cp = g_ascii_strup(ext, -1)); g_free(cp); } g_strfreev(extensions); gtk_file_filter_set_name(filter, _("supported images")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); filter = GTK_FILE_FILTER(gtk_file_filter_new()); gtk_file_filter_add_pattern(filter, "*"); gtk_file_filter_set_name(filter, _("all files")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); GtkWidget *preview = gtk_image_new(); gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(filechooser), preview); g_signal_connect(filechooser, "update-preview", G_CALLBACK(_lib_import_update_preview), preview); dt_lib_import_metadata_t metadata; gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(filechooser), _lib_import_get_extra_widget(&metadata, FALSE)); if(gtk_dialog_run(GTK_DIALOG(filechooser)) == GTK_RESPONSE_ACCEPT) { dt_conf_set_string("ui_last/import_last_directory", gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(filechooser))); _lib_import_evaluate_extra_widget(&metadata, FALSE); char *filename = NULL; dt_film_t film; GSList *list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(filechooser)); GSList *it = list; int id = 0; int filmid = 0; /* reset filter so that view isn't empty */ dt_view_filter_reset(darktable.view_manager, TRUE); while(it) { filename = (char *)it->data; gchar *directory = g_path_get_dirname((const gchar *)filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, filename, TRUE); if(!id) dt_control_log(_("error loading file `%s'"), filename); g_free(filename); g_free(directory); it = g_slist_next(it); } if(id) { dt_film_open(filmid); // make sure buffers are loaded (load full for testing) dt_mipmap_buffer_t buf; dt_mipmap_cache_get(darktable.mipmap_cache, &buf, id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING, 'r'); gboolean loaded = (buf.buf != NULL); dt_mipmap_cache_release(darktable.mipmap_cache, &buf); if(!loaded) { dt_control_log(_("file has unknown format!")); } else { dt_control_set_mouse_over_id(id); dt_ctl_switch_mode_to(DT_DEVELOP); } } } gtk_widget_destroy(metadata.frame); gtk_widget_destroy(filechooser); gtk_widget_queue_draw(dt_ui_center(darktable.gui->ui)); }
void dt_film_import1(dt_film_t *film) { gboolean recursive = dt_conf_get_bool("ui_last/import_recursive"); /* first of all gather all images to import */ GList *images = NULL; images = _film_recursive_get_files(film->dirname, recursive, &images); if(g_list_length(images) == 0) { dt_control_log(_("no supported images were found to be imported")); return; } /* we got ourself a list of images, lets sort and start import */ images = g_list_sort(images,(GCompareFunc)_film_filename_cmp); /* let's start import of images */ gchar message[512] = {0}; double fraction = 0; uint32_t total = g_list_length(images); g_snprintf(message, sizeof(message) - 1, ngettext("importing %d image","importing %d images", total), total); const guint *jid = dt_control_backgroundjobs_create(darktable.control, 0, message); /* loop thru the images and import to current film roll */ dt_film_t *cfr = film; GList *image = g_list_first(images); do { gchar *cdn = g_path_get_dirname((const gchar *)image->data); /* check if we need to initialize a new filmroll */ if(!cfr || g_strcmp0(cfr->dirname, cdn) != 0) { #if GLIB_CHECK_VERSION (2, 26, 0) if(cfr && cfr->dir) { /* check if we can find a gpx data file to be auto applied to images in the jsut imported filmroll */ g_dir_rewind(cfr->dir); const gchar *dfn = NULL; while ((dfn = g_dir_read_name(cfr->dir)) != NULL) { /* check if we have a gpx to be auto applied to filmroll */ if(strcmp(dfn+strlen(dfn)-4,".gpx") == 0 || strcmp(dfn+strlen(dfn)-4,".GPX") == 0) { gchar *gpx_file = g_build_path (G_DIR_SEPARATOR_S, cfr->dirname, dfn, NULL); dt_control_gpx_apply(gpx_file, cfr->id, dt_conf_get_string("plugins/lighttable/geotagging/tz")); g_free(gpx_file); } } } #endif /* cleanup previously imported filmroll*/ if(cfr && cfr!=film) { if(dt_film_is_empty(cfr->id)) { dt_film_remove(cfr->id); } dt_film_cleanup(cfr); g_free(cfr); cfr = NULL; } /* initialize and create a new film to import to */ cfr = g_malloc(sizeof(dt_film_t)); dt_film_init(cfr); dt_film_new(cfr, cdn); } /* import image */ dt_image_import(cfr->id, (const gchar *)image->data, FALSE); fraction+=1.0/total; dt_control_backgroundjobs_progress(darktable.control, jid, fraction); } while( (image = g_list_next(image)) != NULL); // only redraw at the end, to not spam the cpu with exposure events dt_control_queue_redraw_center(); dt_control_signal_raise(darktable.signals,DT_SIGNAL_TAG_CHANGED); dt_control_backgroundjobs_destroy(darktable.control, jid); dt_control_signal_raise(darktable.signals , DT_SIGNAL_FILMROLLS_IMPORTED,film->id); #if GLIB_CHECK_VERSION (2, 26, 0) if(cfr && cfr->dir) { /* check if we can find a gpx data file to be auto applied to images in the just imported filmroll */ g_dir_rewind(cfr->dir); const gchar *dfn = NULL; while ((dfn = g_dir_read_name(cfr->dir)) != NULL) { /* check if we have a gpx to be auto applied to filmroll */ if(strcmp(dfn+strlen(dfn)-4,".gpx") == 0 || strcmp(dfn+strlen(dfn)-4,".GPX") == 0) { gchar *gpx_file = g_build_path (G_DIR_SEPARATOR_S, cfr->dirname, dfn, NULL); dt_control_gpx_apply(gpx_file, cfr->id, dt_conf_get_string("plugins/lighttable/geotagging/tz")); g_free(gpx_file); } } } #endif }
static void _lib_import_single_image_callback(GtkWidget *widget,gpointer user_data) { GtkWidget *win = dt_ui_main_window(darktable.gui->ui); GtkWidget *filechooser = gtk_file_chooser_dialog_new (_("import image"), GTK_WINDOW (win), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, (char *)NULL); gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(filechooser), TRUE); char *last_directory = dt_conf_get_string("ui_last/import_last_directory"); if(last_directory != NULL) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (filechooser), last_directory); char *cp, **extensions, ext[1024]; GtkFileFilter *filter; filter = GTK_FILE_FILTER(gtk_file_filter_new()); extensions = g_strsplit(dt_supported_extensions, ",", 100); for(char **i=extensions; *i!=NULL; i++) { snprintf(ext, 1024, "*.%s", *i); gtk_file_filter_add_pattern(filter, ext); gtk_file_filter_add_pattern(filter, cp=g_ascii_strup(ext, -1)); g_free(cp); } g_strfreev(extensions); gtk_file_filter_set_name(filter, _("supported images")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); filter = GTK_FILE_FILTER(gtk_file_filter_new()); gtk_file_filter_add_pattern(filter, "*"); gtk_file_filter_set_name(filter, _("all files")); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(filechooser), filter); if (gtk_dialog_run (GTK_DIALOG (filechooser)) == GTK_RESPONSE_ACCEPT) { dt_conf_set_string("ui_last/import_last_directory", gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER (filechooser))); char *filename = NULL; dt_film_t film; GSList *list = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (filechooser)); GSList *it = list; int id = 0; int filmid = 0; while(it) { filename = (char *)it->data; gchar *directory = g_path_get_dirname((const gchar *)filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, filename, TRUE); if(!id) dt_control_log(_("error loading file `%s'"), filename); g_free (filename); g_free (directory); it = g_slist_next(it); } if(id) { dt_film_open(filmid); // make sure buffers are loaded (load full for testing) dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, id, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); if(!buf.buf) { dt_control_log(_("file has unknown format!")); } else { dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, id); dt_ctl_switch_mode_to(DT_DEVELOP); } } } gtk_widget_destroy (filechooser); gtk_widget_queue_draw(dt_ui_center(darktable.gui->ui)); }
int32_t dt_control_merge_hdr_job_run(dt_job_t *job) { long int imgid = -1; dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param; GList *t = t1->index; int total = g_list_length(t); char message[512]= {0}; double fraction=0; snprintf(message, 512, ngettext ("merging %d image", "merging %d images", total), total ); const guint *jid = dt_control_backgroundjobs_create(darktable.control, 1, message); float *pixels = NULL; float *weight = NULL; int wd = 0, ht = 0, first_imgid = -1; uint32_t filter = 0; float whitelevel = 0.0f; total ++; while(t) { imgid = (long int)t->data; dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); // just take a copy. also do it after blocking read, so filters and bpp will make sense. const dt_image_t *img = dt_image_cache_read_get(darktable.image_cache, imgid); dt_image_t image = *img; dt_image_cache_read_release(darktable.image_cache, img); if(image.filters == 0 || image.bpp != sizeof(uint16_t)) { dt_control_log(_("exposure bracketing only works on raw images")); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); free(pixels); free(weight); goto error; } filter = dt_image_flipped_filter(img); if(buf.size != DT_MIPMAP_FULL) { dt_control_log(_("failed to get raw buffer from image `%s'"), image.filename); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); free(pixels); free(weight); goto error; } if(!pixels) { first_imgid = imgid; pixels = (float *)malloc(sizeof(float)*image.width*image.height); weight = (float *)malloc(sizeof(float)*image.width*image.height); memset(pixels, 0x0, sizeof(float)*image.width*image.height); memset(weight, 0x0, sizeof(float)*image.width*image.height); wd = image.width; ht = image.height; } else if(image.width != wd || image.height != ht) { dt_control_log(_("images have to be of same size!")); free(pixels); free(weight); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); goto error; } // if no valid exif data can be found, assume peleng fisheye at f/16, 8mm, with half of the light lost in the system => f/22 const float eap = image.exif_aperture > 0.0f ? image.exif_aperture : 22.0f; const float efl = image.exif_focal_length > 0.0f ? image.exif_focal_length : 8.0f; const float rad = .5f * efl/eap; const float aperture = M_PI * rad * rad; const float iso = image.exif_iso > 0.0f ? image.exif_iso : 100.0f; const float exp = image.exif_exposure > 0.0f ? image.exif_exposure : 1.0f; const float cal = 100.0f/(aperture*exp*iso); whitelevel = fmaxf(whitelevel, cal); #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(buf, pixels, weight, wd, ht) #endif for(int k=0; k<wd*ht; k++) { const uint16_t in = ((uint16_t *)buf.buf)[k]; const float w = .001f + (in >= 1000 ? (in < 65000 ? in/65000.0f : 0.0f) : exp * 0.01f); pixels[k] += w * in * cal; weight[k] += w; } t = g_list_delete_link(t, t); /* update backgroundjob ui plate */ fraction+=1.0/total; dt_control_backgroundjobs_progress(darktable.control, jid, fraction); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); } // normalize by white level to make clipping at 1.0 work as expected (to be sure, scale down one more stop, thus the 0.5): #ifdef _OPENMP #pragma omp parallel for schedule(static) default(none) shared(pixels, wd, ht, weight, whitelevel) #endif for(int k=0; k<wd*ht; k++) pixels[k] = fmaxf(0.0f, fminf(2.0f, pixels[k]/((.5f*whitelevel*65535.0f)*weight[k]))); // output hdr as digital negative with exif data. uint8_t exif[65535]; char pathname[1024]; dt_image_full_path(first_imgid, pathname, 1024); const int exif_len = dt_exif_read_blob(exif, pathname, 0, first_imgid); char *c = pathname + strlen(pathname); while(*c != '.' && c > pathname) c--; g_strlcpy(c, "-hdr.dng", sizeof(pathname)-(c-pathname)); dt_imageio_write_dng(pathname, pixels, wd, ht, exif, exif_len, filter, whitelevel); dt_control_backgroundjobs_progress(darktable.control, jid, 1.0f); while(*c != '/' && c > pathname) c--; dt_control_log(_("wrote merged hdr `%s'"), c+1); // import new image gchar *directory = g_path_get_dirname((const gchar *)pathname); dt_film_t film; const int filmid = dt_film_new(&film, directory); dt_image_import(filmid, pathname, TRUE); g_free (directory); free(pixels); free(weight); error: dt_control_backgroundjobs_destroy(darktable.control, jid); return 0; }
int main(int argc, char *arg[]) { bindtextdomain(GETTEXT_PACKAGE, DARKTABLE_LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); if(!gtk_parse_args(&argc, &arg)) exit(1); // parse command line arguments char *input_filename = NULL; char *xmp_filename = NULL; char *output_filename = NULL; int file_counter = 0; int width = 0, height = 0, bpp = 0; gboolean verbose = FALSE, high_quality = TRUE, upscale = FALSE; int k; for(k = 1; k < argc; k++) { if(arg[k][0] == '-') { if(!strcmp(arg[k], "--help")) { usage(arg[0]); exit(1); } else if(!strcmp(arg[k], "--version")) { printf("this is darktable-cli %s\ncopyright (c) 2012-2016 johannes hanika, tobias ellinghaus\n", darktable_package_version); exit(1); } else if(!strcmp(arg[k], "--width") && argc > k + 1) { k++; width = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--height") && argc > k + 1) { k++; height = MAX(atoi(arg[k]), 0); } else if(!strcmp(arg[k], "--bpp") && argc > k + 1) { k++; bpp = MAX(atoi(arg[k]), 0); fprintf(stderr, "%s %d\n", _("TODO: sorry, due to API restrictions we currently cannot set the BPP to"), bpp); } else if(!strcmp(arg[k], "--hq") && argc > k + 1) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) high_quality = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) high_quality = TRUE; else { fprintf(stderr, "%s: %s\n", _("unknown option for --hq"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "--upscale") && argc > k + 1) { k++; gchar *str = g_ascii_strup(arg[k], -1); if(!g_strcmp0(str, "0") || !g_strcmp0(str, "FALSE")) upscale = FALSE; else if(!g_strcmp0(str, "1") || !g_strcmp0(str, "TRUE")) upscale= TRUE; else { fprintf(stderr, "%s: %s\n", _("unknown option for --upscale"), arg[k]); usage(arg[0]); exit(1); } g_free(str); } else if(!strcmp(arg[k], "-v") || !strcmp(arg[k], "--verbose")) { verbose = TRUE; } else if(!strcmp(arg[k], "--core")) { // everything from here on should be passed to the core k++; break; } } else { if(file_counter == 0) input_filename = arg[k]; else if(file_counter == 1) xmp_filename = arg[k]; else if(file_counter == 2) output_filename = arg[k]; file_counter++; } } int m_argc = 0; char **m_arg = malloc((5 + argc - k + 1) * sizeof(char *)); m_arg[m_argc++] = "darktable-cli"; m_arg[m_argc++] = "--library"; m_arg[m_argc++] = ":memory:"; m_arg[m_argc++] = "--conf"; m_arg[m_argc++] = "write_sidecar_files=FALSE"; for(; k < argc; k++) m_arg[m_argc++] = arg[k]; m_arg[m_argc] = NULL; if(file_counter < 2 || file_counter > 3) { usage(arg[0]); free(m_arg); exit(1); } else if(file_counter == 2) { // no xmp file given output_filename = xmp_filename; xmp_filename = NULL; } if(g_file_test(output_filename, G_FILE_TEST_IS_DIR)) { fprintf(stderr, _("error: output file is a directory. please specify file name")); fprintf(stderr, "\n"); free(m_arg); exit(1); } // the output file already exists, so there will be a sequence number added if(g_file_test(output_filename, G_FILE_TEST_EXISTS)) { fprintf(stderr, "%s\n", _("output file already exists, it will get renamed")); } // init dt without gui: if(dt_init(m_argc, m_arg, 0, NULL)) { free(m_arg); exit(1); } GList *id_list = NULL; if(g_file_test(input_filename, G_FILE_TEST_IS_DIR)) { int filmid = dt_film_import(input_filename); if(!filmid) { fprintf(stderr, _("error: can't open folder %s"), input_filename); fprintf(stderr, "\n"); free(m_arg); exit(1); } id_list = dt_film_get_image_ids(filmid); } else { dt_film_t film; int id = 0; int filmid = 0; gchar *directory = g_path_get_dirname(input_filename); filmid = dt_film_new(&film, directory); id = dt_image_import(filmid, input_filename, TRUE); if(!id) { fprintf(stderr, _("error: can't open file %s"), input_filename); fprintf(stderr, "\n"); free(m_arg); exit(1); } g_free(directory); id_list = g_list_append(id_list, GINT_TO_POINTER(id)); } int total = g_list_length(id_list); if(total == 0) { fprintf(stderr, _("no images to export, aborting\n")); free(m_arg); exit(1); } // attach xmp, if requested: if(xmp_filename) { for(GList *iter = id_list; iter; iter = g_list_next(iter)) { int id = GPOINTER_TO_INT(iter->data); dt_image_t *image = dt_image_cache_get(darktable.image_cache, id, 'w'); dt_exif_xmp_read(image, xmp_filename, 1); // don't write new xmp: dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_RELAXED); } } // print the history stack. only look at the first image and assume all got the same processing applied if(verbose) { int id = GPOINTER_TO_INT(id_list->data); gchar *history = dt_history_get_items_as_string(id); if(history) printf("%s\n", history); else printf("[%s]\n", _("empty history stack")); } // try to find out the export format from the output_filename char *ext = output_filename + strlen(output_filename); while(ext > output_filename && *ext != '.') ext--; *ext = '\0'; ext++; if(!strcmp(ext, "jpg")) ext = "jpeg"; if(!strcmp(ext, "tif")) ext = "tiff"; // init the export data structures dt_imageio_module_format_t *format; dt_imageio_module_storage_t *storage; dt_imageio_module_data_t *sdata, *fdata; storage = dt_imageio_get_storage_by_name("disk"); // only exporting to disk makes sense if(storage == NULL) { fprintf( stderr, "%s\n", _("cannot find disk storage module. please check your installation, something seems to be broken.")); free(m_arg); exit(1); } sdata = storage->get_params(storage); if(sdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from storage module, aborting export ...")); free(m_arg); exit(1); } // and now for the really ugly hacks. don't tell your children about this one or they won't sleep at night // any longer ... g_strlcpy((char *)sdata, output_filename, DT_MAX_PATH_FOR_PARAMS); // all is good now, the last line didn't happen. format = dt_imageio_get_format_by_name(ext); if(format == NULL) { fprintf(stderr, _("unknown extension '.%s'"), ext); fprintf(stderr, "\n"); free(m_arg); exit(1); } fdata = format->get_params(format); if(fdata == NULL) { fprintf(stderr, "%s\n", _("failed to get parameters from format module, aborting export ...")); free(m_arg); exit(1); } uint32_t w, h, fw, fh, sw, sh; fw = fh = sw = sh = 0; storage->dimension(storage, sdata, &sw, &sh); format->dimension(format, fdata, &fw, &fh); if(sw == 0 || fw == 0) w = sw > fw ? sw : fw; else w = sw < fw ? sw : fw; if(sh == 0 || fh == 0) h = sh > fh ? sh : fh; else h = sh < fh ? sh : fh; fdata->max_width = width; fdata->max_height = height; fdata->max_width = (w != 0 && fdata->max_width > w) ? w : fdata->max_width; fdata->max_height = (h != 0 && fdata->max_height > h) ? h : fdata->max_height; fdata->style[0] = '\0'; fdata->style_append = 0; if(storage->initialize_store) { storage->initialize_store(storage, sdata, &format, &fdata, &id_list, high_quality, upscale); format->set_params(format, fdata, format->params_size(format)); storage->set_params(storage, sdata, storage->params_size(storage)); } // TODO: add a callback to set the bpp without going through the config int num = 1; for(GList *iter = id_list; iter; iter = g_list_next(iter), num++) { int id = GPOINTER_TO_INT(iter->data); storage->store(storage, sdata, id, format, fdata, num, total, high_quality, upscale); } // cleanup time if(storage->finalize_store) storage->finalize_store(storage, sdata); storage->free_params(storage, sdata); format->free_params(format, fdata); g_list_free(id_list); dt_cleanup(); free(m_arg); }