void reload_defaults(dt_iop_module_t *self) { dt_iop_rawprepare_params_t tmp = { 0 }; // we might be called from presets update infrastructure => there is no image if(!self->dev) goto end; const dt_image_t *const image = &(self->dev->image_storage); tmp = (dt_iop_rawprepare_params_t){.x = image->crop_x, .y = image->crop_y, .width = image->crop_width, .height = image->crop_height, .raw_black_level_separate[0] = image->raw_black_level_separate[0], .raw_black_level_separate[1] = image->raw_black_level_separate[1], .raw_black_level_separate[2] = image->raw_black_level_separate[2], .raw_black_level_separate[3] = image->raw_black_level_separate[3], .raw_white_point = image->raw_white_point }; self->default_enabled = dt_image_is_raw(image) && image->bpp != sizeof(float); end: memcpy(self->params, &tmp, sizeof(dt_iop_rawprepare_params_t)); memcpy(self->default_params, &tmp, sizeof(dt_iop_rawprepare_params_t)); } void init_global(dt_iop_module_so_t *self) { const int program = 2; // basic.cl, from programs.conf self->data = malloc(sizeof(dt_iop_rawprepare_global_data_t)); dt_iop_rawprepare_global_data_t *gd = self->data; gd->kernel_rawprepare_1f = dt_opencl_create_kernel(program, "rawprepare_1f"); gd->kernel_rawprepare_4f = dt_opencl_create_kernel(program, "rawprepare_4f"); } void init(dt_iop_module_t *self) { const dt_image_t *const image = &(self->dev->image_storage); self->params = calloc(1, sizeof(dt_iop_rawprepare_params_t)); self->default_params = calloc(1, sizeof(dt_iop_rawprepare_params_t)); self->hide_enable_button = 1; self->default_enabled = dt_image_is_raw(image) && image->bpp != sizeof(float); self->priority = 10; // module order created by iop_dependencies.py, do not edit! self->params_size = sizeof(dt_iop_rawprepare_params_t); self->gui_data = NULL; } void cleanup(dt_iop_module_t *self) { free(self->params); self->params = NULL; }
static int is_raw_member(lua_State *L) { const dt_image_t *my_image = checkreadimage(L, 1); lua_pushboolean(L, dt_image_is_raw(my_image)); releasereadimage(L, my_image); return 1; }
void reload_defaults(dt_iop_module_t *module) { const dt_iop_hotpixels_params_t tmp = {.strength = 0.25, .threshold = 0.05, .markfixed = FALSE, .permissive = FALSE }; // we might be called from presets update infrastructure => there is no image if(!module->dev) goto end; // can't be switched on for non-raw images: if(dt_image_is_raw(&module->dev->image_storage)) module->hide_enable_button = 0; else module->hide_enable_button = 1; end: memcpy(module->params, &tmp, sizeof(dt_iop_hotpixels_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_hotpixels_params_t)); } void init(dt_iop_module_t *module) { module->data = NULL; module->params = calloc(1, sizeof(dt_iop_hotpixels_params_t)); module->default_params = calloc(1, sizeof(dt_iop_hotpixels_params_t)); module->default_enabled = 0; module->priority = 100; // module order created by iop_dependencies.py, do not edit! module->params_size = sizeof(dt_iop_hotpixels_params_t); module->gui_data = NULL; }
static void deflicker_histogram_source_callback(GtkWidget *combo, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; if(self->dt->gui->reset) return; if(!dt_image_is_raw(&self->dev->image_storage)) return; dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; const dt_iop_exposure_deflicker_histogram_source_t new_mode = GPOINTER_TO_UINT(g_list_nth_data(g->deflicker_histogram_sources, dt_bauhaus_combobox_get(combo))); switch(new_mode) { case DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE: p->deflicker_histogram_source = DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE; deflicker_prepare_histogram(self, &g->deflicker_histogram, &g->deflicker_histogram_stats); break; case DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL: default: p->deflicker_histogram_source = DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL; free(g->deflicker_histogram); g->deflicker_histogram = NULL; break; } dt_dev_add_history_item(darktable.develop, self, TRUE); }
void gui_update(struct dt_iop_module_t *self) { dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; if(!dt_image_is_raw(&self->dev->image_storage)) { gtk_widget_hide(GTK_WIDGET(g->mode)); p->mode = EXPOSURE_MODE_MANUAL; dt_dev_add_history_item(darktable.develop, self, TRUE); } else { gtk_widget_show(GTK_WIDGET(g->mode)); } dt_bauhaus_combobox_set(g->mode, g_list_index(g->modes, GUINT_TO_POINTER(p->mode))); dt_bauhaus_slider_set(g->black, p->black); dt_bauhaus_slider_set_soft(g->exposure, p->exposure); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autoexp), FALSE); dt_bauhaus_slider_set(g->autoexpp, 0.01); gtk_widget_set_sensitive(GTK_WIDGET(g->autoexpp), FALSE); dt_bauhaus_slider_set(g->deflicker_percentile, p->deflicker_percentile); dt_bauhaus_slider_set(g->deflicker_target_level, p->deflicker_target_level); dt_bauhaus_combobox_set(g->deflicker_histogram_source, g_list_index(g->deflicker_histogram_sources, GUINT_TO_POINTER(p->deflicker_histogram_source))); self->request_color_pick = DT_REQUEST_COLORPICK_OFF; free(g->deflicker_histogram); g->deflicker_histogram = NULL; g->reprocess_on_next_expose = FALSE; gtk_label_set_text(g->deflicker_used_EC, ""); g->deflicker_computed_exposure = NAN; switch(p->mode) { case EXPOSURE_MODE_DEFLICKER: autoexp_disable(self); gtk_widget_hide(GTK_WIDGET(g->vbox_manual)); gtk_widget_show(GTK_WIDGET(g->vbox_deflicker)); if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE) deflicker_prepare_histogram(self, &g->deflicker_histogram, &g->deflicker_histogram_stats); break; case EXPOSURE_MODE_MANUAL: default: gtk_widget_hide(GTK_WIDGET(g->vbox_deflicker)); gtk_widget_show(GTK_WIDGET(g->vbox_manual)); break; } }
void reload_defaults(dt_iop_module_t *module) { // only on for raw images: if(dt_image_is_raw(&module->dev->image_storage)) module->default_enabled = 1; else module->default_enabled = 0; dt_iop_highlights_params_t tmp = (dt_iop_highlights_params_t) { 0, 1.0, 0.0, 0.0, 1.0 }; memcpy(module->params, &tmp, sizeof(dt_iop_highlights_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_highlights_params_t)); }
static void deflicker_params_callback(GtkWidget *slider, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; if(self->dt->gui->reset) return; if(!dt_image_is_raw(&self->dev->image_storage)) return; dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; if(p->mode != EXPOSURE_MODE_DEFLICKER) return; p->deflicker_percentile = dt_bauhaus_slider_get(g->deflicker_percentile); p->deflicker_target_level = dt_bauhaus_slider_get(g->deflicker_target_level); dt_dev_add_history_item(darktable.develop, self, TRUE); }
static void mode_callback(GtkWidget *combo, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; if(darktable.gui->reset) return; dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)self->params; const dt_iop_exposure_mode_t new_mode = GPOINTER_TO_UINT(g_list_nth_data(g->modes, dt_bauhaus_combobox_get(combo))); free(g->deflicker_histogram); g->deflicker_histogram = NULL; switch(new_mode) { case EXPOSURE_MODE_DEFLICKER: autoexp_disable(self); if(!dt_image_is_raw(&self->dev->image_storage)) { dt_bauhaus_combobox_set(g->mode, g_list_index(g->modes, GUINT_TO_POINTER(EXPOSURE_MODE_MANUAL))); gtk_widget_hide(GTK_WIDGET(g->mode)); break; } p->mode = EXPOSURE_MODE_DEFLICKER; gtk_widget_hide(GTK_WIDGET(g->vbox_manual)); gtk_widget_show(GTK_WIDGET(g->vbox_deflicker)); if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE) deflicker_prepare_histogram(self, &g->deflicker_histogram, &g->deflicker_histogram_stats); break; case EXPOSURE_MODE_MANUAL: default: p->mode = EXPOSURE_MODE_MANUAL; gtk_widget_hide(GTK_WIDGET(g->vbox_deflicker)); gtk_widget_show(GTK_WIDGET(g->vbox_manual)); break; } dt_dev_add_history_item(darktable.develop, self, TRUE); }
void commit_params(dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece) { const dt_iop_rawprepare_params_t *const p = (dt_iop_rawprepare_params_t *)params; dt_iop_rawprepare_data_t *d = (dt_iop_rawprepare_data_t *)piece->data; d->x = p->x; d->y = p->y; d->width = p->width; d->height = p->height; if(!dt_dev_pixelpipe_uses_downsampled_input(piece->pipe) && piece->pipe->filters) { const float white = (float)p->raw_white_point; for(int i = 0; i < 4; i++) { d->sub[i] = (float)p->raw_black_level_separate[i]; d->div[i] = (white - d->sub[i]); } } else { const float white = (float)p->raw_white_point / (float)UINT16_MAX; float black = 0; for(int i = 0; i < 4; i++) { black += p->raw_black_level_separate[i] / (float)UINT16_MAX; } black /= 4.0f; for(int i = 0; i < 4; i++) { d->sub[i] = black; d->div[i] = (white - black); } } if(!dt_image_is_raw(&piece->pipe->image) || piece->pipe->image.bpp == sizeof(float)) piece->enabled = 0; }
static int image_index(lua_State *L) { const char* membername = lua_tostring(L, -1); const dt_image_t * my_image=checkreadimage(L,-2); if(luaA_struct_has_member_name(L,dt_image_t,membername)) { const int result = luaA_struct_push_member_name(L, dt_image_t, my_image, membername); releasereadimage(L,my_image); return result; } switch(luaL_checkoption(L,-1,NULL,image_fields_name)) { case PATH: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select folder from images, film_rolls where " "images.film_id = film_rolls.id and images.id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); if(sqlite3_step(stmt) == SQLITE_ROW) { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } else { sqlite3_finalize(stmt); releasereadimage(L,my_image); return luaL_error(L,"should never happen"); } sqlite3_finalize(stmt); break; } case DUP_INDEX: { // get duplicate suffix int version = 0; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(id) from images where filename in " "(select filename from images where id = ?1) and film_id in " "(select film_id from images where id = ?1) and id < ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); if(sqlite3_step(stmt) == SQLITE_ROW) version = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); lua_pushinteger(L,version); break; } case IS_LDR: lua_pushboolean(L,dt_image_is_ldr(my_image)); break; case IS_HDR: lua_pushboolean(L,dt_image_is_hdr(my_image)); break; case IS_RAW: lua_pushboolean(L,dt_image_is_raw(my_image)); break; case RATING: { int score = my_image->flags & 0x7; if(score >6) score=5; if(score ==6) score=-1; lua_pushinteger(L,score); break; } case ID: lua_pushinteger(L,my_image->id); break; case FILM: luaA_push(L,dt_lua_film_t,&my_image->film_id); break; case CREATOR: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_CREATOR); if(sqlite3_step(stmt) != SQLITE_ROW) { lua_pushstring(L,""); } else { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } sqlite3_finalize(stmt); break; } case PUBLISHER: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_PUBLISHER); if(sqlite3_step(stmt) != SQLITE_ROW) { lua_pushstring(L,""); } else { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } sqlite3_finalize(stmt); break; } case TITLE: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_TITLE); if(sqlite3_step(stmt) != SQLITE_ROW) { lua_pushstring(L,""); } else { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } sqlite3_finalize(stmt); break; } case DESCRIPTION: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_DESCRIPTION); if(sqlite3_step(stmt) != SQLITE_ROW) { lua_pushstring(L,""); } else { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } sqlite3_finalize(stmt); break; } case RIGHTS: { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db),"select value from meta_data where id = ?1 and key = ?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, my_image->id); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, DT_METADATA_XMP_DC_RIGHTS); if(sqlite3_step(stmt) != SQLITE_ROW) { lua_pushstring(L,""); } else { lua_pushstring(L,(char *)sqlite3_column_text(stmt, 0)); } sqlite3_finalize(stmt); break; } case GROUP_LEADER: { luaA_push(L,dt_lua_image_t,&(my_image->group_id)); break; } case APPLY_STYLE: { lua_pushcfunction(L,dt_lua_style_apply); break; } case CREATE_STYLE: { lua_pushcfunction(L,dt_lua_style_create_from_image); break; } case RESET: { lua_pushcfunction(L,history_delete); break; } case MOVE: { lua_pushcfunction(L,dt_lua_move_image); break; } case COPY: { lua_pushcfunction(L,dt_lua_copy_image); break; } case LOCAL_COPY: { lua_pushboolean(L,my_image->flags &DT_IMAGE_LOCAL_COPY); break; } default: releasereadimage(L,my_image); return luaL_error(L,"should never happen %s",lua_tostring(L,-1)); } releasereadimage(L,my_image); return 1; }
void dt_lightroom_import(int imgid, dt_develop_t *dev, gboolean iauto) { gboolean refresh_needed = FALSE; char imported[256] = { 0 }; // Get full pathname char *pathname = dt_get_lightroom_xmp(imgid); if(!pathname) { if(!iauto) dt_control_log(_("cannot find lightroom XMP!")); return; } // Load LR xmp xmlDocPtr doc; xmlNodePtr entryNode; // Parse xml document doc = xmlParseEntity(pathname); if(doc == NULL) { g_free(pathname); return; } // Enter first node, xmpmeta entryNode = xmlDocGetRootElement(doc); if(entryNode == NULL) { g_free(pathname); xmlFreeDoc(doc); return; } if(xmlStrcmp(entryNode->name, (const xmlChar *)"xmpmeta")) { if(!iauto) dt_control_log(_("`%s' not a lightroom XMP!"), pathname); g_free(pathname); return; } // Check that this is really a Lightroom document xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); if(xpathCtx == NULL) { g_free(pathname); xmlFreeDoc(doc); return; } xmlXPathRegisterNs(xpathCtx, BAD_CAST "stEvt", BAD_CAST "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"); xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar *)"//@stEvt:softwareAgent", xpathCtx); if(xpathObj == NULL) { if(!iauto) dt_control_log(_("`%s' not a lightroom XMP!"), pathname); xmlXPathFreeContext(xpathCtx); g_free(pathname); xmlFreeDoc(doc); return; } xmlNodeSetPtr xnodes = xpathObj->nodesetval; if(xnodes != NULL && xnodes->nodeNr > 0) { xmlNodePtr xnode = xnodes->nodeTab[0]; xmlChar *value = xmlNodeListGetString(doc, xnode->xmlChildrenNode, 1); if(!strstr((char *)value, "Lightroom")) { xmlXPathFreeContext(xpathCtx); xmlXPathFreeObject(xpathObj); xmlFreeDoc(doc); xmlFree(value); if(!iauto) dt_control_log(_("`%s' not a lightroom XMP!"), pathname); g_free(pathname); return; } xmlFree(value); } else { xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); if(!iauto) dt_control_log(_("`%s' not a lightroom XMP!"), pathname); g_free(pathname); return; } xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); // Go safely to Description node if(entryNode) entryNode = entryNode->xmlChildrenNode; if(entryNode) entryNode = entryNode->next; if(entryNode) entryNode = entryNode->xmlChildrenNode; if(entryNode) entryNode = entryNode->next; if(!entryNode || xmlStrcmp(entryNode->name, (const xmlChar *)"Description")) { if(!iauto) dt_control_log(_("`%s' not a lightroom XMP!"), pathname); g_free(pathname); return; } g_free(pathname); // Look for attributes in the Description dt_iop_clipping_params_t pc; memset(&pc, 0, sizeof(pc)); gboolean has_crop = FALSE; dt_iop_flip_params_t pf; memset(&pf, 0, sizeof(pf)); gboolean has_flip = FALSE; dt_iop_exposure_params_t pe; memset(&pe, 0, sizeof(pe)); gboolean has_exposure = FALSE; dt_iop_vignette_params_t pv; memset(&pv, 0, sizeof(pv)); gboolean has_vignette = FALSE; dt_iop_grain_params_t pg; memset(&pg, 0, sizeof(pg)); gboolean has_grain = FALSE; dt_iop_spots_params_t ps; memset(&ps, 0, sizeof(ps)); gboolean has_spots = FALSE; typedef enum lr_curve_kind_t { linear = 0, medium_contrast = 1, string_contrast = 2, custom = 3 } lr_curve_kind_t; #define MAX_PTS 20 dt_iop_tonecurve_params_t ptc; memset(&ptc, 0, sizeof(ptc)); int ptc_value[4] = { 0, 0, 0, 0 }; float ptc_split[3] = { 0.0, 0.0, 0.0 }; lr_curve_kind_t curve_kind = linear; int curve_pts[MAX_PTS][2]; int n_pts = 0; dt_iop_colorzones_params_t pcz; memset(&pcz, 0, sizeof(pcz)); gboolean has_colorzones = FALSE; dt_iop_splittoning_params_t pst; memset(&pst, 0, sizeof(pst)); gboolean has_splittoning = FALSE; dt_iop_bilat_params_t pbl; memset(&pbl, 0, sizeof(pbl)); gboolean has_bilat = FALSE; gboolean has_tags = FALSE; int rating = 0; gboolean has_rating = FALSE; gdouble lat = 0, lon = 0; gboolean has_gps = FALSE; int color = 0; gboolean has_colorlabel = FALSE; float fratio = 0; // factor ratio image float crop_roundness = 0; // from lightroom int n_import = 0; // number of iop imported const float hfactor = 3.0 / 9.0; // hue factor adjustment (use 3 out of 9 boxes in colorzones) const float lfactor = 4.0 / 9.0; // lightness factor adjustment (use 4 out of 9 boxes in colorzones) int iwidth = 0, iheight = 0; // image width / height int orientation = 1; xmlAttr *attribute = entryNode->properties; while(attribute && attribute->name && attribute->children) { xmlChar *value = xmlNodeListGetString(entryNode->doc, attribute->children, 1); if(!xmlStrcmp(attribute->name, (const xmlChar *)"CropTop")) pc.cy = g_ascii_strtod((char *)value, NULL); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"CropRight")) pc.cw = g_ascii_strtod((char *)value, NULL); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"CropLeft")) pc.cx = g_ascii_strtod((char *)value, NULL); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"CropBottom")) pc.ch = g_ascii_strtod((char *)value, NULL); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"CropAngle")) pc.angle = -g_ascii_strtod((char *)value, NULL); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ImageWidth")) iwidth = atoi((char *)value); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ImageLength")) iheight = atoi((char *)value); else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Orientation")) { orientation = atoi((char *)value); if(dev != NULL && ((dev->image_storage.orientation == 6 && orientation != 6) || (dev->image_storage.orientation == 5 && orientation != 8) || (dev->image_storage.orientation == 0 && orientation != 1))) has_flip = TRUE; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HasCrop")) { if(!xmlStrcmp(value, (const xmlChar *)"True")) has_crop = TRUE; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Blacks2012")) { int v = atoi((char *)value); if(v != 0) { has_exposure = TRUE; pe.black = lr2dt_blacks((float)v); } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Exposure2012")) { float v = g_ascii_strtod((char *)value, NULL); if(v != 0.0) { has_exposure = TRUE; pe.exposure = lr2dt_exposure(v); } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"PostCropVignetteAmount")) { int v = atoi((char *)value); if(v != 0) { has_vignette = TRUE; pv.brightness = lr2dt_vignette_gain((float)v); } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"PostCropVignetteMidpoint")) { int v = atoi((char *)value); pv.scale = lr2dt_vignette_midpoint((float)v); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"PostCropVignetteStyle")) { int v = atoi((char *)value); if(v == 1) // Highlight Priority pv.saturation = -0.300; else // Color Priority & Paint Overlay pv.saturation = -0.200; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"PostCropVignetteFeather")) { int v = atoi((char *)value); if(v != 0) pv.falloff_scale = (float)v; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"PostCropVignetteRoundness")) { int v = atoi((char *)value); crop_roundness = (float)v; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"GrainAmount")) { int v = atoi((char *)value); if(v != 0) { has_grain = TRUE; pg.strength = lr2dt_grain_amount((float)v); } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"GrainFrequency")) { int v = atoi((char *)value); if(v != 0) pg.scale = lr2dt_grain_frequency((float)v); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricShadows")) { ptc_value[0] = atoi((char *)value); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricDarks")) { ptc_value[1] = atoi((char *)value); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricLights")) { ptc_value[2] = atoi((char *)value); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricHighlights")) { ptc_value[3] = atoi((char *)value); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricShadowSplit")) { ptc_split[0] = g_ascii_strtod((char *)value, NULL) / 100.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricMidtoneSplit")) { ptc_split[1] = g_ascii_strtod((char *)value, NULL) / 100.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ParametricHighlightSplit")) { ptc_split[2] = g_ascii_strtod((char *)value, NULL) / 100.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"ToneCurveName2012")) { if(!xmlStrcmp(value, (const xmlChar *)"Linear")) curve_kind = linear; else if(!xmlStrcmp(value, (const xmlChar *)"Medium Contrast")) curve_kind = medium_contrast; else if(!xmlStrcmp(value, (const xmlChar *)"Strong Contrast")) curve_kind = medium_contrast; else if(!xmlStrcmp(value, (const xmlChar *)"Custom")) curve_kind = custom; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentRed")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][0] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentOrange")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][1] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentYellow")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][2] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentGreen")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][3] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentAqua")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][4] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentBlue")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][5] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentPurple")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][6] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SaturationAdjustmentMagenta")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[1][7] = 0.5 + (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentRed")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][0] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentOrange")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][1] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentYellow")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][2] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentGreen")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][3] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentAqua")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][4] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentBlue")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][5] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentPurple")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][6] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"LuminanceAdjustmentMagenta")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[0][7] = 0.5 + lfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentRed")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][0] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentOrange")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][1] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentYellow")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][2] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentGreen")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][3] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentAqua")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][4] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentBlue")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][5] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentPurple")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][6] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"HueAdjustmentMagenta")) { int v = atoi((char *)value); if(v != 0) has_colorzones = TRUE; pcz.equalizer_y[2][7] = 0.5 + hfactor * (float)v / 200.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SplitToningShawowHue")) { int v = atoi((char *)value); if(v != 0) has_splittoning = TRUE; pst.shadow_hue = (float)v / 255.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SplitToningShawowSaturation")) { int v = atoi((char *)value); if(v != 0) has_splittoning = TRUE; pst.shadow_saturation = (float)v / 100.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SplitToningHighlightHue")) { int v = atoi((char *)value); if(v != 0) has_splittoning = TRUE; pst.highlight_hue = (float)v / 255.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SplitToningHighlightSaturation")) { int v = atoi((char *)value); if(v != 0) has_splittoning = TRUE; pst.highlight_saturation = (float)v / 100.0; } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"SplitToningBalance")) { float v = g_ascii_strtod((char *)value, NULL); pst.balance = lr2dt_splittoning_balance(v); } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Clarity2012")) { int v = atoi((char *)value); if(v != 0) { has_bilat = TRUE; pbl.detail = lr2dt_clarity((float)v); } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Rating")) { int v = atoi((char *)value); if(v != 0) { rating = v; has_rating = TRUE; } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"GPSLatitude")) { int deg; double msec; char d; if(sscanf((const char *)value, "%d,%lf%c", °, &msec, &d)) { lat = deg + msec / 60.0; if(d == 'S') lat = -lat; has_gps = TRUE; } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"GPSLongitude")) { int deg; double msec; char d; if(sscanf((const char *)value, "%d,%lf%c", °, &msec, &d)) { lon = deg + msec / 60.0; if(d == 'W') lon = -lon; has_gps = TRUE; } } else if(!xmlStrcmp(attribute->name, (const xmlChar *)"Label")) { for(int i = 0; value[i]; i++) value[i] = tolower(value[i]); if(!strcmp((char *)value, _("red"))) color = 0; else if(!strcmp((char *)value, _("yellow"))) color = 1; else if(!strcmp((char *)value, _("green"))) color = 2; else if(!strcmp((char *)value, _("blue"))) color = 3; else // just an else here to catch all other cases as on lightroom one can // change the names of labels. So purple and the user's defined labels // will be mapped to purple on darktable. color = 4; has_colorlabel = TRUE; } xmlFree(value); attribute = attribute->next; } // Look for tags (subject/Bag/* and RetouchInfo/seq/*) entryNode = entryNode->xmlChildrenNode; if(entryNode) entryNode = entryNode->next; while(entryNode) { if(dev == NULL && (!xmlStrcmp(entryNode->name, (const xmlChar *)"subject") || !xmlStrcmp(entryNode->name, (const xmlChar *)"hierarchicalSubject"))) { xmlNodePtr tagNode = entryNode; tagNode = tagNode->xmlChildrenNode; tagNode = tagNode->next; tagNode = tagNode->xmlChildrenNode; tagNode = tagNode->next; while(tagNode) { if(!xmlStrcmp(tagNode->name, (const xmlChar *)"li")) { xmlChar *value = xmlNodeListGetString(doc, tagNode->xmlChildrenNode, 1); guint tagid = 0; if(!dt_tag_exists((char *)value, &tagid)) dt_tag_new((char *)value, &tagid); dt_tag_attach(tagid, imgid); has_tags = TRUE; xmlFree(value); } tagNode = tagNode->next; } } else if(dev != NULL && !xmlStrcmp(entryNode->name, (const xmlChar *)"RetouchInfo")) { xmlNodePtr riNode = entryNode; riNode = riNode->xmlChildrenNode; riNode = riNode->next; riNode = riNode->xmlChildrenNode; riNode = riNode->next; while(riNode) { if(!xmlStrcmp(riNode->name, (const xmlChar *)"li")) { xmlChar *value = xmlNodeListGetString(doc, riNode->xmlChildrenNode, 1); spot_t *p = &ps.spot[ps.num_spots]; if(sscanf((const char *)value, "centerX = %f, centerY = %f, radius = %f, sourceState = %*[a-zA-Z], " "sourceX = %f, sourceY = %f", &(p->x), &(p->y), &(p->radius), &(p->xc), &(p->yc))) { ps.num_spots++; has_spots = TRUE; } xmlFree(value); } if(ps.num_spots == MAX_SPOTS) break; riNode = riNode->next; } } else if(dev != NULL && !xmlStrcmp(entryNode->name, (const xmlChar *)"ToneCurvePV2012")) { xmlNodePtr tcNode = entryNode; tcNode = tcNode->xmlChildrenNode; tcNode = tcNode->next; tcNode = tcNode->xmlChildrenNode; tcNode = tcNode->next; while(tcNode) { if(!xmlStrcmp(tcNode->name, (const xmlChar *)"li")) { xmlChar *value = xmlNodeListGetString(doc, tcNode->xmlChildrenNode, 1); if(sscanf((const char *)value, "%d, %d", &(curve_pts[n_pts][0]), &(curve_pts[n_pts][1]))) n_pts++; xmlFree(value); } if(n_pts == MAX_PTS) break; tcNode = tcNode->next; } } entryNode = entryNode->next; } xmlFreeDoc(doc); // Integrates into the history all the imported iop if(dev != NULL && dt_image_is_raw(&dev->image_storage)) { // set colorin to cmatrix which is the default from Adobe (so closer to what Lightroom does) dt_iop_colorin_params_t pci = (dt_iop_colorin_params_t){ "cmatrix", DT_INTENT_PERCEPTUAL }; dt_add_hist(imgid, "colorin", (dt_iop_params_t *)&pci, sizeof(dt_iop_colorin_params_t), imported, sizeof(imported), LRDT_COLORIN_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_crop) { pc.k_sym = 0; pc.k_apply = 0; pc.crop_auto = 0; pc.k_h = pc.k_v = 0; pc.k_type = 0; pc.kxa = pc.kxd = 0.2f; pc.kxc = pc.kxb = 0.8f; pc.kya = pc.kyb = 0.2f; pc.kyc = pc.kyd = 0.8f; float tmp; if(has_crop) { // adjust crop data according to the rotation switch(dev->image_storage.orientation) { case 5: // portrait - counter-clockwise tmp = pc.ch; pc.ch = 1.0 - pc.cx; pc.cx = pc.cy; pc.cy = 1.0 - pc.cw; pc.cw = tmp; break; case 6: // portrait - clockwise tmp = pc.ch; pc.ch = pc.cw; pc.cw = 1.0 - pc.cy; pc.cy = pc.cx; pc.cx = 1.0 - tmp; break; default: break; } if(pc.angle != 0) { const float rangle = -pc.angle * (3.141592 / 180); float x, y; // do the rotation (rangle) using center of image (0.5, 0.5) x = pc.cx - 0.5; y = 0.5 - pc.cy; pc.cx = 0.5 + x * cos(rangle) - y * sin(rangle); pc.cy = 0.5 - (x * sin(rangle) + y * cos(rangle)); x = pc.cw - 0.5; y = 0.5 - pc.ch; pc.cw = 0.5 + x * cos(rangle) - y * sin(rangle); pc.ch = 0.5 - (x * sin(rangle) + y * cos(rangle)); } } else { pc.angle = 0; pc.cx = 0; pc.cy = 0; pc.cw = 1; pc.ch = 1; } fratio = (pc.cw - pc.cx) / (pc.ch - pc.cy); dt_add_hist(imgid, "clipping", (dt_iop_params_t *)&pc, sizeof(dt_iop_clipping_params_t), imported, sizeof(imported), LRDT_CLIPPING_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_flip) { pf.orientation = 0; if(dev->image_storage.orientation == 5) // portrait switch(orientation) { case 8: pf.orientation = 0; break; case 3: pf.orientation = 5; break; case 6: pf.orientation = 3; break; case 1: pf.orientation = 6; break; // with horizontal flip case 7: pf.orientation = 1; break; case 2: pf.orientation = 4; break; case 5: pf.orientation = 2; break; case 4: pf.orientation = 7; break; } else if(dev->image_storage.orientation == 6) // portrait switch(orientation) { case 8: pf.orientation = 3; break; case 3: pf.orientation = 6; break; case 6: pf.orientation = 0; break; case 1: pf.orientation = 5; break; // with horizontal flip case 7: pf.orientation = 2; break; case 2: pf.orientation = 7; break; case 5: pf.orientation = 1; break; case 4: pf.orientation = 4; break; } else // landscape switch(orientation) { case 8: pf.orientation = 5; break; case 3: pf.orientation = 3; break; case 6: pf.orientation = 6; break; case 1: pf.orientation = 0; break; // with horizontal flip case 7: pf.orientation = 7; break; case 2: pf.orientation = 1; break; case 5: pf.orientation = 4; break; case 4: pf.orientation = 2; break; } dt_add_hist(imgid, "flip", (dt_iop_params_t *)&pf, sizeof(dt_iop_flip_params_t), imported, sizeof(imported), LRDT_FLIP_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_exposure) { dt_add_hist(imgid, "exposure", (dt_iop_params_t *)&pe, sizeof(dt_iop_exposure_params_t), imported, sizeof(imported), LRDT_EXPOSURE_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_grain) { pg.channel = 0; dt_add_hist(imgid, "grain", (dt_iop_params_t *)&pg, sizeof(dt_iop_grain_params_t), imported, sizeof(imported), LRDT_GRAIN_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_vignette) { const float base_ratio = 1.325 / 1.5; pv.autoratio = FALSE; pv.dithering = DITHER_8BIT; pv.center.x = 0.0; pv.center.y = 0.0; pv.shape = 1.0; // defensive code, should not happen, but just in case future Lr version // has not ImageWidth/ImageLength XML tag. if(iwidth == 0 || iheight == 0) pv.whratio = base_ratio; else pv.whratio = base_ratio * ((float)iwidth / (float)iheight); if(has_crop) pv.whratio = pv.whratio * fratio; // Adjust scale and ratio based on the roundness. On Lightroom changing // the roundness change the width and the height of the vignette. if(crop_roundness > 0) { float newratio = pv.whratio - (pv.whratio - 1) * (crop_roundness / 100.0); float dscale = (1 - (newratio / pv.whratio)) / 2.0; pv.scale -= dscale * 100.0; pv.whratio = newratio; } dt_add_hist(imgid, "vignette", (dt_iop_params_t *)&pv, sizeof(dt_iop_vignette_params_t), imported, sizeof(imported), LRDT_VIGNETTE_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_spots) { // Check for orientation, rotate when in portrait mode if(orientation > 4) for(int k = 0; k < ps.num_spots; k++) { float tmp = ps.spot[k].y; ps.spot[k].y = 1.0 - ps.spot[k].x; ps.spot[k].x = tmp; tmp = ps.spot[k].yc; ps.spot[k].yc = 1.0 - ps.spot[k].xc; ps.spot[k].xc = tmp; } dt_add_hist(imgid, "spots", (dt_iop_params_t *)&ps, sizeof(dt_iop_spots_params_t), imported, sizeof(imported), LRDT_SPOTS_VERSION, &n_import); refresh_needed = TRUE; } if(curve_kind != linear || ptc_value[0] != 0 || ptc_value[1] != 0 || ptc_value[2] != 0 || ptc_value[3] != 0) { ptc.tonecurve_nodes[ch_L] = 6; ptc.tonecurve_nodes[ch_a] = 7; ptc.tonecurve_nodes[ch_b] = 7; ptc.tonecurve_type[ch_L] = CUBIC_SPLINE; ptc.tonecurve_type[ch_a] = CUBIC_SPLINE; ptc.tonecurve_type[ch_b] = CUBIC_SPLINE; ptc.tonecurve_autoscale_ab = 1; ptc.tonecurve_preset = 0; float linear_ab[7] = { 0.0, 0.08, 0.3, 0.5, 0.7, 0.92, 1.0 }; // linear a, b curves for(int k = 0; k < 7; k++) ptc.tonecurve[ch_a][k].x = linear_ab[k]; for(int k = 0; k < 7; k++) ptc.tonecurve[ch_a][k].y = linear_ab[k]; for(int k = 0; k < 7; k++) ptc.tonecurve[ch_b][k].x = linear_ab[k]; for(int k = 0; k < 7; k++) ptc.tonecurve[ch_b][k].y = linear_ab[k]; // Set the base tonecurve if(curve_kind == linear) { ptc.tonecurve[ch_L][0].x = 0.0; ptc.tonecurve[ch_L][0].y = 0.0; ptc.tonecurve[ch_L][1].x = ptc_split[0] / 2.0; ptc.tonecurve[ch_L][1].y = ptc_split[0] / 2.0; ptc.tonecurve[ch_L][2].x = ptc_split[1] - (ptc_split[1] - ptc_split[0]) / 2.0; ptc.tonecurve[ch_L][2].y = ptc_split[1] - (ptc_split[1] - ptc_split[0]) / 2.0; ptc.tonecurve[ch_L][3].x = ptc_split[1] + (ptc_split[2] - ptc_split[1]) / 2.0; ptc.tonecurve[ch_L][3].y = ptc_split[1] + (ptc_split[2] - ptc_split[1]) / 2.0; ptc.tonecurve[ch_L][4].x = ptc_split[2] + (1.0 - ptc_split[2]) / 2.0; ptc.tonecurve[ch_L][4].y = ptc_split[2] + (1.0 - ptc_split[2]) / 2.0; ptc.tonecurve[ch_L][5].x = 1.0; ptc.tonecurve[ch_L][5].y = 1.0; } else { for(int k = 0; k < 6; k++) { ptc.tonecurve[ch_L][k].x = curve_pts[k][0] / 255.0; ptc.tonecurve[ch_L][k].y = curve_pts[k][1] / 255.0; } } if(curve_kind != custom) { // set shadows/darks/lights/highlight adjustments ptc.tonecurve[ch_L][1].y += ptc.tonecurve[ch_L][1].y * ((float)ptc_value[0] / 100.0); ptc.tonecurve[ch_L][2].y += ptc.tonecurve[ch_L][1].y * ((float)ptc_value[1] / 100.0); ptc.tonecurve[ch_L][3].y += ptc.tonecurve[ch_L][1].y * ((float)ptc_value[2] / 100.0); ptc.tonecurve[ch_L][4].y += ptc.tonecurve[ch_L][1].y * ((float)ptc_value[3] / 100.0); if(ptc.tonecurve[ch_L][1].y > ptc.tonecurve[ch_L][2].y) ptc.tonecurve[ch_L][1].y = ptc.tonecurve[ch_L][2].y; if(ptc.tonecurve[ch_L][3].y > ptc.tonecurve[ch_L][4].y) ptc.tonecurve[ch_L][4].y = ptc.tonecurve[ch_L][3].y; } dt_add_hist(imgid, "tonecurve", (dt_iop_params_t *)&ptc, sizeof(dt_iop_tonecurve_params_t), imported, sizeof(imported), LRDT_TONECURVE_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_colorzones) { pcz.channel = DT_IOP_COLORZONES_h; for(int i = 0; i < 3; i++) for(int k = 0; k < 8; k++) pcz.equalizer_x[i][k] = k / (DT_IOP_COLORZONES_BANDS - 1.0); dt_add_hist(imgid, "colorzones", (dt_iop_params_t *)&pcz, sizeof(dt_iop_colorzones_params_t), imported, sizeof(imported), LRDT_COLORZONES_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_splittoning) { pst.compress = 50.0; dt_add_hist(imgid, "splittoning", (dt_iop_params_t *)&pst, sizeof(dt_iop_splittoning_params_t), imported, sizeof(imported), LRDT_SPLITTONING_VERSION, &n_import); refresh_needed = TRUE; } if(dev != NULL && has_bilat) { pbl.sigma_r = 100.0; pbl.sigma_s = 100.0; dt_add_hist(imgid, "bilat", (dt_iop_params_t *)&pbl, sizeof(dt_iop_bilat_params_t), imported, sizeof(imported), LRDT_BILAT_VERSION, &n_import); refresh_needed = TRUE; } if(has_tags) { if(imported[0]) g_strlcat(imported, ", ", sizeof(imported)); g_strlcat(imported, _("tags"), sizeof(imported)); n_import++; } if(dev == NULL && has_rating) { dt_ratings_apply_to_image(imgid, rating); if(imported[0]) g_strlcat(imported, ", ", sizeof(imported)); g_strlcat(imported, _("rating"), sizeof(imported)); n_import++; } if(dev == NULL && has_gps) { dt_image_set_location(imgid, lon, lat); if(imported[0]) g_strlcat(imported, ", ", sizeof(imported)); g_strlcat(imported, _("geotagging"), sizeof(imported)); n_import++; } if(dev == NULL && has_colorlabel) { dt_colorlabels_set_label(imgid, color); if(imported[0]) g_strlcat(imported, ", ", sizeof(imported)); g_strlcat(imported, _("color label"), sizeof(imported)); n_import++; } if(dev != NULL && refresh_needed && dev->gui_attached) { char message[512]; g_snprintf(message, sizeof(message), ngettext("%s has been imported", "%s have been imported", n_import), imported); dt_control_log(message); if(!iauto) { /* signal history changed */ dt_dev_reload_history_items(dev); dt_dev_modulegroups_set(darktable.develop, dt_dev_modulegroups_get(darktable.develop)); /* update xmp file */ dt_image_synch_xmp(imgid); dt_control_signal_raise(darktable.signals, DT_SIGNAL_DEVELOP_HISTORY_CHANGE); } } }
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece) { dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)p1; dt_iop_exposure_data_t *d = (dt_iop_exposure_data_t *)piece->data; dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; d->black = p->black; d->exposure = p->exposure; piece->request_histogram &= ~(DT_REQUEST_ON); piece->request_histogram |= (DT_REQUEST_ONLY_IN_GUI); d->deflicker_percentile = p->deflicker_percentile; d->deflicker_target_level = p->deflicker_target_level; if(p->mode == EXPOSURE_MODE_DEFLICKER && dt_image_is_raw(&self->dev->image_storage)) { if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE) { if(g) { // histogram is precomputed and cached compute_correction(self, piece, g->deflicker_histogram, &g->deflicker_histogram_stats, &d->exposure); } else { uint32_t *histogram = NULL; dt_dev_histogram_stats_t histogram_stats; deflicker_prepare_histogram(self, &histogram, &histogram_stats); compute_correction(self, piece, histogram, &histogram_stats, &d->exposure); free(histogram); } d->mode = EXPOSURE_MODE_MANUAL; } else { if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL) { d->mode = EXPOSURE_MODE_DEFLICKER; piece->request_histogram |= (DT_REQUEST_ON); if(!self->dev->gui_attached) piece->request_histogram &= ~(DT_REQUEST_ONLY_IN_GUI); piece->histogram_params.bins_count = 16384; /* * in principle, we do not need/want histogram in FULL pipe * because we will use histogram from preview pipe there, * but it might happen that for some reasons we do not have * histogram of preview pipe yet - e.g. on first pipe run * (just after setting mode to automatic) */ d->exposure = NAN; // commit_params_late() will compute exposure later } } } else { d->mode = EXPOSURE_MODE_MANUAL; } }
void reload_defaults(dt_iop_module_t *module) { // raw images need wb (to convert from uint16_t to float): if(dt_image_is_raw(&module->dev->image_storage)) { module->default_enabled = 1; module->hide_enable_button = 1; } else module->default_enabled = 0; dt_iop_temperature_params_t tmp = (dt_iop_temperature_params_t) { 5000.0, {1.0, 1.0, 1.0} }; // get white balance coefficients, as shot char filename[DT_MAX_PATH_LEN]; int ret=0; /* check if file is raw / hdr */ if(dt_image_is_raw(&module->dev->image_storage)) { gboolean from_cache = TRUE; dt_image_full_path(module->dev->image_storage.id, filename, DT_MAX_PATH_LEN, &from_cache); libraw_data_t *raw = libraw_init(0); ret = libraw_open_file(raw, filename); if(!ret) { module->default_enabled = 1; for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.cam_mul[k]; if(tmp.coeffs[0] <= 0.0) { for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.pre_mul[k]; } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // could not get useful info, try presets: char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model)) { // just take the first preset we find for this camera for(int k=0; k<3; k++) tmp.coeffs[k] = wb_preset[i].channel[k]; break; } } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // final security net: hardcoded default that fits most cams. tmp.coeffs[0] = 2.0f; tmp.coeffs[1] = 1.0f; tmp.coeffs[2] = 1.5f; } } else { tmp.coeffs[0] /= tmp.coeffs[1]; tmp.coeffs[2] /= tmp.coeffs[1]; tmp.coeffs[1] = 1.0f; } // remember daylight wb used for temperature/tint conversion, // assuming it corresponds to CIE daylight (D65) if(module->gui_data) { dt_iop_temperature_gui_data_t *g = (dt_iop_temperature_gui_data_t *)module->gui_data; for(int c = 0; c < 3; c++) g->daylight_wb[c] = raw->color.pre_mul[c]; if(g->daylight_wb[0] == 1.0f && g->daylight_wb[1] == 1.0f && g->daylight_wb[2] == 1.0f) { // if we didn't find anything for daylight wb, look for a wb preset with appropriate name. // we're normalising that to be D65 char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model) && !strncasecmp(wb_preset[i].name, "daylight", 8)) { for(int k=0; k<3; k++) g->daylight_wb[k] = wb_preset[i].channel[k]; break; } } } float temp, tint, mul[3]; for(int k=0; k<3; k++) mul[k] = g->daylight_wb[k]/tmp.coeffs[k]; convert_rgb_to_k(mul, &temp, &tint); dt_bauhaus_slider_set_default(g->scale_k, temp); dt_bauhaus_slider_set_default(g->scale_tint, tint); } } libraw_close(raw); } memcpy(module->params, &tmp, sizeof(dt_iop_temperature_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_temperature_params_t)); }
void reload_defaults(dt_iop_module_t *module) { // raw images need wb (to convert from uint16_t to float): if(dt_image_is_raw(&module->dev->image_storage)) { module->default_enabled = 1; module->hide_enable_button = 1; } else module->default_enabled = 0; dt_iop_temperature_params_t tmp = (dt_iop_temperature_params_t) { 5000.0, {1.0, 1.0, 1.0} }; // get white balance coefficients, as shot char filename[DT_MAX_PATH_LEN]; int ret=0; /* check if file is raw / hdr */ if(dt_image_is_raw(&module->dev->image_storage)) { dt_image_full_path(module->dev->image_storage.id, filename, DT_MAX_PATH_LEN); libraw_data_t *raw = libraw_init(0); ret = libraw_open_file(raw, filename); if(!ret) { module->default_enabled = 1; for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.cam_mul[k]; if(tmp.coeffs[0] <= 0.0) { for(int k=0; k<3; k++) tmp.coeffs[k] = raw->color.pre_mul[k]; } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // could not get useful info, try presets: char makermodel[1024]; char *model = makermodel; dt_colorspaces_get_makermodel_split(makermodel, 1024, &model, module->dev->image_storage.exif_maker, module->dev->image_storage.exif_model); for(int i=0; i<wb_preset_count; i++) { if(!strcmp(wb_preset[i].make, makermodel) && !strcmp(wb_preset[i].model, model)) { // just take the first preset we find for this camera for(int k=0; k<3; k++) tmp.coeffs[k] = wb_preset[i].channel[k]; break; } } if(tmp.coeffs[0] == 0 || tmp.coeffs[1] == 0 || tmp.coeffs[2] == 0) { // final security net: hardcoded default that fits most cams. tmp.coeffs[0] = 2.0f; tmp.coeffs[1] = 1.0f; tmp.coeffs[2] = 1.5f; } } else { tmp.coeffs[0] /= tmp.coeffs[1]; tmp.coeffs[2] /= tmp.coeffs[1]; tmp.coeffs[1] = 1.0f; } } libraw_close(raw); } memcpy(module->params, &tmp, sizeof(dt_iop_temperature_params_t)); memcpy(module->default_params, &tmp, sizeof(dt_iop_temperature_params_t)); }
void commit_params (struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece) { dt_iop_exposure_params_t *p = (dt_iop_exposure_params_t *)p1; dt_iop_exposure_data_t *d = (dt_iop_exposure_data_t *)piece->data; dt_iop_exposure_gui_data_t *g = (dt_iop_exposure_gui_data_t *)self->gui_data; d->black = p->black; d->exposure = p->exposure; self->request_histogram &= ~(DT_REQUEST_ON); self->request_histogram |= (DT_REQUEST_ONLY_IN_GUI); self->request_histogram_source = (DT_DEV_PIXELPIPE_PREVIEW); if(self->dev->gui_attached) { g->reprocess_on_next_expose = FALSE; } gboolean histogram_is_good = ((self->histogram_stats.bins_count == 16384) && (self->histogram != NULL)); d->deflicker_percentile = p->deflicker_percentile; d->deflicker_target_level = p->deflicker_target_level; if(p->mode == EXPOSURE_MODE_DEFLICKER && dt_image_is_raw(&self->dev->image_storage)) { if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_SOURCEFILE) { if(self->dev->gui_attached) { // histogram is precomputed and cached compute_correction(self, piece, g->deflicker_histogram, &g->deflicker_histogram_stats, &d->exposure); } else { uint32_t *histogram = NULL; dt_dev_histogram_stats_t histogram_stats; deflicker_prepare_histogram(self, &histogram, &histogram_stats); compute_correction(self, piece, histogram, &histogram_stats, &d->exposure); free(histogram); } d->mode = EXPOSURE_MODE_MANUAL; } else { if(p->deflicker_histogram_source == DEFLICKER_HISTOGRAM_SOURCE_THUMBNAIL) { self->request_histogram |= (DT_REQUEST_ON); gboolean failed = !histogram_is_good; if(self->dev->gui_attached && histogram_is_good) { /* * if in GUI, user might zoomed main view => we would get histogram of * only part of image, so if in GUI we must always use histogram of * preview pipe, which is always full-size and have biggest size */ d->mode = EXPOSURE_MODE_DEFLICKER; commit_params_late(self, piece); d->mode = EXPOSURE_MODE_MANUAL; if(isnan(d->exposure)) failed = TRUE; } else if(failed || !(self->dev->gui_attached && histogram_is_good)) { d->mode = EXPOSURE_MODE_DEFLICKER; //commit_params_late() will compute correct d->exposure later self->request_histogram &= ~(DT_REQUEST_ONLY_IN_GUI); self->request_histogram_source = (DT_DEV_PIXELPIPE_ANY); if(failed && self->dev->gui_attached) { /* * but sadly we do not yet have a histogram to do so, so this time * we process asif not in gui, and in expose() immediately * reprocess, thus everything works as expected */ g->reprocess_on_next_expose = TRUE; } } } } } else { d->mode = EXPOSURE_MODE_MANUAL; } }
static void dt_gui_presets_popup_menu_show_internal(dt_dev_operation_t op, int32_t version, dt_iop_params_t *params, int32_t params_size, dt_develop_blend_params_t *bl_params, dt_iop_module_t *module, const dt_image_t *image, void (*pick_callback)(GtkMenuItem *, void *), void *callback_data) { GtkMenu *menu = darktable.gui->presets_popup_menu; if(menu) gtk_widget_destroy(GTK_WIDGET(menu)); darktable.gui->presets_popup_menu = GTK_MENU(gtk_menu_new()); menu = darktable.gui->presets_popup_menu; GtkWidget *mi; int active_preset = -1, cnt = 0, writeprotect = 0; //, selected_default = 0; sqlite3_stmt *stmt; // order: get shipped defaults first if(image) { // only matching if filter is on: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, description, blendop_params, " "op_version, enabled from presets where operation=?1 and " "(filter=0 or ( " "((?2 like model and ?3 like maker) or (?4 like model and ?5 like maker)) and " "?6 like lens and " "?7 between iso_min and iso_max and " "?8 between exposure_min and exposure_max and " "?9 between aperture_min and aperture_max and " "?10 between focal_length_min and focal_length_max and " "(format = 0 or format&?9!=0)" " ) )" "order by writeprotect desc, lower(name), rowid", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, image->exif_model, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, image->exif_maker, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, image->camera_alias, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 5, image->camera_maker, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 6, image->exif_lens, -1, SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, image->exif_iso); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, image->exif_exposure); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, image->exif_aperture); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 10, image->exif_focal_length); int ldr = dt_image_is_ldr(image) ? FOR_LDR : (dt_image_is_raw(image) ? FOR_RAW : FOR_HDR); DT_DEBUG_SQLITE3_BIND_INT(stmt, 9, ldr); } else { // don't know for which image. show all we got: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select name, op_params, writeprotect, " "description, blendop_params, op_version, " "enabled from presets where operation=?1 " "order by writeprotect desc, lower(name), rowid", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 1, op, -1, SQLITE_TRANSIENT); } // collect all presets for op from db int found = 0; while(sqlite3_step(stmt) == SQLITE_ROW) { void *op_params = (void *)sqlite3_column_blob(stmt, 1); int32_t op_params_size = sqlite3_column_bytes(stmt, 1); void *blendop_params = (void *)sqlite3_column_blob(stmt, 4); int32_t bl_params_size = sqlite3_column_bytes(stmt, 4); int32_t preset_version = sqlite3_column_int(stmt, 5); int32_t enabled = sqlite3_column_int(stmt, 6); int32_t isdefault = 0; int32_t isdisabled = (preset_version == version ? 0 : 1); const char *name = (char *)sqlite3_column_text(stmt, 0); if(darktable.gui->last_preset && strcmp(darktable.gui->last_preset, name) == 0) found = 1; if(module && !memcmp(module->default_params, op_params, MIN(op_params_size, module->params_size)) && !memcmp(module->default_blendop_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t)))) isdefault = 1; if(module && !memcmp(params, op_params, MIN(op_params_size, params_size)) && !memcmp(bl_params, blendop_params, MIN(bl_params_size, sizeof(dt_develop_blend_params_t))) && module->enabled == enabled) { active_preset = cnt; writeprotect = sqlite3_column_int(stmt, 2); char *markup; mi = gtk_menu_item_new_with_label(""); if(isdefault) { markup = g_markup_printf_escaped("<span weight=\"bold\">%s %s</span>", name, _("(default)")); } else markup = g_markup_printf_escaped("<span weight=\"bold\">%s</span>", name); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_free(markup); } else { if(isdefault) { char *markup; mi = gtk_menu_item_new_with_label(""); markup = g_markup_printf_escaped("%s %s", name, _("(default)")); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_free(markup); } else mi = gtk_menu_item_new_with_label((const char *)name); } if(isdisabled) { gtk_widget_set_sensitive(mi, 0); gtk_widget_set_tooltip_text(mi, _("disabled: wrong module version")); } else { if(module) g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_pick_preset), module); else if(pick_callback) g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(pick_callback), callback_data); gtk_widget_set_tooltip_text(mi, (const char *)sqlite3_column_text(stmt, 3)); } gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); cnt++; } sqlite3_finalize(stmt); if(cnt > 0) gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); if(module) { if(active_preset >= 0 && !writeprotect) { mi = gtk_menu_item_new_with_label(_("edit this preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_edit_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); mi = gtk_menu_item_new_with_label(_("delete this preset")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_delete_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); } else { mi = gtk_menu_item_new_with_label(_("store new preset..")); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_new_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); if(darktable.gui->last_preset && found) { char *markup = g_markup_printf_escaped("%s <span weight=\"bold\">%s</span>", _("update preset"), darktable.gui->last_preset); mi = gtk_menu_item_new_with_label(""); gtk_label_set_markup(GTK_LABEL(gtk_bin_get_child(GTK_BIN(mi))), markup); g_signal_connect(G_OBJECT(mi), "activate", G_CALLBACK(menuitem_update_preset), module); gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi); g_free(markup); } } } }