diff --git a/src/common/history.c b/src/common/history.c index 3e11fe27211c..b58f8bb002fb 100644 --- a/src/common/history.c +++ b/src/common/history.c @@ -92,6 +92,7 @@ void dt_history_delete_on_image_ext(int32_t imgid, gboolean undo) /* make sure mipmaps are recomputed */ dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); + dt_image_reset_final_size(imgid); /* remove darktable|style|* tags */ dt_tag_detach_by_string("darktable|style%", imgid); @@ -167,6 +168,7 @@ int dt_history_load_and_apply(const int imgid, gchar *filename, int history_only dt_image_cache_write_release(darktable.image_cache, img, DT_IMAGE_CACHE_SAFE); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); + dt_image_reset_final_size(imgid); } return 0; } @@ -739,6 +741,7 @@ int dt_history_copy_and_paste_on_image(int32_t imgid, int32_t dest_imgid, gboole dt_image_synch_xmp(dest_imgid); dt_mipmap_cache_remove(darktable.mipmap_cache, dest_imgid); + dt_image_reset_final_size(imgid); /* update the aspect ratio if the current sorting is based on aspect ratio, otherwise the aspect ratio will be recalculated when the mimpap will be recreated */ diff --git a/src/common/image.c b/src/common/image.c index ba8608aa7043..cff27e2e6c82 100644 --- a/src/common/image.c +++ b/src/common/image.c @@ -383,16 +383,54 @@ void dt_image_set_location_and_elevation(const int32_t imgid, dt_image_geoloc_t dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); } +void dt_image_reset_final_size(const int32_t imgid) +{ + dt_image_t *imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w'); + imgtmp->final_width = imgtmp->final_height = 0; + dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED); +} + gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height) { - dt_develop_t dev; + // get the img strcut + dt_image_t *imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'r'); + dt_image_t img = *imgtmp; + dt_image_cache_read_release(darktable.image_cache, imgtmp); + // if we already have computed them + if(img.final_height > 0 && img.final_width > 0) + { + *width = img.final_width; + *height = img.final_height; + return 0; + } + + // special case if we try to load embedded preview of raw file + // the orientation for this camera is not read correctly from exiv2, so we need + // to go the full path (as the thumbnail will be flipped the wrong way round) + const int incompatible = !strncmp(img.exif_maker, "Phase One", 9); + if(!img.verified_size && !dt_image_altered(imgid) && !dt_conf_get_bool("never_use_embedded_thumb") + && !incompatible) + { + // we want to be sure to have the real image size. + // some raw files need a pass via rawspeed to get it. + char filename[PATH_MAX] = { 0 }; + gboolean from_cache = TRUE; + dt_image_full_path(imgid, filename, sizeof(filename), &from_cache); + imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w'); + dt_imageio_open(imgtmp, filename, NULL); + imgtmp->verified_size = 1; + img = *imgtmp; + dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED); + } + + // and now we can do the pipe stuff to get final image size + dt_develop_t dev; dt_dev_init(&dev, 0); dt_dev_load_image(&dev, imgid); - const dt_image_t *img = &dev.image_storage; dt_dev_pixelpipe_t pipe; - int wd = img->width, ht = img->height; + int wd = img.width, ht = img.height; int res = dt_dev_pixelpipe_init_dummy(&pipe, wd, ht); if(res) { @@ -409,8 +447,11 @@ gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height) } dt_dev_cleanup(&dev); - *width = wd; - *height = ht; + imgtmp = dt_image_cache_get(darktable.image_cache, imgid, 'w'); + imgtmp->final_width = *width = wd; + imgtmp->final_height = *height = ht; + dt_image_cache_write_release(darktable.image_cache, imgtmp, DT_IMAGE_CACHE_RELAXED); + return res; } @@ -461,6 +502,7 @@ void dt_image_set_flip(const int32_t imgid, const dt_image_orientation_t orienta sqlite3_finalize(stmt); dt_mipmap_cache_remove(darktable.mipmap_cache, imgid); + dt_image_reset_final_size(imgid); // write that through to xmp: dt_image_write_sidecar_file(imgid); } @@ -1195,6 +1237,7 @@ uint32_t dt_image_import_lua(const int32_t film_id, const char *filename, gboole void dt_image_init(dt_image_t *img) { img->width = img->height = img->verified_size = 0; + img->final_width = img->final_height = 0; img->crop_x = img->crop_y = img->crop_width = img->crop_height = 0; img->orientation = ORIENTATION_NULL; img->legacy_flip.legacy = 0; diff --git a/src/common/image.h b/src/common/image.h index 9b3119faabc0..853a825deeb8 100644 --- a/src/common/image.h +++ b/src/common/image.h @@ -153,7 +153,7 @@ typedef struct dt_image_t // common stuff // to understand this, look at comment for dt_histogram_roi_t - int32_t width, height, verified_size; + int32_t width, height, verified_size, final_width, final_height; int32_t crop_x, crop_y, crop_width, crop_height; // used by library @@ -235,6 +235,7 @@ void dt_image_set_flip(const int32_t imgid, const dt_image_orientation_t user_fl dt_image_orientation_t dt_image_get_orientation(const int imgid); /** get max width and height of the final processed image with its current hisotry stack */ gboolean dt_image_get_final_size(const int32_t imgid, int *width, int *height); +void dt_image_reset_final_size(const int32_t imgid); /** set image location lon/lat */ void dt_image_set_location(const int32_t imgid, dt_image_geoloc_t *geoloc); /** get image location lon/lat */ diff --git a/src/common/mipmap_cache.c b/src/common/mipmap_cache.c index 764fdd9bae47..99009883f9be 100644 --- a/src/common/mipmap_cache.c +++ b/src/common/mipmap_cache.c @@ -317,47 +317,11 @@ void dt_mipmap_cache_allocate_dynamic(void *data, dt_cache_entry_t *entry) { if(mip == DT_MIPMAP_8) { - const uint32_t imgid = get_imgid(entry->key); - if(!dt_image_altered(imgid)) - { - // the image has not been been altered, so output size = input size - // and the orientation doesn't matter here - const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r'); - entry->data_size = sizeof(struct dt_mipmap_buffer_dsc) + (img2->width + 4) * (img2->height + 4) * 4; - dt_image_cache_read_release(darktable.image_cache, img2); - } - else - { - // we first need to get the final output size of our image - // let's create a dummy pipe for that - const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r'); - dt_image_t imgtmp = *img2; - dt_image_cache_read_release(darktable.image_cache, img2); - dt_develop_t dev; - dt_dev_init(&dev, 0); - dt_dev_load_image(&dev, imgid); - dt_dev_pixelpipe_t pipe; - const int res = dt_dev_pixelpipe_init_dummy(&pipe, imgtmp.width, imgtmp.height); - if(res) - { - // set mem pointer to 0, won't be used. - dt_dev_pixelpipe_set_input(&pipe, &dev, NULL, imgtmp.width, imgtmp.height, 1.0f); - dt_dev_pixelpipe_create_nodes(&pipe, &dev); - dt_dev_pixelpipe_synch_all(&pipe, &dev); - dt_dev_pixelpipe_get_dimensions(&pipe, &dev, pipe.iwidth, pipe.iheight, &pipe.processed_width, - &pipe.processed_height); - dt_dev_pixelpipe_cleanup(&pipe); - // we enlarge the output size by 4 to handle rounding errors in mipmap computation - entry->data_size - = sizeof(struct dt_mipmap_buffer_dsc) + (pipe.processed_width + 4) * (pipe.processed_height + 4) * 4; - } - else - { - // for some raison pipeline didn't succeed, let's allocate huge memory - entry->data_size = cache->buffer_size[mip]; - } - dt_dev_cleanup(&dev); - } + int imgfw, imgfh; + imgfw = imgfh = 0; + // be sure that we have the right size values + dt_image_get_final_size(get_imgid(entry->key), &imgfw, &imgfh); + entry->data_size = sizeof(struct dt_mipmap_buffer_dsc) + (imgfw + 4) * (imgfh + 4) * 4; } else if(mip <= DT_MIPMAP_F) { @@ -1243,25 +1207,13 @@ static void _init_8(uint8_t *buf, uint32_t *width, uint32_t *height, float *isca } else { - // we want to be sure to have the real image size. - // some raw files need a pass via rawspeed to get it. - dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r'); - const int verified_size = img2->verified_size; - dt_image_cache_read_release(darktable.image_cache, img2); - if(!verified_size) - { - img2 = dt_image_cache_get(darktable.image_cache, imgid, 'w'); - dt_imageio_open(img2, filename, NULL); - img2->verified_size = 1; - dt_image_cache_write_release(darktable.image_cache, img2, DT_IMAGE_CACHE_RELAXED); - } uint8_t *tmp = 0; int32_t thumb_width, thumb_height; res = dt_imageio_large_thumbnail(filename, &tmp, &thumb_width, &thumb_height, color_space); if(!res) { // if the thumbnail is not large enough, we compute one - img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r'); + const dt_image_t *img2 = dt_image_cache_get(darktable.image_cache, imgid, 'r'); const int imgwd = img2->width; const int imght = img2->height; dt_image_cache_read_release(darktable.image_cache, img2); diff --git a/src/common/styles.c b/src/common/styles.c index 777fe86d22dc..b72ecdea934d 100644 --- a/src/common/styles.c +++ b/src/common/styles.c @@ -756,6 +756,7 @@ void dt_styles_apply_to_image(const char *name, gboolean duplicate, int32_t imgi /* remove old obsolete thumbnails */ dt_mipmap_cache_remove(darktable.mipmap_cache, newimgid); + dt_image_reset_final_size(newimgid); /* if we have created a duplicate, reset collected images */ if(duplicate) dt_control_signal_raise(darktable.signals, DT_SIGNAL_COLLECTION_CHANGED); diff --git a/src/external/rawspeed b/src/external/rawspeed index 521c6c6b763b..e30e3ead932a 160000 --- a/src/external/rawspeed +++ b/src/external/rawspeed @@ -1 +1 @@ -Subproject commit 521c6c6b763bed22ed1d4ad12ba224b1f39d29e2 +Subproject commit e30e3ead932a27871a3d16ec70d2ab395556f322 diff --git a/src/views/darkroom.c b/src/views/darkroom.c index 2133ef531493..19c89e422ff4 100644 --- a/src/views/darkroom.c +++ b/src/views/darkroom.c @@ -615,6 +615,7 @@ static void dt_dev_change_image(dt_develop_t *dev, const uint32_t imgid) // if() { dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id); + dt_image_reset_final_size(dev->image_storage.id); dt_image_synch_xmp(dev->image_storage.id); } @@ -2517,6 +2518,7 @@ void leave(dt_view_t *self) // if() { dt_mipmap_cache_remove(darktable.mipmap_cache, dev->image_storage.id); + dt_image_reset_final_size(dev->image_storage.id); // dump new xmp data dt_image_synch_xmp(dev->image_storage.id); } diff --git a/src/views/lighttable.c b/src/views/lighttable.c index f89a676f7b5d..32627d36711f 100644 --- a/src/views/lighttable.c +++ b/src/views/lighttable.c @@ -353,7 +353,7 @@ static inline void _destroy_preview_surface(dt_preview_surface_t *fp_surf) fp_surf->imgid = -1; fp_surf->w_lock = 0; - fp_surf->zoom_100 = 40.0f; + fp_surf->zoom_100 = 1001.0f; // dummy vaule to say it need recompute fp_surf->w_fit = 0.0f; fp_surf->h_fit = 0.0f; @@ -1790,6 +1790,18 @@ static int expose_zoomable(dt_view_t *self, cairo_t *cr, int32_t width, int32_t return missing; } +static float _preview_get_zoom100(int32_t width, int32_t height, uint32_t imgid) +{ + int w, h; + w = h = 0; + dt_image_get_final_size(imgid, &w, &h); + // 0.97f value come from dt_view_image_expose + float zoom_100 = fmaxf((float)w / ((float)width * 0.97f), (float)h / ((float)height * 0.97f)); + if(zoom_100 < 1.0f) zoom_100 = 1.0f; + + return zoom_100; +} + static int expose_expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery, const dt_lighttable_layout_t layout) { @@ -2131,7 +2143,9 @@ static int expose_expose(dt_view_t *self, cairo_t *cr, int32_t width, int32_t he params.full_surface_wd = &lib->fp_surf[i].width; params.full_surface_ht = &lib->fp_surf[i].height; params.full_surface_w_lock = &lib->fp_surf[i].w_lock; - params.full_zoom100 = &lib->fp_surf[i].zoom_100; + if(lib->fp_surf[i].zoom_100 >= 1000.0f || lib->fp_surf[i].imgid != images[i].imgid) + lib->fp_surf[i].zoom_100 = _preview_get_zoom100(images[i].width, images[i].height, images[i].imgid); + params.full_zoom100 = lib->fp_surf[i].zoom_100; params.full_w1 = &lib->fp_surf[i].w_fit; params.full_h1 = &lib->fp_surf[i].h_fit; params.full_maxdx = &lib->fp_surf[i].max_dx; @@ -2306,7 +2320,9 @@ static int expose_full_preview(dt_view_t *self, cairo_t *cr, int32_t width, int3 params.zoom = 1; params.full_preview = TRUE; params.full_zoom = lib->full_zoom; - params.full_zoom100 = &lib->fp_surf[0].zoom_100; + if(lib->fp_surf[0].zoom_100 >= 1000.0f || lib->fp_surf[0].imgid != lib->full_preview_id) + lib->fp_surf[0].zoom_100 = _preview_get_zoom100(width, height, lib->full_preview_id); + params.full_zoom100 = lib->fp_surf[0].zoom_100; params.full_maxdx = &lib->fp_surf[0].max_dx; params.full_maxdy = &lib->fp_surf[0].max_dy; params.full_w1 = &lib->fp_surf[0].w_fit; diff --git a/src/views/view.c b/src/views/view.c index 6dcda1e70f22..6360c2127699 100644 --- a/src/views/view.c +++ b/src/views/view.c @@ -1095,11 +1095,9 @@ int dt_view_image_expose(dt_view_image_expose_t *vals) dt_mipmap_cache_t *cache = darktable.mipmap_cache; - if(vals->full_surface_id && vals->full_zoom100 && *(vals->full_surface_id) != imgid) - *(vals->full_zoom100) = 40.0f; float fz = 1.0f; if(full_zoom > 0.0f) fz = full_zoom; - if(vals->full_zoom100 && *(vals->full_zoom100) > 0.0f) fz = fminf(*(vals->full_zoom100), fz); + if(vals->full_zoom100 > 0.0f) fz = fminf(vals->full_zoom100, fz); dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(cache, imgwd * width * fz, imgwd * height * fz); @@ -1139,21 +1137,6 @@ int dt_view_image_expose(dt_view_image_expose_t *vals) buf_wd = *(vals->full_surface_wd); buf_ht = *(vals->full_surface_ht); } - // we want to sanitize full_zoom value to be sure not to exceed 100% - if(fz > 1.0f && buf_sizeok) - { - // is the mipmap loaded the full one ? - if(cache->max_width[mip] > buf_wd + 4 && cache->max_height[mip] > buf_ht + 4) - { - float zoom_100 = fmaxf((float)buf_wd / ((float)width * imgwd), (float)buf_ht / ((float)height * imgwd)); - if(zoom_100 < 1.0f) zoom_100 = 1.0f; - if(vals->full_zoom100) *(vals->full_zoom100) = zoom_100; - if(fz > zoom_100) - { - fz = zoom_100; - } - } - } if(draw_thumb_background) { diff --git a/src/views/view.h b/src/views/view.h index 11722ed04428..4849eb5ed293 100644 --- a/src/views/view.h +++ b/src/views/view.h @@ -167,7 +167,7 @@ typedef struct dt_view_image_expose_t gboolean full_preview; gboolean image_only; float full_zoom; - float *full_zoom100; + float full_zoom100; float *full_w1; float *full_h1; float full_x;