void dt_image_cache_init(dt_image_cache_t *cache) { // the image cache does no serialization. // (unsafe. data should be in db/xmp, not in any other additional cache, // also, it should be relatively fast to get the image_t structs from sql.) // TODO: actually an independent conf var? // too large: dangerous and wasteful? // can we get away with a fixed size? const uint32_t max_mem = 50*1024*1024; uint32_t num = (uint32_t)(1.5f*max_mem/sizeof(dt_image_t)); dt_cache_init(&cache->cache, num, 16, 64, max_mem); dt_cache_set_allocate_callback(&cache->cache, &dt_image_cache_allocate, cache); dt_cache_set_cleanup_callback (&cache->cache, &dt_image_cache_deallocate, cache); // might have been rounded to power of two: num = dt_cache_capacity(&cache->cache); cache->images = dt_alloc_align(64, sizeof(dt_image_t)*num); dt_print(DT_DEBUG_CACHE, "[image_cache] has %d entries\n", num); // initialize first image as empty data: dt_image_init(cache->images); for(uint32_t k=1; k<num; k++) { // optimized initialization (avoid accessing conf): memcpy(cache->images + k, cache->images, sizeof(dt_image_t)); } }
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached) { memset(dev,0,sizeof(dt_develop_t)); dev->preview_downsampling = 1.0f; dev->gui_module = NULL; dev->timestamp = 0; dev->average_delay = DT_DEV_AVERAGE_DELAY_START; dev->preview_average_delay = DT_DEV_PREVIEW_AVERAGE_DELAY_START; dev->gui_leaving = 0; dev->gui_synch = 0; dt_pthread_mutex_init(&dev->history_mutex, NULL); dev->history_end = 0; dev->history = NULL; // empty list dev->gui_attached = gui_attached; dev->width = -1; dev->height = -1; dt_image_init(&dev->image_storage); dev->image_dirty = dev->preview_dirty = 1; dev->image_loading = dev->preview_loading = 0; dev->image_force_reload = 0; dev->preview_input_changed = 0; dev->pipe = dev->preview_pipe = NULL; dev->histogram = NULL; dev->histogram_pre_tonecurve = NULL; dev->histogram_pre_levels = NULL; if(g_strcmp0(dt_conf_get_string("plugins/darkroom/histogram/mode"), "linear") == 0) dev->histogram_linear = TRUE; else dev->histogram_linear = FALSE; if(dev->gui_attached) { dev->pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dev->preview_pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dt_dev_pixelpipe_init(dev->pipe); dt_dev_pixelpipe_init_preview(dev->preview_pipe); dev->histogram = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_tonecurve = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_levels = (float*)malloc(sizeof(float) * 4 * 256); memset(dev->histogram, 0, sizeof(float)*256*4); memset(dev->histogram_pre_tonecurve, 0, sizeof(float)*256*4); memset(dev->histogram_pre_levels, 0, sizeof(float)*256*4); dev->histogram_max = -1; dev->histogram_pre_tonecurve_max = -1; dev->histogram_pre_levels_max = -1; } dev->iop_instance = 0; dev->iop = NULL; dev->overexposed.enabled = FALSE; dev->overexposed.colorscheme = dt_conf_get_int("darkroom/ui/overexposed/colorscheme"); dev->overexposed.lower = dt_conf_get_int("darkroom/ui/overexposed/lower"); dev->overexposed.upper = dt_conf_get_int("darkroom/ui/overexposed/upper"); }
void dt_image_cache_deallocate(void *data, const uint32_t key, void *payload) { // don't free. memory is only allocated once. dt_image_t *img = (dt_image_t *)payload; // but reset all the stuff. not strictly necessary, but experience tells // it might be best to make sure star ratings and such don't spill. // // note that no flushing to xmp takes place here, it is only done // when write_release is called. dt_image_init(img); }
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached) { memset(dev,0,sizeof(dt_develop_t)); dev->preview_downsampling = 1.0f; dev->gui_module = NULL; dev->timestamp = 0; dev->gui_leaving = 0; dev->gui_synch = 0; dt_pthread_mutex_init(&dev->history_mutex, NULL); dev->history_end = 0; dev->history = NULL; // empty list dev->gui_attached = gui_attached; dev->width = -1; dev->height = -1; dt_image_init(&dev->image_storage); dev->image_dirty = dev->preview_dirty = 1; dev->image_loading = dev->preview_loading = 0; dev->image_force_reload = 0; dev->preview_input_changed = 0; dev->pipe = dev->preview_pipe = NULL; dev->histogram = NULL; dev->histogram_pre_tonecurve = NULL; dev->histogram_pre_levels = NULL; if(dev->gui_attached) { dev->pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dev->preview_pipe = (dt_dev_pixelpipe_t *)malloc(sizeof(dt_dev_pixelpipe_t)); dt_dev_pixelpipe_init(dev->pipe); dt_dev_pixelpipe_init(dev->preview_pipe); dev->histogram = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_tonecurve = (float *)malloc(sizeof(float)*4*256); dev->histogram_pre_levels = (float*)malloc(sizeof(float) * 4 * 256); memset(dev->histogram, 0, sizeof(float)*256*4); memset(dev->histogram_pre_tonecurve, 0, sizeof(float)*256*4); memset(dev->histogram_pre_levels, 0, sizeof(float)*256*4); dev->histogram_max = -1; dev->histogram_pre_tonecurve_max = -1; dev->histogram_pre_levels_max = -1; } dev->iop_instance = 0; dev->iop = NULL; }
void dt_history_delete_on_image(int32_t imgid) { sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "delete from history where imgid = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); sqlite3_step (stmt); sqlite3_finalize (stmt); dt_image_t tmp; dt_image_init (&tmp); /* if current image in develop reload history */ if (dt_dev_is_current_image (darktable.develop, imgid)) dt_dev_reload_history_items (darktable.develop); /* make sure mipmaps are recomputed */ dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); /* remove darktable|style|* tags */ dt_tag_detach_by_string("darktable|style%",imgid); }
void dt_image_cache_allocate(void *data, dt_cache_entry_t *entry) { entry->cost = sizeof(dt_image_t); dt_image_t *img = (dt_image_t *)g_malloc(sizeof(dt_image_t)); dt_image_init(img); entry->data = img; // load stuff from db and store in cache: char *str; sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2( dt_database_get(darktable.db), "SELECT id, group_id, film_id, width, height, filename, maker, model, lens, exposure, " "aperture, iso, focal_length, datetime_taken, flags, crop, orientation, focus_distance, " "raw_parameters, longitude, latitude, altitude, color_matrix, colorspace, version, raw_black, " "raw_maximum FROM main.images WHERE id = ?1", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, entry->key); if(sqlite3_step(stmt) == SQLITE_ROW) { img->id = sqlite3_column_int(stmt, 0); img->group_id = sqlite3_column_int(stmt, 1); img->film_id = sqlite3_column_int(stmt, 2); img->width = sqlite3_column_int(stmt, 3); img->height = sqlite3_column_int(stmt, 4); img->crop_x = img->crop_y = img->crop_width = img->crop_height = 0; img->filename[0] = img->exif_maker[0] = img->exif_model[0] = img->exif_lens[0] = img->exif_datetime_taken[0] = '\0'; str = (char *)sqlite3_column_text(stmt, 5); if(str) g_strlcpy(img->filename, str, sizeof(img->filename)); str = (char *)sqlite3_column_text(stmt, 6); if(str) g_strlcpy(img->exif_maker, str, sizeof(img->exif_maker)); str = (char *)sqlite3_column_text(stmt, 7); if(str) g_strlcpy(img->exif_model, str, sizeof(img->exif_model)); str = (char *)sqlite3_column_text(stmt, 8); if(str) g_strlcpy(img->exif_lens, str, sizeof(img->exif_lens)); img->exif_exposure = sqlite3_column_double(stmt, 9); img->exif_aperture = sqlite3_column_double(stmt, 10); img->exif_iso = sqlite3_column_double(stmt, 11); img->exif_focal_length = sqlite3_column_double(stmt, 12); str = (char *)sqlite3_column_text(stmt, 13); if(str) g_strlcpy(img->exif_datetime_taken, str, sizeof(img->exif_datetime_taken)); img->flags = sqlite3_column_int(stmt, 14); img->loader = LOADER_UNKNOWN; img->exif_crop = sqlite3_column_double(stmt, 15); img->orientation = sqlite3_column_int(stmt, 16); img->exif_focus_distance = sqlite3_column_double(stmt, 17); if(img->exif_focus_distance >= 0 && img->orientation >= 0) img->exif_inited = 1; uint32_t tmp = sqlite3_column_int(stmt, 18); memcpy(&img->legacy_flip, &tmp, sizeof(dt_image_raw_parameters_t)); if(sqlite3_column_type(stmt, 19) == SQLITE_FLOAT) img->longitude = sqlite3_column_double(stmt, 19); else img->longitude = NAN; if(sqlite3_column_type(stmt, 20) == SQLITE_FLOAT) img->latitude = sqlite3_column_double(stmt, 20); else img->latitude = NAN; if(sqlite3_column_type(stmt, 21) == SQLITE_FLOAT) img->elevation = sqlite3_column_double(stmt, 21); else img->elevation = NAN; const void *color_matrix = sqlite3_column_blob(stmt, 22); if(color_matrix) memcpy(img->d65_color_matrix, color_matrix, sizeof(img->d65_color_matrix)); else img->d65_color_matrix[0] = NAN; g_free(img->profile); img->profile = NULL; img->profile_size = 0; img->colorspace = sqlite3_column_int(stmt, 23); img->version = sqlite3_column_int(stmt, 24); img->raw_black_level = sqlite3_column_int(stmt, 25); for(uint8_t i = 0; i < 4; i++) img->raw_black_level_separate[i] = 0; img->raw_white_point = sqlite3_column_int(stmt, 26); // buffer size? if(img->flags & DT_IMAGE_LDR) { img->buf_dsc.channels = 4; img->buf_dsc.datatype = TYPE_FLOAT; } else if(img->flags & DT_IMAGE_HDR) { if(img->flags & DT_IMAGE_RAW) { img->buf_dsc.channels = 1; img->buf_dsc.datatype = TYPE_FLOAT; } else { img->buf_dsc.channels = 4; img->buf_dsc.datatype = TYPE_FLOAT; } } else { // raw img->buf_dsc.channels = 1; img->buf_dsc.datatype = TYPE_UINT16; } } else { img->id = -1; fprintf(stderr, "[image_cache_allocate] failed to open image %d from database: %s\n", entry->key, sqlite3_errmsg(dt_database_get(darktable.db))); } sqlite3_finalize(stmt); img->cache_entry = entry; // init backref // could downgrade lock write->read on entry->lock if we were using concurrencykit.. dt_image_refresh_makermodel(img); }